source: patches/mpfr-2.3.2-branch_update-1.patch@ e53465ee

clfs-1.2 clfs-2.1 clfs-3.0.0-systemd clfs-3.0.0-sysvinit systemd sysvinit
Last change on this file since e53465ee was c75433a, checked in by Jim Gifford <clfs@…>, 16 years ago

Added: MPFR Branch Update Patch

  • Property mode set to 100644
File size: 16.4 KB
RevLine 
[c75433a]1Submitted By: Jim Gifford (jim at cross-lfs dot org)
2Date: 2009-01-05
3Initial Package Version: 2.3.2
4Origin: MPFR Website
5Upstream Status: Fixed
6Description: See http://www.mpfr.org Website Under Bugs
7
8diff -Naur mpfr-2.3.2.orig/strtofr.c mpfr-2.3.2/strtofr.c
9--- mpfr-2.3.2.orig/strtofr.c 2008-09-12 06:47:25.000000000 -0700
10+++ mpfr-2.3.2/strtofr.c 2009-01-05 03:26:12.000000000 -0800
11@@ -31,14 +31,24 @@
12 #define MPFR_MAX_BASE 62
13
14 struct parsed_string {
15- int negative;
16- int base;
17- unsigned char *mantissa, *mant;
18- size_t prec, alloc;
19- mp_exp_t exp_base, exp_bin;
20+ int negative; /* non-zero iff the number is negative */
21+ int base; /* base of the string */
22+ unsigned char *mantissa; /* raw significand (without any point) */
23+ unsigned char *mant; /* stripped significand (without starting and
24+ ending zeroes) */
25+ size_t prec; /* length of mant (zero for +/-0) */
26+ size_t alloc; /* allocation size of mantissa */
27+ mp_exp_t exp_base; /* number of digits before the point */
28+ mp_exp_t exp_bin; /* exponent in case base=2 or 16, and the pxxx
29+ format is used (i.e., exponent is given in
30+ base 10) */
31 };
32
33-/* This table has been generated by the following program */
34+/* This table has been generated by the following program.
35+ For 2 <= b <= MPFR_MAX_BASE,
36+ RedInvLog2Table[b-2][0] / RedInvLog2Table[b-2][1]
37+ is an upper approximation of log(2)/log(b).
38+*/
39 static const unsigned long RedInvLog2Table[MPFR_MAX_BASE-1][2] = {
40 {1UL, 1UL},
41 {53UL, 84UL},
42@@ -441,7 +451,7 @@
43 MPFR_ZIV_DECL (loop);
44 MPFR_TMP_DECL (marker);
45
46- /* determine the minimal precision for the computation */
47+ /* initialize the working precision */
48 prec = MPFR_PREC (x) + MPFR_INT_CEIL_LOG2 (MPFR_PREC (x));
49
50 /* compute y as long as rounding is not possible */
51@@ -449,60 +459,88 @@
52 MPFR_ZIV_INIT (loop, prec);
53 for (;;)
54 {
55- /* initialize y to the value of 0.mant_s[0]...mant_s[pr-1] */
56+ /* Set y to the value of the ~prec most significant bits of pstr->mant
57+ (as long as we guarantee correct rounding, we don't need to get
58+ exactly prec bits). */
59 ysize = (prec - 1) / BITS_PER_MP_LIMB + 1;
60+ /* prec bits corresponds to ysize limbs */
61 ysize_bits = ysize * BITS_PER_MP_LIMB;
62+ /* and to ysize_bits >= prec > MPFR_PREC (x) bits */
63 y = (mp_limb_t*) MPFR_TMP_ALLOC ((2 * ysize + 1) * sizeof (mp_limb_t));
64- y += ysize;
65+ y += ysize; /* y has (ysize+1) allocated limbs */
66
67- /* required precision for str to have ~ysize limbs
68- We must have (2^(BITS_PER_MP_LIMB))^ysize ~= base^pstr_size
69- aka pstr_size = ceil (ysize*BITS_PER_MP_LIMB/log2(base))
70- ysize ~ prec/BITS_PER_MP_LIMB and prec < Umax/2 =>
71+ /* pstr_size is the number of characters we read in pstr->mant
72+ to have at least ysize full limbs.
73+ We must have base^(pstr_size-1) >= (2^(BITS_PER_MP_LIMB))^ysize
74+ (in the worst case, the first digit is one and all others are zero).
75+ i.e., pstr_size >= 1 + ysize*BITS_PER_MP_LIMB/log2(base)
76+ Since ysize ~ prec/BITS_PER_MP_LIMB and prec < Umax/2 =>
77 ysize*BITS_PER_MP_LIMB can not overflow.
78- Compute pstr_size = ysize_bits * Num / Den
79- Where Num/Den ~ 1/log2(base)
80+ We compute pstr_size = 1 + ceil(ysize_bits * Num / Den)
81+ where Num/Den >= 1/log2(base)
82 It is not exactly ceil(1/log2(base)) but could be one more (base 2)
83- Quite ugly since it tries to avoid overflow */
84- pstr_size = ( ysize_bits / RedInvLog2Table[pstr->base-2][1]
85- * RedInvLog2Table[pstr->base-2][0] )
86- + (( ysize_bits % RedInvLog2Table[pstr->base-2][1])
87- * RedInvLog2Table[pstr->base-2][0]
88- / RedInvLog2Table[pstr->base-2][1] )
89- + 1;
90+ Quite ugly since it tries to avoid overflow:
91+ let Num = RedInvLog2Table[pstr->base-2][0]
92+ and Den = RedInvLog2Table[pstr->base-2][1],
93+ and ysize_bits = a*Den+b,
94+ then ysize_bits * Num/Den = a*Num + (b * Num)/Den,
95+ thus ceil(ysize_bits * Num/Den) = a*Num + floor(b * Num + Den - 1)/Den
96+ */
97+ {
98+ unsigned long Num = RedInvLog2Table[pstr->base-2][0];
99+ unsigned long Den = RedInvLog2Table[pstr->base-2][1];
100+ pstr_size = ((ysize_bits / Den) * Num)
101+ + (((ysize_bits % Den) * Num + Den - 1) / Den)
102+ + 1;
103+ }
104+
105+ /* since pstr_size corresponds to at least ysize_bits full bits,
106+ and ysize_bits > prec, the weight of the neglected part of
107+ pstr->mant (if any) is < ulp(y) < ulp(x) */
108
109+ /* if the number of wanted characters is more than what we have in
110+ pstr->mant, round it down */
111 if (pstr_size >= pstr->prec)
112 pstr_size = pstr->prec;
113- MPFR_ASSERTD ((mp_exp_t) pstr_size == (mp_exp_t) pstr_size);
114+ MPFR_ASSERTD (pstr_size == (mp_exp_t) pstr_size);
115
116- /* convert str into binary */
117+ /* convert str into binary: note that pstr->mant is big endian,
118+ thus no offset is needed */
119 real_ysize = mpn_set_str (y, pstr->mant, pstr_size, pstr->base);
120- MPFR_ASSERTD ( real_ysize <= ysize+1);
121+ MPFR_ASSERTD (real_ysize <= ysize+1);
122
123 /* normalize y: warning we can get even get ysize+1 limbs! */
124- MPFR_ASSERTD (y[real_ysize - 1] != 0);
125+ MPFR_ASSERTD (y[real_ysize - 1] != 0); /* mpn_set_str guarantees this */
126 count_leading_zeros (count, y[real_ysize - 1]);
127- exact = (real_ysize <= ysize);
128- if (exact != 0) /* shift y to the left in that case y should be exact */
129+ /* exact means that the number of limbs of the output of mpn_set_str
130+ is less or equal to ysize */
131+ exact = real_ysize <= ysize;
132+ if (exact) /* shift y to the left in that case y should be exact */
133 {
134+ /* we have enough limbs to store {y, real_ysize} */
135 /* shift {y, num_limb} for count bits to the left */
136 if (count != 0)
137- mpn_lshift (y, y, real_ysize, count);
138- /* shift {y, num_limb} for (ysize-num_limb) limbs to the left */
139+ mpn_lshift (y + ysize - real_ysize, y, real_ysize, count);
140 if (real_ysize != ysize)
141 {
142- MPN_COPY_DECR (y + ysize - real_ysize, y, real_ysize);
143+ if (count == 0)
144+ MPN_COPY_DECR (y + ysize - real_ysize, y, real_ysize);
145 MPN_ZERO (y, ysize - real_ysize);
146 }
147 /* for each bit shift decrease exponent of y */
148 /* (This should not overflow) */
149 exp = - ((ysize - real_ysize) * BITS_PER_MP_LIMB + count);
150 }
151- else /* shift y for the right */
152+ else /* shift y to the right, by doing this we might lose some
153+ bits from the result of mpn_set_str (in addition to the
154+ characters neglected from pstr->mant) */
155 {
156 /* shift {y, num_limb} for (BITS_PER_MP_LIMB - count) bits
157- to the right */
158- mpn_rshift (y, y, real_ysize, BITS_PER_MP_LIMB - count);
159+ to the right. FIXME: can we prove that count cannot be zero here,
160+ since mpn_rshift does not accept a shift of BITS_PER_MP_LIMB? */
161+ MPFR_ASSERTD (count != 0);
162+ exact = mpn_rshift (y, y, real_ysize, BITS_PER_MP_LIMB - count) ==
163+ MPFR_LIMB_ZERO;
164 /* for each bit shift increase exponent of y */
165 exp = BITS_PER_MP_LIMB - count;
166 }
167@@ -542,7 +580,7 @@
168 result = y;
169 err = 0;
170 }
171- /* case pstr->exp_base > pstr_size */
172+ /* case non-power-of-two-base, and pstr->exp_base > pstr_size */
173 else if (pstr->exp_base > (mp_exp_t) pstr_size)
174 {
175 mp_limb_t *z;
176@@ -559,6 +597,13 @@
177 goto overflow;
178 exact = exact && (err == -1);
179
180+ /* If exact is non zero, then z equals exactly the value of the
181+ pstr_size most significant digits from pstr->mant, i.e., the
182+ only difference can come from the neglected pstr->prec-pstr_size
183+ least significant digits of pstr->mant.
184+ If exact is zero, then z is rounded towards zero with respect
185+ to that value. */
186+
187 /* multiply(y = 0.mant_s[0]...mant_s[pr-1])_base by base^(exp_s-g) */
188 mpn_mul_n (result, y, z, ysize);
189
190@@ -588,6 +633,8 @@
191 exp --;
192 }
193
194+ /* if the low ysize limbs of {result, 2*ysize} are all zero,
195+ then the result is still "exact" (if it was before) */
196 exact = exact && (mpn_scan1 (result, 0)
197 >= (unsigned long) ysize_bits);
198 result += ysize;
199@@ -598,7 +645,7 @@
200 mp_limb_t *z;
201 mp_exp_t exp_z;
202
203- result = (mp_limb_t*) MPFR_TMP_ALLOC ( (3*ysize+1) * BYTES_PER_MP_LIMB);
204+ result = (mp_limb_t*) MPFR_TMP_ALLOC ((3*ysize+1) * BYTES_PER_MP_LIMB);
205
206 /* set y to y * K^ysize */
207 y = y - ysize; /* we have allocated ysize limbs at y - ysize */
208@@ -622,7 +669,7 @@
209 /* compute y / z */
210 /* result will be put into result + n, and remainder into result */
211 mpn_tdiv_qr (result + ysize, result, (mp_size_t) 0, y,
212- 2*ysize, z, ysize);
213+ 2 * ysize, z, ysize);
214
215 /* exp -= exp_z + ysize_bits with overflow checking
216 and check that we can add/substract 2 to exp without overflow */
217@@ -635,6 +682,8 @@
218 MPFR_EXP_MIN+2, MPFR_EXP_MAX-2,
219 goto overflow, goto underflow);
220 err += 2;
221+ /* if the remainder of the division is zero, then the result is
222+ still "exact" if it was before */
223 exact = exact && (mpn_popcount (result, ysize) == 0);
224
225 /* normalize result */
226@@ -648,7 +697,7 @@
227 }
228 result += ysize;
229 }
230- /* case exp_base = pstr_size */
231+ /* case exp_base = pstr_size: no multiplication or division needed */
232 else
233 {
234 /* base^(exp_s-pr) = 1 nothing to compute */
235@@ -656,6 +705,17 @@
236 err = 0;
237 }
238
239+ /* If result is exact, we still have to consider the neglected part
240+ of the input string. For a directed rounding, in that case we could
241+ still correctly round, since the neglected part is less than
242+ one ulp, but that would make the code more complex, and give a
243+ speedup for rare cases only. */
244+ exact = exact && (pstr_size == pstr->prec);
245+
246+ /* at this point, result is an approximation rounded towards zero
247+ of the pstr_size most significant digits of pstr->mant, with
248+ equality in case exact is non-zero. */
249+
250 /* test if rounding is possible, and if so exit the loop */
251 if (exact || mpfr_can_round_raw (result, ysize,
252 (pstr->negative) ? -1 : 1,
253@@ -679,6 +739,13 @@
254 exp ++;
255 }
256
257+ if (res == 0) /* fix ternary value */
258+ {
259+ exact = exact && (pstr_size == pstr->prec);
260+ if (!exact)
261+ res = (pstr->negative) ? 1 : -1;
262+ }
263+
264 /* Set sign of x before exp since check_range needs a valid sign */
265 (pstr->negative) ? MPFR_SET_NEG (x) : MPFR_SET_POS (x);
266
267diff -Naur mpfr-2.3.2.orig/tests/tset_str.c mpfr-2.3.2/tests/tset_str.c
268--- mpfr-2.3.2.orig/tests/tset_str.c 2008-09-12 06:47:25.000000000 -0700
269+++ mpfr-2.3.2/tests/tset_str.c 2009-01-05 03:25:12.000000000 -0800
270@@ -81,6 +81,24 @@
271 mpfr_clear (a);
272 }
273
274+/* Bug found by Christoph Lauter. */
275+static void
276+bug20081028 (void)
277+{
278+ mpfr_t x;
279+ const char *s = "0.10000000000000000000000000000001E1";
280+
281+ mpfr_init2 (x, 32);
282+ mpfr_set_str (x, "1.00000000000000000006", 10, GMP_RNDU);
283+ if (! mpfr_greater_p (x, __gmpfr_one))
284+ {
285+ printf ("Error in bug20081028:\nExpected %s\nGot ", s);
286+ mpfr_dump (x);
287+ exit (1);
288+ }
289+ mpfr_clear (x);
290+}
291+
292 int
293 main (int argc, char *argv[])
294 {
295@@ -845,6 +863,7 @@
296 mpfr_clear (y);
297
298 check_underflow ();
299+ bug20081028 ();
300
301 tests_end_mpfr ();
302 return 0;
303diff -Naur mpfr-2.3.2.orig/tests/tstrtofr.c mpfr-2.3.2/tests/tstrtofr.c
304--- mpfr-2.3.2.orig/tests/tstrtofr.c 2008-09-12 06:47:25.000000000 -0700
305+++ mpfr-2.3.2/tests/tstrtofr.c 2009-01-05 03:26:12.000000000 -0800
306@@ -27,28 +27,7 @@
307
308 #include "mpfr-test.h"
309
310-static void check_reftable (void);
311-static void check_special (void);
312-static void check_retval (void);
313-static void check_overflow (void);
314-static void check_parse (void);
315-
316-int
317-main (int argc, char *argv[])
318-{
319- tests_start_mpfr ();
320-
321- check_special();
322- check_reftable ();
323- check_parse ();
324- check_overflow ();
325- check_retval ();
326-
327- tests_end_mpfr ();
328- return 0;
329-}
330-
331-void
332+static void
333 check_special (void)
334 {
335 mpfr_t x, y;
336@@ -551,8 +530,7 @@
337 "1.001000010110011011000101100000101111101001100011101101001111110111000010010110010001100e-16920"}
338 };
339
340-
341-void
342+static void
343 check_reftable ()
344 {
345 int i, base;
346@@ -597,7 +575,7 @@
347 mpfr_clear (x);
348 }
349
350-void
351+static void
352 check_parse (void)
353 {
354 mpfr_t x;
355@@ -951,3 +929,104 @@
356
357 mpfr_clear (x);
358 }
359+
360+/* Bug found by Christoph Lauter (in mpfr_set_str). */
361+static struct bug20081025_test {
362+ mpfr_rnd_t rnd;
363+ int inexact;
364+ const char *str;
365+ const char *binstr;
366+} Bug20081028Table[] = {
367+ {GMP_RNDN, -1, "1.00000000000000000006", "1"},
368+ {GMP_RNDZ, -1, "1.00000000000000000006", "1"},
369+ {GMP_RNDU, +1, "1.00000000000000000006",
370+ "10000000000000000000000000000001e-31"},
371+ {GMP_RNDD, -1, "1.00000000000000000006", "1"},
372+
373+
374+ {GMP_RNDN, +1, "-1.00000000000000000006", "-1"},
375+ {GMP_RNDZ, +1, "-1.00000000000000000006", "-1"},
376+ {GMP_RNDU, +1, "-1.00000000000000000006", "-1"},
377+ {GMP_RNDD, -1, "-1.00000000000000000006",
378+ "-10000000000000000000000000000001e-31"},
379+
380+ {GMP_RNDN, +1, "0.999999999999999999999999999999999999999999999", "1"},
381+ {GMP_RNDZ, -1, "0.999999999999999999999999999999999999999999999",
382+ "11111111111111111111111111111111e-32"},
383+ {GMP_RNDU, +1, "0.999999999999999999999999999999999999999999999", "1"},
384+ {GMP_RNDD, -1, "0.999999999999999999999999999999999999999999999",
385+ "11111111111111111111111111111111e-32"},
386+
387+ {GMP_RNDN, -1, "-0.999999999999999999999999999999999999999999999", "-1"},
388+ {GMP_RNDZ, +1, "-0.999999999999999999999999999999999999999999999",
389+ "-11111111111111111111111111111111e-32"},
390+ {GMP_RNDU, +1, "-0.999999999999999999999999999999999999999999999",
391+ "-11111111111111111111111111111111e-32"},
392+ {GMP_RNDD, -1, "-0.999999999999999999999999999999999999999999999", "-1"}
393+};
394+
395+static void
396+bug20081028 (void)
397+{
398+ int i;
399+ int inexact, res;
400+ mpfr_rnd_t rnd;
401+ mpfr_t x, y;
402+ char *s;
403+
404+ mpfr_init2 (x, 32);
405+ mpfr_init2 (y, 32);
406+ for (i = 0 ; i < numberof (Bug20081028Table) ; i++)
407+ {
408+ rnd = Bug20081028Table[i].rnd;
409+ inexact = Bug20081028Table[i].inexact;
410+ mpfr_set_str_binary (x, Bug20081028Table[i].binstr);
411+ res = mpfr_strtofr (y, Bug20081028Table[i].str, &s, 10, rnd);
412+ if (s == NULL || *s != 0)
413+ {
414+ printf ("Error in Bug20081028: strtofr didn't parse entire input\n"
415+ "for (i=%d) Str=\"%s\"", i, Bug20081028Table[i].str);
416+ exit (1);
417+ }
418+ if (! SAME_SIGN (res, inexact))
419+ {
420+ printf ("Error in Bug20081028: expected %s ternary value, "
421+ "got %d\nfor (i=%d) Rnd=%s Str=\"%s\"\n Set binary gives: ",
422+ inexact > 0 ? "positive" : "negative",
423+ res, i, mpfr_print_rnd_mode(rnd), Bug20081028Table[i].str);
424+ mpfr_dump (x);
425+ printf (" strtofr gives: ");
426+ mpfr_dump (y);
427+ exit (1);
428+ }
429+ if (mpfr_cmp (x, y))
430+ {
431+ printf ("Error in Bug20081028: Results differ between strtofr and "
432+ "set_binary\nfor (i=%d) Rnd=%s Str=\"%s\"\n"
433+ " Set binary gives: ",
434+ i, mpfr_print_rnd_mode(rnd), Bug20081028Table[i].str);
435+ mpfr_dump (x);
436+ printf (" strtofr gives: ");
437+ mpfr_dump (y);
438+ exit (1);
439+ }
440+ }
441+ mpfr_clear (y);
442+ mpfr_clear (x);
443+}
444+
445+int
446+main (int argc, char *argv[])
447+{
448+ tests_start_mpfr ();
449+
450+ check_special();
451+ check_reftable ();
452+ check_parse ();
453+ check_overflow ();
454+ check_retval ();
455+ bug20081028 ();
456+
457+ tests_end_mpfr ();
458+ return 0;
459+}
Note: See TracBrowser for help on using the repository browser.