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