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