Macaulay2 Engine
Loading...
Searching...
No Matches

◆ mpfc_sqrt()

void mpfc_sqrt ( gmp_CCmutable result,
gmp_CC a )

Definition at line 282 of file complex.c.

283{
284 // The idea is: write a = a1 + i * a2
285 // first make it numerically more stable by dividing by the larger
286 // answer will be multiplied by larger afterwards, if needed
287 // To take the square root of 1+di, or -1+di
288 // it is enough to solve (if sqrt is e+fi), e^2+f^2 = sqrt(1+d^2),
289 // and e^2-f^2 = 1 (or -1).
290
291 if (mpfr_zero_p(a->re) && mpfr_zero_p(a->im))
292 {
293 mpfr_set_si(result->re, 0, MPFR_RNDN);
294 mpfr_set_si(result->im, 0, MPFR_RNDN);
295 return;
296 }
297
298 mpfr_t b, c, d, d2;
299
300 unsigned long p = mpfr_get_prec(a->re);
301 mpfr_init2(b, p);
302 mpfr_init2(c, p);
303 mpfr_init2(d, p);
304 mpfr_init2(d2, p);
305
306 // b = fabs(a.re);
307 // c = fabs(a.im);
308 mpfr_abs(b, a->re, MPFR_RNDN);
309 mpfr_abs(c, a->im, MPFR_RNDN);
310 if (mpfr_greater_p(b, c))
311 {
312 // d = c/b;
313 // e = ::sqrt(b) * ::sqrt(0.5 * (1.0 + ::sqrt(1.0 + d*d)));
314 // but use c as d, and also as e
315 mpfr_div(d, c, b, MPFR_RNDN);
316 mpfr_sqr(d, d, MPFR_RNDN);
317 mpfr_add_si(d, d, 1, MPFR_RNDN);
318 mpfr_sqrt(d, d, MPFR_RNDN);
319 mpfr_add_si(d, d, 1, MPFR_RNDN);
320 mpfr_div_2ui(d, d, 1, MPFR_RNDN);
321 mpfr_sqrt(d, d, MPFR_RNDN);
322 mpfr_sqrt(b, b, MPFR_RNDN);
323 mpfr_mul(d, d, b, MPFR_RNDN); /* this is now e ! */
324 }
325 else
326 {
327 // d = b/c;
328 // e = ::sqrt(c) * ::sqrt(0.5 * (d + ::sqrt(1.0 + d*d)));
329 mpfr_div(d, b, c, MPFR_RNDN);
330 mpfr_sqr(d2, d, MPFR_RNDN);
331 mpfr_add_si(d2, d2, 1, MPFR_RNDN);
332 mpfr_sqrt(d2, d2, MPFR_RNDN);
333 mpfr_add(d, d2, d, MPFR_RNDN);
334 mpfr_div_2ui(d, d, 1, MPFR_RNDN);
335 mpfr_sqrt(d, d, MPFR_RNDN);
336 mpfr_sqrt(c, c, MPFR_RNDN);
337 mpfr_mul(d, d, c, MPFR_RNDN); /* this is now e ! */
338 }
339 if (mpfr_sgn(a->re) >= 0)
340 {
341 // result.re = e;
342 // result.im = a.im/(2.0 * e);
343 mpfr_set(result->re, d, MPFR_RNDN);
344 mpfr_mul_2ui(d, d, 1, MPFR_RNDN);
345 mpfr_div(result->im, a->im, d, MPFR_RNDN);
346 }
347 else
348 {
349 // result.im = (a.im >= 0.0 ? e : -e);
350 // result.re = a.re/(2.0*result.im);
351 mpfr_set(result->im, d, MPFR_RNDN);
352 if (mpfr_sgn(a->im) < 0) mpfr_neg(result->im, result->im, MPFR_RNDN);
353 mpfr_mul_2ui(d, result->im, 1, MPFR_RNDN);
354 mpfr_div(result->re, a->im, d, MPFR_RNDN);
355 }
356
357 mpfr_clear(b);
358 mpfr_clear(c);
359 mpfr_clear(d);
360 mpfr_clear(d2);
361
362#if 0
363 static void sqrt(elem &result, elem a)
364 {
365 double b,c,d,e;
366 if (a.re == 0.0 && a.im == 0.0)
367 {
368 result.re = 0.0;
369 result.im = 0.0;
370 }
371 else
372 {
373 b = fabs(a.re);
374 c = fabs(a.im);
375 if (b > c)
376 {
377 d = c/b;
378 e = ::sqrt(b) * ::sqrt(0.5 * (1.0 + ::sqrt(1.0 + d*d)));
379 }
380 else
381 {
382 d = b/c;
383 e = ::sqrt(c) * ::sqrt(0.5 * (d + ::sqrt(1.0 + d*d)));
384 }
385 // Now be careful with the signs:
386 if (a.re >= 0.0)
387 {
388 result.re = e;
389 result.im = a.im/(2.0 * e);
390 }
391 else
392 {
393 result.im = (a.im >= 0.0 ? e : -e);
394 result.re = a.re/(2.0*result.im);
395 }
396 }
397 }
398#endif
399}
int p
VALGRIND_MAKE_MEM_DEFINED & result(result)
const mpreal sqrt(const unsigned int v, mp_rnd_t rnd_mode=mpreal::get_default_rnd())
Definition mpreal.h:2244
const mpreal fabs(const mpreal &x, mp_rnd_t r=mpreal::get_default_rnd())
Definition mpreal.h:2293

References p, and result().