1 /*
2 Copyright (C) 2014 Fredrik Johansson
3
4 This file is part of Arb.
5
6 Arb is free software: you can redistribute it and/or modify it under
7 the terms of the GNU Lesser General Public License (LGPL) as published
8 by the Free Software Foundation; either version 2.1 of the License, or
9 (at your option) any later version. See <http://www.gnu.org/licenses/>.
10 */
11
12 #ifndef MAG_H
13 #define MAG_H
14
15 #ifdef MAG_INLINES_C
16 #define MAG_INLINE
17 #else
18 #define MAG_INLINE static __inline__
19 #endif
20
21 #include <stdio.h>
22 #include <math.h>
23 #include "flint/flint.h"
24 #include "flint/fmpz.h"
25 #include "fmpz_extras.h"
26
27 #ifndef flint_abort
28 #if __FLINT_RELEASE <= 20502
29 #define flint_abort abort
30 #endif
31 #endif
32
33 #ifdef __cplusplus
34 extern "C" {
35 #endif
36
37 #define LIMB_ONE ((mp_limb_t) 1)
38 #define LIMB_ONES (-(mp_limb_t) 1)
39 #define LIMB_TOP (((mp_limb_t) 1) << (FLINT_BITS - 1))
40 #define MASK_LIMB(n, c) ((n) & (LIMB_ONES << (c)))
41
42 #define MAG_MAX_LAGOM_EXP (COEFF_MAX / 4)
43 #define MAG_MIN_LAGOM_EXP (-MAG_MAX_LAGOM_EXP)
44
45 #define ADD2_FAST_MAX (COEFF_MAX / 4)
46 #define ADD2_FAST_MIN (-ADD2_FAST_MAX)
47
48 /* TODO: rename these and move them to fmpz_extras */
49
50 static __inline__ void
_fmpz_set_fast(fmpz_t f,const fmpz_t g)51 _fmpz_set_fast(fmpz_t f, const fmpz_t g)
52 {
53 if (!COEFF_IS_MPZ(*f) && !COEFF_IS_MPZ(*g))
54 *f = *g;
55 else
56 fmpz_set(f, g);
57 }
58
59 static __inline__ void
_fmpz_add_fast(fmpz_t z,const fmpz_t x,slong c)60 _fmpz_add_fast(fmpz_t z, const fmpz_t x, slong c)
61 {
62 fmpz ze, xe;
63
64 ze = *z;
65 xe = *x;
66
67 if (!COEFF_IS_MPZ(ze) && (xe > ADD2_FAST_MIN && xe < ADD2_FAST_MAX))
68 *z = xe + c;
69 else
70 fmpz_add_si(z, x, c);
71 }
72
73 static __inline__ void
_fmpz_add2_fast(fmpz_t z,const fmpz_t x,const fmpz_t y,slong c)74 _fmpz_add2_fast(fmpz_t z, const fmpz_t x, const fmpz_t y, slong c)
75 {
76 fmpz ze, xe, ye;
77
78 ze = *z;
79 xe = *x;
80 ye = *y;
81
82 if (!COEFF_IS_MPZ(ze) && (xe > ADD2_FAST_MIN && xe < ADD2_FAST_MAX) &&
83 (ye > ADD2_FAST_MIN && ye < ADD2_FAST_MAX))
84 {
85 *z = xe + ye + c;
86 }
87 else
88 {
89 fmpz_add(z, x, y);
90 fmpz_add_si(z, z, c);
91 }
92 }
93
94 static __inline__ void
_fmpz_sub2_fast(fmpz_t z,const fmpz_t x,const fmpz_t y,slong c)95 _fmpz_sub2_fast(fmpz_t z, const fmpz_t x, const fmpz_t y, slong c)
96 {
97 fmpz ze, xe, ye;
98
99 ze = *z;
100 xe = *x;
101 ye = *y;
102
103 if (!COEFF_IS_MPZ(ze) && (xe > ADD2_FAST_MIN && xe < ADD2_FAST_MAX) &&
104 (ye > ADD2_FAST_MIN && ye < ADD2_FAST_MAX))
105 {
106 *z = xe - ye + c;
107 }
108 else
109 {
110 fmpz_sub(z, x, y);
111 fmpz_add_si(z, z, c);
112 }
113 }
114
115
116 #define MAG_EXP_POS_INF (COEFF_MIN+1)
117
118 /* Finite and with lagom big exponents. */
119 #define MAG_IS_LAGOM(x) (MAG_EXP(x) >= MAG_MIN_LAGOM_EXP && \
120 MAG_EXP(x) <= MAG_MAX_LAGOM_EXP)
121
122 #define MAG_EXPREF(x) (&(x)->exp)
123 #define MAG_EXP(x) ((x)->exp)
124 #define MAG_MAN(x) ((x)->man)
125
126 #define MAG_BITS 30
127
128 #define MAG_ONE_HALF (UWORD(1) << (MAG_BITS - 1))
129
130 static __inline__ mp_limb_t
__mag_fixmul32(mp_limb_t x,mp_limb_t y)131 __mag_fixmul32(mp_limb_t x, mp_limb_t y)
132 {
133 mp_limb_t u, v;
134 umul_ppmm(u, v, x, y);
135 return (u << (32 - MAG_BITS)) | (v >> MAG_BITS);
136 }
137
138 #if FLINT_BITS == 64
139 #define MAG_FIXMUL(x, y) (((x) * (y)) >> MAG_BITS)
140 #else
141 #define MAG_FIXMUL(x, y) __mag_fixmul32((x), (y))
142 #endif
143
144 #define MAG_CHECK_BITS(rr) \
145 if (MAG_MAN(rr) != 0 && FLINT_BIT_COUNT(MAG_MAN(rr)) != MAG_BITS) \
146 { \
147 flint_printf("FAIL: wrong number of bits in mantissa!\n"); \
148 flint_abort(); \
149 }
150
151 /* Note: assumes mantissa either has the right number of bits, or
152 one more bit (but in that case must not be all ones, as that
153 would round up to one extra bit again, requiring a second
154 correction). */
155
156 #define MAG_ADJUST_ONE_TOO_LARGE(x) \
157 do { \
158 mp_limb_t __t = MAG_MAN(x) >> MAG_BITS; \
159 MAG_MAN(x) = (MAG_MAN(x) >> __t) + (__t & MAG_MAN(x)); \
160 if (__t) \
161 fmpz_add_ui(MAG_EXPREF(x), MAG_EXPREF(x), __t); \
162 } while (0)
163
164 #define MAG_FAST_ADJUST_ONE_TOO_LARGE(x) \
165 do { \
166 mp_limb_t __t = MAG_MAN(x) >> MAG_BITS; \
167 MAG_MAN(x) = (MAG_MAN(x) >> __t) + (__t & MAG_MAN(x)); \
168 MAG_EXP(x) += __t; \
169 } while (0)
170
171 #define MAG_ADJUST_ONE_TOO_SMALL(x) \
172 do { \
173 mp_limb_t __t = !(MAG_MAN(x) >> (MAG_BITS - 1)); \
174 MAG_MAN(x) = (MAG_MAN(x) << __t); \
175 if (__t) \
176 fmpz_sub_ui(MAG_EXPREF(x), MAG_EXPREF(x), __t); \
177 } while (0)
178
179 #define MAG_FAST_ADJUST_ONE_TOO_SMALL(x) \
180 do { \
181 mp_limb_t __t = !(MAG_MAN(x) >> (MAG_BITS - 1)); \
182 MAG_MAN(x) = (MAG_MAN(x) << __t); \
183 MAG_EXP(x) -= __t; \
184 } while (0)
185
186
187 typedef struct
188 {
189 fmpz exp;
190 mp_limb_t man;
191 }
192 mag_struct;
193
194 typedef mag_struct mag_t[1];
195 typedef mag_struct * mag_ptr;
196 typedef const mag_struct * mag_srcptr;
197
198 MAG_INLINE void
mag_init(mag_t x)199 mag_init(mag_t x)
200 {
201 fmpz_init(MAG_EXPREF(x));
202 MAG_MAN(x) = 0;
203 }
204
205 MAG_INLINE void
mag_init_set(mag_t x,const mag_t y)206 mag_init_set(mag_t x, const mag_t y)
207 {
208 fmpz_init_set(MAG_EXPREF(x), MAG_EXPREF(y));
209 MAG_MAN(x) = MAG_MAN(y);
210 }
211
212 void mag_clear(mag_t x);
213
214 MAG_INLINE void
mag_swap(mag_t x,mag_t y)215 mag_swap(mag_t x, mag_t y)
216 {
217 mag_struct t = *x;
218 *x = *y;
219 *y = t;
220 }
221
222 MAG_INLINE void
mag_set(mag_t x,const mag_t y)223 mag_set(mag_t x, const mag_t y)
224 {
225 _fmpz_set_fast(MAG_EXPREF(x), MAG_EXPREF(y));
226 x->man = y->man;
227 }
228
229 MAG_INLINE void
mag_zero(mag_t x)230 mag_zero(mag_t x)
231 {
232 fmpz_zero(MAG_EXPREF(x));
233 MAG_MAN(x) = 0;
234 }
235
236 MAG_INLINE void
mag_one(mag_t x)237 mag_one(mag_t x)
238 {
239 fmpz_one(MAG_EXPREF(x));
240 MAG_MAN(x) = MAG_ONE_HALF;
241 }
242
243 MAG_INLINE int
mag_is_special(const mag_t x)244 mag_is_special(const mag_t x)
245 {
246 return MAG_MAN(x) == 0;
247 }
248
249 MAG_INLINE int
mag_is_zero(const mag_t x)250 mag_is_zero(const mag_t x)
251 {
252 return (MAG_MAN(x) == 0) && (MAG_EXP(x) == 0);
253 }
254
255 MAG_INLINE void
mag_inf(mag_t x)256 mag_inf(mag_t x)
257 {
258 fmpz_clear(MAG_EXPREF(x));
259 MAG_EXP(x) = MAG_EXP_POS_INF;
260 MAG_MAN(x) = 0;
261 }
262
263 MAG_INLINE int
mag_is_inf(const mag_t x)264 mag_is_inf(const mag_t x)
265 {
266 return (MAG_MAN(x) == 0) && (MAG_EXP(x) != 0);
267 }
268
269 MAG_INLINE int
mag_is_finite(const mag_t x)270 mag_is_finite(const mag_t x)
271 {
272 return !mag_is_inf(x);
273 }
274
275 MAG_INLINE int
mag_equal(const mag_t x,const mag_t y)276 mag_equal(const mag_t x, const mag_t y)
277 {
278 return (MAG_MAN(x) == MAG_MAN(y))
279 && fmpz_equal(MAG_EXPREF(x), MAG_EXPREF(y));
280 }
281
282 /* general versions */
283
284 void mag_mul(mag_t z, const mag_t x, const mag_t y);
285
286 void mag_mul_lower(mag_t z, const mag_t x, const mag_t y);
287
288 void mag_addmul(mag_t z, const mag_t x, const mag_t y);
289
290 void mag_add_2exp_fmpz(mag_t z, const mag_t x, const fmpz_t e);
291
292 void mag_add(mag_t z, const mag_t x, const mag_t y);
293
294 void mag_add_lower(mag_t z, const mag_t x, const mag_t y);
295
296 void mag_add_ui(mag_t z, const mag_t x, ulong y);
297 void mag_add_ui_lower(mag_t res, const mag_t x, ulong y);
298
299 void mag_add_ui_2exp_si(mag_t z, const mag_t x, ulong y, slong e);
300
301 void mag_div(mag_t z, const mag_t x, const mag_t y);
302 void mag_div_lower(mag_t z, const mag_t x, const mag_t y);
303
304 MAG_INLINE void
mag_inv(mag_t res,const mag_t x)305 mag_inv(mag_t res, const mag_t x)
306 {
307 mag_t t;
308 mag_init(t); /* no need to free */
309 mag_one(t);
310 mag_div(res, t, x);
311 }
312
313 MAG_INLINE void
mag_inv_lower(mag_t res,const mag_t x)314 mag_inv_lower(mag_t res, const mag_t x)
315 {
316 mag_t t;
317 mag_init(t); /* no need to free */
318 mag_one(t);
319 mag_div_lower(res, t, x);
320 }
321
322 void mag_mul_2exp_si(mag_t z, const mag_t x, slong y);
323
324 void mag_mul_2exp_fmpz(mag_t z, const mag_t x, const fmpz_t y);
325
326 void mag_sub(mag_t z, const mag_t x, const mag_t y);
327
328 void mag_sub_lower(mag_t z, const mag_t x, const mag_t y);
329
330 /* Fast versions (no infs/nans, small exponents). Note that this
331 applies to outputs too! */
332
333 MAG_INLINE void
mag_fast_init_set(mag_t x,const mag_t y)334 mag_fast_init_set(mag_t x, const mag_t y)
335 {
336 MAG_EXP(x) = MAG_EXP(y);
337 MAG_MAN(x) = MAG_MAN(y);
338 }
339
340 MAG_INLINE void
mag_fast_zero(mag_t x)341 mag_fast_zero(mag_t x)
342 {
343 MAG_EXP(x) = 0;
344 MAG_MAN(x) = 0;
345 }
346
347 MAG_INLINE int
mag_fast_is_zero(const mag_t x)348 mag_fast_is_zero(const mag_t x)
349 {
350 return MAG_MAN(x) == 0;
351 }
352
353 MAG_INLINE void
mag_fast_mul(mag_t z,const mag_t x,const mag_t y)354 mag_fast_mul(mag_t z, const mag_t x, const mag_t y)
355 {
356 if (MAG_MAN(x) == 0 || MAG_MAN(y) == 0)
357 {
358 mag_fast_zero(z);
359 }
360 else
361 {
362 MAG_MAN(z) = MAG_FIXMUL(MAG_MAN(x), MAG_MAN(y)) + LIMB_ONE;
363 MAG_EXP(z) = MAG_EXP(x) + MAG_EXP(y);
364 MAG_FAST_ADJUST_ONE_TOO_SMALL(z);
365 }
366 }
367
368 MAG_INLINE void
mag_fast_mul_2exp_si(mag_t z,const mag_t x,slong y)369 mag_fast_mul_2exp_si(mag_t z, const mag_t x, slong y)
370 {
371 if (MAG_MAN(x) == 0)
372 {
373 mag_fast_zero(z);
374 }
375 else
376 {
377 MAG_MAN(z) = MAG_MAN(x);
378 MAG_EXP(z) = MAG_EXP(x) + y;
379 }
380 }
381
382 MAG_INLINE void
mag_fast_addmul(mag_t z,const mag_t x,const mag_t y)383 mag_fast_addmul(mag_t z, const mag_t x, const mag_t y)
384 {
385 if (MAG_MAN(z) == 0)
386 {
387 mag_fast_mul(z, x, y);
388 }
389 else if (MAG_MAN(x) == 0 || MAG_MAN(y) == 0)
390 {
391 return;
392 }
393 else
394 {
395 slong shift, e;
396
397 /* x*y < 2^e */
398 e = MAG_EXP(x) + MAG_EXP(y);
399 shift = MAG_EXP(z) - e;
400
401 if (shift >= 0)
402 {
403 if (shift >= MAG_BITS)
404 MAG_MAN(z)++;
405 else
406 MAG_MAN(z) = MAG_MAN(z) + (MAG_FIXMUL(MAG_MAN(x), MAG_MAN(y)) >> shift) + 1;
407 }
408 else
409 {
410 shift = -shift;
411 MAG_EXP(z) = e;
412
413 if (shift >= MAG_BITS)
414 MAG_MAN(z) = MAG_FIXMUL(MAG_MAN(x), MAG_MAN(y)) + 2;
415 else
416 MAG_MAN(z) = MAG_FIXMUL(MAG_MAN(x), MAG_MAN(y)) + (MAG_MAN(z) >> shift) + 2;
417
418 MAG_FAST_ADJUST_ONE_TOO_SMALL(z);
419 }
420
421 MAG_FAST_ADJUST_ONE_TOO_LARGE(z);
422 }
423 }
424
425 MAG_INLINE void
mag_fast_add_2exp_si(mag_t z,const mag_t x,slong e)426 mag_fast_add_2exp_si(mag_t z, const mag_t x, slong e)
427 {
428 /* Must be zero */
429 if (mag_is_special(x))
430 {
431 MAG_MAN(z) = MAG_ONE_HALF;
432 MAG_EXP(z) = e + 1;
433 }
434 else
435 {
436 slong shift;
437 shift = MAG_EXP(x) - e;
438
439 if (shift > 0)
440 {
441 MAG_EXP(z) = MAG_EXP(x);
442
443 if (shift >= MAG_BITS)
444 MAG_MAN(z) = MAG_MAN(x) + LIMB_ONE;
445 else
446 MAG_MAN(z) = MAG_MAN(x) + (LIMB_ONE << (MAG_BITS - shift));
447 }
448 else
449 {
450 shift = -shift;
451
452 MAG_EXP(z) = e + 1;
453
454 if (shift >= MAG_BITS)
455 MAG_MAN(z) = MAG_ONE_HALF + LIMB_ONE;
456 else
457 MAG_MAN(z) = MAG_ONE_HALF + (MAG_MAN(x) >> (shift + 1)) + LIMB_ONE;
458 }
459
460 MAG_FAST_ADJUST_ONE_TOO_LARGE(z);
461 }
462 }
463
464 /* requires that x is positive and finite */
465 #define MAG_SET_D_2EXP(man, exp, x, xexp) \
466 do { \
467 int __cexp; \
468 double __x; \
469 int __fix; \
470 mp_limb_t __man; \
471 __x = frexp((x), &__cexp); \
472 __man = (mp_limb_t)(__x * (double)(LIMB_ONE << MAG_BITS)) + 1; \
473 __fix = __man >> (MAG_BITS); \
474 __man = (__man >> __fix) + __fix; \
475 (man) = __man; \
476 (exp) = (xexp) + __cexp + __fix; \
477 } while (0);
478
479 /* requires that x is positive and finite */
480 #define MAG_SET_D_2EXP_LOWER(man, exp, x, xexp) \
481 do { \
482 int __cexp; \
483 double __x; \
484 int __fix; \
485 mp_limb_t __man; \
486 __x = frexp((x), &__cexp); \
487 __man = (mp_limb_t)(__x * (double)(LIMB_ONE << MAG_BITS)) - 1; \
488 __fix = __man < MAG_ONE_HALF; \
489 __man = (__man << __fix); \
490 (man) = __man; \
491 (exp) = (xexp) + __cexp - __fix; \
492 } while (0);
493
494 void mag_set_d(mag_t z, double x);
495 void mag_set_d_lower(mag_t z, double x);
496 void mag_set_d_2exp_fmpz(mag_t z, double c, const fmpz_t exp);
497 void mag_set_d_2exp_fmpz_lower(mag_t z, double c, const fmpz_t exp);
498
499 void mag_set_fmpz_2exp_fmpz(mag_t z, const fmpz_t man, const fmpz_t exp);
500
501 #include "fmpr.h"
502
503 void mag_set_fmpr(mag_t x, const fmpr_t y);
504
505 void mag_get_fmpr(fmpr_t x, const mag_t r);
506
507 void mag_randtest_special(mag_t x, flint_rand_t state, slong expbits);
508
509 void mag_randtest(mag_t x, flint_rand_t state, slong expbits);
510
511 void mag_fprint(FILE * file, const mag_t x);
512
513 void mag_fprintd(FILE * file, const mag_t x, slong d);
514
515 MAG_INLINE void
mag_print(const mag_t x)516 mag_print(const mag_t x)
517 {
518 mag_fprint(stdout, x);
519 }
520
521 MAG_INLINE void
mag_printd(const mag_t x,slong d)522 mag_printd(const mag_t x, slong d)
523 {
524 mag_fprintd(stdout, x, d);
525 }
526
527 void mag_get_fmpq(fmpq_t y, const mag_t x);
528
529 void mag_get_fmpz(fmpz_t res, const mag_t x);
530 void mag_get_fmpz_lower(fmpz_t res, const mag_t x);
531
532 int mag_cmp(const mag_t x, const mag_t y);
533
534 int mag_cmp_2exp_si(const mag_t x, slong e);
535
536 MAG_INLINE void
mag_min(mag_t z,const mag_t x,const mag_t y)537 mag_min(mag_t z, const mag_t x, const mag_t y)
538 {
539 if (mag_cmp(x, y) <= 0)
540 mag_set(z, x);
541 else
542 mag_set(z, y);
543 }
544
545 MAG_INLINE void
mag_max(mag_t z,const mag_t x,const mag_t y)546 mag_max(mag_t z, const mag_t x, const mag_t y)
547 {
548 if (mag_cmp(x, y) >= 0)
549 mag_set(z, x);
550 else
551 mag_set(z, y);
552 }
553
554 MAG_INLINE mag_ptr
_mag_vec_init(slong n)555 _mag_vec_init(slong n)
556 {
557 slong i;
558 mag_ptr v = (mag_ptr) flint_malloc(sizeof(mag_struct) * n);
559
560 for (i = 0; i < n; i++)
561 mag_init(v + i);
562
563 return v;
564 }
565
566 MAG_INLINE void
_mag_vec_clear(mag_ptr v,slong n)567 _mag_vec_clear(mag_ptr v, slong n)
568 {
569 slong i;
570 for (i = 0; i < n; i++)
571 mag_clear(v + i);
572 flint_free(v);
573 }
574
575 double mag_get_d(const mag_t z);
576
577 double mag_get_d_log2_approx(const mag_t x);
578
579 /* TODO: document */
580 double mag_d_log_upper_bound(double x);
581 double mag_d_log_lower_bound(double x);
582
583 void mag_log1p(mag_t z, const mag_t x);
584
585 void mag_log_ui(mag_t t, ulong n);
586
587 void mag_log(mag_t z, const mag_t x);
588 void mag_log_lower(mag_t z, const mag_t x);
589 void mag_neg_log(mag_t z, const mag_t x);
590 void mag_neg_log_lower(mag_t z, const mag_t x);
591
592 void mag_exp(mag_t y, const mag_t x);
593 void mag_exp_lower(mag_t y, const mag_t x);
594
595 void mag_expinv(mag_t res, const mag_t x);
596 void mag_expinv_lower(mag_t y, const mag_t x);
597
598 void mag_expm1(mag_t y, const mag_t x);
599 void mag_exp_tail(mag_t z, const mag_t x, ulong N);
600
601 void mag_sinh(mag_t y, const mag_t x);
602 void mag_sinh_lower(mag_t y, const mag_t x);
603
604 void mag_cosh(mag_t y, const mag_t x);
605 void mag_cosh_lower(mag_t y, const mag_t x);
606
607 void mag_pow_ui(mag_t z, const mag_t x, ulong e);
608 void mag_pow_ui_lower(mag_t z, const mag_t x, ulong e);
609 void mag_pow_fmpz(mag_t z, const mag_t x, const fmpz_t e);
610 void mag_pow_fmpz_lower(mag_t z, const mag_t x, const fmpz_t e);
611
612 void mag_const_pi(mag_t res);
613 void mag_const_pi_lower(mag_t res);
614
615 void mag_atan(mag_t res, const mag_t x);
616 void mag_atan_lower(mag_t res, const mag_t x);
617
618 void mag_fac_ui(mag_t z, ulong n);
619 void mag_rfac_ui(mag_t z, ulong n);
620 void mag_bin_uiui(mag_t res, ulong n, ulong k);
621
622 /* TODO: test */
623 void mag_bernoulli_div_fac_ui(mag_t z, ulong n);
624
625 /* TODO: test */
626 void mag_set_fmpz_2exp_fmpz_lower(mag_t z, const fmpz_t man, const fmpz_t exp);
627
628 void mag_sqrt(mag_t y, const mag_t x);
629 void mag_sqrt_lower(mag_t y, const mag_t x);
630 void mag_rsqrt(mag_t y, const mag_t x);
631 void mag_rsqrt_lower(mag_t y, const mag_t x);
632
633 void mag_root(mag_t y, const mag_t x, ulong n);
634
635 void mag_hypot(mag_t z, const mag_t x, const mag_t y);
636
637 void mag_binpow_uiui(mag_t b, ulong m, ulong n);
638
639 void mag_polylog_tail(mag_t u, const mag_t z, slong sigma, ulong d, ulong N);
640
641 void mag_geom_series(mag_t res, const mag_t x, ulong n);
642
643 void mag_hurwitz_zeta_uiui(mag_t res, ulong s, ulong a);
644
645 void mag_set_ui(mag_t z, ulong x);
646 void mag_set_ui_lower(mag_t z, ulong x);
647
648 /* TODO: test functions below */
649 void mag_set_ui_2exp_si(mag_t z, ulong v, slong e);
650
651 MAG_INLINE void
mag_set_fmpz(mag_t z,const fmpz_t x)652 mag_set_fmpz(mag_t z, const fmpz_t x)
653 {
654 fmpz_t exp;
655 *exp = 0;
656 mag_set_fmpz_2exp_fmpz(z, x, exp);
657 }
658
659 MAG_INLINE void
mag_set_fmpz_lower(mag_t z,const fmpz_t x)660 mag_set_fmpz_lower(mag_t z, const fmpz_t x)
661 {
662 fmpz_t exp;
663 *exp = 0;
664 mag_set_fmpz_2exp_fmpz_lower(z, x, exp);
665 }
666
667 MAG_INLINE void
mag_mul_ui(mag_t z,const mag_t x,ulong y)668 mag_mul_ui(mag_t z, const mag_t x, ulong y)
669 {
670 mag_t t;
671 mag_init(t); /* no need to clear */
672 mag_set_ui(t, y);
673 mag_mul(z, x, t);
674 }
675
676 MAG_INLINE void
mag_mul_ui_lower(mag_t z,const mag_t x,ulong y)677 mag_mul_ui_lower(mag_t z, const mag_t x, ulong y)
678 {
679 mag_t t;
680 mag_init(t); /* no need to clear */
681 mag_set_ui_lower(t, y);
682 mag_mul_lower(z, x, t);
683 }
684
685 MAG_INLINE void
mag_mul_fmpz(mag_t z,const mag_t x,const fmpz_t y)686 mag_mul_fmpz(mag_t z, const mag_t x, const fmpz_t y)
687 {
688 mag_t t;
689 mag_init(t);
690 mag_set_fmpz(t, y);
691 mag_mul(z, x, t);
692 mag_clear(t);
693 }
694
695 MAG_INLINE void
mag_mul_fmpz_lower(mag_t z,const mag_t x,const fmpz_t y)696 mag_mul_fmpz_lower(mag_t z, const mag_t x, const fmpz_t y)
697 {
698 mag_t t;
699 mag_init(t);
700 mag_set_fmpz_lower(t, y);
701 mag_mul_lower(z, x, t);
702 mag_clear(t);
703 }
704
705 MAG_INLINE void
mag_div_ui(mag_t z,const mag_t x,ulong y)706 mag_div_ui(mag_t z, const mag_t x, ulong y)
707 {
708 mag_t t;
709 mag_init(t); /* no need to clear */
710 mag_set_ui_lower(t, y);
711 mag_div(z, x, t);
712 }
713
714 MAG_INLINE void
mag_div_fmpz(mag_t z,const mag_t x,const fmpz_t y)715 mag_div_fmpz(mag_t z, const mag_t x, const fmpz_t y)
716 {
717 mag_t t;
718 mag_init(t);
719 mag_set_fmpz_lower(t, y);
720 mag_div(z, x, t);
721 mag_clear(t);
722 }
723
mag_allocated_bytes(const mag_t x)724 MAG_INLINE slong mag_allocated_bytes(const mag_t x)
725 {
726 return fmpz_allocated_bytes(MAG_EXPREF(x));
727 }
728
729 int mag_load_str(mag_t res, const char * data);
730
731 char * mag_dump_str(const mag_t x);
732
733 int mag_load_file(mag_t res, FILE *stream);
734
735 int mag_dump_file(FILE* stream, const mag_t x);
736
737 #ifdef __cplusplus
738 }
739 #endif
740
741 #endif
742
743