Mercurial > hg > xemacs-beta
comparison src/floatfns.c @ 1983:9c872f33ecbe
[xemacs-hg @ 2004-04-05 22:49:31 by james]
Add bignum, ratio, and bigfloat support.
author | james |
---|---|
date | Mon, 05 Apr 2004 22:50:11 +0000 |
parents | e22b0213b713 |
children | 4e6a63799f08 |
comparison
equal
deleted
inserted
replaced
1982:a748951fd4fb | 1983:9c872f33ecbe |
---|---|
117 #define domain_error2(op,a1,a2) \ | 117 #define domain_error2(op,a1,a2) \ |
118 Fsignal (Qdomain_error, list3 (build_msg_string (op), a1, a2)) | 118 Fsignal (Qdomain_error, list3 (build_msg_string (op), a1, a2)) |
119 | 119 |
120 | 120 |
121 /* Convert float to Lisp Integer if it fits, else signal a range | 121 /* Convert float to Lisp Integer if it fits, else signal a range |
122 error using the given arguments. */ | 122 error using the given arguments. If bignums are available, range errors |
123 are never signaled. */ | |
123 static Lisp_Object | 124 static Lisp_Object |
124 float_to_int (double x, const char *name, Lisp_Object num, Lisp_Object num2) | 125 float_to_int (double x, const char *name, Lisp_Object num, Lisp_Object num2) |
125 { | 126 { |
127 #ifdef HAVE_BIGNUM | |
128 bignum_set_double (scratch_bignum, x); | |
129 return Fcanonicalize_number (make_bignum_bg (scratch_bignum)); | |
130 #else | |
126 if (x >= ((EMACS_INT) 1 << (VALBITS-1)) | 131 if (x >= ((EMACS_INT) 1 << (VALBITS-1)) |
127 || x <= - ((EMACS_INT) 1 << (VALBITS-1)) - (EMACS_INT) 1) | 132 || x <= - ((EMACS_INT) 1 << (VALBITS-1)) - (EMACS_INT) 1) |
128 { | 133 { |
129 if (!UNBOUNDP (num2)) | 134 if (!UNBOUNDP (num2)) |
130 range_error2 (name, num, num2); | 135 range_error2 (name, num, num2); |
131 else | 136 else |
132 range_error (name, num); | 137 range_error (name, num); |
133 } | 138 } |
134 return (make_int ((EMACS_INT) x)); | 139 return (make_int ((EMACS_INT) x)); |
140 #endif /* HAVE_BIGNUM */ | |
135 } | 141 } |
136 | 142 |
137 | 143 |
138 static void | 144 static void |
139 in_float_error (void) | 145 in_float_error (void) |
197 return XFLOAT_DATA (num); | 203 return XFLOAT_DATA (num); |
198 | 204 |
199 if (INTP (num)) | 205 if (INTP (num)) |
200 return (double) XINT (num); | 206 return (double) XINT (num); |
201 | 207 |
208 #ifdef HAVE_BIGNUM | |
209 if (BIGNUMP (num)) | |
210 return bignum_to_double (XBIGNUM_DATA (num)); | |
211 #endif | |
212 | |
213 #ifdef HAVE_RATIO | |
214 if (RATIOP (num)) | |
215 return ratio_to_double (XRATIO_DATA (num)); | |
216 #endif | |
217 | |
218 #ifdef HAVE_BIGFLOAT | |
219 if (BIGFLOATP (num)) | |
220 return bigfloat_to_double (XBIGFLOAT_DATA (num)); | |
221 #endif | |
222 | |
202 return extract_float (wrong_type_argument (Qnumberp, num)); | 223 return extract_float (wrong_type_argument (Qnumberp, num)); |
203 } | 224 } |
204 | 225 |
205 /* Trig functions. */ | 226 /* Trig functions. */ |
206 | 227 |
419 DEFUN ("expt", Fexpt, 2, 2, 0, /* | 440 DEFUN ("expt", Fexpt, 2, 2, 0, /* |
420 Return the exponential NUMBER1 ** NUMBER2. | 441 Return the exponential NUMBER1 ** NUMBER2. |
421 */ | 442 */ |
422 (number1, number2)) | 443 (number1, number2)) |
423 { | 444 { |
445 #ifdef HAVE_BIGNUM | |
446 if (INTEGERP (number1) && INTP (number2)) | |
447 { | |
448 if (INTP (number1)) | |
449 { | |
450 bignum_set_long (scratch_bignum2, XREALINT (number1)); | |
451 bignum_pow (scratch_bignum, scratch_bignum2, XREALINT (number2)); | |
452 } | |
453 else | |
454 bignum_pow (scratch_bignum, XBIGNUM_DATA (number1), | |
455 XREALINT (number2)); | |
456 return Fcanonicalize_number (make_bignum_bg (scratch_bignum)); | |
457 } | |
458 #endif | |
459 | |
424 if (INTP (number1) && /* common lisp spec */ | 460 if (INTP (number1) && /* common lisp spec */ |
425 INTP (number2)) /* don't promote, if both are ints */ | 461 INTP (number2)) /* don't promote, if both are ints */ |
426 { | 462 { |
427 EMACS_INT retval; | 463 EMACS_INT retval; |
428 EMACS_INT x = XINT (number1); | 464 EMACS_INT x = XINT (number1); |
449 } | 485 } |
450 } | 486 } |
451 return make_int (retval); | 487 return make_int (retval); |
452 } | 488 } |
453 | 489 |
490 #if defined(HAVE_BIGFLOAT) && defined(bigfloat_pow) | |
491 if (BIGFLOATP (number1) && INTEGERP (number2)) | |
492 { | |
493 unsigned long exp; | |
494 | |
495 #ifdef HAVE_BIGNUM | |
496 if (BIGNUMP (number2)) | |
497 exp = bignum_to_ulong (XBIGNUM_DATA (number2)); | |
498 else | |
499 #endif | |
500 exp = XUINT (number2); | |
501 bigfloat_set_prec (scratch_bigfloat, XBIGFLOAT_GET_PREC (number1)); | |
502 bigfloat_pow (scratch_bigfloat, XBIGFLOAT_DATA (number1), exp); | |
503 return make_bigfloat_bf (scratch_bigfloat); | |
504 } | |
505 #endif | |
506 | |
454 { | 507 { |
455 double f1 = extract_float (number1); | 508 double f1 = extract_float (number1); |
456 double f2 = extract_float (number2); | 509 double f2 = extract_float (number2); |
457 /* Really should check for overflow, too */ | 510 /* Really should check for overflow, too */ |
458 if (f1 == 0.0 && f2 == 0.0) | 511 if (f1 == 0.0 && f2 == 0.0) |
514 DEFUN ("sqrt", Fsqrt, 1, 1, 0, /* | 567 DEFUN ("sqrt", Fsqrt, 1, 1, 0, /* |
515 Return the square root of NUMBER. | 568 Return the square root of NUMBER. |
516 */ | 569 */ |
517 (number)) | 570 (number)) |
518 { | 571 { |
519 double d = extract_float (number); | 572 double d; |
573 | |
574 #if defined(HAVE_BIGFLOAT) && defined(bigfloat_sqrt) | |
575 if (BIGFLOATP (number)) | |
576 { | |
577 bigfloat_set_prec (scratch_bigfloat, XBIGFLOAT_GET_PREC (number)); | |
578 bigfloat_sqrt (scratch_bigfloat, XBIGFLOAT_DATA (number)); | |
579 return make_bigfloat_bf (scratch_bigfloat); | |
580 } | |
581 #endif /* HAVE_BIGFLOAT */ | |
582 d = extract_float (number); | |
520 #ifdef FLOAT_CHECK_DOMAIN | 583 #ifdef FLOAT_CHECK_DOMAIN |
521 if (d < 0.0) | 584 if (d < 0.0) |
522 domain_error ("sqrt", number); | 585 domain_error ("sqrt", number); |
523 #endif | 586 #endif |
524 IN_FLOAT (d = sqrt (d), "sqrt", number); | 587 IN_FLOAT (d = sqrt (d), "sqrt", number); |
646 "abs", number); | 709 "abs", number); |
647 return number; | 710 return number; |
648 } | 711 } |
649 | 712 |
650 if (INTP (number)) | 713 if (INTP (number)) |
714 #ifdef HAVE_BIGNUM | |
715 /* The most negative Lisp fixnum will overflow */ | |
716 return (XINT (number) >= 0) ? number : make_integer (- XINT (number)); | |
717 #else | |
651 return (XINT (number) >= 0) ? number : make_int (- XINT (number)); | 718 return (XINT (number) >= 0) ? number : make_int (- XINT (number)); |
719 #endif | |
720 | |
721 #ifdef HAVE_BIGNUM | |
722 if (BIGNUMP (number)) | |
723 { | |
724 if (bignum_sign (XBIGNUM_DATA (number)) >= 0) | |
725 return number; | |
726 bignum_abs (scratch_bignum, XBIGNUM_DATA (number)); | |
727 return make_bignum_bg (scratch_bignum); | |
728 } | |
729 #endif | |
730 | |
731 #ifdef HAVE_RATIO | |
732 if (RATIOP (number)) | |
733 { | |
734 if (ratio_sign (XRATIO_DATA (number)) >= 0) | |
735 return number; | |
736 ratio_abs (scratch_ratio, XRATIO_DATA (number)); | |
737 return make_ratio_rt (scratch_ratio); | |
738 } | |
739 #endif | |
740 | |
741 #ifdef HAVE_BIGFLOAT | |
742 if (BIGFLOATP (number)) | |
743 { | |
744 if (bigfloat_sign (XBIGFLOAT_DATA (number)) >= 0) | |
745 return number; | |
746 bigfloat_set_prec (scratch_bigfloat, XBIGFLOAT_GET_PREC (number)); | |
747 bigfloat_abs (scratch_bigfloat, XBIGFLOAT_DATA (number)); | |
748 return make_bigfloat_bf (scratch_bigfloat); | |
749 } | |
750 #endif | |
652 | 751 |
653 return Fabs (wrong_type_argument (Qnumberp, number)); | 752 return Fabs (wrong_type_argument (Qnumberp, number)); |
654 } | 753 } |
655 | 754 |
656 DEFUN ("float", Ffloat, 1, 1, 0, /* | 755 DEFUN ("float", Ffloat, 1, 1, 0, /* |
658 */ | 757 */ |
659 (number)) | 758 (number)) |
660 { | 759 { |
661 if (INTP (number)) | 760 if (INTP (number)) |
662 return make_float ((double) XINT (number)); | 761 return make_float ((double) XINT (number)); |
762 | |
763 #ifdef HAVE_BIGNUM | |
764 if (BIGFLOATP (number)) | |
765 { | |
766 #ifdef HAVE_BIGFLOAT | |
767 if (ZEROP (Vdefault_float_precision)) | |
768 #endif | |
769 return make_float (bignum_to_double (XBIGNUM_DATA (number))); | |
770 #ifdef HAVE_BIGFLOAT | |
771 else | |
772 { | |
773 bigfloat_set_prec (scratch_bigfloat, bigfloat_get_default_prec ()); | |
774 bigfloat_set_bignum (scratch_bigfloat, XBIGNUM_DATA (number)); | |
775 return make_bigfloat_bf (scratch_bigfloat); | |
776 } | |
777 #endif /* HAVE_BIGFLOAT */ | |
778 } | |
779 #endif /* HAVE_BIGNUM */ | |
780 | |
781 #ifdef HAVE_RATIO | |
782 if (RATIOP (number)) | |
783 make_float (ratio_to_double (XRATIO_DATA (number))); | |
784 #endif | |
663 | 785 |
664 if (FLOATP (number)) /* give 'em the same float back */ | 786 if (FLOATP (number)) /* give 'em the same float back */ |
665 return number; | 787 return number; |
666 | 788 |
667 return Ffloat (wrong_type_argument (Qnumberp, number)); | 789 return Ffloat (wrong_type_argument (Qnumberp, number)); |
728 double d; | 850 double d; |
729 IN_FLOAT ((d = ceil (XFLOAT_DATA (number))), "ceiling", number); | 851 IN_FLOAT ((d = ceil (XFLOAT_DATA (number))), "ceiling", number); |
730 return (float_to_int (d, "ceiling", number, Qunbound)); | 852 return (float_to_int (d, "ceiling", number, Qunbound)); |
731 } | 853 } |
732 | 854 |
855 #ifdef HAVE_BIGNUM | |
856 if (INTEGERP (number)) | |
857 #else | |
733 if (INTP (number)) | 858 if (INTP (number)) |
859 #endif | |
734 return number; | 860 return number; |
861 | |
862 #ifdef HAVE_RATIO | |
863 if (RATIOP (number)) | |
864 { | |
865 bignum_ceil (scratch_bignum, XRATIO_NUMERATOR (number), | |
866 XRATIO_DENOMINATOR (number)); | |
867 return Fcanonicalize_number (make_bignum_bg (scratch_bignum)); | |
868 } | |
869 #endif | |
870 | |
871 #ifdef HAVE_BIGFLOAT | |
872 if (BIGFLOATP (number)) | |
873 { | |
874 bigfloat_set_prec (scratch_bigfloat, XBIGFLOAT_GET_PREC (number)); | |
875 bigfloat_ceil (scratch_bigfloat, XBIGFLOAT_DATA (number)); | |
876 #ifdef HAVE_BIGNUM | |
877 bignum_set_bigfloat (scratch_bignum, scratch_bigfloat); | |
878 return Fcanonicalize_number (make_bignum_bg (scratch_bignum)); | |
879 #else | |
880 return make_int ((EMACS_INT) bigfloat_to_long (scratch_bigfloat)); | |
881 #endif /* HAVE_BIGNUM */ | |
882 } | |
883 #endif /* HAVE_BIGFLOAT */ | |
735 | 884 |
736 return Fceiling (wrong_type_argument (Qnumberp, number)); | 885 return Fceiling (wrong_type_argument (Qnumberp, number)); |
737 } | 886 } |
738 | 887 |
739 | 888 |
742 With optional second argument DIVISOR, return the largest integer no | 891 With optional second argument DIVISOR, return the largest integer no |
743 greater than NUMBER/DIVISOR. | 892 greater than NUMBER/DIVISOR. |
744 */ | 893 */ |
745 (number, divisor)) | 894 (number, divisor)) |
746 { | 895 { |
896 #ifdef WITH_NUMBER_TYPES | |
897 CHECK_REAL (number); | |
898 if (NILP (divisor)) | |
899 { | |
900 if (FLOATP (number)) | |
901 { | |
902 double d; | |
903 IN_FLOAT ((d = floor (XFLOAT_DATA (number))), "floor", number); | |
904 return (float_to_int (d, "floor", number, Qunbound)); | |
905 } | |
906 #ifdef HAVE_RATIO | |
907 else if (RATIOP (number)) | |
908 { | |
909 bignum_floor (scratch_bignum, XRATIO_NUMERATOR (number), | |
910 XRATIO_DENOMINATOR (number)); | |
911 return Fcanonicalize_number (make_bignum_bg (scratch_bignum)); | |
912 } | |
913 #endif | |
914 #ifdef HAVE_BIGFLOAT | |
915 else if (BIGFLOATP (number)) | |
916 { | |
917 bigfloat_set_prec (scratch_bigfloat, XBIGFLOAT_GET_PREC (number)); | |
918 bigfloat_floor (scratch_bigfloat, XBIGFLOAT_DATA (number)); | |
919 return make_bigfloat_bf (scratch_bigfloat); | |
920 } | |
921 #endif | |
922 return number; | |
923 } | |
924 else | |
925 { | |
926 CHECK_REAL (divisor); | |
927 switch (promote_args (&number, &divisor)) | |
928 { | |
929 case FIXNUM_T: | |
930 { | |
931 EMACS_INT i1 = XREALINT (number); | |
932 EMACS_INT i2 = XREALINT (divisor); | |
933 | |
934 if (i2 == 0) | |
935 Fsignal (Qarith_error, Qnil); | |
936 | |
937 /* With C's /, the result is implementation-defined if either | |
938 operand is negative, so use only nonnegative operands. */ | |
939 i1 = (i2 < 0 | |
940 ? (i1 <= 0 ? -i1 / -i2 : -1 - ((i1 - 1) / -i2)) | |
941 : (i1 < 0 ? -1 - ((-1 - i1) / i2) : i1 / i2)); | |
942 | |
943 return make_int (i1); | |
944 } | |
945 #ifdef HAVE_BIGNUM | |
946 case BIGNUM_T: | |
947 if (bignum_sign (XBIGNUM_DATA (divisor)) == 0) | |
948 Fsignal (Qarith_error, Qnil); | |
949 bignum_floor (scratch_bignum, XBIGNUM_DATA (number), | |
950 XBIGNUM_DATA (divisor)); | |
951 return Fcanonicalize_number (make_bignum_bg (scratch_bignum)); | |
952 #endif | |
953 case FLOAT_T: | |
954 { | |
955 double f1 = extract_float (number); | |
956 double f2 = extract_float (divisor); | |
957 | |
958 if (f2 == 0.0) | |
959 Fsignal (Qarith_error, Qnil); | |
960 | |
961 IN_FLOAT2 (f1 = floor (f1 / f2), "floor", number, divisor); | |
962 return float_to_int (f1, "floor", number, divisor); | |
963 } | |
964 #ifdef HAVE_RATIO | |
965 case RATIO_T: | |
966 if (ratio_sign (XRATIO_DATA (divisor)) == 0) | |
967 Fsignal (Qarith_error, Qnil); | |
968 ratio_div (scratch_ratio, XRATIO_DATA (number), | |
969 XRATIO_DATA (divisor)); | |
970 bignum_floor (scratch_bignum, ratio_numerator (scratch_ratio), | |
971 ratio_denominator (scratch_ratio)); | |
972 return Fcanonicalize_number (make_bignum_bg (scratch_bignum)); | |
973 #endif | |
974 #ifdef HAVE_BIGFLOAT | |
975 case BIGFLOAT_T: | |
976 if (bigfloat_sign (XBIGFLOAT_DATA (divisor)) == 0) | |
977 Fsignal (Qarith_error, Qnil); | |
978 bigfloat_set_prec (scratch_bigfloat, | |
979 max (XBIGFLOAT_GET_PREC (number), | |
980 XBIGFLOAT_GET_PREC (divisor))); | |
981 bigfloat_div (scratch_bigfloat, XBIGFLOAT_DATA (number), | |
982 XBIGFLOAT_DATA (divisor)); | |
983 bigfloat_floor (scratch_bigfloat, scratch_bigfloat); | |
984 return make_bigfloat_bf (scratch_bigfloat); | |
985 #endif | |
986 } | |
987 } | |
988 #else /* !WITH_NUMBER_TYPES */ | |
747 CHECK_INT_OR_FLOAT (number); | 989 CHECK_INT_OR_FLOAT (number); |
748 | 990 |
749 if (! NILP (divisor)) | 991 if (! NILP (divisor)) |
750 { | 992 { |
751 EMACS_INT i1, i2; | 993 EMACS_INT i1, i2; |
785 IN_FLOAT ((d = floor (XFLOAT_DATA (number))), "floor", number); | 1027 IN_FLOAT ((d = floor (XFLOAT_DATA (number))), "floor", number); |
786 return (float_to_int (d, "floor", number, Qunbound)); | 1028 return (float_to_int (d, "floor", number, Qunbound)); |
787 } | 1029 } |
788 | 1030 |
789 return number; | 1031 return number; |
1032 #endif /* WITH_NUMBER_TYPES */ | |
790 } | 1033 } |
791 | 1034 |
792 DEFUN ("round", Fround, 1, 1, 0, /* | 1035 DEFUN ("round", Fround, 1, 1, 0, /* |
793 Return the nearest integer to NUMBER. | 1036 Return the nearest integer to NUMBER. |
794 */ | 1037 */ |
800 /* Screw the prevailing rounding mode. */ | 1043 /* Screw the prevailing rounding mode. */ |
801 IN_FLOAT ((d = emacs_rint (XFLOAT_DATA (number))), "round", number); | 1044 IN_FLOAT ((d = emacs_rint (XFLOAT_DATA (number))), "round", number); |
802 return (float_to_int (d, "round", number, Qunbound)); | 1045 return (float_to_int (d, "round", number, Qunbound)); |
803 } | 1046 } |
804 | 1047 |
1048 #ifdef HAVE_BIGNUM | |
1049 if (INTEGERP (number)) | |
1050 #else | |
805 if (INTP (number)) | 1051 if (INTP (number)) |
1052 #endif | |
806 return number; | 1053 return number; |
1054 | |
1055 #ifdef HAVE_RATIO | |
1056 if (RATIOP (number)) | |
1057 { | |
1058 if (bignum_divisible_p (XRATIO_NUMERATOR (number), | |
1059 XRATIO_DENOMINATOR (number))) | |
1060 { | |
1061 bignum_div (scratch_bignum, XRATIO_NUMERATOR (number), | |
1062 XRATIO_DENOMINATOR (number)); | |
1063 } | |
1064 else | |
1065 { | |
1066 bignum_add (scratch_bignum2, XRATIO_NUMERATOR (number), | |
1067 XRATIO_DENOMINATOR (number)); | |
1068 bignum_div (scratch_bignum, scratch_bignum2, | |
1069 XRATIO_DENOMINATOR (number)); | |
1070 } | |
1071 return Fcanonicalize_number (make_bignum_bg (scratch_bignum)); | |
1072 } | |
1073 #endif | |
1074 | |
1075 #ifdef HAVE_BIGFLOAT | |
1076 if (BIGFLOATP (number)) | |
1077 { | |
1078 unsigned long prec = XBIGFLOAT_GET_PREC (number); | |
1079 bigfloat_set_prec (scratch_bigfloat, prec); | |
1080 bigfloat_set_prec (scratch_bigfloat2, prec); | |
1081 bigfloat_set_double (scratch_bigfloat2, | |
1082 bigfloat_sign (XBIGFLOAT_DATA (number)) * 0.5); | |
1083 bigfloat_floor (scratch_bigfloat, scratch_bigfloat2); | |
1084 #ifdef HAVE_BIGNUM | |
1085 bignum_set_bigfloat (scratch_bignum, scratch_bigfloat); | |
1086 return Fcanonicalize_number (make_bignum_bg (scratch_bignum)); | |
1087 #else | |
1088 return make_int ((EMACS_INT) bigfloat_to_long (scratch_bigfloat)); | |
1089 #endif /* HAVE_BIGNUM */ | |
1090 } | |
1091 #endif /* HAVE_BIGFLOAT */ | |
807 | 1092 |
808 return Fround (wrong_type_argument (Qnumberp, number)); | 1093 return Fround (wrong_type_argument (Qnumberp, number)); |
809 } | 1094 } |
810 | 1095 |
811 DEFUN ("truncate", Ftruncate, 1, 1, 0, /* | 1096 DEFUN ("truncate", Ftruncate, 1, 1, 0, /* |
815 (number)) | 1100 (number)) |
816 { | 1101 { |
817 if (FLOATP (number)) | 1102 if (FLOATP (number)) |
818 return float_to_int (XFLOAT_DATA (number), "truncate", number, Qunbound); | 1103 return float_to_int (XFLOAT_DATA (number), "truncate", number, Qunbound); |
819 | 1104 |
1105 #ifdef HAVE_BIGNUM | |
1106 if (INTEGERP (number)) | |
1107 #else | |
820 if (INTP (number)) | 1108 if (INTP (number)) |
1109 #endif | |
821 return number; | 1110 return number; |
1111 | |
1112 #ifdef HAVE_RATIO | |
1113 if (RATIOP (number)) | |
1114 { | |
1115 bignum_div (scratch_bignum, XRATIO_NUMERATOR (number), | |
1116 XRATIO_DENOMINATOR (number)); | |
1117 return Fcanonicalize_number (make_bignum_bg (scratch_bignum)); | |
1118 } | |
1119 #endif | |
1120 | |
1121 #ifdef HAVE_BIGFLOAT | |
1122 if (BIGFLOATP (number)) | |
1123 { | |
1124 bigfloat_set_prec (scratch_bigfloat, XBIGFLOAT_GET_PREC (number)); | |
1125 bigfloat_trunc (scratch_bigfloat, XBIGFLOAT_DATA (number)); | |
1126 #ifdef HAVE_BIGNUM | |
1127 bignum_set_bigfloat (scratch_bignum, scratch_bigfloat); | |
1128 return Fcanonicalize_number (make_bignum_bg (scratch_bignum)); | |
1129 #else | |
1130 return make_int ((EMACS_INT) bigfloat_to_long (scratch_bigfloat)); | |
1131 #endif /* HAVE_BIGNUM */ | |
1132 } | |
1133 #endif /* HAVE_BIGFLOAT */ | |
822 | 1134 |
823 return Ftruncate (wrong_type_argument (Qnumberp, number)); | 1135 return Ftruncate (wrong_type_argument (Qnumberp, number)); |
824 } | 1136 } |
825 | 1137 |
826 /* Float-rounding functions. */ | 1138 /* Float-rounding functions. */ |