comparison src/floatfns.c @ 398:74fd4e045ea6 r21-2-29

Import from CVS: tag r21-2-29
author cvs
date Mon, 13 Aug 2007 11:13:30 +0200
parents 8626e4521993
children a86b2b5e0111
comparison
equal deleted inserted replaced
397:f4aeb21a5bad 398:74fd4e045ea6
53 53
54 /* Need to define a differentiating symbol -- see sysfloat.h */ 54 /* Need to define a differentiating symbol -- see sysfloat.h */
55 #define THIS_FILENAME floatfns 55 #define THIS_FILENAME floatfns
56 #include "sysfloat.h" 56 #include "sysfloat.h"
57 57
58 #ifndef HAVE_RINT 58 /* The code uses emacs_rint, so that it works to undefine HAVE_RINT
59 if `rint' exists but does not work right. */
60 #ifdef HAVE_RINT
61 #define emacs_rint rint
62 #else
59 static double 63 static double
60 rint (double x) 64 emacs_rint (double x)
61 { 65 {
62 double r = floor (x + 0.5); 66 double r = floor (x + 0.5);
63 double diff = fabs (r - x); 67 double diff = fabs (r - x);
64 /* Round to even and correct for any roundoff errors. */ 68 /* Round to even and correct for any roundoff errors. */
65 if (diff >= 0.5 && (diff > 0.5 || r != 2.0 * floor (r / 2.0))) 69 if (diff >= 0.5 && (diff > 0.5 || r != 2.0 * floor (r / 2.0)))
73 static int in_float; 77 static int in_float;
74 78
75 /* If an argument is out of range for a mathematical function, 79 /* If an argument is out of range for a mathematical function,
76 here is the actual argument value to use in the error message. */ 80 here is the actual argument value to use in the error message. */
77 static Lisp_Object float_error_arg, float_error_arg2; 81 static Lisp_Object float_error_arg, float_error_arg2;
78 static CONST char *float_error_fn_name; 82 static const char *float_error_fn_name;
79 83
80 /* Evaluate the floating point expression D, recording NUM 84 /* Evaluate the floating point expression D, recording NUM
81 as the original argument for error messages. 85 as the original argument for error messages.
82 D is normally an assignment expression. 86 D is normally an assignment expression.
83 Handle errors which may result in signals or may set errno. 87 Handle errors which may result in signals or may set errno.
106 #define IN_FLOAT2(d, name, num, num2) (in_float = 2, (d), in_float = 0) 110 #define IN_FLOAT2(d, name, num, num2) (in_float = 2, (d), in_float = 0)
107 #endif 111 #endif
108 112
109 113
110 #define arith_error(op,arg) \ 114 #define arith_error(op,arg) \
111 Fsignal (Qarith_error, list2 (build_string ((op)), (arg))) 115 Fsignal (Qarith_error, list2 (build_string (op), arg))
112 #define range_error(op,arg) \ 116 #define range_error(op,arg) \
113 Fsignal (Qrange_error, list2 (build_string ((op)), (arg))) 117 Fsignal (Qrange_error, list2 (build_string (op), arg))
114 #define range_error2(op,a1,a2) \ 118 #define range_error2(op,a1,a2) \
115 Fsignal (Qrange_error, list3 (build_string ((op)), (a1), (a2))) 119 Fsignal (Qrange_error, list3 (build_string (op), a1, a2))
116 #define domain_error(op,arg) \ 120 #define domain_error(op,arg) \
117 Fsignal (Qdomain_error, list2 (build_string ((op)), (arg))) 121 Fsignal (Qdomain_error, list2 (build_string (op), arg))
118 #define domain_error2(op,a1,a2) \ 122 #define domain_error2(op,a1,a2) \
119 Fsignal (Qdomain_error, list3 (build_string ((op)), (a1), (a2))) 123 Fsignal (Qdomain_error, list3 (build_string (op), a1, a2))
120 124
121 125
122 /* Convert float to Lisp Integer if it fits, else signal a range 126 /* Convert float to Lisp Integer if it fits, else signal a range
123 error using the given arguments. */ 127 error using the given arguments. */
124 static Lisp_Object 128 static Lisp_Object
125 float_to_int (double x, CONST char *name, Lisp_Object num, Lisp_Object num2) 129 float_to_int (double x, const char *name, Lisp_Object num, Lisp_Object num2)
126 { 130 {
127 if (x >= ((EMACS_INT) 1 << (VALBITS-1)) 131 if (x >= ((EMACS_INT) 1 << (VALBITS-1))
128 || x <= - ((EMACS_INT) 1 << (VALBITS-1)) - (EMACS_INT) 1) 132 || x <= - ((EMACS_INT) 1 << (VALBITS-1)) - (EMACS_INT) 1)
129 { 133 {
130 if (!UNBOUNDP (num2)) 134 if (!UNBOUNDP (num2))
158 } 162 }
159 } 163 }
160 164
161 165
162 static Lisp_Object 166 static Lisp_Object
163 mark_float (Lisp_Object obj, void (*markobj) (Lisp_Object)) 167 mark_float (Lisp_Object obj)
164 { 168 {
165 return Qnil; 169 return Qnil;
166 } 170 }
167 171
168 static int 172 static int
177 /* mod the value down to 32-bit range */ 181 /* mod the value down to 32-bit range */
178 /* #### change for 64-bit machines */ 182 /* #### change for 64-bit machines */
179 return (unsigned long) fmod (extract_float (obj), 4e9); 183 return (unsigned long) fmod (extract_float (obj), 4e9);
180 } 184 }
181 185
186 static const struct lrecord_description float_description[] = {
187 { XD_END }
188 };
189
182 DEFINE_BASIC_LRECORD_IMPLEMENTATION ("float", float, 190 DEFINE_BASIC_LRECORD_IMPLEMENTATION ("float", float,
183 mark_float, print_float, 0, float_equal, 191 mark_float, print_float, 0, float_equal,
184 float_hash, struct Lisp_Float); 192 float_hash, float_description,
193 Lisp_Float);
185 194
186 /* Extract a Lisp number as a `double', or signal an error. */ 195 /* Extract a Lisp number as a `double', or signal an error. */
187 196
188 double 197 double
189 extract_float (Lisp_Object num) 198 extract_float (Lisp_Object num)
192 return XFLOAT_DATA (num); 201 return XFLOAT_DATA (num);
193 202
194 if (INTP (num)) 203 if (INTP (num))
195 return (double) XINT (num); 204 return (double) XINT (num);
196 205
197 return extract_float (wrong_type_argument (num, Qnumberp)); 206 return extract_float (wrong_type_argument (Qnumberp, num));
198 } 207 }
199 #endif /* LISP_FLOAT_TYPE */ 208 #endif /* LISP_FLOAT_TYPE */
200 209
201 210
202 /* Trig functions. */ 211 /* Trig functions. */
664 #endif /* LISP_FLOAT_TYPE */ 673 #endif /* LISP_FLOAT_TYPE */
665 674
666 if (INTP (arg)) 675 if (INTP (arg))
667 return (XINT (arg) >= 0) ? arg : make_int (- XINT (arg)); 676 return (XINT (arg) >= 0) ? arg : make_int (- XINT (arg));
668 677
669 return Fabs (wrong_type_argument (arg, Qnumberp)); 678 return Fabs (wrong_type_argument (Qnumberp, arg));
670 } 679 }
671 680
672 #ifdef LISP_FLOAT_TYPE 681 #ifdef LISP_FLOAT_TYPE
673 DEFUN ("float", Ffloat, 1, 1, 0, /* 682 DEFUN ("float", Ffloat, 1, 1, 0, /*
674 Return the floating point number equal to ARG. 683 Return the floating point number numerically equal to ARG.
675 */ 684 */
676 (arg)) 685 (arg))
677 { 686 {
678 if (INTP (arg)) 687 if (INTP (arg))
679 return make_float ((double) XINT (arg)); 688 return make_float ((double) XINT (arg));
680 689
681 if (FLOATP (arg)) /* give 'em the same float back */ 690 if (FLOATP (arg)) /* give 'em the same float back */
682 return arg; 691 return arg;
683 692
684 return Ffloat (wrong_type_argument (arg, Qnumberp)); 693 return Ffloat (wrong_type_argument (Qnumberp, arg));
685 } 694 }
686 #endif /* LISP_FLOAT_TYPE */ 695 #endif /* LISP_FLOAT_TYPE */
687 696
688 697
689 #ifdef LISP_FLOAT_TYPE 698 #ifdef LISP_FLOAT_TYPE
694 (arg)) 703 (arg))
695 { 704 {
696 double f = extract_float (arg); 705 double f = extract_float (arg);
697 706
698 if (f == 0.0) 707 if (f == 0.0)
699 return make_int (- (int)((((EMACS_UINT) 1) << (VALBITS - 1)))); /* most-negative-fixnum */ 708 return make_int (- (EMACS_INT)(((EMACS_UINT) 1) << (VALBITS - 1))); /* most-negative-fixnum */
700 #ifdef HAVE_LOGB 709 #ifdef HAVE_LOGB
701 { 710 {
702 Lisp_Object val; 711 Lisp_Object val;
703 IN_FLOAT (val = make_int ((int) logb (f)), "logb", arg); 712 IN_FLOAT (val = make_int ((EMACS_INT) logb (f)), "logb", arg);
704 return (val); 713 return val;
705 } 714 }
706 #else 715 #else
707 #ifdef HAVE_FREXP 716 #ifdef HAVE_FREXP
708 { 717 {
709 int exqp; 718 int exqp;
710 IN_FLOAT (frexp (f, &exqp), "logb", arg); 719 IN_FLOAT (frexp (f, &exqp), "logb", arg);
711 return (make_int (exqp - 1)); 720 return make_int (exqp - 1);
712 } 721 }
713 #else 722 #else
714 { 723 {
715 int i; 724 int i;
716 double d; 725 double d;
730 for (i = 1, d = 2.0; d * d <= f; i += i) 739 for (i = 1, d = 2.0; d * d <= f; i += i)
731 d *= d; 740 d *= d;
732 f /= d; 741 f /= d;
733 val += i; 742 val += i;
734 } 743 }
735 return (make_int (val)); 744 return make_int (val);
736 } 745 }
737 #endif /* ! HAVE_FREXP */ 746 #endif /* ! HAVE_FREXP */
738 #endif /* ! HAVE_LOGB */ 747 #endif /* ! HAVE_LOGB */
739 } 748 }
740 #endif /* LISP_FLOAT_TYPE */ 749 #endif /* LISP_FLOAT_TYPE */
755 #endif /* LISP_FLOAT_TYPE */ 764 #endif /* LISP_FLOAT_TYPE */
756 765
757 if (INTP (arg)) 766 if (INTP (arg))
758 return arg; 767 return arg;
759 768
760 return Fceiling (wrong_type_argument (arg, Qnumberp)); 769 return Fceiling (wrong_type_argument (Qnumberp, arg));
761 } 770 }
762 771
763 772
764 DEFUN ("floor", Ffloor, 1, 2, 0, /* 773 DEFUN ("floor", Ffloor, 1, 2, 0, /*
765 Return the largest integer no greater than ARG. (Round towards -inf.) 774 Return the largest integer no greater than ARG. (Round towards -inf.)
824 #ifdef LISP_FLOAT_TYPE 833 #ifdef LISP_FLOAT_TYPE
825 if (FLOATP (arg)) 834 if (FLOATP (arg))
826 { 835 {
827 double d; 836 double d;
828 /* Screw the prevailing rounding mode. */ 837 /* Screw the prevailing rounding mode. */
829 IN_FLOAT ((d = rint (XFLOAT_DATA (arg))), "round", arg); 838 IN_FLOAT ((d = emacs_rint (XFLOAT_DATA (arg))), "round", arg);
830 return (float_to_int (d, "round", arg, Qunbound)); 839 return (float_to_int (d, "round", arg, Qunbound));
831 } 840 }
832 #endif /* LISP_FLOAT_TYPE */ 841 #endif /* LISP_FLOAT_TYPE */
833 842
834 if (INTP (arg)) 843 if (INTP (arg))
835 return arg; 844 return arg;
836 845
837 return Fround (wrong_type_argument (arg, Qnumberp)); 846 return Fround (wrong_type_argument (Qnumberp, arg));
838 } 847 }
839 848
840 DEFUN ("truncate", Ftruncate, 1, 1, 0, /* 849 DEFUN ("truncate", Ftruncate, 1, 1, 0, /*
841 Truncate a floating point number to an integer. 850 Truncate a floating point number to an integer.
842 Rounds the value toward zero. 851 Rounds the value toward zero.
849 #endif /* LISP_FLOAT_TYPE */ 858 #endif /* LISP_FLOAT_TYPE */
850 859
851 if (INTP (arg)) 860 if (INTP (arg))
852 return arg; 861 return arg;
853 862
854 return Ftruncate (wrong_type_argument (arg, Qnumberp)); 863 return Ftruncate (wrong_type_argument (Qnumberp, arg));
855 } 864 }
856 865
857 /* Float-rounding functions. */ 866 /* Float-rounding functions. */
858 #ifdef LISP_FLOAT_TYPE 867 #ifdef LISP_FLOAT_TYPE
859 /* #if 1 It's not clear these are worth adding... */ 868 /* #if 1 It's not clear these are worth adding... */
884 Return the nearest integer to ARG, as a float. 893 Return the nearest integer to ARG, as a float.
885 */ 894 */
886 (arg)) 895 (arg))
887 { 896 {
888 double d = extract_float (arg); 897 double d = extract_float (arg);
889 IN_FLOAT (d = rint (d), "fround", arg); 898 IN_FLOAT (d = emacs_rint (d), "fround", arg);
890 return make_float (d); 899 return make_float (d);
891 } 900 }
892 901
893 DEFUN ("ftruncate", Fftruncate, 1, 1, 0, /* 902 DEFUN ("ftruncate", Fftruncate, 1, 1, 0, /*
894 Truncate a floating point number to an integral float value. 903 Truncate a floating point number to an integral float value.