Mercurial > hg > xemacs-beta
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 } |