1 /*
2     Copyright (C) 2014 Fredrik Johansson
3 
4     2x2 mul code taken from MPFR 2.3.0
5     (Copyright (C) 1991-2007 Free Software Foundation, Inc.)
6 
7     This file is part of Arb.
8 
9     Arb is free software: you can redistribute it and/or modify it under
10     the terms of the GNU Lesser General Public License (LGPL) as published
11     by the Free Software Foundation; either version 2.1 of the License, or
12     (at your option) any later version.  See <http://www.gnu.org/licenses/>.
13 */
14 
15 #ifndef ARF_H
16 #define ARF_H
17 
18 #ifdef ARF_INLINES_C
19 #define ARF_INLINE
20 #else
21 #define ARF_INLINE static __inline__
22 #endif
23 
24 #include <stdio.h>
25 #include <math.h>
26 #include "flint/flint.h"
27 #include "fmpr.h"
28 #include "mag.h"
29 
30 #ifndef flint_abort
31 #if __FLINT_RELEASE <= 20502
32 #define flint_abort abort
33 #endif
34 #endif
35 
36 #ifdef __cplusplus
37 extern "C" {
38 #endif
39 
40 #define arf_rnd_t fmpr_rnd_t
41 #define ARF_RND_DOWN FMPR_RND_DOWN
42 #define ARF_RND_UP FMPR_RND_UP
43 #define ARF_RND_FLOOR FMPR_RND_FLOOR
44 #define ARF_RND_CEIL FMPR_RND_CEIL
45 #define ARF_RND_NEAR FMPR_RND_NEAR
46 
47 ARF_INLINE int
arf_rounds_down(arf_rnd_t rnd,int sgnbit)48 arf_rounds_down(arf_rnd_t rnd, int sgnbit)
49 {
50     if (rnd == ARF_RND_DOWN) return 1;
51     if (rnd == ARF_RND_UP) return 0;
52     if (rnd == ARF_RND_FLOOR) return !sgnbit;
53     return sgnbit;
54 }
55 
56 ARF_INLINE int
arf_rounds_up(arf_rnd_t rnd,int sgnbit)57 arf_rounds_up(arf_rnd_t rnd, int sgnbit)
58 {
59     if (rnd == ARF_RND_DOWN) return 0;
60     if (rnd == ARF_RND_UP) return 1;
61     if (rnd == ARF_RND_FLOOR) return sgnbit;
62     return !sgnbit;
63 }
64 
65 ARF_INLINE mpfr_rnd_t
arf_rnd_to_mpfr(arf_rnd_t rnd)66 arf_rnd_to_mpfr(arf_rnd_t rnd)
67 {
68     if (rnd == ARF_RND_DOWN) return MPFR_RNDZ;
69     else if (rnd == ARF_RND_UP) return MPFR_RNDA;
70     else if (rnd == ARF_RND_FLOOR) return MPFR_RNDD;
71     else if (rnd == ARF_RND_CEIL) return MPFR_RNDU;
72     else return MPFR_RNDN;
73 }
74 
75 /* Allow 'infinite' precision for operations where a result can be computed exactly. */
76 #define ARF_PREC_EXACT WORD_MAX
77 
78 #define ARF_PREC_ADD(prec,extra) ((prec) == ARF_PREC_EXACT ? ARF_PREC_EXACT : (prec) + (extra))
79 
80 #define ARF_RESULT_EXACT 0
81 #define ARF_RESULT_INEXACT 1
82 
83 /* Range where we can skip fmpz overflow checks for exponent manipulation. */
84 #define ARF_MAX_LAGOM_EXP MAG_MAX_LAGOM_EXP
85 #define ARF_MIN_LAGOM_EXP MAG_MIN_LAGOM_EXP
86 
87 /* Exponent values used to encode special values. */
88 #define ARF_EXP_ZERO 0
89 #define ARF_EXP_NAN COEFF_MIN
90 #define ARF_EXP_POS_INF (COEFF_MIN+1)
91 #define ARF_EXP_NEG_INF (COEFF_MIN+2)
92 
93 /* Direct access to the exponent. */
94 #define ARF_EXP(x) ((x)->exp)
95 #define ARF_EXPREF(x) (&(x)->exp)
96 
97 /* Finite and with lagom big exponents. */
98 #define ARF_IS_LAGOM(x) (ARF_EXP(x) >= ARF_MIN_LAGOM_EXP && \
99                          ARF_EXP(x) <= ARF_MAX_LAGOM_EXP)
100 
101 /* More than two limbs (needs pointer). */
102 #define ARF_HAS_PTR(x) ((x)->size > ((2 << 1) + 1))
103 
104 /* Raw size field (encodes both limb size and sign). */
105 #define ARF_XSIZE(x) ((x)->size)
106 
107 /* Construct size field value from size in limbs and sign bit. */
108 #define ARF_MAKE_XSIZE(size, sgnbit) ((((mp_size_t) size) << 1) | (sgnbit))
109 
110 /* The limb size, and the sign bit. */
111 #define ARF_SIZE(x) (ARF_XSIZE(x) >> 1)
112 #define ARF_SGNBIT(x) (ARF_XSIZE(x) & 1)
113 
114 /* Assumes non-special value */
115 #define ARF_NEG(x) (ARF_XSIZE(x) ^= 1)
116 
117 /* Note: may also be hardcoded in a few places. */
118 #define ARF_NOPTR_LIMBS 2
119 
120 /* Direct access to the limb data. */
121 #define ARF_NOPTR_D(x)   ((x)->d.noptr.d)
122 #define ARF_PTR_D(x)     ((x)->d.ptr.d)
123 #define ARF_PTR_ALLOC(x) ((x)->d.ptr.alloc)
124 
125 /* Encoding for special values. */
126 #define ARF_IS_SPECIAL(x) (ARF_XSIZE(x) == 0)
127 
128 /* Value is +/- a power of two */
129 #define ARF_IS_POW2(x) (ARF_SIZE(x) == 1) && (ARF_NOPTR_D(x)[0] == LIMB_TOP)
130 
131 /* To set a special value, first call this and then set the exponent. */
132 #define ARF_MAKE_SPECIAL(x)         \
133     do {                            \
134         fmpz_clear(ARF_EXPREF(x));  \
135         ARF_DEMOTE(x);              \
136         ARF_XSIZE(x) = 0;           \
137     } while (0)
138 
139 
140 typedef struct
141 {
142     mp_limb_t d[ARF_NOPTR_LIMBS];
143 }
144 mantissa_noptr_struct;
145 
146 typedef struct
147 {
148     mp_size_t alloc;
149     mp_ptr d;
150 }
151 mantissa_ptr_struct;
152 
153 typedef union
154 {
155     mantissa_noptr_struct noptr;
156     mantissa_ptr_struct ptr;
157 }
158 mantissa_struct;
159 
160 typedef struct
161 {
162     fmpz exp;
163     mp_size_t size;
164     mantissa_struct d;
165 }
166 arf_struct;
167 
168 typedef arf_struct arf_t[1];
169 typedef arf_struct * arf_ptr;
170 typedef const arf_struct * arf_srcptr;
171 
172 void _arf_promote(arf_t x, mp_size_t n);
173 
174 void _arf_demote(arf_t x);
175 
176 
177 /* Warning: does not set size! -- also doesn't demote exponent. */
178 #define ARF_DEMOTE(x)                 \
179     do {                              \
180         if (ARF_HAS_PTR(x))           \
181             _arf_demote(x);           \
182     } while (0)
183 
184 /* Get mpn pointer and size (xptr, xn) for read-only use. */
185 #define ARF_GET_MPN_READONLY(xptr, xn, x)   \
186     do {                                    \
187         xn = ARF_SIZE(x);                   \
188         if (xn <= ARF_NOPTR_LIMBS)          \
189             xptr = ARF_NOPTR_D(x);          \
190         else                                \
191             xptr = ARF_PTR_D(x);            \
192     } while (0)
193 
194 /* Assumes non-special! */
195 #define ARF_GET_TOP_LIMB(lmb, x)                     \
196     do {                                             \
197         mp_srcptr __xptr;                            \
198         mp_size_t __xn;                              \
199         ARF_GET_MPN_READONLY(__xptr, __xn, (x));     \
200         (lmb) = __xptr[__xn - 1];                    \
201     } while (0)
202 
203 /* Get mpn pointer xptr for writing *exactly* xn limbs to x. */
204 #define ARF_GET_MPN_WRITE(xptr, xn, x)                      \
205     do {                                                    \
206         mp_size_t __xn = (xn);                              \
207         if ((__xn) <= ARF_NOPTR_LIMBS)                      \
208         {                                                   \
209             ARF_DEMOTE(x);                                  \
210             xptr = ARF_NOPTR_D(x);                          \
211         }                                                   \
212         else                                                \
213         {                                                   \
214             if (!ARF_HAS_PTR(x))                            \
215             {                                               \
216                 _arf_promote(x, __xn);                      \
217             }                                               \
218             else if (ARF_PTR_ALLOC(x) < (__xn))             \
219             {                                               \
220                 ARF_PTR_D(x) = (mp_ptr)                     \
221                         flint_realloc(ARF_PTR_D(x),         \
222                         (xn) * sizeof(mp_limb_t));          \
223                 ARF_PTR_ALLOC(x) = (__xn);                  \
224             }                                               \
225             xptr = ARF_PTR_D(x);                            \
226         }                                                   \
227         ARF_XSIZE(x) = ARF_MAKE_XSIZE(__xn, 0);             \
228     } while (0)
229 
230 ARF_INLINE void
arf_init(arf_t x)231 arf_init(arf_t x)
232 {
233     fmpz_init(ARF_EXPREF(x));
234     ARF_XSIZE(x) = 0;
235 }
236 
237 void arf_clear(arf_t x);
238 
239 ARF_INLINE void
arf_zero(arf_t x)240 arf_zero(arf_t x)
241 {
242     ARF_MAKE_SPECIAL(x);
243     ARF_EXP(x) = ARF_EXP_ZERO;
244 }
245 
246 ARF_INLINE void
arf_pos_inf(arf_t x)247 arf_pos_inf(arf_t x)
248 {
249     ARF_MAKE_SPECIAL(x);
250     ARF_EXP(x) = ARF_EXP_POS_INF;
251 }
252 
253 ARF_INLINE void
arf_neg_inf(arf_t x)254 arf_neg_inf(arf_t x)
255 {
256     ARF_MAKE_SPECIAL(x);
257     ARF_EXP(x) = ARF_EXP_NEG_INF;
258 }
259 
260 ARF_INLINE void
arf_nan(arf_t x)261 arf_nan(arf_t x)
262 {
263     ARF_MAKE_SPECIAL(x);
264     ARF_EXP(x) = ARF_EXP_NAN;
265 }
266 
267 ARF_INLINE int
arf_is_special(const arf_t x)268 arf_is_special(const arf_t x)
269 {
270     return ARF_IS_SPECIAL(x);
271 }
272 
273 ARF_INLINE int
arf_is_zero(const arf_t x)274 arf_is_zero(const arf_t x)
275 {
276     return ARF_IS_SPECIAL(x) && (ARF_EXP(x) == ARF_EXP_ZERO);
277 }
278 
279 ARF_INLINE int
arf_is_pos_inf(const arf_t x)280 arf_is_pos_inf(const arf_t x)
281 {
282     return ARF_IS_SPECIAL(x) && (ARF_EXP(x) == ARF_EXP_POS_INF);
283 }
284 
285 ARF_INLINE int
arf_is_neg_inf(const arf_t x)286 arf_is_neg_inf(const arf_t x)
287 {
288     return ARF_IS_SPECIAL(x) && (ARF_EXP(x) == ARF_EXP_NEG_INF);
289 }
290 
291 ARF_INLINE int
arf_is_nan(const arf_t x)292 arf_is_nan(const arf_t x)
293 {
294     return ARF_IS_SPECIAL(x) && (ARF_EXP(x) == ARF_EXP_NAN);
295 }
296 
297 ARF_INLINE int
arf_is_normal(const arf_t x)298 arf_is_normal(const arf_t x)
299 {
300     return !ARF_IS_SPECIAL(x);
301 }
302 
303 ARF_INLINE int
arf_is_finite(const arf_t x)304 arf_is_finite(const arf_t x)
305 {
306     return !ARF_IS_SPECIAL(x) || (ARF_EXP(x) == ARF_EXP_ZERO);
307 }
308 
309 ARF_INLINE int
arf_is_inf(const arf_t x)310 arf_is_inf(const arf_t x)
311 {
312     return ARF_IS_SPECIAL(x) && (ARF_EXP(x) == ARF_EXP_POS_INF ||
313                                  ARF_EXP(x) == ARF_EXP_NEG_INF);
314 }
315 
316 ARF_INLINE void
arf_one(arf_t x)317 arf_one(arf_t x)
318 {
319     fmpz_clear(ARF_EXPREF(x));
320     ARF_DEMOTE(x);
321     ARF_EXP(x) = 1;
322     ARF_XSIZE(x) = ARF_MAKE_XSIZE(1, 0);
323     ARF_NOPTR_D(x)[0] = LIMB_TOP;
324 }
325 
326 ARF_INLINE int
arf_is_one(const arf_t x)327 arf_is_one(const arf_t x)
328 {
329     return (ARF_EXP(x) == 1) && (ARF_XSIZE(x) == ARF_MAKE_XSIZE(1, 0))
330                              && ARF_NOPTR_D(x)[0] == LIMB_TOP;
331 }
332 
333 ARF_INLINE int
arf_sgn(const arf_t x)334 arf_sgn(const arf_t x)
335 {
336     if (arf_is_special(x))
337     {
338         if (arf_is_zero(x) || arf_is_nan(x))
339             return 0;
340         return arf_is_pos_inf(x) ? 1 : -1;
341     }
342     else
343     {
344         return ARF_SGNBIT(x) ? -1 : 1;
345     }
346 }
347 
348 int arf_cmp(const arf_t x, const arf_t y);
349 
350 int arf_cmpabs(const arf_t x, const arf_t y);
351 
352 int arf_cmpabs_ui(const arf_t x, ulong y);
353 
354 int arf_cmpabs_d(const arf_t x, double y);
355 
356 int arf_cmp_si(const arf_t x, slong y);
357 
358 int arf_cmp_ui(const arf_t x, ulong y);
359 
360 int arf_cmp_d(const arf_t x, double y);
361 
362 ARF_INLINE void
arf_swap(arf_t y,arf_t x)363 arf_swap(arf_t y, arf_t x)
364 {
365     if (x != y)
366     {
367         arf_struct t = *x;
368         *x = *y;
369         *y = t;
370     }
371 }
372 
373 ARF_INLINE void
arf_set(arf_t y,const arf_t x)374 arf_set(arf_t y, const arf_t x)
375 {
376     if (x != y)
377     {
378         /* Fast path */
379         if (!COEFF_IS_MPZ(ARF_EXP(x)) && !COEFF_IS_MPZ(ARF_EXP(y)))
380             ARF_EXP(y) = ARF_EXP(x);
381         else
382             fmpz_set(ARF_EXPREF(y), ARF_EXPREF(x));
383 
384         /* Fast path */
385         if (!ARF_HAS_PTR(x))
386         {
387             ARF_DEMOTE(y);
388             (y)->d = (x)->d;
389         }
390         else
391         {
392             mp_ptr yptr;
393             mp_srcptr xptr;
394             mp_size_t n;
395 
396             ARF_GET_MPN_READONLY(xptr, n, x);
397             ARF_GET_MPN_WRITE(yptr, n, y);
398             flint_mpn_copyi(yptr, xptr, n);
399         }
400 
401         /* Important. */
402         ARF_XSIZE(y) = ARF_XSIZE(x);
403     }
404 }
405 
406 ARF_INLINE void
arf_neg(arf_t y,const arf_t x)407 arf_neg(arf_t y, const arf_t x)
408 {
409     arf_set(y, x);
410 
411     if (arf_is_special(y))
412     {
413         if (arf_is_pos_inf(y))
414             arf_neg_inf(y);
415         else if (arf_is_neg_inf(y))
416             arf_pos_inf(y);
417     }
418     else
419     {
420         ARF_NEG(y);
421     }
422 }
423 
424 ARF_INLINE void
arf_init_set_ui(arf_t x,ulong v)425 arf_init_set_ui(arf_t x, ulong v)
426 {
427     if (v == 0)
428     {
429         ARF_EXP(x) = ARF_EXP_ZERO;
430         ARF_XSIZE(x) = 0;
431     }
432     else
433     {
434         unsigned int c;
435         count_leading_zeros(c, v);
436         ARF_EXP(x) = FLINT_BITS - c;
437         ARF_NOPTR_D(x)[0] = v << c;
438         ARF_XSIZE(x) = ARF_MAKE_XSIZE(1, 0);
439     }
440 }
441 
442 /* FLINT_ABS is unsafe for x = WORD_MIN */
443 #define UI_ABS_SI(x) (((slong)(x) < 0) ? (-(ulong)(x)) : ((ulong)(x)))
444 
445 ARF_INLINE void
arf_init_set_si(arf_t x,slong v)446 arf_init_set_si(arf_t x, slong v)
447 {
448     arf_init_set_ui(x, UI_ABS_SI(v));
449     if (v < 0)
450         ARF_NEG(x);
451 }
452 
453 ARF_INLINE void
arf_set_ui(arf_t x,ulong v)454 arf_set_ui(arf_t x, ulong v)
455 {
456     ARF_DEMOTE(x);
457     _fmpz_demote(ARF_EXPREF(x));
458 
459     if (v == 0)
460     {
461         ARF_EXP(x) = ARF_EXP_ZERO;
462         ARF_XSIZE(x) = 0;
463     }
464     else
465     {
466         unsigned int c;
467         count_leading_zeros(c, v);
468         ARF_EXP(x) = FLINT_BITS - c;
469         ARF_NOPTR_D(x)[0] = v << c;
470         ARF_XSIZE(x) = ARF_MAKE_XSIZE(1, 0);
471     }
472 }
473 
474 ARF_INLINE void
arf_set_si(arf_t x,slong v)475 arf_set_si(arf_t x, slong v)
476 {
477     arf_set_ui(x, UI_ABS_SI(v));
478     if (v < 0)
479         ARF_NEG(x);
480 }
481 
482 ARF_INLINE void
arf_init_set_shallow(arf_t z,const arf_t x)483 arf_init_set_shallow(arf_t z, const arf_t x)
484 {
485     *z = *x;
486 }
487 
488 ARF_INLINE void
arf_init_neg_shallow(arf_t z,const arf_t x)489 arf_init_neg_shallow(arf_t z, const arf_t x)
490 {
491     *z = *x;
492     arf_neg(z, z);
493 }
494 
495 ARF_INLINE void
arf_init_set_mag_shallow(arf_t y,const mag_t x)496 arf_init_set_mag_shallow(arf_t y, const mag_t x)
497 {
498     mp_limb_t t = MAG_MAN(x);
499     ARF_XSIZE(y) = ARF_MAKE_XSIZE(t != 0, 0);
500     ARF_EXP(y) = MAG_EXP(x);
501     ARF_NOPTR_D(y)[0] = t << (FLINT_BITS - MAG_BITS);
502 }
503 
504 ARF_INLINE void
arf_init_neg_mag_shallow(arf_t z,const mag_t x)505 arf_init_neg_mag_shallow(arf_t z, const mag_t x)
506 {
507     arf_init_set_mag_shallow(z, x);
508     arf_neg(z, z);
509 }
510 
511 ARF_INLINE int
arf_cmpabs_mag(const arf_t x,const mag_t y)512 arf_cmpabs_mag(const arf_t x, const mag_t y)
513 {
514     arf_t t;
515     arf_init_set_mag_shallow(t, y);  /* no need to free */
516     return arf_cmpabs(x, t);
517 }
518 
519 ARF_INLINE int
arf_mag_cmpabs(const mag_t x,const arf_t y)520 arf_mag_cmpabs(const mag_t x, const arf_t y)
521 {
522     arf_t t;
523     arf_init_set_mag_shallow(t, x);  /* no need to free */
524     return arf_cmpabs(t, y);
525 }
526 
527 /* Assumes xn > 0, x[xn-1] != 0. */
528 /* TBD: 1, 2 limb versions */
529 void arf_set_mpn(arf_t y, mp_srcptr x, mp_size_t xn, int sgnbit);
530 
531 ARF_INLINE void
arf_set_mpz(arf_t y,const mpz_t x)532 arf_set_mpz(arf_t y, const mpz_t x)
533 {
534     slong size = x->_mp_size;
535 
536     if (size == 0)
537         arf_zero(y);
538     else
539         arf_set_mpn(y, x->_mp_d, FLINT_ABS(size), size < 0);
540 }
541 
542 ARF_INLINE void
arf_set_fmpz(arf_t y,const fmpz_t x)543 arf_set_fmpz(arf_t y, const fmpz_t x)
544 {
545     if (!COEFF_IS_MPZ(*x))
546         arf_set_si(y, *x);
547     else
548         arf_set_mpz(y, COEFF_TO_PTR(*x));
549 }
550 
551 int _arf_set_round_ui(arf_t x, ulong v, int sgnbit, slong prec, arf_rnd_t rnd);
552 
553 int _arf_set_round_uiui(arf_t z, slong * fix, mp_limb_t hi, mp_limb_t lo, int sgnbit, slong prec, arf_rnd_t rnd);
554 
555 int
556 _arf_set_round_mpn(arf_t y, slong * exp_shift, mp_srcptr x, mp_size_t xn,
557     int sgnbit, slong prec, arf_rnd_t rnd);
558 
559 ARF_INLINE int
arf_set_round_ui(arf_t x,ulong v,slong prec,arf_rnd_t rnd)560 arf_set_round_ui(arf_t x, ulong v, slong prec, arf_rnd_t rnd)
561 {
562     return _arf_set_round_ui(x, v, 0, prec, rnd);
563 }
564 
565 ARF_INLINE int
arf_set_round_si(arf_t x,slong v,slong prec,arf_rnd_t rnd)566 arf_set_round_si(arf_t x, slong v, slong prec, arf_rnd_t rnd)
567 {
568     return _arf_set_round_ui(x, UI_ABS_SI(v), v < 0, prec, rnd);
569 }
570 
571 ARF_INLINE int
arf_set_round_mpz(arf_t y,const mpz_t x,slong prec,arf_rnd_t rnd)572 arf_set_round_mpz(arf_t y, const mpz_t x, slong prec, arf_rnd_t rnd)
573 {
574     int inexact;
575     slong size = x->_mp_size;
576     slong fix;
577 
578     if (size == 0)
579     {
580         arf_zero(y);
581         return 0;
582     }
583 
584     inexact = _arf_set_round_mpn(y, &fix, x->_mp_d, FLINT_ABS(size),
585         (size < 0), prec, rnd);
586     _fmpz_demote(ARF_EXPREF(y));
587     ARF_EXP(y) = FLINT_ABS(size) * FLINT_BITS + fix;
588     return inexact;
589 }
590 
591 ARF_INLINE int
arf_set_round_fmpz(arf_t y,const fmpz_t x,slong prec,arf_rnd_t rnd)592 arf_set_round_fmpz(arf_t y, const fmpz_t x, slong prec, arf_rnd_t rnd)
593 {
594     if (!COEFF_IS_MPZ(*x))
595         return arf_set_round_si(y, *x, prec, rnd);
596     else
597         return arf_set_round_mpz(y, COEFF_TO_PTR(*x), prec, rnd);
598 }
599 
600 int arf_set_round(arf_t y, const arf_t x, slong prec, arf_rnd_t rnd);
601 
602 int arf_neg_round(arf_t y, const arf_t x, slong prec, arf_rnd_t rnd);
603 
604 void arf_get_fmpr(fmpr_t y, const arf_t x);
605 
606 void arf_set_fmpr(arf_t y, const fmpr_t x);
607 
608 int arf_get_mpfr(mpfr_t x, const arf_t y, mpfr_rnd_t rnd);
609 
610 void arf_set_mpfr(arf_t x, const mpfr_t y);
611 
612 int arf_equal(const arf_t x, const arf_t y);
613 
614 int arf_equal_si(const arf_t x, slong y);
615 
616 ARF_INLINE void
arf_min(arf_t z,const arf_t a,const arf_t b)617 arf_min(arf_t z, const arf_t a, const arf_t b)
618 {
619     if (arf_cmp(a, b) <= 0)
620         arf_set(z, a);
621     else
622         arf_set(z, b);
623 }
624 
625 ARF_INLINE void
arf_max(arf_t z,const arf_t a,const arf_t b)626 arf_max(arf_t z, const arf_t a, const arf_t b)
627 {
628     if (arf_cmp(a, b) > 0)
629         arf_set(z, a);
630     else
631         arf_set(z, b);
632 }
633 
634 ARF_INLINE void
arf_abs(arf_t y,const arf_t x)635 arf_abs(arf_t y, const arf_t x)
636 {
637     if (arf_sgn(x) < 0)
638         arf_neg(y, x);
639     else
640         arf_set(y, x);
641 }
642 
643 ARF_INLINE slong
arf_bits(const arf_t x)644 arf_bits(const arf_t x)
645 {
646     if (arf_is_special(x))
647         return 0;
648     else
649     {
650         mp_srcptr xp;
651         mp_size_t xn;
652         slong c;
653 
654         ARF_GET_MPN_READONLY(xp, xn, x);
655         count_trailing_zeros(c, xp[0]);
656         return xn * FLINT_BITS - c;
657     }
658 }
659 
660 ARF_INLINE void
arf_bot(fmpz_t e,const arf_t x)661 arf_bot(fmpz_t e, const arf_t x)
662 {
663     if (arf_is_special(x))
664         fmpz_zero(e);
665     else
666         fmpz_sub_si(e, ARF_EXPREF(x), arf_bits(x));
667 }
668 
669 int arf_is_int(const arf_t x);
670 
671 int arf_is_int_2exp_si(const arf_t x, slong e);
672 
673 int arf_cmp_2exp_si(const arf_t x, slong e);
674 
675 int arf_cmpabs_2exp_si(const arf_t x, slong e);
676 
677 ARF_INLINE void
arf_set_si_2exp_si(arf_t x,slong man,slong exp)678 arf_set_si_2exp_si(arf_t x, slong man, slong exp)
679 {
680     arf_set_si(x, man);
681     if (man != 0)
682         fmpz_add_si_inline(ARF_EXPREF(x), ARF_EXPREF(x), exp);
683 }
684 
685 ARF_INLINE void
arf_set_ui_2exp_si(arf_t x,ulong man,slong exp)686 arf_set_ui_2exp_si(arf_t x, ulong man, slong exp)
687 {
688     arf_set_ui(x, man);
689     if (man != 0)
690         fmpz_add_si_inline(ARF_EXPREF(x), ARF_EXPREF(x), exp);
691 }
692 
693 ARF_INLINE void
arf_mul_2exp_si(arf_t y,const arf_t x,slong e)694 arf_mul_2exp_si(arf_t y, const arf_t x, slong e)
695 {
696     arf_set(y, x);
697     if (!arf_is_special(y))
698         fmpz_add_si_inline(ARF_EXPREF(y), ARF_EXPREF(y), e);
699 }
700 
701 ARF_INLINE void
arf_mul_2exp_fmpz(arf_t y,const arf_t x,const fmpz_t e)702 arf_mul_2exp_fmpz(arf_t y, const arf_t x, const fmpz_t e)
703 {
704     arf_set(y, x);
705     if (!arf_is_special(y))
706         fmpz_add_inline(ARF_EXPREF(y), ARF_EXPREF(y), e);
707 }
708 
709 ARF_INLINE int
arf_set_round_fmpz_2exp(arf_t y,const fmpz_t x,const fmpz_t exp,slong prec,arf_rnd_t rnd)710 arf_set_round_fmpz_2exp(arf_t y, const fmpz_t x, const fmpz_t exp, slong prec, arf_rnd_t rnd)
711 {
712     if (fmpz_is_zero(x))
713     {
714         arf_zero(y);
715         return 0;
716     }
717     else
718     {
719         int r = arf_set_round_fmpz(y, x, prec, rnd);
720         fmpz_add_inline(ARF_EXPREF(y), ARF_EXPREF(y), exp);
721         return r;
722     }
723 }
724 
725 ARF_INLINE void
arf_abs_bound_lt_2exp_fmpz(fmpz_t b,const arf_t x)726 arf_abs_bound_lt_2exp_fmpz(fmpz_t b, const arf_t x)
727 {
728     if (arf_is_special(x))
729         fmpz_zero(b);
730     else
731         fmpz_set(b, ARF_EXPREF(x));
732 }
733 
734 ARF_INLINE void
arf_abs_bound_le_2exp_fmpz(fmpz_t b,const arf_t x)735 arf_abs_bound_le_2exp_fmpz(fmpz_t b, const arf_t x)
736 {
737     if (arf_is_special(x))
738         fmpz_zero(b);
739     else if (ARF_IS_POW2(x))
740         fmpz_sub_ui(b, ARF_EXPREF(x), 1);
741     else
742         fmpz_set(b, ARF_EXPREF(x));
743 }
744 
745 slong arf_abs_bound_lt_2exp_si(const arf_t x);
746 
747 void arf_frexp(arf_t man, fmpz_t exp, const arf_t x);
748 
749 void arf_get_fmpz_2exp(fmpz_t man, fmpz_t exp, const arf_t x);
750 
751 int _arf_get_integer_mpn(mp_ptr y, mp_srcptr x, mp_size_t xn, slong exp);
752 
753 int _arf_set_mpn_fixed(arf_t z, mp_srcptr xp, mp_size_t xn,
754         mp_size_t fixn, int negative, slong prec, arf_rnd_t rnd);
755 
756 int arf_get_fmpz(fmpz_t z, const arf_t x, arf_rnd_t rnd);
757 
758 slong arf_get_si(const arf_t x, arf_rnd_t rnd);
759 
760 int arf_get_fmpz_fixed_fmpz(fmpz_t y, const arf_t x, const fmpz_t e);
761 
762 int arf_get_fmpz_fixed_si(fmpz_t y, const arf_t x, slong e);
763 
764 ARF_INLINE void
arf_set_fmpz_2exp(arf_t x,const fmpz_t man,const fmpz_t exp)765 arf_set_fmpz_2exp(arf_t x, const fmpz_t man, const fmpz_t exp)
766 {
767     arf_set_fmpz(x, man);
768     if (!arf_is_zero(x))
769         fmpz_add_inline(ARF_EXPREF(x), ARF_EXPREF(x), exp);
770 }
771 
772 void arf_floor(arf_t z, const arf_t x);
773 
774 void arf_ceil(arf_t z, const arf_t x);
775 
776 void arf_debug(const arf_t x);
777 
778 void arf_fprint(FILE * file, const arf_t x);
779 
780 void arf_fprintd(FILE * file, const arf_t y, slong d);
781 
782 ARF_INLINE void
arf_print(const arf_t x)783 arf_print(const arf_t x)
784 {
785     arf_fprint(stdout, x);
786 }
787 
788 ARF_INLINE void
arf_printd(const arf_t y,slong d)789 arf_printd(const arf_t y, slong d)
790 {
791     arf_fprintd(stdout, y, d);
792 }
793 
794 void arf_randtest(arf_t x, flint_rand_t state, slong bits, slong mag_bits);
795 
796 void arf_randtest_not_zero(arf_t x, flint_rand_t state, slong bits, slong mag_bits);
797 
798 void arf_randtest_special(arf_t x, flint_rand_t state, slong bits, slong mag_bits);
799 
800 void arf_urandom(arf_t x, flint_rand_t state, slong bits, arf_rnd_t rnd);
801 
802 #define MUL_MPFR_MIN_LIMBS 25
803 #define MUL_MPFR_MAX_LIMBS 10000
804 
805 #define nn_mul_2x1(r2, r1, r0, a1, a0, b0)                  \
806     do {                                                    \
807         mp_limb_t t1;                                       \
808         umul_ppmm(r1, r0, a0, b0);                          \
809         umul_ppmm(r2, t1, a1, b0);                          \
810         add_ssaaaa(r2, r1, r2, r1, 0, t1);                  \
811     } while (0)
812 
813 #define nn_mul_2x2(r3, r2, r1, r0, a1, a0, b1, b0)          \
814     do {                                                    \
815         mp_limb_t t1, t2, t3;                               \
816         umul_ppmm(r1, r0, a0, b0);                          \
817         umul_ppmm(r2, t1, a1, b0);                          \
818         add_ssaaaa(r2, r1, r2, r1, 0, t1);                  \
819         umul_ppmm(t1, t2, a0, b1);                          \
820         umul_ppmm(r3, t3, a1, b1);                          \
821         add_ssaaaa(r3, t1, r3, t1, 0, t3);                  \
822         add_ssaaaa(r2, r1, r2, r1, t1, t2);                 \
823         r3 += r2 < t1;                                      \
824     } while (0)
825 
826 #define ARF_MPN_MUL(_z, _x, _xn, _y, _yn) \
827     if ((_xn) == (_yn)) \
828     { \
829         if ((_xn) == 1) \
830         { \
831             umul_ppmm((_z)[1], (_z)[0], (_x)[0], (_y)[0]); \
832         } \
833         else if ((_xn) == 2) \
834         { \
835             mp_limb_t __arb_x1, __arb_x0, __arb_y1, __arb_y0; \
836             __arb_x0 = (_x)[0]; \
837             __arb_x1 = (_x)[1]; \
838             __arb_y0 = (_y)[0]; \
839             __arb_y1 = (_y)[1]; \
840             nn_mul_2x2((_z)[3], (_z)[2], (_z)[1], (_z)[0], __arb_x1, __arb_x0, __arb_y1, __arb_y0); \
841         } \
842         else if ((_x) == (_y)) \
843         { \
844             mpn_sqr((_z), (_x), (_xn)); \
845         } \
846         else \
847         { \
848             mpn_mul_n((_z), (_x), (_y), (_xn)); \
849         } \
850     } \
851     else if ((_xn) > (_yn)) \
852     { \
853         if ((_yn) == 1) \
854             (_z)[(_xn) + (_yn) - 1] = mpn_mul_1((_z), (_x), (_xn), (_y)[0]); \
855         else \
856             mpn_mul((_z), (_x), (_xn), (_y), (_yn)); \
857     } \
858     else \
859     { \
860         if ((_xn) == 1) \
861             (_z)[(_xn) + (_yn) - 1] = mpn_mul_1((_z), (_y), (_yn), (_x)[0]); \
862         else \
863             mpn_mul((_z), (_y), (_yn), (_x), (_xn)); \
864     }
865 
866 #define ARF_MUL_STACK_ALLOC 40
867 #define ARF_MUL_TLS_ALLOC 1000
868 
869 extern TLS_PREFIX mp_ptr __arf_mul_tmp;
870 extern TLS_PREFIX slong __arf_mul_alloc;
871 
872 ARB_DLL extern void _arf_mul_tmp_cleanup(void);
873 
874 #define ARF_MUL_TMP_DECL \
875     mp_limb_t tmp_stack[ARF_MUL_STACK_ALLOC]; \
876 
877 #define ARF_MUL_TMP_ALLOC(tmp, alloc) \
878     if (alloc <= ARF_MUL_STACK_ALLOC) \
879     { \
880         tmp = tmp_stack; \
881     } \
882     else if (alloc <= ARF_MUL_TLS_ALLOC) \
883     { \
884         if (__arf_mul_alloc < alloc) \
885         { \
886             if (__arf_mul_alloc == 0) \
887             { \
888                 flint_register_cleanup_function(_arf_mul_tmp_cleanup); \
889             } \
890             __arf_mul_tmp = flint_realloc(__arf_mul_tmp, sizeof(mp_limb_t) * alloc); \
891             __arf_mul_alloc = alloc; \
892         } \
893         tmp = __arf_mul_tmp; \
894     } \
895     else \
896     { \
897         tmp = flint_malloc(sizeof(mp_limb_t) * alloc); \
898     }
899 
900 #define ARF_MUL_TMP_FREE(tmp, alloc) \
901     if (alloc > ARF_MUL_TLS_ALLOC) \
902         flint_free(tmp);
903 
904 void arf_mul_special(arf_t z, const arf_t x, const arf_t y);
905 
906 int arf_mul_via_mpfr(arf_t z, const arf_t x, const arf_t y, slong prec, arf_rnd_t rnd);
907 
908 int arf_mul_rnd_any(arf_ptr z, arf_srcptr x, arf_srcptr y, slong prec, arf_rnd_t rnd);
909 
910 int arf_mul_rnd_down(arf_ptr z, arf_srcptr x, arf_srcptr y, slong prec);
911 
912 #define arf_mul(z, x, y, prec, rnd)              \
913     ((rnd == FMPR_RND_DOWN)                      \
914         ? arf_mul_rnd_down(z, x, y, prec)        \
915         : arf_mul_rnd_any(z, x, y, prec, rnd))
916 
917 ARF_INLINE int
arf_neg_mul(arf_t z,const arf_t x,const arf_t y,slong prec,arf_rnd_t rnd)918 arf_neg_mul(arf_t z, const arf_t x, const arf_t y, slong prec, arf_rnd_t rnd)
919 {
920     if (arf_is_special(y))
921     {
922         arf_mul(z, x, y, prec, rnd);
923         arf_neg(z, z);
924         return 0;
925     }
926     else
927     {
928         arf_t t;
929         *t = *y;
930         ARF_NEG(t);
931         return arf_mul(z, x, t, prec, rnd);
932     }
933 }
934 
935 ARF_INLINE int
arf_mul_ui(arf_ptr z,arf_srcptr x,ulong y,slong prec,arf_rnd_t rnd)936 arf_mul_ui(arf_ptr z, arf_srcptr x, ulong y, slong prec, arf_rnd_t rnd)
937 {
938     arf_t t;
939     arf_init_set_ui(t, y); /* no need to free */
940     return arf_mul(z, x, t, prec, rnd);
941 }
942 
943 ARF_INLINE int
arf_mul_si(arf_ptr z,arf_srcptr x,slong y,slong prec,arf_rnd_t rnd)944 arf_mul_si(arf_ptr z, arf_srcptr x, slong y, slong prec, arf_rnd_t rnd)
945 {
946     arf_t t;
947     arf_init_set_si(t, y); /* no need to free */
948     return arf_mul(z, x, t, prec, rnd);
949 }
950 
951 int arf_mul_mpz(arf_ptr z, arf_srcptr x, const mpz_t y, slong prec, arf_rnd_t rnd);
952 
953 ARF_INLINE int
arf_mul_fmpz(arf_ptr z,arf_srcptr x,const fmpz_t y,slong prec,arf_rnd_t rnd)954 arf_mul_fmpz(arf_ptr z, arf_srcptr x, const fmpz_t y, slong prec, arf_rnd_t rnd)
955 {
956     if (!COEFF_IS_MPZ(*y))
957         return arf_mul_si(z, x, *y, prec, rnd);
958     else
959         return arf_mul_mpz(z, x, COEFF_TO_PTR(*y), prec, rnd);
960 }
961 
962 #define ARF_ADD_STACK_ALLOC 40
963 #define ARF_ADD_TLS_ALLOC 1000
964 
965 extern TLS_PREFIX mp_ptr __arf_add_tmp;
966 extern TLS_PREFIX slong __arf_add_alloc;
967 
968 ARB_DLL extern void _arf_add_tmp_cleanup(void);
969 
970 #define ARF_ADD_TMP_DECL \
971     mp_limb_t tmp_stack[ARF_ADD_STACK_ALLOC]; \
972 
973 #define ARF_ADD_TMP_ALLOC(tmp, alloc) \
974     if (alloc <= ARF_ADD_STACK_ALLOC) \
975     { \
976         tmp = tmp_stack; \
977     } \
978     else if (alloc <= ARF_ADD_TLS_ALLOC) \
979     { \
980         if (__arf_add_alloc < alloc) \
981         { \
982             if (__arf_add_alloc == 0) \
983             { \
984                 flint_register_cleanup_function(_arf_add_tmp_cleanup); \
985             } \
986             __arf_add_tmp = flint_realloc(__arf_add_tmp, sizeof(mp_limb_t) * alloc); \
987             __arf_add_alloc = alloc; \
988         } \
989         tmp = __arf_add_tmp; \
990     } \
991     else \
992     { \
993         tmp = flint_malloc(sizeof(mp_limb_t) * alloc); \
994     }
995 
996 #define ARF_ADD_TMP_FREE(tmp, alloc) \
997     if (alloc > ARF_ADD_TLS_ALLOC) \
998         flint_free(tmp);
999 
1000 int _arf_add_mpn(arf_t z, mp_srcptr xp, mp_size_t xn, int xsgnbit,
1001     const fmpz_t xexp, mp_srcptr yp, mp_size_t yn, int ysgnbit,
1002     flint_bitcnt_t shift, slong prec, arf_rnd_t rnd);
1003 
1004 int arf_add(arf_ptr z, arf_srcptr x, arf_srcptr y, slong prec, arf_rnd_t rnd);
1005 int arf_add_si(arf_ptr z, arf_srcptr x, slong y, slong prec, arf_rnd_t rnd);
1006 int arf_add_ui(arf_ptr z, arf_srcptr x, ulong y, slong prec, arf_rnd_t rnd);
1007 int arf_add_fmpz(arf_ptr z, arf_srcptr x, const fmpz_t y, slong prec, arf_rnd_t rnd);
1008 
1009 int arf_add_fmpz_2exp(arf_ptr z, arf_srcptr x, const fmpz_t y, const fmpz_t exp, slong prec, arf_rnd_t rnd);
1010 
1011 int arf_sub(arf_ptr z, arf_srcptr x, arf_srcptr y, slong prec, arf_rnd_t rnd);
1012 int arf_sub_si(arf_ptr z, arf_srcptr x, slong y, slong prec, arf_rnd_t rnd);
1013 int arf_sub_ui(arf_ptr z, arf_srcptr x, ulong y, slong prec, arf_rnd_t rnd);
1014 int arf_sub_fmpz(arf_ptr z, arf_srcptr x, const fmpz_t y, slong prec, arf_rnd_t rnd);
1015 
1016 int arf_addmul(arf_ptr z, arf_srcptr x, arf_srcptr y, slong prec, arf_rnd_t rnd);
1017 
1018 ARF_INLINE int
arf_addmul_ui(arf_ptr z,arf_srcptr x,ulong y,slong prec,arf_rnd_t rnd)1019 arf_addmul_ui(arf_ptr z, arf_srcptr x, ulong y, slong prec, arf_rnd_t rnd)
1020 {
1021     arf_t t;
1022     arf_init_set_ui(t, y); /* no need to free */
1023     return arf_addmul(z, x, t, prec, rnd);
1024 }
1025 
1026 ARF_INLINE int
arf_addmul_si(arf_ptr z,arf_srcptr x,slong y,slong prec,arf_rnd_t rnd)1027 arf_addmul_si(arf_ptr z, arf_srcptr x, slong y, slong prec, arf_rnd_t rnd)
1028 {
1029     arf_t t;
1030     arf_init_set_si(t, y); /* no need to free */
1031     return arf_addmul(z, x, t, prec, rnd);
1032 }
1033 
1034 int arf_addmul_mpz(arf_ptr z, arf_srcptr x, const mpz_t y, slong prec, arf_rnd_t rnd);
1035 
1036 ARF_INLINE int
arf_addmul_fmpz(arf_ptr z,arf_srcptr x,const fmpz_t y,slong prec,arf_rnd_t rnd)1037 arf_addmul_fmpz(arf_ptr z, arf_srcptr x, const fmpz_t y, slong prec, arf_rnd_t rnd)
1038 {
1039     if (!COEFF_IS_MPZ(*y))
1040         return arf_addmul_si(z, x, *y, prec, rnd);
1041     else
1042         return arf_addmul_mpz(z, x, COEFF_TO_PTR(*y), prec, rnd);
1043 }
1044 
1045 int arf_submul(arf_ptr z, arf_srcptr x, arf_srcptr y, slong prec, arf_rnd_t rnd);
1046 
1047 ARF_INLINE int
arf_submul_ui(arf_ptr z,arf_srcptr x,ulong y,slong prec,arf_rnd_t rnd)1048 arf_submul_ui(arf_ptr z, arf_srcptr x, ulong y, slong prec, arf_rnd_t rnd)
1049 {
1050     arf_t t;
1051     arf_init_set_ui(t, y); /* no need to free */
1052     return arf_submul(z, x, t, prec, rnd);
1053 }
1054 
1055 ARF_INLINE int
arf_submul_si(arf_ptr z,arf_srcptr x,slong y,slong prec,arf_rnd_t rnd)1056 arf_submul_si(arf_ptr z, arf_srcptr x, slong y, slong prec, arf_rnd_t rnd)
1057 {
1058     arf_t t;
1059     arf_init_set_si(t, y); /* no need to free */
1060     return arf_submul(z, x, t, prec, rnd);
1061 }
1062 
1063 int arf_submul_mpz(arf_ptr z, arf_srcptr x, const mpz_t y, slong prec, arf_rnd_t rnd);
1064 
1065 ARF_INLINE int
arf_submul_fmpz(arf_ptr z,arf_srcptr x,const fmpz_t y,slong prec,arf_rnd_t rnd)1066 arf_submul_fmpz(arf_ptr z, arf_srcptr x, const fmpz_t y, slong prec, arf_rnd_t rnd)
1067 {
1068     if (!COEFF_IS_MPZ(*y))
1069         return arf_submul_si(z, x, *y, prec, rnd);
1070     else
1071         return arf_submul_mpz(z, x, COEFF_TO_PTR(*y), prec, rnd);
1072 }
1073 
1074 int arf_fma(arf_ptr res, arf_srcptr x, arf_srcptr y, arf_srcptr z, slong prec, arf_rnd_t rnd);
1075 
1076 int arf_sosq(arf_t z, const arf_t x, const arf_t y, slong prec, arf_rnd_t rnd);
1077 
1078 int arf_div(arf_ptr z, arf_srcptr x, arf_srcptr y, slong prec, arf_rnd_t rnd);
1079 
1080 ARF_INLINE int
arf_div_ui(arf_ptr z,arf_srcptr x,ulong y,slong prec,arf_rnd_t rnd)1081 arf_div_ui(arf_ptr z, arf_srcptr x, ulong y, slong prec, arf_rnd_t rnd)
1082 {
1083     arf_t t;
1084     arf_init_set_ui(t, y); /* no need to free */
1085     return arf_div(z, x, t, prec, rnd);
1086 }
1087 
1088 ARF_INLINE int
arf_ui_div(arf_ptr z,ulong x,arf_srcptr y,slong prec,arf_rnd_t rnd)1089 arf_ui_div(arf_ptr z, ulong x, arf_srcptr y, slong prec, arf_rnd_t rnd)
1090 {
1091     arf_t t;
1092     arf_init_set_ui(t, x); /* no need to free */
1093     return arf_div(z, t, y, prec, rnd);
1094 }
1095 
1096 ARF_INLINE int
arf_div_si(arf_ptr z,arf_srcptr x,slong y,slong prec,arf_rnd_t rnd)1097 arf_div_si(arf_ptr z, arf_srcptr x, slong y, slong prec, arf_rnd_t rnd)
1098 {
1099     arf_t t;
1100     arf_init_set_si(t, y); /* no need to free */
1101     return arf_div(z, x, t, prec, rnd);
1102 }
1103 
1104 ARF_INLINE int
arf_si_div(arf_ptr z,slong x,arf_srcptr y,slong prec,arf_rnd_t rnd)1105 arf_si_div(arf_ptr z, slong x, arf_srcptr y, slong prec, arf_rnd_t rnd)
1106 {
1107     arf_t t;
1108     arf_init_set_si(t, x); /* no need to free */
1109     return arf_div(z, t, y, prec, rnd);
1110 }
1111 
1112 ARF_INLINE int
arf_div_fmpz(arf_ptr z,arf_srcptr x,const fmpz_t y,slong prec,arf_rnd_t rnd)1113 arf_div_fmpz(arf_ptr z, arf_srcptr x, const fmpz_t y, slong prec, arf_rnd_t rnd)
1114 {
1115     arf_t t;
1116     int r;
1117     arf_init(t);
1118     arf_set_fmpz(t, y);
1119     r = arf_div(z, x, t, prec, rnd);
1120     arf_clear(t);
1121     return r;
1122 }
1123 
1124 ARF_INLINE int
arf_fmpz_div(arf_ptr z,const fmpz_t x,arf_srcptr y,slong prec,arf_rnd_t rnd)1125 arf_fmpz_div(arf_ptr z, const fmpz_t x, arf_srcptr y, slong prec, arf_rnd_t rnd)
1126 {
1127     arf_t t;
1128     int r;
1129     arf_init(t);
1130     arf_set_fmpz(t, x);
1131     r = arf_div(z, t, y, prec, rnd);
1132     arf_clear(t);
1133     return r;
1134 }
1135 
1136 ARF_INLINE int
arf_fmpz_div_fmpz(arf_ptr z,const fmpz_t x,const fmpz_t y,slong prec,arf_rnd_t rnd)1137 arf_fmpz_div_fmpz(arf_ptr z, const fmpz_t x, const fmpz_t y, slong prec, arf_rnd_t rnd)
1138 {
1139     arf_t t, u;
1140     int r;
1141     arf_init(t);
1142     arf_init(u);
1143     arf_set_fmpz(t, x);
1144     arf_set_fmpz(u, y);
1145     r = arf_div(z, t, u, prec, rnd);
1146     arf_clear(t);
1147     arf_clear(u);
1148     return r;
1149 }
1150 
1151 int arf_sqrt(arf_ptr z, arf_srcptr x, slong prec, arf_rnd_t rnd);
1152 
1153 int arf_sqrt_ui(arf_t z, ulong x, slong prec, arf_rnd_t rnd);
1154 
1155 int arf_sqrt_fmpz(arf_t z, const fmpz_t x, slong prec, arf_rnd_t rnd);
1156 
1157 int arf_rsqrt(arf_ptr z, arf_srcptr x, slong prec, arf_rnd_t rnd);
1158 
1159 int arf_root(arf_t z, const arf_t x, ulong k, slong prec, arf_rnd_t rnd);
1160 
1161 /* Magnitude bounds */
1162 
1163 void arf_get_mag(mag_t y, const arf_t x);
1164 
1165 void arf_get_mag_lower(mag_t y, const arf_t x);
1166 
1167 ARF_INLINE void
arf_set_mag(arf_t y,const mag_t x)1168 arf_set_mag(arf_t y, const mag_t x)
1169 {
1170     if (mag_is_zero(x))
1171     {
1172         arf_zero(y);
1173     }
1174     else if (mag_is_inf(x))
1175     {
1176         arf_pos_inf(y);
1177     }
1178     else
1179     {
1180         _fmpz_set_fast(ARF_EXPREF(y), MAG_EXPREF(x));
1181         ARF_DEMOTE(y);
1182         ARF_XSIZE(y) = ARF_MAKE_XSIZE(1, 0);
1183         ARF_NOPTR_D(y)[0] = MAG_MAN(x) << (FLINT_BITS - MAG_BITS);
1184     }
1185 }
1186 
1187 ARF_INLINE void
mag_init_set_arf(mag_t y,const arf_t x)1188 mag_init_set_arf(mag_t y, const arf_t x)
1189 {
1190     mag_init(y);
1191     arf_get_mag(y, x);
1192 }
1193 
1194 ARF_INLINE void
mag_fast_init_set_arf(mag_t y,const arf_t x)1195 mag_fast_init_set_arf(mag_t y, const arf_t x)
1196 {
1197     if (ARF_IS_SPECIAL(x))   /* x == 0 */
1198     {
1199         mag_fast_zero(y);
1200     }
1201     else
1202     {
1203         mp_srcptr xp;
1204         mp_size_t xn;
1205 
1206         ARF_GET_MPN_READONLY(xp, xn, x);
1207 
1208         MAG_MAN(y) = (xp[xn - 1] >> (FLINT_BITS - MAG_BITS)) + LIMB_ONE;
1209         MAG_EXP(y) = ARF_EXP(x);
1210 
1211         MAG_FAST_ADJUST_ONE_TOO_LARGE(y);
1212     }
1213 }
1214 
1215 ARF_INLINE void
arf_mag_fast_add_ulp(mag_t z,const mag_t x,const arf_t y,slong prec)1216 arf_mag_fast_add_ulp(mag_t z, const mag_t x, const arf_t y, slong prec)
1217 {
1218     mag_fast_add_2exp_si(z, x, ARF_EXP(y) - prec);
1219 }
1220 
1221 ARF_INLINE void
arf_mag_add_ulp(mag_t z,const mag_t x,const arf_t y,slong prec)1222 arf_mag_add_ulp(mag_t z, const mag_t x, const arf_t y, slong prec)
1223 {
1224     if (ARF_IS_SPECIAL(y))
1225     {
1226         flint_printf("error: ulp error not defined for special value!\n");
1227         flint_abort();
1228     }
1229     else if (MAG_IS_LAGOM(z) && MAG_IS_LAGOM(x) && ARF_IS_LAGOM(y))
1230     {
1231         arf_mag_fast_add_ulp(z, x, y, prec);
1232     }
1233     else
1234     {
1235         fmpz_t e;
1236         fmpz_init(e);
1237         fmpz_sub_ui(e, ARF_EXPREF(y), prec);
1238         mag_add_2exp_fmpz(z, x, e);
1239         fmpz_clear(e);
1240     }
1241 }
1242 
1243 ARF_INLINE void
arf_mag_set_ulp(mag_t z,const arf_t y,slong prec)1244 arf_mag_set_ulp(mag_t z, const arf_t y, slong prec)
1245 {
1246     if (ARF_IS_SPECIAL(y))
1247     {
1248         flint_printf("error: ulp error not defined for special value!\n");
1249         flint_abort();
1250     }
1251     else
1252     {
1253         _fmpz_add_fast(MAG_EXPREF(z), ARF_EXPREF(y), 1 - prec);
1254         MAG_MAN(z) = MAG_ONE_HALF;
1255     }
1256 }
1257 
1258 void arf_get_fmpq(fmpq_t y, const arf_t x);
1259 
1260 ARF_INLINE int
arf_set_fmpq(arf_t y,const fmpq_t x,slong prec,arf_rnd_t rnd)1261 arf_set_fmpq(arf_t y, const fmpq_t x, slong prec, arf_rnd_t rnd)
1262 {
1263     return arf_fmpz_div_fmpz(y, fmpq_numref(x), fmpq_denref(x), prec, rnd);
1264 }
1265 
1266 int arf_complex_mul(arf_t e, arf_t f, const arf_t a, const arf_t b,
1267                                       const arf_t c, const arf_t d,
1268                                       slong prec, arf_rnd_t rnd);
1269 
1270 int arf_complex_mul_fallback(arf_t e, arf_t f,
1271         const arf_t a, const arf_t b,
1272         const arf_t c, const arf_t d,
1273         slong prec, arf_rnd_t rnd);
1274 
1275 int arf_complex_sqr(arf_t e, arf_t f, const arf_t a, const arf_t b,
1276                                       slong prec, arf_rnd_t rnd);
1277 
1278 int arf_sum(arf_t s, arf_srcptr terms, slong len, slong prec, arf_rnd_t rnd);
1279 
1280 double arf_get_d(const arf_t x, arf_rnd_t rnd);
1281 void arf_set_d(arf_t x, double v);
1282 
1283 ARF_INLINE slong
arf_allocated_bytes(const arf_t x)1284 arf_allocated_bytes(const arf_t x)
1285 {
1286     slong size = fmpz_allocated_bytes(ARF_EXPREF(x));
1287 
1288     if (ARF_HAS_PTR(x))
1289         size += ARF_PTR_ALLOC(x) * sizeof(mp_limb_t);
1290 
1291     return size;
1292 }
1293 
1294 int arf_load_str(arf_t res, const char * data);
1295 
1296 char * arf_dump_str(const arf_t x);
1297 
1298 int arf_load_file(arf_t res, FILE *stream);
1299 
1300 int arf_dump_file(FILE* stream, const arf_t x);
1301 
1302 #ifdef __cplusplus
1303 }
1304 #endif
1305 
1306 #endif
1307 
1308