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... */