1 /* Reference floating point routines.
3 Copyright 1996, 2001, 2004, 2005 Free Software Foundation, Inc.
5 This file is part of the GNU MP Library.
7 The GNU MP Library is free software; you can redistribute it and/or modify
8 it under the terms of the GNU Lesser General Public License as published by
9 the Free Software Foundation; either version 3 of the License, or (at your
10 option) any later version.
12 The GNU MP Library is distributed in the hope that it will be useful, but
13 WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
14 or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
15 License for more details.
17 You should have received a copy of the GNU Lesser General Public License
18 along with the GNU MP Library. If not, see http://www.gnu.org/licenses/. */
29 refmpf_add (mpf_ptr w, mpf_srcptr u, mpf_srcptr v)
31 mp_size_t hi, lo, size;
43 wt = TMP_ALLOC_LIMBS (size + 1);
44 MPN_COPY (wt, PTR (v), size);
52 wt = TMP_ALLOC_LIMBS (size + 1);
53 MPN_COPY (wt, PTR (u), size);
58 if ((SIZ (u) ^ SIZ (v)) < 0)
64 refmpf_sub (w, u, tmp);
69 /* Compute the significance of the hi and lo end of the result. */
70 hi = MAX (EXP (u), EXP (v));
71 lo = MIN (EXP (u) - ABSIZ (u), EXP (v) - ABSIZ (v));
73 ut = TMP_ALLOC_LIMBS (size + 1);
74 vt = TMP_ALLOC_LIMBS (size + 1);
75 wt = TMP_ALLOC_LIMBS (size + 1);
79 off = size + (EXP (u) - hi) - ABSIZ (u);
80 MPN_COPY (ut + off, PTR (u), ABSIZ (u));
81 off = size + (EXP (v) - hi) - ABSIZ (v);
82 MPN_COPY (vt + off, PTR (v), ABSIZ (v));
85 cy = mpn_add_n (wt, ut, vt, size);
93 wt += size - PREC (w);
96 MPN_COPY (PTR (w), wt, size);
97 SIZ (w) = neg == 0 ? size : -size;
103 /* Add 1 "unit in last place" (ie. in the least significant limb) to f.
104 f cannot be zero, since that has no well-defined "last place".
106 This routine is designed for use in cases where we pay close attention to
107 the size of the data value and are using that (and the exponent) to
108 indicate the accurate part of a result, or similar. For this reason, if
109 there's a carry out we don't store 1 and adjust the exponent, we just
110 leave 100..00. We don't even adjust if there's a carry out of prec+1
111 limbs, but instead give up in that case (which we intend shouldn't arise
112 in normal circumstances). */
115 refmpf_add_ulp (mpf_ptr f)
118 mp_size_t fsize = SIZ(f);
119 mp_size_t abs_fsize = ABSIZ(f);
124 printf ("Oops, refmpf_add_ulp called with f==0\n");
128 c = refmpn_add_1 (fp, fp, abs_fsize, CNST_LIMB(1));
131 if (abs_fsize >= PREC(f) + 1)
133 printf ("Oops, refmpf_add_ulp carried out of prec+1 limbs\n");
139 SIZ(f) = (fsize > 0 ? abs_fsize : - abs_fsize);
144 /* Fill f with size limbs of the given value, setup as an integer. */
146 refmpf_fill (mpf_ptr f, mp_size_t size, mp_limb_t value)
149 size = MIN (PREC(f) + 1, size);
152 refmpn_fill (PTR(f), size, value);
155 /* Strip high zero limbs from the f data, adjusting exponent accordingly. */
157 refmpf_normalize (mpf_ptr f)
159 while (SIZ(f) != 0 && PTR(f)[ABSIZ(f)-1] == 0)
161 SIZ(f) = (SIZ(f) >= 0 ? SIZ(f)-1 : SIZ(f)+1);
168 /* refmpf_set_overlap sets up dst as a copy of src, but with PREC(dst)
169 unchanged, in preparation for an overlap test.
171 The full value of src is copied, and the space at PTR(dst) is extended as
172 necessary. The way PREC(dst) is unchanged is as per an mpf_set_prec_raw.
173 The return value is the new PTR(dst) space precision, in bits, ready for
174 a restoring mpf_set_prec_raw before mpf_clear. */
177 refmpf_set_overlap (mpf_ptr dst, mpf_srcptr src)
179 mp_size_t dprec = PREC(dst);
180 mp_size_t ssize = ABSIZ(src);
183 refmpf_set_prec_limbs (dst, (unsigned long) MAX (dprec, ssize));
186 ret = mpf_get_prec (dst);
191 /* Like mpf_set_prec, but taking a precision in limbs.
192 PREC(f) ends up as the given "prec" value. */
194 refmpf_set_prec_limbs (mpf_ptr f, unsigned long prec)
196 mpf_set_prec (f, __GMPF_PREC_TO_BITS (prec));
201 refmpf_sub (mpf_ptr w, mpf_srcptr u, mpf_srcptr v)
203 mp_size_t hi, lo, size;
214 wt = TMP_ALLOC_LIMBS (size + 1);
215 MPN_COPY (wt, PTR (v), size);
223 wt = TMP_ALLOC_LIMBS (size + 1);
224 MPN_COPY (wt, PTR (u), size);
229 if ((SIZ (u) ^ SIZ (v)) < 0)
232 SIZ (tmp) = -SIZ (v);
235 refmpf_add (w, u, tmp);
242 /* Compute the significance of the hi and lo end of the result. */
243 hi = MAX (EXP (u), EXP (v));
244 lo = MIN (EXP (u) - ABSIZ (u), EXP (v) - ABSIZ (v));
246 ut = TMP_ALLOC_LIMBS (size + 1);
247 vt = TMP_ALLOC_LIMBS (size + 1);
248 wt = TMP_ALLOC_LIMBS (size + 1);
252 off = size + (EXP (u) - hi) - ABSIZ (u);
253 MPN_COPY (ut + off, PTR (u), ABSIZ (u));
254 off = size + (EXP (v) - hi) - ABSIZ (v);
255 MPN_COPY (vt + off, PTR (v), ABSIZ (v));
258 if (mpn_cmp (ut, vt, size) >= 0)
259 mpn_sub_n (wt, ut, vt, size);
262 mpn_sub_n (wt, vt, ut, size);
266 while (size != 0 && wt[size - 1] == 0)
275 wt += size - PREC (w);
278 MPN_COPY (PTR (w), wt, size);
279 SIZ (w) = neg == 0 ? size : -size;
285 /* Validate got by comparing to want. Return 1 if good, 0 if bad.
287 The data in got is compared to that in want, up to either PREC(got) limbs
288 or the size of got, whichever is bigger. Clearly we always demand
289 PREC(got) of accuracy, but we go further and say that if got is bigger
290 then any extra must be correct too.
292 want needs to have enough data to allow this comparison. The size in
293 want doesn't have to be that big though, if it's smaller then further low
294 limbs are taken to be zero.
296 This validation approach is designed to allow some flexibility in exactly
297 how much data is generated by an mpf function, ie. either prec or prec+1
298 limbs. We don't try to make a reference function that emulates that same
299 size decision, instead the idea is for a validation function to generate
300 at least as much data as the real function, then compare. */
303 refmpf_validate (const char *name, mpf_srcptr got, mpf_srcptr want)
306 mp_size_t gsize, wsize, cmpsize, i;
308 mp_limb_t glimb, wlimb;
310 MPF_CHECK_FORMAT (got);
312 if (EXP (got) != EXP (want))
314 printf ("%s: wrong exponent\n", name);
320 if ((gsize < 0 && wsize > 0) || (gsize > 0 && wsize < 0))
322 printf ("%s: wrong sign\n", name);
329 /* most significant limb of respective data */
330 gp = PTR (got) + gsize - 1;
331 wp = PTR (want) + wsize - 1;
333 /* compare limb data */
334 cmpsize = MAX (PREC (got), gsize);
335 for (i = 0; i < cmpsize; i++)
337 glimb = (i < gsize ? gp[-i] : 0);
338 wlimb = (i < wsize ? wp[-i] : 0);
342 printf ("%s: wrong data starting at index %ld from top\n",
351 printf (" prec %d\n", PREC(got));
352 printf (" exp got %ld\n", (long) EXP(got));
353 printf (" exp want %ld\n", (long) EXP(want));
354 printf (" size got %d\n", SIZ(got));
355 printf (" size want %d\n", SIZ(want));
356 printf (" limbs (high to low)\n");
358 for (i = ABSIZ(got)-1; i >= 0; i--)
360 gmp_printf ("%MX", PTR(got)[i]);
366 for (i = ABSIZ(want)-1; i >= 0; i--)
368 gmp_printf ("%MX", PTR(want)[i]);
381 refmpf_validate_division (const char *name, mpf_srcptr got,
382 mpf_srcptr n, mpf_srcptr d)
384 mp_size_t nsize, dsize, sign, prec, qsize, tsize;
392 ASSERT_ALWAYS (dsize != 0);
394 sign = nsize ^ dsize;
402 EXP (want) = EXP (n) - EXP (d) + 1;
404 qsize = prec + 2; /* at least prec+1 limbs, after high zero */
405 tsize = qsize + dsize - 1; /* dividend size to give desired qsize */
407 /* dividend n, extended or truncated */
408 tp = refmpn_malloc_limbs (tsize);
409 refmpn_copy_extend (tp, tsize, np, nsize);
411 qp = refmpn_malloc_limbs (qsize);
412 rp = refmpn_malloc_limbs (dsize); /* remainder, unused */
414 ASSERT_ALWAYS (qsize == tsize - dsize + 1);
415 refmpn_tdiv_qr (qp, rp, (mp_size_t) 0, tp, tsize, dp, dsize);
418 SIZ (want) = (sign >= 0 ? qsize : -qsize);
419 refmpf_normalize (want);
421 ret = refmpf_validate (name, got, want);