comparison src/number-gmp.c @ 5118:e0db3c197671 ben-lisp-object

merge up to latest default branch, doesn't compile yet
author Ben Wing <ben@xemacs.org>
date Sat, 26 Dec 2009 21:18:49 -0600
parents 313c2cc696b9
children 2fc0e2f18322
comparison
equal deleted inserted replaced
5117:3742ea8250b5 5118:e0db3c197671
24 #include <limits.h> 24 #include <limits.h>
25 #include <math.h> 25 #include <math.h>
26 #include "lisp.h" 26 #include "lisp.h"
27 #include "sysproc.h" /* For qxe_getpid */ 27 #include "sysproc.h" /* For qxe_getpid */
28 28
29 static mpf_t float_print_min, float_print_max; 29 static mp_exp_t float_print_min, float_print_max;
30 gmp_randstate_t random_state; 30 gmp_randstate_t random_state;
31 31
32 CIbyte * 32 CIbyte *
33 bigfloat_to_string(mpf_t f, int base) 33 bigfloat_to_string(mpf_t f, int base)
34 { 34 {
36 CIbyte *str = mpf_get_str (NULL, &expt, base, 0, f); 36 CIbyte *str = mpf_get_str (NULL, &expt, base, 0, f);
37 const int sign = mpf_sgn (f); 37 const int sign = mpf_sgn (f);
38 const int neg = (sign < 0) ? 1 : 0; 38 const int neg = (sign < 0) ? 1 : 0;
39 int len = strlen (str) + 1; /* Count the null terminator */ 39 int len = strlen (str) + 1; /* Count the null terminator */
40 40
41 if (sign == 0 || (mpf_cmp (float_print_min, f) <= 0 && 41 if (sign == 0)
42 mpf_cmp (f, float_print_max) <= 0))
43 { 42 {
44 /* Move digits down to insert a radix point */ 43 XREALLOC_ARRAY (str, CIbyte, 4);
45 if (expt <= 0) 44 strncpy (str, "0.0", 4);
46 { 45 }
47 /* We need room for a radix point and leading zeroes */ 46 else if (float_print_min <= expt && expt <= float_print_max)
48 const int space = -expt + 2; 47 {
49 XREALLOC_ARRAY (str, CIbyte, len + space); 48 if (expt < 0)
50 memmove (&str[space + neg], &str[neg], len - neg); 49 {
51 memset (&str[neg], '0', space); 50 /* We need room for a radix point and leading zeroes */
52 str[neg + 1] = '.'; 51 const int space = -expt + 2;
53 len += space; 52 XREALLOC_ARRAY (str, CIbyte, len + space);
54 } 53 memmove (&str[space + neg], &str[neg], len - neg);
54 memset (&str[neg], '0', space);
55 str[neg + 1] = '.';
56 }
57 else if (len <= expt + neg + 1)
58 {
59 /* We need room for a radix point and trailing zeroes */
60 XREALLOC_ARRAY (str, CIbyte, expt + neg + 3);
61 memset (&str[len - 1], '0', expt + neg + 3 - len);
62 str[expt + neg] = '.';
63 str[expt + neg + 2] = '\0';
64 }
55 else 65 else
56 { 66 {
57 /* We just need room for a radix point */ 67 /* We just need room for a radix point */
58 XREALLOC_ARRAY (str, CIbyte, len + 1); 68 XREALLOC_ARRAY (str, CIbyte, len + 1);
59 memmove (&str[expt + neg + 1], &str[expt + neg], len - (expt + neg)); 69 memmove (&str[expt + neg + 1], &str[expt + neg], len - (expt + neg));
60 str[expt + neg] = '.'; 70 str[expt + neg] = '.';
61 len++; 71 }
62 }
63 } 72 }
64 else 73 else
65 { 74 {
66 /* Computerized scientific notation */ 75 /* Computerized scientific notation: We need room for a possible radix
67 /* We need room for a radix point, format identifier, and exponent */ 76 point, format identifier, and exponent */
68 const int space = (expt < 0) 77 /* GMP's idea of the exponent is 1 greater than scientific notation's */
69 ? (int)(log ((double) (-expt)) / log ((double) base)) + 3 78 expt--;
70 : (int)(log ((double) expt) / log ((double) base)) + 2; 79 const int point = (len == neg + 2) ? 0 : 1;
80 const int exponent = (expt < 0)
81 ? (int)(log ((double) (-expt)) / log ((double) base)) + 3
82 : (int)(log ((double) expt) / log ((double) base)) + 2;
83 const int space = point + exponent;
71 XREALLOC_ARRAY (str, CIbyte, len + space); 84 XREALLOC_ARRAY (str, CIbyte, len + space);
72 memmove (&str[neg + 2], &str[neg + 1], len - neg); 85 if (point > 0)
73 str[len + 1] = 'l'; 86 {
74 sprintf (&str[len + 2], "%ld", expt); 87 memmove (&str[neg + 2], &str[neg + 1], len - neg);
88 str[neg + 1] = '.';
89 }
90 sprintf (&str[len + point - 1], "E%ld", expt);
75 } 91 }
76 return str; 92 return str;
77 } 93 }
78 94
79 /* We need the next two functions since GNU MP insists on giving us an extra 95 /* We need the next two functions since GNU MP insists on giving us an extra
92 init_number_gmp () 108 init_number_gmp ()
93 { 109 {
94 mp_set_memory_functions ((void *(*) (size_t)) xmalloc, gmp_realloc, 110 mp_set_memory_functions ((void *(*) (size_t)) xmalloc, gmp_realloc,
95 gmp_free); 111 gmp_free);
96 112
97 /* The smallest number that is printed without exponents */ 113 /* Numbers with smaller exponents than this are printed in scientific
98 mpf_init_set_d (float_print_min, 0.001); 114 notation. */
115 float_print_min = -4;
99 116
100 /* The largest number that is printed without exponents */ 117 /* Numbers with larger exponents than this are printed in scientific
101 mpf_init_set_ui (float_print_max, 10000000UL); 118 notation. */
119 float_print_max = 8;
102 120
103 /* Prepare the bignum/bigfloat random number generator */ 121 /* Prepare the bignum/bigfloat random number generator */
104 gmp_randinit_default (random_state); 122 gmp_randinit_default (random_state);
105 gmp_randseed_ui (random_state, qxe_getpid () + time (NULL)); 123 gmp_randseed_ui (random_state, qxe_getpid () + time (NULL));
106 } 124 }