1 /* balls -- Functions for complex ball arithmetic. 2 3 Copyright (C) 2018, 2020, 2021, 2022 INRIA 4 5 This file is part of GNU MPC. 6 7 GNU MPC is free software; you can redistribute it and/or modify it under 8 the terms of the GNU Lesser General Public License as published by the 9 Free Software Foundation; either version 3 of the License, or (at your 10 option) any later version. 11 12 GNU MPC is distributed in the hope that it will be useful, but WITHOUT ANY 13 WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 14 FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for 15 more details. 16 17 You should have received a copy of the GNU Lesser General Public License 18 along with this program. If not, see http://www.gnu.org/licenses/ . 19 */ 20 21 #include <limits.h> /* for CHAR_BIT */ 22 #include <stdio.h> /* for FILE */ 23 #include "mpc-impl.h" 24 25 void mpcb_out_str (FILE *f, mpcb_srcptr op) 26 { 27 mpc_out_str (f, 10, 0, op->c, MPC_RNDNN); 28 fprintf (f, " "); 29 mpcr_out_str (f, op->r); 30 fprintf (f, "\n"); 31 } 32 33 void 34 mpcb_init (mpcb_ptr rop) 35 { 36 mpc_init2 (rop->c, 2); 37 mpcr_set_inf (rop->r); 38 } 39 40 41 void 42 mpcb_clear (mpcb_ptr rop) 43 { 44 mpc_clear (rop->c); 45 } 46 47 48 mpfr_prec_t 49 mpcb_get_prec (mpcb_srcptr op) 50 { 51 return mpc_get_prec (op->c); 52 } 53 54 55 void 56 mpcb_set_prec (mpcb_ptr rop, mpfr_prec_t prec) 57 { 58 mpc_set_prec (rop->c, prec); 59 mpcr_set_inf (rop->r); 60 } 61 62 63 void 64 mpcb_set (mpcb_ptr rop, mpcb_srcptr op) 65 { 66 if (rop != op) { 67 mpc_set_prec (rop->c, mpc_get_prec (op->c)); 68 mpc_set (rop->c, op->c, MPC_RNDNN); 69 mpcr_set (rop->r, op->r); 70 } 71 } 72 73 74 void 75 mpcb_set_inf (mpcb_ptr rop) 76 { 77 mpc_set_prec (rop->c, 2); 78 mpc_set_ui_ui (rop->c, 0, 0, MPC_RNDNN); 79 mpcr_set_inf (rop->r); 80 } 81 82 83 void 84 mpcb_set_c (mpcb_ptr rop, mpc_srcptr op, mpfr_prec_t prec, 85 unsigned long int err_re, unsigned long int err_im) 86 /* Set the precision of rop to prec and assign a ball with centre op 87 to it. err_re and err_im contain potential errors in the real and 88 imaginary parts of op as multiples of a half ulp. For instance, 89 if the real part of op is exact, err_re should be set to 0; 90 if it is the result of rounding to nearest, it should be set to 1; 91 if it is the result of directed rounding, it should be set to 2. 92 The radius of the ball reflects err_re and err_im and the potential 93 additional rounding error that can occur when the precision of op 94 is higher than prec. If the real part of op is 0, then err_re 95 should be 0, since then ulp notation makes no sense, and similarly 96 for the imaginary part; otherwise the radius is set to infinity. 97 The implementation takes potential different precisions in the real 98 and imaginary parts of op into account. */ 99 { 100 int inex; 101 mpcr_t relerr_re, relerr_im; 102 103 mpc_set_prec (rop->c, prec); 104 inex = mpc_set (rop->c, op, MPC_RNDNN); 105 106 if ( (mpfr_zero_p (mpc_realref (op)) && err_re > 0) 107 || (mpfr_zero_p (mpc_imagref (op)) && err_im > 0) 108 || !mpc_fin_p (op)) 109 mpcr_set_inf (rop->r); 110 else { 111 mpcr_set_ui64_2si64 (relerr_re, (uint64_t) err_re, 112 (int64_t) (-mpfr_get_prec (mpc_realref (op)))); 113 /* prop:relerror of algorithms.tex */ 114 if (MPC_INEX_RE (inex)) 115 mpcr_add_rounding_error (relerr_re, prec, MPFR_RNDN); 116 mpcr_set_ui64_2si64 (relerr_im, (uint64_t) err_im, 117 (int64_t) (-mpfr_get_prec (mpc_imagref (op)))); 118 if (MPC_INEX_IM (inex)) 119 mpcr_add_rounding_error (relerr_im, prec, MPFR_RNDN); 120 mpcr_max (rop->r, relerr_re, relerr_im); 121 /* prop:comrelerror in algorithms.tex */ 122 } 123 } 124 125 126 void 127 mpcb_set_ui_ui (mpcb_ptr z, unsigned long int re, unsigned long int im, 128 mpfr_prec_t prec) 129 /* Set the precision of z to prec and assign a ball with centre 130 re+I*im to it. If prec is too small to hold the centre coordinates 131 without rounding, use the minimal possible precision instead. */ 132 { 133 prec = MPC_MAX (prec, 134 (mpfr_prec_t) (CHAR_BIT * sizeof (unsigned long int))); 135 mpc_set_prec (z->c, prec); 136 mpc_set_ui_ui (z->c, re, im, MPC_RNDNN); 137 mpcr_set_zero (z->r); 138 } 139 140 141 void 142 mpcb_neg (mpcb_ptr z, mpcb_srcptr z1) 143 { 144 mpfr_prec_t p; 145 int overlap = (z == z1); 146 147 if (!overlap) { 148 p = mpcb_get_prec (z1); 149 if (mpcb_get_prec (z) != p) 150 mpcb_set_prec (z, p); 151 } 152 153 mpc_neg (z->c, z1->c, MPC_RNDNN); /* exact */ 154 mpcr_set (z->r, z1->r); 155 } 156 157 158 void 159 mpcb_mul (mpcb_ptr z, mpcb_srcptr z1, mpcb_srcptr z2) 160 { 161 mpcr_t r; 162 mpfr_prec_t p = MPC_MIN (mpcb_get_prec (z1), mpcb_get_prec (z2)); 163 int overlap = (z == z1 || z == z2); 164 mpc_t zc; 165 166 if (overlap) 167 mpc_init2 (zc, p); 168 else { 169 zc [0] = z->c [0]; 170 mpc_set_prec (zc, p); 171 } 172 mpc_mul (zc, z1->c, z2->c, MPC_RNDNN); 173 if (overlap) 174 mpc_clear (z->c); 175 z->c [0] = zc [0]; 176 177 /* generic error of multiplication */ 178 mpcr_mul (r, z1->r, z2->r); 179 mpcr_add (r, r, z1->r); 180 mpcr_add (r, r, z2->r); 181 /* error of rounding to nearest */ 182 mpcr_add_rounding_error (r, p, MPFR_RNDN); 183 mpcr_set (z->r, r); 184 } 185 186 187 void 188 mpcb_sqr (mpcb_ptr z, mpcb_srcptr z1) 189 { 190 mpcr_t r, r2; 191 mpfr_prec_t p = mpcb_get_prec (z1); 192 int overlap = (z == z1); 193 194 /* Compute the error first in case there is overlap. */ 195 mpcr_mul_2ui (r2, z1->r, 1); 196 mpcr_sqr (r, z1->r); 197 mpcr_add (r, r, r2); 198 mpcr_add_rounding_error (r, p, MPFR_RNDN); 199 200 if (!overlap) 201 mpcb_set_prec (z, p); 202 mpc_sqr (z->c, z1->c, MPC_RNDNN); 203 mpcr_set (z->r, r); 204 } 205 206 void 207 mpcb_pow_ui (mpcb_ptr z, mpcb_srcptr z1, unsigned long int e) 208 { 209 mpcb_t pow; 210 211 if (e == 0) 212 mpcb_set_ui_ui (z, 1, 0, mpcb_get_prec (z1)); 213 else if (e == 1) 214 mpcb_set (z, z1); 215 else { 216 /* Right to left powering is easier to implement, but requires an 217 additional variable even when there is no overlap. */ 218 mpcb_init (pow); 219 mpcb_set (pow, z1); 220 /* Avoid setting z to 1 and multiplying by it, instead set it to the 221 smallest 2-power multiple of z1 that is occurring. */ 222 while (e % 2 == 0) { 223 mpcb_sqr (pow, pow); 224 e /= 2; 225 } 226 mpcb_set (z, pow); 227 e /= 2; 228 while (e != 0) { 229 mpcb_sqr (pow, pow); 230 if (e % 2 == 1) 231 mpcb_mul (z, z, pow); 232 e /= 2; 233 } 234 mpcb_clear (pow); 235 } 236 } 237 238 239 void 240 mpcb_add (mpcb_ptr z, mpcb_srcptr z1, mpcb_srcptr z2) 241 { 242 mpcr_t r, s, denom; 243 mpfr_prec_t p = MPC_MIN (mpcb_get_prec (z1), mpcb_get_prec (z2)); 244 int overlap = (z == z1 || z == z2); 245 mpc_t zc; 246 247 if (overlap) 248 mpc_init2 (zc, p); 249 else { 250 zc [0] = z->c [0]; 251 mpc_set_prec (zc, p); 252 } 253 mpc_add (zc, z1->c, z2->c, MPC_RNDZZ); 254 /* rounding towards 0 makes the generic error easier to compute, 255 but incurs a tiny penalty for the rounding error */ 256 257 /* generic error of addition: 258 r <= (|z1|*r1 + |z2|*r2) / |z1+z2| 259 <= (|z1|*r1 + |z2|*r2) / |z| since we rounded towards 0 */ 260 mpcr_c_abs_rnd (denom, zc, MPFR_RNDD); 261 mpcr_c_abs_rnd (r, z1->c, MPFR_RNDU); 262 mpcr_mul (r, r, z1->r); 263 mpcr_c_abs_rnd (s, z2->c, MPFR_RNDU); 264 mpcr_mul (s, s, z2->r); 265 mpcr_add (r, r, s); 266 mpcr_div (r, r, denom); 267 /* error of directed rounding */ 268 mpcr_add_rounding_error (r, p, MPFR_RNDZ); 269 270 if (overlap) 271 mpc_clear (z->c); 272 z->c [0] = zc [0]; 273 mpcr_set (z->r, r); 274 } 275 276 277 void 278 mpcb_sqrt (mpcb_ptr z, mpcb_srcptr z1) 279 /* The function "glides over" the branch cut on the negative real axis: 280 In fact it always returns a ball with centre the square root of the 281 centre of z1, and a reasonable radius even when the input ball has a 282 crosses the negative real axis. This is inconsistent in a sense: The 283 output ball does not contain all the possible outputs of a call to 284 mpc_sqrt on an element of the input ball. On the other hand, it does 285 contain square roots of all elements of the input ball. This comes 286 handy for the alternative implementation of mpc_agm using ball 287 arithmetic, but would also cause a potential implementation of 288 mpcb_agm to ignore the branch cut. */ 289 { 290 mpcr_t r; 291 mpfr_prec_t p = mpcb_get_prec (z1); 292 int overlap = (z == z1); 293 294 /* Compute the error first in case there is overlap. */ 295 /* generic error of square root for z1->r <= 0.5: 296 0.5*epsilon1 + (sqrt(2)-1) * epsilon1^2 297 <= 0.5 * epsilon1 * (1 + epsilon1), 298 see eq:propsqrt in algorithms.tex, together with a Taylor 299 expansion of 1/sqrt(1-epsilon1) */ 300 if (!mpcr_lt_half_p (z1->r)) 301 mpcr_set_inf (r); 302 else { 303 mpcr_set_one (r); 304 mpcr_add (r, r, z1->r); 305 mpcr_mul (r, r, z1->r); 306 mpcr_div_2ui (r, r, 1); 307 /* error of rounding to nearest */ 308 mpcr_add_rounding_error (r, p, MPFR_RNDN); 309 } 310 311 if (!overlap) 312 mpcb_set_prec (z, p); 313 mpc_sqrt (z->c, z1->c, MPC_RNDNN); 314 mpcr_set (z->r, r); 315 } 316 317 318 void 319 mpcb_div (mpcb_ptr z, mpcb_srcptr z1, mpcb_srcptr z2) 320 { 321 mpcr_t r, s; 322 mpfr_prec_t p = MPC_MIN (mpcb_get_prec (z1), mpcb_get_prec (z2)); 323 int overlap = (z == z1 || z == z2); 324 mpc_t zc; 325 326 if (overlap) 327 mpc_init2 (zc, p); 328 else { 329 zc [0] = z->c [0]; 330 mpc_set_prec (zc, p); 331 } 332 mpc_div (zc, z1->c, z2->c, MPC_RNDNN); 333 if (overlap) 334 mpc_clear (z->c); 335 z->c [0] = zc [0]; 336 337 /* generic error of division */ 338 mpcr_add (r, z1->r, z2->r); 339 mpcr_set_one (s); 340 mpcr_sub_rnd (s, s, z2->r, MPFR_RNDD); 341 mpcr_div (r, r, s); 342 /* error of rounding to nearest */ 343 mpcr_add_rounding_error (r, p, MPFR_RNDN); 344 mpcr_set (z->r, r); 345 } 346 347 348 void 349 mpcb_div_2ui (mpcb_ptr z, mpcb_srcptr z1, unsigned long int e) 350 { 351 mpc_div_2ui (z->c, z1->c, e, MPC_RNDNN); 352 mpcr_set (z->r, z1->r); 353 } 354 355 356 int 357 mpcb_can_round (mpcb_srcptr op, mpfr_prec_t prec_re, mpfr_prec_t prec_im, 358 mpc_rnd_t rnd) 359 /* The function returns true if it can decide that rounding the centre 360 of op to an mpc_t variable of precision prec_re for the real and 361 prec_im for the imaginary part returns a correctly rounded result 362 of the ball in direction rnd for which the rounding direction value 363 can be determined. The second condition implies that if the centre 364 can be represented at the target precisions and the radius is small, 365 but non-zero, the function returns false although correct rounding 366 would be possible, while the rounding direction value could be 367 anything. 368 If the return value is true, then using mpcb_round with the same 369 rounding mode sets a correct result and returns a correct rounding 370 direction value with the usual MPC semantic. */ 371 { 372 mpfr_srcptr re, im; 373 mpfr_exp_t exp_re, exp_im, exp_err; 374 375 if (mpcr_inf_p (op->r)) 376 return 0; 377 else if (mpcr_zero_p (op->r)) 378 return 1; 379 380 re = mpc_realref (op->c); 381 im = mpc_imagref (op->c); 382 /* If the real or the imaginary part of the centre is 0, directed 383 rounding is impossible, and rounding to nearest is only possible 384 if the absolute error is less than the smallest representable 385 number; since rounding only once at precision p introduces an error 386 of about 2^-p, this means that the precision needs to be about as 387 big as the negative of the minimal exponent, which is astronomically 388 large. In any case, even then we could not determine the rounding 389 direction value. */ 390 if (mpfr_zero_p (re) || mpfr_zero_p (im)) 391 return 0; 392 393 exp_re = mpfr_get_exp (re); 394 exp_im = mpfr_get_exp (im); 395 396 /* Absolute error of the real part, as given in the proof of 397 prop:comrelerror of algorithms.tex: 398 |x-x~| = |x~*theta_R - y~*theta_I| 399 <= (|x~|+|y~|) * epsilon, 400 where epsilon is the complex relative error 401 <= 2 * max (|x~|, |y~|) * epsilon 402 To call mpfr_can_round, we only need the exponent in base 2, 403 which is then bounded above by 404 1 + max (exp_re, exp_im) + exponent (epsilon) */ 405 exp_err = 1 + MPC_MAX (exp_re, exp_im) + mpcr_get_exp (op->r); 406 407 /* To check whether the rounding direction value can be determined 408 when rounding to nearest, use the trick described in the 409 documentation of mpfr_can_round to check for directed rounding 410 at precision larger by 1. */ 411 return ( mpfr_can_round (re, exp_re - exp_err, MPFR_RNDN, 412 MPFR_RNDZ, prec_re + (MPC_RND_RE (rnd) == MPFR_RNDN)) 413 && mpfr_can_round (im, exp_im - exp_err, MPFR_RNDN, 414 MPFR_RNDZ, prec_im + (MPC_RND_IM (rnd) == MPFR_RNDN))); 415 } 416 417 418 int 419 mpcb_round (mpc_ptr rop, mpcb_srcptr op, mpc_rnd_t rnd) 420 /* Set rop to the centre of op and return the corresponding rounding 421 direction value. To make sure that this corresponds to the MPC 422 semantics of returning a correctly rounded result and a correct 423 rounding direction value, one needs to call mpcb_can_round first. */ 424 { 425 return mpc_set (rop, op->c, rnd); 426 } 427 428