Mercurial > hg > xemacs-beta
comparison src/floatfns.c @ 380:8626e4521993 r21-2-5
Import from CVS: tag r21-2-5
author | cvs |
---|---|
date | Mon, 13 Aug 2007 11:07:10 +0200 |
parents | e11d67e05968 |
children | 74fd4e045ea6 |
comparison
equal
deleted
inserted
replaced
379:76b7d63099ad | 380:8626e4521993 |
---|---|
160 | 160 |
161 | 161 |
162 static Lisp_Object | 162 static Lisp_Object |
163 mark_float (Lisp_Object obj, void (*markobj) (Lisp_Object)) | 163 mark_float (Lisp_Object obj, void (*markobj) (Lisp_Object)) |
164 { | 164 { |
165 return (Qnil); | 165 return Qnil; |
166 } | 166 } |
167 | 167 |
168 static int | 168 static int |
169 float_equal (Lisp_Object o1, Lisp_Object o2, int depth) | 169 float_equal (Lisp_Object obj1, Lisp_Object obj2, int depth) |
170 { | 170 { |
171 return (extract_float (o1) == extract_float (o2)); | 171 return (extract_float (obj1) == extract_float (obj2)); |
172 } | 172 } |
173 | 173 |
174 static unsigned long | 174 static unsigned long |
175 float_hash (Lisp_Object obj, int depth) | 175 float_hash (Lisp_Object obj, int depth) |
176 { | 176 { |
186 /* Extract a Lisp number as a `double', or signal an error. */ | 186 /* Extract a Lisp number as a `double', or signal an error. */ |
187 | 187 |
188 double | 188 double |
189 extract_float (Lisp_Object num) | 189 extract_float (Lisp_Object num) |
190 { | 190 { |
191 CHECK_INT_OR_FLOAT (num); | |
192 | |
193 if (FLOATP (num)) | 191 if (FLOATP (num)) |
194 return (float_data (XFLOAT (num))); | 192 return XFLOAT_DATA (num); |
195 return (double) XINT (num); | 193 |
194 if (INTP (num)) | |
195 return (double) XINT (num); | |
196 | |
197 return extract_float (wrong_type_argument (num, Qnumberp)); | |
196 } | 198 } |
197 #endif /* LISP_FLOAT_TYPE */ | 199 #endif /* LISP_FLOAT_TYPE */ |
198 | 200 |
199 | 201 |
200 /* Trig functions. */ | 202 /* Trig functions. */ |
420 DEFUN ("expt", Fexpt, 2, 2, 0, /* | 422 DEFUN ("expt", Fexpt, 2, 2, 0, /* |
421 Return the exponential ARG1 ** ARG2. | 423 Return the exponential ARG1 ** ARG2. |
422 */ | 424 */ |
423 (arg1, arg2)) | 425 (arg1, arg2)) |
424 { | 426 { |
425 double f1, f2; | 427 if (INTP (arg1) && /* common lisp spec */ |
426 | 428 INTP (arg2)) /* don't promote, if both are ints */ |
427 CHECK_INT_OR_FLOAT (arg1); | |
428 CHECK_INT_OR_FLOAT (arg2); | |
429 if ((INTP (arg1)) && /* common lisp spec */ | |
430 (INTP (arg2))) /* don't promote, if both are ints */ | |
431 { | 429 { |
432 EMACS_INT acc, x, y; | 430 EMACS_INT retval; |
433 x = XINT (arg1); | 431 EMACS_INT x = XINT (arg1); |
434 y = XINT (arg2); | 432 EMACS_INT y = XINT (arg2); |
435 | 433 |
436 if (y < 0) | 434 if (y < 0) |
437 { | 435 { |
438 if (x == 1) | 436 if (x == 1) |
439 acc = 1; | 437 retval = 1; |
440 else if (x == -1) | 438 else if (x == -1) |
441 acc = (y & 1) ? -1 : 1; | 439 retval = (y & 1) ? -1 : 1; |
442 else | 440 else |
443 acc = 0; | 441 retval = 0; |
444 } | 442 } |
445 else | 443 else |
446 { | 444 { |
447 acc = 1; | 445 retval = 1; |
448 while (y > 0) | 446 while (y > 0) |
449 { | 447 { |
450 if (y & 1) | 448 if (y & 1) |
451 acc *= x; | 449 retval *= x; |
452 x *= x; | 450 x *= x; |
453 y = (EMACS_UINT) y >> 1; | 451 y = (EMACS_UINT) y >> 1; |
454 } | 452 } |
455 } | 453 } |
456 return (make_int (acc)); | 454 return make_int (retval); |
457 } | 455 } |
458 #ifdef LISP_FLOAT_TYPE | 456 |
459 f1 = (FLOATP (arg1)) ? float_data (XFLOAT (arg1)) : XINT (arg1); | 457 #ifdef LISP_FLOAT_TYPE |
460 f2 = (FLOATP (arg2)) ? float_data (XFLOAT (arg2)) : XINT (arg2); | 458 { |
461 /* Really should check for overflow, too */ | 459 double f1 = extract_float (arg1); |
462 if (f1 == 0.0 && f2 == 0.0) | 460 double f2 = extract_float (arg2); |
463 f1 = 1.0; | 461 /* Really should check for overflow, too */ |
462 if (f1 == 0.0 && f2 == 0.0) | |
463 f1 = 1.0; | |
464 # ifdef FLOAT_CHECK_DOMAIN | 464 # ifdef FLOAT_CHECK_DOMAIN |
465 else if ((f1 == 0.0 && f2 < 0.0) || (f1 < 0 && f2 != floor(f2))) | 465 else if ((f1 == 0.0 && f2 < 0.0) || (f1 < 0 && f2 != floor(f2))) |
466 domain_error2 ("expt", arg1, arg2); | 466 domain_error2 ("expt", arg1, arg2); |
467 # endif /* FLOAT_CHECK_DOMAIN */ | 467 # endif /* FLOAT_CHECK_DOMAIN */ |
468 IN_FLOAT2 (f1 = pow (f1, f2), "expt", arg1, arg2); | 468 IN_FLOAT2 (f1 = pow (f1, f2), "expt", arg1, arg2); |
469 return make_float (f1); | 469 return make_float (f1); |
470 #else /* !LISP_FLOAT_TYPE */ | 470 } |
471 abort (); | 471 #else |
472 CHECK_INT_OR_FLOAT (arg1); | |
473 CHECK_INT_OR_FLOAT (arg2); | |
474 return Fexpt (arg1, arg2); | |
472 #endif /* LISP_FLOAT_TYPE */ | 475 #endif /* LISP_FLOAT_TYPE */ |
473 } | 476 } |
474 | 477 |
475 #ifdef LISP_FLOAT_TYPE | 478 #ifdef LISP_FLOAT_TYPE |
476 DEFUN ("log", Flog, 1, 2, 0, /* | 479 DEFUN ("log", Flog, 1, 2, 0, /* |
649 DEFUN ("abs", Fabs, 1, 1, 0, /* | 652 DEFUN ("abs", Fabs, 1, 1, 0, /* |
650 Return the absolute value of ARG. | 653 Return the absolute value of ARG. |
651 */ | 654 */ |
652 (arg)) | 655 (arg)) |
653 { | 656 { |
654 CHECK_INT_OR_FLOAT (arg); | |
655 | |
656 #ifdef LISP_FLOAT_TYPE | 657 #ifdef LISP_FLOAT_TYPE |
657 if (FLOATP (arg)) | 658 if (FLOATP (arg)) |
658 { | 659 { |
659 IN_FLOAT (arg = make_float ((double) fabs (float_data (XFLOAT (arg)))), | 660 IN_FLOAT (arg = make_float (fabs (XFLOAT_DATA (arg))), |
660 "abs", arg); | 661 "abs", arg); |
661 return (arg); | 662 return arg; |
662 } | 663 } |
663 else | 664 #endif /* LISP_FLOAT_TYPE */ |
664 #endif /* LISP_FLOAT_TYPE */ | 665 |
665 if (XINT (arg) < 0) | 666 if (INTP (arg)) |
666 return (make_int (- XINT (arg))); | 667 return (XINT (arg) >= 0) ? arg : make_int (- XINT (arg)); |
667 else | 668 |
668 return (arg); | 669 return Fabs (wrong_type_argument (arg, Qnumberp)); |
669 } | 670 } |
670 | 671 |
671 #ifdef LISP_FLOAT_TYPE | 672 #ifdef LISP_FLOAT_TYPE |
672 DEFUN ("float", Ffloat, 1, 1, 0, /* | 673 DEFUN ("float", Ffloat, 1, 1, 0, /* |
673 Return the floating point number equal to ARG. | 674 Return the floating point number equal to ARG. |
674 */ | 675 */ |
675 (arg)) | 676 (arg)) |
676 { | 677 { |
677 CHECK_INT_OR_FLOAT (arg); | |
678 | |
679 if (INTP (arg)) | 678 if (INTP (arg)) |
680 return make_float ((double) XINT (arg)); | 679 return make_float ((double) XINT (arg)); |
681 else /* give 'em the same float back */ | 680 |
681 if (FLOATP (arg)) /* give 'em the same float back */ | |
682 return arg; | 682 return arg; |
683 | |
684 return Ffloat (wrong_type_argument (arg, Qnumberp)); | |
683 } | 685 } |
684 #endif /* LISP_FLOAT_TYPE */ | 686 #endif /* LISP_FLOAT_TYPE */ |
685 | 687 |
686 | 688 |
687 #ifdef LISP_FLOAT_TYPE | 689 #ifdef LISP_FLOAT_TYPE |
741 DEFUN ("ceiling", Fceiling, 1, 1, 0, /* | 743 DEFUN ("ceiling", Fceiling, 1, 1, 0, /* |
742 Return the smallest integer no less than ARG. (Round toward +inf.) | 744 Return the smallest integer no less than ARG. (Round toward +inf.) |
743 */ | 745 */ |
744 (arg)) | 746 (arg)) |
745 { | 747 { |
746 CHECK_INT_OR_FLOAT (arg); | |
747 | |
748 #ifdef LISP_FLOAT_TYPE | 748 #ifdef LISP_FLOAT_TYPE |
749 if (FLOATP (arg)) | 749 if (FLOATP (arg)) |
750 { | 750 { |
751 double d; | 751 double d; |
752 IN_FLOAT ((d = ceil (float_data (XFLOAT (arg)))), "ceiling", arg); | 752 IN_FLOAT ((d = ceil (XFLOAT_DATA (arg))), "ceiling", arg); |
753 return (float_to_int (d, "ceiling", arg, Qunbound)); | 753 return (float_to_int (d, "ceiling", arg, Qunbound)); |
754 } | 754 } |
755 #endif /* LISP_FLOAT_TYPE */ | 755 #endif /* LISP_FLOAT_TYPE */ |
756 | 756 |
757 return arg; | 757 if (INTP (arg)) |
758 return arg; | |
759 | |
760 return Fceiling (wrong_type_argument (arg, Qnumberp)); | |
758 } | 761 } |
759 | 762 |
760 | 763 |
761 DEFUN ("floor", Ffloor, 1, 2, 0, /* | 764 DEFUN ("floor", Ffloor, 1, 2, 0, /* |
762 Return the largest integer no greater than ARG. (Round towards -inf.) | 765 Return the largest integer no greater than ARG. (Round towards -inf.) |
773 CHECK_INT_OR_FLOAT (divisor); | 776 CHECK_INT_OR_FLOAT (divisor); |
774 | 777 |
775 #ifdef LISP_FLOAT_TYPE | 778 #ifdef LISP_FLOAT_TYPE |
776 if (FLOATP (arg) || FLOATP (divisor)) | 779 if (FLOATP (arg) || FLOATP (divisor)) |
777 { | 780 { |
778 double f1, f2; | 781 double f1 = extract_float (arg); |
779 | 782 double f2 = extract_float (divisor); |
780 f1 = ((FLOATP (arg)) ? float_data (XFLOAT (arg)) : XINT (arg)); | 783 |
781 f2 = ((FLOATP (divisor)) ? float_data (XFLOAT (divisor)) : XINT (divisor)); | |
782 if (f2 == 0) | 784 if (f2 == 0) |
783 Fsignal (Qarith_error, Qnil); | 785 Fsignal (Qarith_error, Qnil); |
784 | 786 |
785 IN_FLOAT2 (f1 = floor (f1 / f2), "floor", arg, divisor); | 787 IN_FLOAT2 (f1 = floor (f1 / f2), "floor", arg, divisor); |
786 return float_to_int (f1, "floor", arg, divisor); | 788 return float_to_int (f1, "floor", arg, divisor); |
802 return (make_int (i1)); | 804 return (make_int (i1)); |
803 } | 805 } |
804 | 806 |
805 #ifdef LISP_FLOAT_TYPE | 807 #ifdef LISP_FLOAT_TYPE |
806 if (FLOATP (arg)) | 808 if (FLOATP (arg)) |
807 { | 809 { |
808 double d; | 810 double d; |
809 IN_FLOAT ((d = floor (float_data (XFLOAT (arg)))), "floor", arg); | 811 IN_FLOAT ((d = floor (XFLOAT_DATA (arg))), "floor", arg); |
810 return (float_to_int (d, "floor", arg, Qunbound)); | 812 return (float_to_int (d, "floor", arg, Qunbound)); |
811 } | 813 } |
812 #endif /* LISP_FLOAT_TYPE */ | 814 #endif /* LISP_FLOAT_TYPE */ |
813 | 815 |
814 return arg; | 816 return arg; |
815 } | 817 } |
816 | 818 |
817 DEFUN ("round", Fround, 1, 1, 0, /* | 819 DEFUN ("round", Fround, 1, 1, 0, /* |
818 Return the nearest integer to ARG. | 820 Return the nearest integer to ARG. |
819 */ | 821 */ |
820 (arg)) | 822 (arg)) |
821 { | 823 { |
822 CHECK_INT_OR_FLOAT (arg); | |
823 | |
824 #ifdef LISP_FLOAT_TYPE | 824 #ifdef LISP_FLOAT_TYPE |
825 if (FLOATP (arg)) | 825 if (FLOATP (arg)) |
826 { | 826 { |
827 double d; | 827 double d; |
828 /* Screw the prevailing rounding mode. */ | 828 /* Screw the prevailing rounding mode. */ |
829 IN_FLOAT ((d = rint (float_data (XFLOAT (arg)))), "round", arg); | 829 IN_FLOAT ((d = rint (XFLOAT_DATA (arg))), "round", arg); |
830 return (float_to_int (d, "round", arg, Qunbound)); | 830 return (float_to_int (d, "round", arg, Qunbound)); |
831 } | 831 } |
832 #endif /* LISP_FLOAT_TYPE */ | 832 #endif /* LISP_FLOAT_TYPE */ |
833 | 833 |
834 return arg; | 834 if (INTP (arg)) |
835 return arg; | |
836 | |
837 return Fround (wrong_type_argument (arg, Qnumberp)); | |
835 } | 838 } |
836 | 839 |
837 DEFUN ("truncate", Ftruncate, 1, 1, 0, /* | 840 DEFUN ("truncate", Ftruncate, 1, 1, 0, /* |
838 Truncate a floating point number to an integer. | 841 Truncate a floating point number to an integer. |
839 Rounds the value toward zero. | 842 Rounds the value toward zero. |
840 */ | 843 */ |
841 (arg)) | 844 (arg)) |
842 { | 845 { |
843 CHECK_INT_OR_FLOAT (arg); | |
844 | |
845 #ifdef LISP_FLOAT_TYPE | 846 #ifdef LISP_FLOAT_TYPE |
846 if (FLOATP (arg)) | 847 if (FLOATP (arg)) |
847 return (float_to_int (float_data (XFLOAT (arg)), | 848 return float_to_int (XFLOAT_DATA (arg), "truncate", arg, Qunbound); |
848 "truncate", arg, Qunbound)); | 849 #endif /* LISP_FLOAT_TYPE */ |
849 #endif /* LISP_FLOAT_TYPE */ | 850 |
850 | 851 if (INTP (arg)) |
851 return arg; | 852 return arg; |
853 | |
854 return Ftruncate (wrong_type_argument (arg, Qnumberp)); | |
852 } | 855 } |
853 | 856 |
854 /* Float-rounding functions. */ | 857 /* Float-rounding functions. */ |
855 #ifdef LISP_FLOAT_TYPE | 858 #ifdef LISP_FLOAT_TYPE |
856 /* #if 1 It's not clear these are worth adding... */ | 859 /* #if 1 It's not clear these are worth adding... */ |