1 1.1 mrg /* mini-mpq, a minimalistic implementation of a GNU GMP subset. 2 1.1 mrg 3 1.1 mrg Contributed to the GNU project by Marco Bodrato 4 1.1 mrg 5 1.1 mrg Acknowledgment: special thanks to Bradley Lucier for his comments 6 1.1 mrg to the preliminary version of this code. 7 1.1 mrg 8 1.1.1.2 mrg Copyright 2018-2020 Free Software Foundation, Inc. 9 1.1 mrg 10 1.1 mrg This file is part of the GNU MP Library. 11 1.1 mrg 12 1.1 mrg The GNU MP Library is free software; you can redistribute it and/or modify 13 1.1 mrg it under the terms of either: 14 1.1 mrg 15 1.1 mrg * the GNU Lesser General Public License as published by the Free 16 1.1 mrg Software Foundation; either version 3 of the License, or (at your 17 1.1 mrg option) any later version. 18 1.1 mrg 19 1.1 mrg or 20 1.1 mrg 21 1.1 mrg * the GNU General Public License as published by the Free Software 22 1.1 mrg Foundation; either version 2 of the License, or (at your option) any 23 1.1 mrg later version. 24 1.1 mrg 25 1.1 mrg or both in parallel, as here. 26 1.1 mrg 27 1.1 mrg The GNU MP Library is distributed in the hope that it will be useful, but 28 1.1 mrg WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 29 1.1 mrg or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 30 1.1 mrg for more details. 31 1.1 mrg 32 1.1 mrg You should have received copies of the GNU General Public License and the 33 1.1 mrg GNU Lesser General Public License along with the GNU MP Library. If not, 34 1.1 mrg see https://www.gnu.org/licenses/. */ 35 1.1 mrg 36 1.1 mrg #include <assert.h> 37 1.1 mrg #include <limits.h> 38 1.1 mrg #include <stdio.h> 39 1.1 mrg #include <stdlib.h> 40 1.1 mrg #include <string.h> 41 1.1 mrg 42 1.1 mrg #include "mini-mpq.h" 43 1.1 mrg 44 1.1 mrg #ifndef GMP_LIMB_HIGHBIT 45 1.1 mrg /* Define macros and static functions already defined by mini-gmp.c */ 46 1.1 mrg #define GMP_LIMB_BITS (sizeof(mp_limb_t) * CHAR_BIT) 47 1.1 mrg #define GMP_LIMB_HIGHBIT ((mp_limb_t) 1 << (GMP_LIMB_BITS - 1)) 48 1.1 mrg #define GMP_NEG_CAST(T,x) (-((T)((x) + 1) - 1)) 49 1.1 mrg #define GMP_MIN(a, b) ((a) < (b) ? (a) : (b)) 50 1.1 mrg 51 1.1 mrg static mpz_srcptr 52 1.1 mrg mpz_roinit_normal_n (mpz_t x, mp_srcptr xp, mp_size_t xs) 53 1.1 mrg { 54 1.1 mrg x->_mp_alloc = 0; 55 1.1 mrg x->_mp_d = (mp_ptr) xp; 56 1.1 mrg x->_mp_size = xs; 57 1.1 mrg return x; 58 1.1 mrg } 59 1.1 mrg 60 1.1 mrg static void 61 1.1 mrg gmp_die (const char *msg) 62 1.1 mrg { 63 1.1 mrg fprintf (stderr, "%s\n", msg); 64 1.1 mrg abort(); 65 1.1 mrg } 66 1.1 mrg #endif 67 1.1 mrg 68 1.1 mrg 69 1.1 mrg /* MPQ helper functions */ 71 1.1 mrg static mpq_srcptr 72 1.1 mrg mpq_roinit_normal_nn (mpq_t x, mp_srcptr np, mp_size_t ns, 73 1.1 mrg mp_srcptr dp, mp_size_t ds) 74 1.1 mrg { 75 1.1 mrg mpz_roinit_normal_n (mpq_numref(x), np, ns); 76 1.1 mrg mpz_roinit_normal_n (mpq_denref(x), dp, ds); 77 1.1 mrg return x; 78 1.1 mrg } 79 1.1 mrg 80 1.1 mrg static mpq_srcptr 81 1.1 mrg mpq_roinit_zz (mpq_t x, mpz_srcptr n, mpz_srcptr d) 82 1.1 mrg { 83 1.1 mrg return mpq_roinit_normal_nn (x, n->_mp_d, n->_mp_size, 84 1.1 mrg d->_mp_d, d->_mp_size); 85 1.1 mrg } 86 1.1 mrg 87 1.1 mrg static void 88 1.1 mrg mpq_nan_init (mpq_t x) 89 1.1 mrg { 90 1.1 mrg mpz_init (mpq_numref (x)); 91 1.1 mrg mpz_init (mpq_denref (x)); 92 1.1 mrg } 93 1.1 mrg 94 1.1 mrg void 95 1.1 mrg mpq_init (mpq_t x) 96 1.1 mrg { 97 1.1 mrg mpz_init (mpq_numref (x)); 98 1.1 mrg mpz_init_set_ui (mpq_denref (x), 1); 99 1.1 mrg } 100 1.1 mrg 101 1.1 mrg void 102 1.1 mrg mpq_clear (mpq_t x) 103 1.1 mrg { 104 1.1 mrg mpz_clear (mpq_numref (x)); 105 1.1 mrg mpz_clear (mpq_denref (x)); 106 1.1 mrg } 107 1.1 mrg 108 1.1 mrg static void 109 1.1 mrg mpq_canonical_sign (mpq_t r) 110 1.1.1.2 mrg { 111 1.1.1.2 mrg mp_size_t ds = mpq_denref (r)->_mp_size; 112 1.1 mrg if (ds <= 0) 113 1.1.1.2 mrg { 114 1.1 mrg if (ds == 0) 115 1.1 mrg gmp_die("mpq: Fraction with zero denominator."); 116 1.1 mrg mpz_neg (mpq_denref (r), mpq_denref (r)); 117 1.1 mrg mpz_neg (mpq_numref (r), mpq_numref (r)); 118 1.1 mrg } 119 1.1 mrg } 120 1.1 mrg 121 1.1 mrg static void 122 1.1 mrg mpq_helper_canonicalize (mpq_t r, const mpz_t num, const mpz_t den, mpz_t g) 123 1.1 mrg { 124 1.1 mrg if (num->_mp_size == 0) 125 1.1 mrg mpq_set_ui (r, 0, 1); 126 1.1 mrg else 127 1.1 mrg { 128 1.1 mrg mpz_gcd (g, num, den); 129 1.1 mrg mpz_tdiv_q (mpq_numref (r), num, g); 130 1.1 mrg mpz_tdiv_q (mpq_denref (r), den, g); 131 1.1 mrg mpq_canonical_sign (r); 132 1.1 mrg } 133 1.1 mrg } 134 1.1 mrg 135 1.1 mrg void 136 1.1 mrg mpq_canonicalize (mpq_t r) 137 1.1 mrg { 138 1.1 mrg mpz_t t; 139 1.1 mrg 140 1.1 mrg mpz_init (t); 141 1.1 mrg mpq_helper_canonicalize (r, mpq_numref (r), mpq_denref (r), t); 142 1.1 mrg mpz_clear (t); 143 1.1 mrg } 144 1.1 mrg 145 1.1 mrg void 146 1.1 mrg mpq_swap (mpq_t a, mpq_t b) 147 1.1 mrg { 148 1.1 mrg mpz_swap (mpq_numref (a), mpq_numref (b)); 149 1.1 mrg mpz_swap (mpq_denref (a), mpq_denref (b)); 150 1.1 mrg } 151 1.1 mrg 152 1.1 mrg 153 1.1 mrg /* MPQ assignment and conversions. */ 155 1.1 mrg void 156 1.1 mrg mpz_set_q (mpz_t r, const mpq_t q) 157 1.1 mrg { 158 1.1 mrg mpz_tdiv_q (r, mpq_numref (q), mpq_denref (q)); 159 1.1 mrg } 160 1.1 mrg 161 1.1 mrg void 162 1.1 mrg mpq_set (mpq_t r, const mpq_t q) 163 1.1 mrg { 164 1.1 mrg mpz_set (mpq_numref (r), mpq_numref (q)); 165 1.1 mrg mpz_set (mpq_denref (r), mpq_denref (q)); 166 1.1 mrg } 167 1.1 mrg 168 1.1 mrg void 169 1.1 mrg mpq_set_ui (mpq_t r, unsigned long n, unsigned long d) 170 1.1 mrg { 171 1.1 mrg mpz_set_ui (mpq_numref (r), n); 172 1.1 mrg mpz_set_ui (mpq_denref (r), d); 173 1.1 mrg } 174 1.1 mrg 175 1.1 mrg void 176 1.1 mrg mpq_set_si (mpq_t r, signed long n, unsigned long d) 177 1.1 mrg { 178 1.1 mrg mpz_set_si (mpq_numref (r), n); 179 1.1 mrg mpz_set_ui (mpq_denref (r), d); 180 1.1 mrg } 181 1.1 mrg 182 1.1 mrg void 183 1.1 mrg mpq_set_z (mpq_t r, const mpz_t n) 184 1.1 mrg { 185 1.1 mrg mpz_set_ui (mpq_denref (r), 1); 186 1.1 mrg mpz_set (mpq_numref (r), n); 187 1.1 mrg } 188 1.1 mrg 189 1.1 mrg void 190 1.1 mrg mpq_set_num (mpq_t r, const mpz_t z) 191 1.1 mrg { 192 1.1 mrg mpz_set (mpq_numref (r), z); 193 1.1 mrg } 194 1.1 mrg 195 1.1 mrg void 196 1.1 mrg mpq_set_den (mpq_t r, const mpz_t z) 197 1.1 mrg { 198 1.1 mrg mpz_set (mpq_denref (r), z); 199 1.1 mrg } 200 1.1 mrg 201 1.1 mrg void 202 1.1 mrg mpq_get_num (mpz_t r, const mpq_t q) 203 1.1 mrg { 204 1.1 mrg mpz_set (r, mpq_numref (q)); 205 1.1 mrg } 206 1.1 mrg 207 1.1 mrg void 208 1.1 mrg mpq_get_den (mpz_t r, const mpq_t q) 209 1.1 mrg { 210 1.1 mrg mpz_set (r, mpq_denref (q)); 211 1.1 mrg } 212 1.1 mrg 213 1.1 mrg 214 1.1 mrg /* MPQ comparisons and the like. */ 216 1.1 mrg int 217 1.1 mrg mpq_cmp (const mpq_t a, const mpq_t b) 218 1.1 mrg { 219 1.1 mrg mpz_t t1, t2; 220 1.1 mrg int res; 221 1.1 mrg 222 1.1 mrg mpz_init (t1); 223 1.1 mrg mpz_init (t2); 224 1.1 mrg mpz_mul (t1, mpq_numref (a), mpq_denref (b)); 225 1.1 mrg mpz_mul (t2, mpq_numref (b), mpq_denref (a)); 226 1.1 mrg res = mpz_cmp (t1, t2); 227 1.1 mrg mpz_clear (t1); 228 1.1 mrg mpz_clear (t2); 229 1.1 mrg 230 1.1 mrg return res; 231 1.1 mrg } 232 1.1 mrg 233 1.1 mrg int 234 1.1 mrg mpq_cmp_z (const mpq_t a, const mpz_t b) 235 1.1 mrg { 236 1.1 mrg mpz_t t; 237 1.1 mrg int res; 238 1.1 mrg 239 1.1 mrg mpz_init (t); 240 1.1 mrg mpz_mul (t, b, mpq_denref (a)); 241 1.1 mrg res = mpz_cmp (mpq_numref (a), t); 242 1.1 mrg mpz_clear (t); 243 1.1 mrg 244 1.1 mrg return res; 245 1.1 mrg } 246 1.1 mrg 247 1.1 mrg int 248 1.1 mrg mpq_equal (const mpq_t a, const mpq_t b) 249 1.1 mrg { 250 1.1 mrg return (mpz_cmp (mpq_numref (a), mpq_numref (b)) == 0) && 251 1.1 mrg (mpz_cmp (mpq_denref (a), mpq_denref (b)) == 0); 252 1.1 mrg } 253 1.1 mrg 254 1.1 mrg int 255 1.1 mrg mpq_cmp_ui (const mpq_t q, unsigned long n, unsigned long d) 256 1.1 mrg { 257 1.1 mrg mpq_t t; 258 1.1 mrg assert (d != 0); 259 1.1 mrg if (ULONG_MAX <= GMP_LIMB_MAX) { 260 1.1 mrg mp_limb_t nl = n, dl = d; 261 1.1 mrg return mpq_cmp (q, mpq_roinit_normal_nn (t, &nl, n != 0, &dl, 1)); 262 1.1 mrg } else { 263 1.1 mrg int ret; 264 1.1 mrg 265 1.1 mrg mpq_init (t); 266 1.1 mrg mpq_set_ui (t, n, d); 267 1.1 mrg ret = mpq_cmp (q, t); 268 1.1 mrg mpq_clear (t); 269 1.1 mrg 270 1.1 mrg return ret; 271 1.1 mrg } 272 1.1 mrg } 273 1.1 mrg 274 1.1 mrg int 275 1.1 mrg mpq_cmp_si (const mpq_t q, signed long n, unsigned long d) 276 1.1 mrg { 277 1.1 mrg assert (d != 0); 278 1.1 mrg 279 1.1 mrg if (n >= 0) 280 1.1 mrg return mpq_cmp_ui (q, n, d); 281 1.1 mrg else 282 1.1 mrg { 283 1.1 mrg mpq_t t; 284 1.1 mrg 285 1.1 mrg if (ULONG_MAX <= GMP_LIMB_MAX) 286 1.1 mrg { 287 1.1 mrg mp_limb_t nl = GMP_NEG_CAST (unsigned long, n), dl = d; 288 1.1 mrg return mpq_cmp (q, mpq_roinit_normal_nn (t, &nl, -1, &dl, 1)); 289 1.1 mrg } 290 1.1 mrg else 291 1.1 mrg { 292 1.1 mrg unsigned long l_n = GMP_NEG_CAST (unsigned long, n); 293 1.1 mrg 294 1.1 mrg mpq_roinit_normal_nn (t, mpq_numref (q)->_mp_d, - mpq_numref (q)->_mp_size, 295 1.1 mrg mpq_denref (q)->_mp_d, mpq_denref (q)->_mp_size); 296 1.1 mrg return - mpq_cmp_ui (t, l_n, d); 297 1.1 mrg } 298 1.1 mrg } 299 1.1 mrg } 300 1.1 mrg 301 1.1 mrg int 302 1.1 mrg mpq_sgn (const mpq_t a) 303 1.1 mrg { 304 1.1 mrg return mpz_sgn (mpq_numref (a)); 305 1.1 mrg } 306 1.1 mrg 307 1.1 mrg 308 1.1 mrg /* MPQ arithmetic. */ 310 1.1 mrg void 311 1.1 mrg mpq_abs (mpq_t r, const mpq_t q) 312 1.1 mrg { 313 1.1 mrg mpz_abs (mpq_numref (r), mpq_numref (q)); 314 1.1 mrg mpz_set (mpq_denref (r), mpq_denref (q)); 315 1.1 mrg } 316 1.1 mrg 317 1.1 mrg void 318 1.1 mrg mpq_neg (mpq_t r, const mpq_t q) 319 1.1 mrg { 320 1.1 mrg mpz_neg (mpq_numref (r), mpq_numref (q)); 321 1.1 mrg mpz_set (mpq_denref (r), mpq_denref (q)); 322 1.1 mrg } 323 1.1 mrg 324 1.1 mrg void 325 1.1 mrg mpq_add (mpq_t r, const mpq_t a, const mpq_t b) 326 1.1 mrg { 327 1.1 mrg mpz_t t; 328 1.1 mrg 329 1.1 mrg mpz_init (t); 330 1.1 mrg mpz_gcd (t, mpq_denref (a), mpq_denref (b)); 331 1.1 mrg if (mpz_cmp_ui (t, 1) == 0) 332 1.1 mrg { 333 1.1 mrg mpz_mul (t, mpq_numref (a), mpq_denref (b)); 334 1.1 mrg mpz_addmul (t, mpq_numref (b), mpq_denref (a)); 335 1.1 mrg mpz_mul (mpq_denref (r), mpq_denref (a), mpq_denref (b)); 336 1.1 mrg mpz_swap (mpq_numref (r), t); 337 1.1 mrg } 338 1.1 mrg else 339 1.1 mrg { 340 1.1 mrg mpz_t x, y; 341 1.1 mrg mpz_init (x); 342 1.1 mrg mpz_init (y); 343 1.1 mrg 344 1.1 mrg mpz_tdiv_q (x, mpq_denref (b), t); 345 1.1 mrg mpz_tdiv_q (y, mpq_denref (a), t); 346 1.1 mrg mpz_mul (x, mpq_numref (a), x); 347 1.1 mrg mpz_addmul (x, mpq_numref (b), y); 348 1.1 mrg 349 1.1 mrg mpz_gcd (t, x, t); 350 1.1 mrg mpz_tdiv_q (mpq_numref (r), x, t); 351 1.1 mrg mpz_tdiv_q (x, mpq_denref (b), t); 352 1.1 mrg mpz_mul (mpq_denref (r), x, y); 353 1.1 mrg 354 1.1 mrg mpz_clear (x); 355 1.1 mrg mpz_clear (y); 356 1.1 mrg } 357 1.1 mrg mpz_clear (t); 358 1.1 mrg } 359 1.1 mrg 360 1.1 mrg void 361 1.1 mrg mpq_sub (mpq_t r, const mpq_t a, const mpq_t b) 362 1.1 mrg { 363 1.1 mrg mpq_t t; 364 1.1 mrg 365 1.1 mrg mpq_roinit_normal_nn (t, mpq_numref (b)->_mp_d, - mpq_numref (b)->_mp_size, 366 1.1 mrg mpq_denref (b)->_mp_d, mpq_denref (b)->_mp_size); 367 1.1 mrg mpq_add (r, a, t); 368 1.1 mrg } 369 1.1 mrg 370 1.1 mrg void 371 1.1 mrg mpq_div (mpq_t r, const mpq_t a, const mpq_t b) 372 1.1 mrg { 373 1.1 mrg mpq_t t; 374 1.1 mrg mpq_mul (r, a, mpq_roinit_zz (t, mpq_denref (b), mpq_numref (b))); 375 1.1 mrg } 376 1.1 mrg 377 1.1 mrg void 378 1.1 mrg mpq_mul (mpq_t r, const mpq_t a, const mpq_t b) 379 1.1 mrg { 380 1.1 mrg mpq_t t; 381 1.1 mrg mpq_nan_init (t); 382 1.1 mrg 383 1.1 mrg if (a != b) { 384 1.1 mrg mpz_t g; 385 1.1 mrg 386 1.1 mrg mpz_init (g); 387 1.1 mrg mpq_helper_canonicalize (t, mpq_numref (a), mpq_denref (b), g); 388 1.1 mrg mpq_helper_canonicalize (r, mpq_numref (b), mpq_denref (a), g); 389 1.1 mrg mpz_clear (g); 390 1.1 mrg 391 1.1 mrg a = r; 392 1.1 mrg b = t; 393 1.1 mrg } 394 1.1 mrg 395 1.1 mrg mpz_mul (mpq_numref (r), mpq_numref (a), mpq_numref (b)); 396 1.1 mrg mpz_mul (mpq_denref (r), mpq_denref (a), mpq_denref (b)); 397 1.1 mrg mpq_clear (t); 398 1.1 mrg } 399 1.1 mrg 400 1.1 mrg void 401 1.1 mrg mpq_div_2exp (mpq_t r, const mpq_t q, mp_bitcnt_t e) 402 1.1 mrg { 403 1.1 mrg mp_bitcnt_t z = mpz_scan1 (mpq_numref (q), 0); 404 1.1 mrg z = GMP_MIN (z, e); 405 1.1 mrg mpz_mul_2exp (mpq_denref (r), mpq_denref (q), e - z); 406 1.1 mrg mpz_tdiv_q_2exp (mpq_numref (r), mpq_numref (q), z); 407 1.1 mrg } 408 1.1 mrg 409 1.1 mrg void 410 1.1 mrg mpq_mul_2exp (mpq_t r, const mpq_t q, mp_bitcnt_t e) 411 1.1 mrg { 412 1.1 mrg mp_bitcnt_t z = mpz_scan1 (mpq_denref (q), 0); 413 1.1 mrg z = GMP_MIN (z, e); 414 1.1 mrg mpz_mul_2exp (mpq_numref (r), mpq_numref (q), e - z); 415 1.1 mrg mpz_tdiv_q_2exp (mpq_denref (r), mpq_denref (q), z); 416 1.1 mrg } 417 1.1 mrg 418 1.1 mrg void 419 1.1 mrg mpq_inv (mpq_t r, const mpq_t q) 420 1.1 mrg { 421 1.1 mrg mpq_set (r, q); 422 1.1 mrg mpz_swap (mpq_denref (r), mpq_numref (r)); 423 1.1 mrg mpq_canonical_sign (r); 424 1.1 mrg } 425 1.1 mrg 426 1.1 mrg 427 1.1 mrg /* MPQ to/from double. */ 429 1.1 mrg void 430 1.1 mrg mpq_set_d (mpq_t r, double x) 431 1.1 mrg { 432 1.1 mrg mpz_set_ui (mpq_denref (r), 1); 433 1.1 mrg 434 1.1 mrg /* x != x is true when x is a NaN, and x == x * 0.5 is true when x is 435 1.1 mrg zero or infinity. */ 436 1.1 mrg if (x == x * 0.5 || x != x) 437 1.1 mrg mpq_numref (r)->_mp_size = 0; 438 1.1 mrg else 439 1.1 mrg { 440 1.1 mrg double B; 441 1.1 mrg mp_bitcnt_t e; 442 1.1 mrg 443 1.1 mrg B = 4.0 * (double) (GMP_LIMB_HIGHBIT >> 1); 444 1.1 mrg for (e = 0; x != x + 0.5; e += GMP_LIMB_BITS) 445 1.1 mrg x *= B; 446 1.1 mrg 447 1.1 mrg mpz_set_d (mpq_numref (r), x); 448 1.1 mrg mpq_div_2exp (r, r, e); 449 1.1 mrg } 450 1.1 mrg } 451 1.1 mrg 452 1.1 mrg double 453 1.1 mrg mpq_get_d (const mpq_t u) 454 1.1 mrg { 455 1.1 mrg mp_bitcnt_t ne, de, ee; 456 1.1 mrg mpz_t z; 457 1.1 mrg double B, ret; 458 1.1 mrg 459 1.1 mrg ne = mpz_sizeinbase (mpq_numref (u), 2); 460 1.1 mrg de = mpz_sizeinbase (mpq_denref (u), 2); 461 1.1 mrg 462 1.1 mrg ee = CHAR_BIT * sizeof (double); 463 1.1 mrg if (de == 1 || ne > de + ee) 464 1.1 mrg ee = 0; 465 1.1 mrg else 466 1.1 mrg ee = (ee + de - ne) / GMP_LIMB_BITS + 1; 467 1.1 mrg 468 1.1 mrg mpz_init (z); 469 1.1 mrg mpz_mul_2exp (z, mpq_numref (u), ee * GMP_LIMB_BITS); 470 1.1 mrg mpz_tdiv_q (z, z, mpq_denref (u)); 471 1.1 mrg ret = mpz_get_d (z); 472 1.1 mrg mpz_clear (z); 473 1.1 mrg 474 1.1 mrg B = 4.0 * (double) (GMP_LIMB_HIGHBIT >> 1); 475 1.1 mrg for (B = 1 / B; ee != 0; --ee) 476 1.1 mrg ret *= B; 477 1.1 mrg 478 1.1 mrg return ret; 479 1.1 mrg } 480 1.1 mrg 481 1.1 mrg 482 1.1 mrg /* MPQ and strings/streams. */ 484 1.1 mrg char * 485 1.1 mrg mpq_get_str (char *sp, int base, const mpq_t q) 486 1.1 mrg { 487 1.1 mrg char *res; 488 1.1 mrg char *rden; 489 1.1 mrg size_t len; 490 1.1 mrg 491 1.1 mrg res = mpz_get_str (sp, base, mpq_numref (q)); 492 1.1 mrg if (res == NULL || mpz_cmp_ui (mpq_denref (q), 1) == 0) 493 1.1 mrg return res; 494 1.1 mrg 495 1.1 mrg len = strlen (res) + 1; 496 1.1 mrg rden = sp ? sp + len : NULL; 497 1.1 mrg rden = mpz_get_str (rden, base, mpq_denref (q)); 498 1.1 mrg assert (rden != NULL); 499 1.1 mrg 500 1.1 mrg if (sp == NULL) { 501 1.1 mrg void * (*gmp_reallocate_func) (void *, size_t, size_t); 502 1.1 mrg void (*gmp_free_func) (void *, size_t); 503 1.1 mrg size_t lden; 504 1.1 mrg 505 1.1 mrg mp_get_memory_functions (NULL, &gmp_reallocate_func, &gmp_free_func); 506 1.1 mrg lden = strlen (rden) + 1; 507 1.1 mrg res = (char *) gmp_reallocate_func (res, 0, (lden + len) * sizeof (char)); 508 1.1 mrg memcpy (res + len, rden, lden); 509 1.1 mrg gmp_free_func (rden, 0); 510 1.1 mrg } 511 1.1 mrg 512 1.1 mrg res [len - 1] = '/'; 513 1.1 mrg return res; 514 1.1 mrg } 515 1.1 mrg 516 1.1 mrg size_t 517 1.1 mrg mpq_out_str (FILE *stream, int base, const mpq_t x) 518 1.1.1.2 mrg { 519 1.1.1.2 mrg char * str; 520 1.1 mrg size_t len; 521 1.1 mrg void (*gmp_free_func) (void *, size_t); 522 1.1 mrg 523 1.1 mrg str = mpq_get_str (NULL, base, x); 524 1.1 mrg if (!str) 525 1.1 mrg return 0; 526 1.1 mrg len = strlen (str); 527 1.1 mrg len = fwrite (str, 1, len, stream); 528 1.1 mrg mp_get_memory_functions (NULL, NULL, &gmp_free_func); 529 1.1 mrg gmp_free_func (str, 0); 530 1.1 mrg return len; 531 1.1 mrg } 532 1.1 mrg 533 1.1 mrg int 534 1.1 mrg mpq_set_str (mpq_t r, const char *sp, int base) 535 1.1 mrg { 536 1.1 mrg const char *slash; 537 1.1 mrg 538 1.1 mrg slash = strchr (sp, '/'); 539 1.1 mrg if (slash == NULL) { 540 1.1 mrg mpz_set_ui (mpq_denref(r), 1); 541 1.1 mrg return mpz_set_str (mpq_numref(r), sp, base); 542 1.1 mrg } else { 543 1.1 mrg char *num; 544 1.1 mrg size_t numlen; 545 1.1 mrg int ret; 546 1.1 mrg void * (*gmp_allocate_func) (size_t); 547 1.1 mrg void (*gmp_free_func) (void *, size_t); 548 1.1 mrg 549 1.1 mrg mp_get_memory_functions (&gmp_allocate_func, NULL, &gmp_free_func); 550 1.1 mrg numlen = slash - sp; 551 1.1 mrg num = (char *) gmp_allocate_func ((numlen + 1) * sizeof (char)); 552 1.1 mrg memcpy (num, sp, numlen); 553 1.1 mrg num[numlen] = '\0'; 554 1.1 mrg ret = mpz_set_str (mpq_numref(r), num, base); 555 1.1 mrg gmp_free_func (num, 0); 556 1.1 mrg 557 if (ret != 0) 558 return ret; 559 560 return mpz_set_str (mpq_denref(r), slash + 1, base); 561 } 562 } 563