comparison src/number.c @ 5125:b5df3737028a ben-lisp-object

merge
author Ben Wing <ben@xemacs.org>
date Wed, 24 Feb 2010 01:58:04 -0600
parents 623d57b7fbe8 16112448d484
children 0dcd22290039
comparison
equal deleted inserted replaced
5124:623d57b7fbe8 5125:b5df3737028a
1 /* Numeric types for XEmacs. 1 /* Numeric types for XEmacs.
2 Copyright (C) 2004 Jerry James. 2 Copyright (C) 2004 Jerry James.
3 Copyright (C) 2010 Ben Wing.
3 4
4 This file is part of XEmacs. 5 This file is part of XEmacs.
5 6
6 XEmacs is free software; you can redistribute it and/or modify it 7 XEmacs is free software; you can redistribute it and/or modify it
7 under the terms of the GNU General Public License as published by the 8 under the terms of the GNU General Public License as published by the
13 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 for more details. 15 for more details.
15 16
16 You should have received a copy of the GNU General Public License 17 You should have received a copy of the GNU General Public License
17 along with XEmacs; see the file COPYING. If not, write to 18 along with XEmacs; see the file COPYING. If not, write to
18 the Free Software Foundation, Inc., 59 Temple Place - Suite 330, 19 the Free Software Foundation, Inc., 51 Franklin St - Fifth Floor,
19 Boston, MA 02111-1307, USA. */ 20 Boston, MA 02111-1301, USA. */
20 21
21 /* Synched up with: Not in FSF. */ 22 /* Synched up with: Not in FSF. */
22 23
23 #include <config.h> 24 #include <config.h>
24 #include <limits.h> 25 #include <limits.h>
30 #define USED_IF_BIGFLOAT(decl) UNUSED (decl) 31 #define USED_IF_BIGFLOAT(decl) UNUSED (decl)
31 #endif 32 #endif
32 33
33 Lisp_Object Qrationalp, Qfloatingp, Qrealp; 34 Lisp_Object Qrationalp, Qfloatingp, Qrealp;
34 Lisp_Object Vdefault_float_precision; 35 Lisp_Object Vdefault_float_precision;
35 Fixnum Vmost_negative_fixnum, Vmost_positive_fixnum; 36
36 static Lisp_Object Qunsupported_type; 37 static Lisp_Object Qunsupported_type;
37 static Lisp_Object Vbigfloat_max_prec; 38 static Lisp_Object Vbigfloat_max_prec;
38 static int number_initialized; 39 static int number_initialized;
39 40
40 #ifdef HAVE_BIGNUM 41 #ifdef HAVE_BIGNUM
51 #ifdef HAVE_BIGNUM 52 #ifdef HAVE_BIGNUM
52 static void 53 static void
53 bignum_print (Lisp_Object obj, Lisp_Object printcharfun, 54 bignum_print (Lisp_Object obj, Lisp_Object printcharfun,
54 int UNUSED (escapeflag)) 55 int UNUSED (escapeflag))
55 { 56 {
56 CIbyte *bstr = bignum_to_string (XBIGNUM_DATA (obj), 10); 57 Ascbyte *bstr = bignum_to_string (XBIGNUM_DATA (obj), 10);
57 write_c_string (printcharfun, bstr); 58 write_ascstring (printcharfun, bstr);
58 xfree (bstr, CIbyte *); 59 xfree (bstr);
59 } 60 }
61
62 #ifdef NEW_GC
63 static void
64 bignum_finalize (void *header)
65 {
66 struct Lisp_Bignum *num = (struct Lisp_Bignum *) header;
67 /* #### WARNING: It would be better to put some sort of check to make
68 sure this doesn't happen more than once, just in case ---
69 e.g. checking if it's zero before finalizing and then setting it to
70 zero after finalizing. */
71 bignum_fini (num->data);
72 }
73 #define BIGNUM_FINALIZE bignum_finalize
74 #else
75 #define BIGNUM_FINALIZE 0
76 #endif
60 77
61 static int 78 static int
62 bignum_equal (Lisp_Object obj1, Lisp_Object obj2, int UNUSED (depth)) 79 bignum_equal (Lisp_Object obj1, Lisp_Object obj2, int UNUSED (depth),
80 int UNUSED (foldcase))
63 { 81 {
64 return bignum_eql (XBIGNUM_DATA (obj1), XBIGNUM_DATA (obj2)); 82 return bignum_eql (XBIGNUM_DATA (obj1), XBIGNUM_DATA (obj2));
65 } 83 }
66 84
67 static Hashcode 85 static Hashcode
80 98
81 static void 99 static void
82 bignum_convfree (const void * UNUSED (object), void *data, 100 bignum_convfree (const void * UNUSED (object), void *data,
83 Bytecount UNUSED (size)) 101 Bytecount UNUSED (size))
84 { 102 {
85 xfree (data, void *); 103 xfree (data);
86 } 104 }
87 105
88 static void * 106 static void *
89 bignum_deconvert (void *object, void *data, Bytecount UNUSED (size)) 107 bignum_deconvert (void *object, void *data, Bytecount UNUSED (size))
90 { 108 {
105 0, { &bignum_opc }, XD_FLAG_NO_KKCC }, 123 0, { &bignum_opc }, XD_FLAG_NO_KKCC },
106 { XD_END } 124 { XD_END }
107 }; 125 };
108 126
109 DEFINE_DUMPABLE_FROB_BLOCK_LISP_OBJECT ("bignum", bignum, 0, bignum_print, 127 DEFINE_DUMPABLE_FROB_BLOCK_LISP_OBJECT ("bignum", bignum, 0, bignum_print,
110 0, bignum_equal, bignum_hash, 128 BIGNUM_FINALIZE, bignum_equal,
111 bignum_description, Lisp_Bignum); 129 bignum_hash, bignum_description,
130 Lisp_Bignum);
112 131
113 #endif /* HAVE_BIGNUM */ 132 #endif /* HAVE_BIGNUM */
114 133
115 Lisp_Object Qbignump; 134 Lisp_Object Qbignump;
116 135
118 Return t if OBJECT is a bignum, nil otherwise. 137 Return t if OBJECT is a bignum, nil otherwise.
119 */ 138 */
120 (object)) 139 (object))
121 { 140 {
122 return BIGNUMP (object) ? Qt : Qnil; 141 return BIGNUMP (object) ? Qt : Qnil;
123 }
124
125
126 /********************************* Integers *********************************/
127 DEFUN ("integerp", Fintegerp, 1, 1, 0, /*
128 Return t if OBJECT is an integer, nil otherwise.
129 */
130 (object))
131 {
132 return INTEGERP (object) ? Qt : Qnil;
133 }
134
135 DEFUN ("evenp", Fevenp, 1, 1, 0, /*
136 Return t if INTEGER is even, nil otherwise.
137 */
138 (integer))
139 {
140 CONCHECK_INTEGER (integer);
141 return (BIGNUMP (integer)
142 ? bignum_evenp (XBIGNUM_DATA (integer))
143 : XTYPE (integer) == Lisp_Type_Int_Even) ? Qt : Qnil;
144 }
145
146 DEFUN ("oddp", Foddp, 1, 1, 0, /*
147 Return t if INTEGER is odd, nil otherwise.
148 */
149 (integer))
150 {
151 CONCHECK_INTEGER (integer);
152 return (BIGNUMP (integer)
153 ? bignum_oddp (XBIGNUM_DATA (integer))
154 : XTYPE (integer) == Lisp_Type_Int_Odd) ? Qt : Qnil;
155 } 142 }
156 143
157 144
158 /********************************** Ratios **********************************/ 145 /********************************** Ratios **********************************/
159 #ifdef HAVE_RATIO 146 #ifdef HAVE_RATIO
160 static void 147 static void
161 ratio_print (Lisp_Object obj, Lisp_Object printcharfun, 148 ratio_print (Lisp_Object obj, Lisp_Object printcharfun,
162 int UNUSED (escapeflag)) 149 int UNUSED (escapeflag))
163 { 150 {
164 CIbyte *rstr = ratio_to_string (XRATIO_DATA (obj), 10); 151 CIbyte *rstr = ratio_to_string (XRATIO_DATA (obj), 10);
165 write_c_string (printcharfun, rstr); 152 write_ascstring (printcharfun, rstr);
166 xfree (rstr, CIbyte *); 153 xfree (rstr);
167 } 154 }
155
156 #ifdef NEW_GC
157 static void
158 ratio_finalize (void *header)
159 {
160 struct Lisp_Ratio *num = (struct Lisp_Ratio *) header;
161 /* #### WARNING: It would be better to put some sort of check to make
162 sure this doesn't happen more than once, just in case ---
163 e.g. checking if it's zero before finalizing and then setting it to
164 zero after finalizing. */
165 ratio_fini (num->data);
166 }
167 #define RATIO_FINALIZE ratio_finalize
168 #else
169 #define RATIO_FINALIZE 0
170 #endif
168 171
169 static int 172 static int
170 ratio_equal (Lisp_Object obj1, Lisp_Object obj2, int UNUSED (depth)) 173 ratio_equal (Lisp_Object obj1, Lisp_Object obj2, int UNUSED (depth),
174 int UNUSED (foldcase))
171 { 175 {
172 return ratio_eql (XRATIO_DATA (obj1), XRATIO_DATA (obj2)); 176 return ratio_eql (XRATIO_DATA (obj1), XRATIO_DATA (obj2));
173 } 177 }
174 178
175 static Hashcode 179 static Hashcode
182 { XD_OPAQUE_PTR, offsetof (Lisp_Ratio, data) }, 186 { XD_OPAQUE_PTR, offsetof (Lisp_Ratio, data) },
183 { XD_END } 187 { XD_END }
184 }; 188 };
185 189
186 DEFINE_NODUMP_FROB_BLOCK_LISP_OBJECT ("ratio", ratio, 0, ratio_print, 190 DEFINE_NODUMP_FROB_BLOCK_LISP_OBJECT ("ratio", ratio, 0, ratio_print,
187 0, ratio_equal, ratio_hash, 191 RATIO_FINALIZE, ratio_equal, ratio_hash,
188 ratio_description, Lisp_Ratio); 192 ratio_description, Lisp_Ratio);
189 193
190 #endif /* HAVE_RATIO */ 194 #endif /* HAVE_RATIO */
191 195
192 Lisp_Object Qratiop; 196 Lisp_Object Qratiop;
215 */ 219 */
216 (rational)) 220 (rational))
217 { 221 {
218 CONCHECK_RATIONAL (rational); 222 CONCHECK_RATIONAL (rational);
219 #ifdef HAVE_RATIO 223 #ifdef HAVE_RATIO
220 return RATIOP (rational) 224 if (RATIOP (rational))
221 ? make_bignum_bg (XRATIO_NUMERATOR (rational)) 225 {
222 : rational; 226 return
223 #else 227 Fcanonicalize_number (make_bignum_bg (XRATIO_NUMERATOR (rational)));
228 }
229 #endif
224 return rational; 230 return rational;
225 #endif
226 } 231 }
227 232
228 DEFUN ("denominator", Fdenominator, 1, 1, 0, /* 233 DEFUN ("denominator", Fdenominator, 1, 1, 0, /*
229 Return the denominator of the canonical form of RATIONAL. 234 Return the denominator of the canonical form of RATIONAL.
230 If RATIONAL is an integer, 1 is returned. 235 If RATIONAL is an integer, 1 is returned.
231 */ 236 */
232 (rational)) 237 (rational))
233 { 238 {
234 CONCHECK_RATIONAL (rational); 239 CONCHECK_RATIONAL (rational);
235 #ifdef HAVE_RATIO 240 #ifdef HAVE_RATIO
236 return RATIOP (rational) 241 if (RATIOP (rational))
237 ? make_bignum_bg (XRATIO_DENOMINATOR (rational)) 242 {
238 : make_int (1); 243 return Fcanonicalize_number (make_bignum_bg
239 #else 244 (XRATIO_DENOMINATOR (rational)));
240 return rational; 245 }
241 #endif 246 #endif
247 return make_int (1);
242 } 248 }
243 249
244 250
245 /******************************** Bigfloats *********************************/ 251 /******************************** Bigfloats *********************************/
246 #ifdef HAVE_BIGFLOAT 252 #ifdef HAVE_BIGFLOAT
247 static void 253 static void
248 bigfloat_print (Lisp_Object obj, Lisp_Object printcharfun, 254 bigfloat_print (Lisp_Object obj, Lisp_Object printcharfun,
249 int UNUSED (escapeflag)) 255 int UNUSED (escapeflag))
250 { 256 {
251 CIbyte *fstr = bigfloat_to_string (XBIGFLOAT_DATA (obj), 10); 257 Ascbyte *fstr = bigfloat_to_string (XBIGFLOAT_DATA (obj), 10);
252 write_c_string (printcharfun, fstr); 258 write_ascstring (printcharfun, fstr);
253 xfree (fstr, CIbyte *); 259 xfree (fstr);
254 } 260 }
261
262 #ifdef NEW_GC
263 static void
264 bigfloat_finalize (void *header)
265 {
266 struct Lisp_Bigfloat *num = (struct Lisp_Bigfloat *) header;
267 /* #### WARNING: It would be better to put some sort of check to make
268 sure this doesn't happen more than once, just in case ---
269 e.g. checking if it's zero before finalizing and then setting it to
270 zero after finalizing. */
271 bigfloat_fini (num->bf);
272 }
273 #define BIGFLOAT_FINALIZE bigfloat_finalize
274 #else
275 #define BIGFLOAT_FINALIZE 0
276 #endif
255 277
256 static int 278 static int
257 bigfloat_equal (Lisp_Object obj1, Lisp_Object obj2, int UNUSED (depth)) 279 bigfloat_equal (Lisp_Object obj1, Lisp_Object obj2, int UNUSED (depth),
280 int UNUSED (foldcase))
258 { 281 {
259 return bigfloat_eql (XBIGFLOAT_DATA (obj1), XBIGFLOAT_DATA (obj2)); 282 return bigfloat_eql (XBIGFLOAT_DATA (obj1), XBIGFLOAT_DATA (obj2));
260 } 283 }
261 284
262 static Hashcode 285 static Hashcode
269 { XD_OPAQUE_PTR, offsetof (Lisp_Bigfloat, bf) }, 292 { XD_OPAQUE_PTR, offsetof (Lisp_Bigfloat, bf) },
270 { XD_END } 293 { XD_END }
271 }; 294 };
272 295
273 DEFINE_DUMPABLE_FROB_BLOCK_LISP_OBJECT ("bigfloat", bigfloat, 0, 296 DEFINE_DUMPABLE_FROB_BLOCK_LISP_OBJECT ("bigfloat", bigfloat, 0,
274 bigfloat_print, 0, 297 bigfloat_print, BIGFLOAT_FINALIZE,
275 bigfloat_equal, bigfloat_hash, 298 bigfloat_equal, bigfloat_hash,
276 bigfloat_description, Lisp_Bigfloat); 299 bigfloat_description, Lisp_Bigfloat);
277 300
278 #endif /* HAVE_BIGFLOAT */ 301 #endif /* HAVE_BIGFLOAT */
279 302
343 366
344 CONCHECK_INTEGER (*val); 367 CONCHECK_INTEGER (*val);
345 #ifdef HAVE_BIGFLOAT 368 #ifdef HAVE_BIGFLOAT
346 if (INTP (*val)) 369 if (INTP (*val))
347 prec = XINT (*val); 370 prec = XINT (*val);
348 else 371 else
349 { 372 {
350 if (!bignum_fits_ulong_p (XBIGNUM_DATA (*val))) 373 if (!bignum_fits_ulong_p (XBIGNUM_DATA (*val)))
351 args_out_of_range_3 (*val, Qzero, Vbigfloat_max_prec); 374 args_out_of_range_3 (*val, Qzero, Vbigfloat_max_prec);
352 prec = bignum_to_ulong (XBIGNUM_DATA (*val)); 375 prec = bignum_to_ulong (XBIGNUM_DATA (*val));
353 } 376 }
403 appropriate. */ 426 appropriate. */
404 #ifdef HAVE_RATIO 427 #ifdef HAVE_RATIO
405 if (RATIOP (number) && 428 if (RATIOP (number) &&
406 bignum_fits_long_p (XRATIO_DENOMINATOR (number)) && 429 bignum_fits_long_p (XRATIO_DENOMINATOR (number)) &&
407 bignum_to_long (XRATIO_DENOMINATOR (number)) == 1L) 430 bignum_to_long (XRATIO_DENOMINATOR (number)) == 1L)
408 number = make_bignum_bg (XRATIO_NUMERATOR (number)); 431 number = Fcanonicalize_number (make_bignum_bg (XRATIO_NUMERATOR (number)));
409 #endif 432 #endif
410 #ifdef HAVE_BIGNUM 433 #ifdef HAVE_BIGNUM
411 if (BIGNUMP (number) && bignum_fits_emacs_int_p (XBIGNUM_DATA (number))) 434 if (BIGNUMP (number) && bignum_fits_emacs_int_p (XBIGNUM_DATA (number)))
412 { 435 {
413 EMACS_INT n = bignum_to_emacs_int (XBIGNUM_DATA (number)); 436 EMACS_INT n = bignum_to_emacs_int (XBIGNUM_DATA (number));
653 ? XBIGFLOAT_GET_PREC (*arg2) : 676 ? XBIGFLOAT_GET_PREC (*arg2) :
654 #endif 677 #endif
655 0UL); 678 0UL);
656 return type2; 679 return type2;
657 } 680 }
658 681
659 if (type2 < type1) 682 if (type2 < type1)
660 { 683 {
661 *arg2 = internal_coerce_number (*arg2, type1, 684 *arg2 = internal_coerce_number (*arg2, type1,
662 #ifdef HAVE_BIGFLOAT 685 #ifdef HAVE_BIGFLOAT
663 type1 == BIGFLOAT_T 686 type1 == BIGFLOAT_T
760 DEFSYMBOL (Qratiop); 783 DEFSYMBOL (Qratiop);
761 DEFSYMBOL (Qbigfloatp); 784 DEFSYMBOL (Qbigfloatp);
762 785
763 /* Functions */ 786 /* Functions */
764 DEFSUBR (Fbignump); 787 DEFSUBR (Fbignump);
765 DEFSUBR (Fintegerp);
766 DEFSUBR (Fevenp);
767 DEFSUBR (Foddp);
768 DEFSUBR (Fratiop); 788 DEFSUBR (Fratiop);
769 DEFSUBR (Frationalp); 789 DEFSUBR (Frationalp);
770 DEFSUBR (Fnumerator); 790 DEFSUBR (Fnumerator);
771 DEFSUBR (Fdenominator); 791 DEFSUBR (Fdenominator);
772 DEFSUBR (Fbigfloatp); 792 DEFSUBR (Fbigfloatp);
798 The maximum number of bits of precision a bigfloat can have. 818 The maximum number of bits of precision a bigfloat can have.
799 This is determined by the underlying library used to implement bigfloats. 819 This is determined by the underlying library used to implement bigfloats.
800 */); 820 */);
801 821
802 #ifdef HAVE_BIGFLOAT 822 #ifdef HAVE_BIGFLOAT
803 #ifdef HAVE_BIGNUM 823 /* Don't create a bignum here. Otherwise, we lose with NEW_GC + pdump.
824 See reinit_vars_of_number(). */
825 Vbigfloat_max_prec = make_int (EMACS_INT_MAX);
826 #else
827 Vbigfloat_max_prec = make_int (0);
828 #endif /* HAVE_BIGFLOAT */
829
830 Fprovide (intern ("number-types"));
831 #ifdef HAVE_BIGNUM
832 Fprovide (intern ("bignum"));
833 #endif
834 #ifdef HAVE_RATIO
835 Fprovide (intern ("ratio"));
836 #endif
837 #ifdef HAVE_BIGFLOAT
838 Fprovide (intern ("bigfloat"));
839 #endif
840 }
841
842 void
843 reinit_vars_of_number (void)
844 {
845 #if defined(HAVE_BIGFLOAT) && defined(HAVE_BIGNUM)
804 Vbigfloat_max_prec = make_bignum (0L); 846 Vbigfloat_max_prec = make_bignum (0L);
805 bignum_set_ulong (XBIGNUM_DATA (Vbigfloat_max_prec), ULONG_MAX); 847 bignum_set_ulong (XBIGNUM_DATA (Vbigfloat_max_prec), ULONG_MAX);
806 #else
807 Vbigfloat_max_prec = make_int (EMACS_INT_MAX);
808 #endif
809 #else
810 Vbigfloat_max_prec = make_int (0);
811 #endif /* HAVE_BIGFLOAT */
812
813 DEFVAR_CONST_INT ("most-negative-fixnum", &Vmost_negative_fixnum /*
814 The fixnum closest in value to negative infinity.
815 */);
816 Vmost_negative_fixnum = EMACS_INT_MIN;
817
818 DEFVAR_CONST_INT ("most-positive-fixnum", &Vmost_positive_fixnum /*
819 The fixnum closest in value to positive infinity.
820 */);
821 Vmost_positive_fixnum = EMACS_INT_MAX;
822
823 Fprovide (intern ("number-types"));
824 #ifdef HAVE_BIGNUM
825 Fprovide (intern ("bignum"));
826 #endif
827 #ifdef HAVE_RATIO
828 Fprovide (intern ("ratio"));
829 #endif
830 #ifdef HAVE_BIGFLOAT
831 Fprovide (intern ("bigfloat"));
832 #endif 848 #endif
833 } 849 }
834 850
835 void 851 void
836 init_number (void) 852 init_number (void)
858 874
859 #ifdef HAVE_BIGFLOAT 875 #ifdef HAVE_BIGFLOAT
860 bigfloat_init (scratch_bigfloat); 876 bigfloat_init (scratch_bigfloat);
861 bigfloat_init (scratch_bigfloat2); 877 bigfloat_init (scratch_bigfloat2);
862 #endif 878 #endif
863 } 879
864 } 880 #ifndef PDUMP
881 reinit_vars_of_number ();
882 #endif
883 }
884 }