Mercurial > hg > xemacs-beta
comparison src/floatfns.c @ 4678:b5e1d4f6b66f
Make #'floor, #'ceiling, #'round, #'truncate conform to Common Lisp.
lisp/ChangeLog addition:
2009-08-11 Aidan Kehoe <kehoea@parhasard.net>
* cl-extra.el (ceiling*, floor*, round*, truncate*):
Implement these in terms of the C functions; mark them as
obsolete.
(mod*, rem*): Use #'nth-value with the C functions, not #'nth with
the CL emulation functions.
man/ChangeLog addition:
2009-08-11 Aidan Kehoe <kehoea@parhasard.net>
* lispref/numbers.texi (Bigfloat Basics):
Correct this documentation (ignoring for the moment that it breaks
off in mid-sentence).
tests/ChangeLog addition:
2009-08-11 Aidan Kehoe <kehoea@parhasard.net>
* automated/lisp-tests.el:
Test the new Common Lisp-compatible rounding functions available in
C.
(generate-rounding-output): Provide a function useful for
generating the data for the rounding functions tests.
src/ChangeLog addition:
2009-08-11 Aidan Kehoe <kehoea@parhasard.net>
* floatfns.c (ROUNDING_CONVERT, CONVERT_WITH_NUMBER_TYPES)
(CONVERT_WITHOUT_NUMBER_TYPES, MAYBE_TWO_ARGS_BIGNUM)
(MAYBE_ONE_ARG_BIGNUM, MAYBE_TWO_ARGS_RATIO)
(MAYBE_ONE_ARG_RATIO, MAYBE_TWO_ARGS_BIGFLOAT)
(MAYBE_ONE_ARG_BIGFLOAT, MAYBE_EFF, MAYBE_CHAR_OR_MARKER):
New macros, used in the implementation of the rounding functions.
(ceiling_two_fixnum, ceiling_two_bignum, ceiling_two_ratio)
(ceiling_two_bigfloat, ceiling_one_ratio, ceiling_one_bigfloat)
(ceiling_two_float, ceiling_one_float, ceiling_one_mundane_arg)
(floor_two_fixnum, floor_two_bignum, floor_two_ratio)
(floor_two_bigfloat, floor_one_ratio, floor_one_bigfloat)
(floor_two_float, floor_one_mundane_arg, round_two_fixnum)
(round_two_bignum_1, round_two_bignum, round_two_ratio)
(round_one_bigfloat_1, round_two_bigfloat, round_one_ratio)
(round_one_bigfloat, round_two_float, round_one_float)
(round_one_mundane_arg, truncate_two_fixnum)
(truncate_two_bignum, truncate_two_ratio, truncate_two_bigfloat)
(truncate_one_ratio, truncate_one_bigfloat, truncate_two_float)
(truncate_one_float, truncate_one_mundane_arg):
New functions, used in the implementation of the rounding
functions.
(Fceiling, Ffloor, Fround, Ftruncate, Ffceiling, Fffloor)
(Ffround, Fftruncate):
Revise to fully support Common Lisp conventions. This means:
-- All functions have optional DIVISOR arguments
-- All functions return multiple values; see #'values
-- All functions do their arithmetic with the correct number types
according to the contamination rules.
-- #'round and #'fround always round towards the even number
in ambiguous cases.
* doprnt.c (emacs_doprnt_1):
* number.c (internal_coerce_number):
Call Ftruncate with two arguments, not one.
* floatfns.c (Ffloat):
Correct this, if NUMBER is a bignum.
* lisp.h:
Declare Ftruncate as taking two arguments.
* number.c:
Provide scratch_ratio2, init it appropriately.
* number.h:
Make scratch_ratio2 available.
* number.h (BIGFLOAT_ARITH_RETURN):
* number.h (BIGFLOAT_ARITH_RETURN1):
Correct these functions.
author | Aidan Kehoe <kehoea@parhasard.net> |
---|---|
date | Tue, 11 Aug 2009 17:59:23 +0100 |
parents | 04bc9d2f42c7 |
children | fcc7e89d5e68 |
comparison
equal
deleted
inserted
replaced
4677:8f1ee2d15784 | 4678:b5e1d4f6b66f |
---|---|
767 { | 767 { |
768 if (INTP (number)) | 768 if (INTP (number)) |
769 return make_float ((double) XINT (number)); | 769 return make_float ((double) XINT (number)); |
770 | 770 |
771 #ifdef HAVE_BIGNUM | 771 #ifdef HAVE_BIGNUM |
772 if (BIGFLOATP (number)) | 772 if (BIGNUMP (number)) |
773 { | 773 { |
774 #ifdef HAVE_BIGFLOAT | 774 #ifdef HAVE_BIGFLOAT |
775 if (ZEROP (Vdefault_float_precision)) | 775 if (ZEROP (Vdefault_float_precision)) |
776 #endif | 776 #endif |
777 return make_float (bignum_to_double (XBIGNUM_DATA (number))); | 777 return make_float (bignum_to_double (XBIGNUM_DATA (number))); |
846 } | 846 } |
847 #endif /* ! HAVE_FREXP */ | 847 #endif /* ! HAVE_FREXP */ |
848 #endif /* ! HAVE_LOGB */ | 848 #endif /* ! HAVE_LOGB */ |
849 } | 849 } |
850 | 850 |
851 DEFUN ("ceiling", Fceiling, 1, 1, 0, /* | 851 #ifdef WITH_NUMBER_TYPES |
852 Return the smallest integer no less than NUMBER. (Round toward +inf.) | 852 #define ROUNDING_CONVERT(conversion, return_float) \ |
853 */ | 853 CONVERT_WITH_NUMBER_TYPES(conversion, return_float) |
854 (number)) | 854 #else |
855 { | 855 #define ROUNDING_CONVERT(conversion, return_float) \ |
856 if (FLOATP (number)) | 856 CONVERT_WITHOUT_NUMBER_TYPES(conversion, return_float) |
857 { | 857 #endif |
858 double d; | 858 |
859 IN_FLOAT ((d = ceil (XFLOAT_DATA (number))), "ceiling", number); | 859 #define CONVERT_WITH_NUMBER_TYPES(conversion, return_float) \ |
860 return (float_to_int (d, "ceiling", number, Qunbound)); | 860 if (!NILP (divisor)) \ |
861 } | 861 { \ |
862 | 862 switch (promote_args (&number, &divisor)) \ |
863 { \ | |
864 case FIXNUM_T: \ | |
865 return conversion##_two_fixnum (number, divisor, \ | |
866 return_float); \ | |
867 MAYBE_TWO_ARGS_WITH_NUMBER_TYPES (conversion, \ | |
868 BIGNUM, \ | |
869 return_float); \ | |
870 MAYBE_TWO_ARGS_WITH_NUMBER_TYPES (conversion, \ | |
871 RATIO, \ | |
872 return_float); \ | |
873 MAYBE_TWO_ARGS_WITH_NUMBER_TYPES (conversion, \ | |
874 BIGFLOAT, \ | |
875 return_float); \ | |
876 default: /* FLOAT_T */ \ | |
877 return conversion##_two_float (number,divisor, \ | |
878 return_float); \ | |
879 } \ | |
880 } \ | |
881 \ | |
882 /* Try this first, the arg is probably a float: */ \ | |
883 if (FLOATP (number)) \ | |
884 return conversion##_one_float (number, return_float); \ | |
885 \ | |
886 MAYBE_ONE_ARG_WITH_NUMBER_TYPES (conversion, \ | |
887 RATIO, return_float); \ | |
888 MAYBE_ONE_ARG_WITH_NUMBER_TYPES (conversion, \ | |
889 BIGFLOAT, return_float); \ | |
890 return conversion##_one_mundane_arg (number, divisor, \ | |
891 return_float) | |
892 | |
893 | |
894 #define CONVERT_WITHOUT_NUMBER_TYPES(conversion, return_float) \ | |
895 if (!NILP (divisor)) \ | |
896 { \ | |
897 /* The promote_args call if number types are available \ | |
898 does these conversions, we do them too for symmetry: */\ | |
899 if (CHARP (number)) \ | |
900 { \ | |
901 number = make_int (XCHAR (number)); \ | |
902 } \ | |
903 else if (MARKERP (number)) \ | |
904 { \ | |
905 number = make_int (marker_position (number)); \ | |
906 } \ | |
907 \ | |
908 if (CHARP (divisor)) \ | |
909 { \ | |
910 divisor = make_int (XCHAR (divisor)); \ | |
911 } \ | |
912 else if (MARKERP (divisor)) \ | |
913 { \ | |
914 divisor = make_int (marker_position (divisor)); \ | |
915 } \ | |
916 \ | |
917 CHECK_INT_OR_FLOAT (divisor); \ | |
918 if (INTP (number) && INTP (divisor)) \ | |
919 { \ | |
920 return conversion##_two_fixnum (number, divisor, \ | |
921 return_float); \ | |
922 } \ | |
923 else \ | |
924 { \ | |
925 return conversion##_two_float (number, divisor, \ | |
926 return_float); \ | |
927 } \ | |
928 } \ | |
929 \ | |
930 /* Try this first, the arg is probably a float: */ \ | |
931 if (FLOATP (number)) \ | |
932 return conversion##_one_float (number, return_float); \ | |
933 \ | |
934 return conversion##_one_mundane_arg (number, divisor, \ | |
935 return_float) \ | |
936 | |
937 #ifdef WITH_NUMBER_TYPES | |
938 | |
939 #ifdef HAVE_BIGNUM | |
940 #define MAYBE_TWO_ARGS_BIGNUM(conversion, return_float) \ | |
941 case BIGNUM_T: \ | |
942 return conversion##_two_bignum (number, divisor, return_float) | |
943 | |
944 #define MAYBE_ONE_ARG_BIGNUM(converse, return_float) \ | |
945 if (BIGNUM_P (number)) \ | |
946 return conversion##_one_bignum (number, divisor, return_float) | |
947 #else | |
948 #define MAYBE_TWO_ARGS_BIGNUM(conversion, return_float) | |
949 #define MAYBE_ONE_ARG_BIGNUM(converse, return_float) | |
950 #endif | |
951 | |
952 #ifdef HAVE_RATIO | |
953 #define MAYBE_TWO_ARGS_RATIO(conversion, return_float) \ | |
954 case RATIO_T: \ | |
955 return conversion##_two_ratio (number, divisor, return_float) | |
956 | |
957 #define MAYBE_ONE_ARG_RATIO(conversion, return_float) \ | |
958 if (RATIOP (number)) \ | |
959 return conversion##_one_ratio (number, divisor, return_float) | |
960 #else | |
961 #define MAYBE_TWO_ARGS_RATIO(conversion, return_float) | |
962 #define MAYBE_ONE_ARG_RATIO(converse, return_float) | |
963 #endif | |
964 | |
965 #ifdef HAVE_BIGFLOAT | |
966 #define MAYBE_TWO_ARGS_BIGFLOAT(conversion, return_float) \ | |
967 case BIGFLOAT_T: \ | |
968 return conversion##_two_bigfloat (number, divisor, return_float) | |
969 | |
970 #define MAYBE_ONE_ARG_BIGFLOAT(conversion, return_float) \ | |
971 if (BIGFLOATP (number)) \ | |
972 return conversion##_one_bigfloat (number, divisor, return_float) | |
973 #else | |
974 #define MAYBE_TWO_ARGS_BIGFLOAT(conversion, return_float) | |
975 #define MAYBE_ONE_ARG_BIGFLOAT(converse, return_float) | |
976 #endif | |
977 | |
978 #define MAYBE_TWO_ARGS_WITH_NUMBER_TYPES(convers, upcase, return_float) \ | |
979 MAYBE_TWO_ARGS_##upcase(convers, return_float) | |
980 | |
981 #define MAYBE_ONE_ARG_WITH_NUMBER_TYPES(convers, upcase, return_float) \ | |
982 MAYBE_ONE_ARG_##upcase(convers, return_float) | |
983 | |
984 #endif /* WITH_NUMBER_TYPES */ | |
985 | |
986 #define MAYBE_EFF(str) (return_float ? "f" str : str) | |
987 | |
988 /* The WITH_NUMBER_TYPES code calls promote_args, which accepts chars and | |
989 markers as equivalent to ints. This block does the same for | |
990 single-argument calls. */ | |
991 #define MAYBE_CHAR_OR_MARKER(conversion) do { \ | |
992 if (CHARP (number)) \ | |
993 { \ | |
994 return conversion##_one_mundane_arg (make_int (XCHAR (number)), \ | |
995 divisor, return_float); \ | |
996 } \ | |
997 \ | |
998 if (MARKERP (number)) \ | |
999 { \ | |
1000 return conversion##_one_mundane_arg (make_int \ | |
1001 (marker_position(number)), \ | |
1002 divisor, return_float); \ | |
1003 } \ | |
1004 } while (0) | |
1005 | |
1006 | |
1007 /* The guts of the implementations of the various rounding functions: */ | |
1008 | |
1009 static Lisp_Object | |
1010 ceiling_two_fixnum (Lisp_Object number, Lisp_Object divisor, | |
1011 int return_float) | |
1012 { | |
1013 EMACS_INT i1 = XREALINT (number); | |
1014 EMACS_INT i2 = XREALINT (divisor); | |
1015 EMACS_INT i3 = 0, i4 = 0; | |
1016 | |
1017 if (i2 == 0) | |
1018 Fsignal (Qarith_error, Qnil); | |
1019 | |
1020 /* With C89's integer /, the result is implementation-defined if either | |
1021 operand is negative, so use only nonnegative operands. Here we do | |
1022 basically the opposite of what floor_two_fixnum does, we add one in the | |
1023 non-negative case: */ | |
1024 | |
1025 /* Make sure we use the same signs for the modulus calculation as for the | |
1026 quotient calculation: */ | |
1027 if (i2 < 0) | |
1028 { | |
1029 if (i1 <= 0) | |
1030 { | |
1031 i3 = -i1 / -i2; | |
1032 /* Quotient is positive; add one to give the figure for | |
1033 ceiling. */ | |
1034 if (0 != (-i1 % -i2)) | |
1035 { | |
1036 ++i3; | |
1037 } | |
1038 } | |
1039 else | |
1040 { | |
1041 /* Quotient is negative; no need to add one. */ | |
1042 i3 = -(i1 / -i2); | |
1043 } | |
1044 } | |
1045 else | |
1046 { | |
1047 if (i1 < 0) | |
1048 { | |
1049 /* Quotient is negative; no need to add one. */ | |
1050 i3 = -(-i1 / i2); | |
1051 } | |
1052 else | |
1053 { | |
1054 i3 = i1 / i2; | |
1055 /* Quotient is positive; add one to give the figure for | |
1056 ceiling. */ | |
1057 if (0 != (i1 % i2)) | |
1058 { | |
1059 ++i3; | |
1060 } | |
1061 } | |
1062 } | |
1063 | |
1064 i4 = i1 - (i3 * i2); | |
1065 | |
1066 if (!return_float) | |
1067 { | |
1068 return values2 (make_int (i3), make_int (i4)); | |
1069 } | |
1070 | |
1071 return values2 (make_float ((double)i3), | |
1072 make_int (i4)); | |
1073 } | |
1074 | |
1075 #ifdef HAVE_BIGNUM | |
1076 static Lisp_Object | |
1077 ceiling_two_bignum (Lisp_Object number, Lisp_Object divisor, | |
1078 int return_float) | |
1079 { | |
1080 Lisp_Object res0, res1; | |
1081 | |
1082 if (bignum_sign (XBIGNUM_DATA (divisor)) == 0) | |
1083 { | |
1084 Fsignal (Qarith_error, Qnil); | |
1085 } | |
1086 | |
1087 bignum_ceil (scratch_bignum, XBIGNUM_DATA (number), XBIGNUM_DATA (divisor)); | |
1088 | |
1089 res0 = return_float ? make_float (bignum_to_double (scratch_bignum)) : | |
1090 Fcanonicalize_number (make_bignum_bg (scratch_bignum)); | |
1091 | |
1092 if (bignum_divisible_p (XBIGNUM_DATA (number), XBIGNUM_DATA (divisor))) | |
1093 { | |
1094 res1 = Qzero; | |
1095 } | |
1096 else | |
1097 { | |
1098 bignum_mul (scratch_bignum, scratch_bignum, XBIGNUM_DATA (divisor)); | |
1099 bignum_sub (scratch_bignum, XBIGNUM_DATA (number), scratch_bignum); | |
1100 res1 = Fcanonicalize_number (make_bignum_bg (scratch_bignum)); | |
1101 } | |
1102 | |
1103 return values2 (res0, res1); | |
1104 } | |
1105 #endif /* HAVE_BIGNUM */ | |
1106 | |
1107 #ifdef HAVE_RATIO | |
1108 static Lisp_Object | |
1109 ceiling_two_ratio (Lisp_Object number, Lisp_Object divisor, | |
1110 int return_float) | |
1111 { | |
1112 Lisp_Object res0, res1; | |
1113 | |
1114 if (ratio_sign (XRATIO_DATA (divisor)) == 0) | |
1115 { | |
1116 Fsignal (Qarith_error, Qnil); | |
1117 } | |
1118 | |
1119 ratio_div (scratch_ratio, XRATIO_DATA (number), XRATIO_DATA (divisor)); | |
1120 | |
1121 bignum_ceil (scratch_bignum, ratio_numerator (scratch_ratio), | |
1122 ratio_denominator (scratch_ratio)); | |
1123 | |
1124 res0 = return_float ? make_float (bignum_to_double (scratch_bignum)) : | |
1125 Fcanonicalize_number (make_bignum_bg (scratch_bignum)); | |
1126 | |
1127 if (bignum_divisible_p (ratio_numerator (scratch_ratio), | |
1128 ratio_denominator (scratch_ratio))) | |
1129 { | |
1130 res1 = Qzero; | |
1131 } | |
1132 else | |
1133 { | |
1134 ratio_set_bignum (scratch_ratio, scratch_bignum); | |
1135 ratio_mul (scratch_ratio2, scratch_ratio, XRATIO_DATA (divisor)); | |
1136 ratio_sub (scratch_ratio, XRATIO_DATA (number), scratch_ratio2); | |
1137 res1 = Fcanonicalize_number (make_ratio_rt (scratch_ratio)); | |
1138 } | |
1139 | |
1140 return values2 (res0, res1); | |
1141 } | |
1142 #endif /* HAVE_RATIO */ | |
1143 | |
1144 #ifdef HAVE_BIGFLOAT | |
1145 static Lisp_Object | |
1146 ceiling_two_bigfloat (Lisp_Object number, Lisp_Object divisor, | |
1147 int return_float) | |
1148 { | |
1149 Lisp_Object res0; | |
1150 | |
1151 if (bigfloat_sign (XBIGFLOAT_DATA (divisor)) == 0) | |
1152 { | |
1153 Fsignal (Qarith_error, Qnil); | |
1154 } | |
1155 | |
1156 bigfloat_set_prec (scratch_bigfloat, max (XBIGFLOAT_GET_PREC (number), | |
1157 XBIGFLOAT_GET_PREC (divisor))); | |
1158 bigfloat_div (scratch_bigfloat, XBIGFLOAT_DATA (number), | |
1159 XBIGFLOAT_DATA (divisor)); | |
1160 bigfloat_ceil (scratch_bigfloat, scratch_bigfloat); | |
1161 | |
1162 if (return_float) | |
1163 { | |
1164 res0 = make_bigfloat_bf (scratch_bigfloat); | |
1165 } | |
1166 else | |
1167 { | |
1168 #ifdef HAVE_BIGNUM | |
1169 bignum_set_bigfloat (scratch_bignum, scratch_bigfloat); | |
1170 res0 = Fcanonicalize_number (make_bignum_bg (scratch_bignum)); | |
1171 #else | |
1172 res0 = make_int ((EMACS_INT) bigfloat_to_long (scratch_bigfloat)); | |
1173 #endif /* HAVE_BIGNUM */ | |
1174 } | |
1175 | |
1176 bigfloat_mul (scratch_bigfloat, scratch_bigfloat, XBIGFLOAT_DATA (divisor)); | |
1177 bigfloat_sub (scratch_bigfloat, XBIGFLOAT_DATA (number), scratch_bigfloat); | |
1178 return values2 (res0, | |
1179 Fcanonicalize_number (make_bigfloat_bf (scratch_bigfloat))); | |
1180 } | |
1181 #endif /* HAVE_BIGFLOAT */ | |
1182 | |
1183 #ifdef HAVE_RATIO | |
1184 static Lisp_Object | |
1185 ceiling_one_ratio (Lisp_Object number, Lisp_Object UNUSED (divisor), | |
1186 int return_float) | |
1187 { | |
1188 Lisp_Object res0, res1; | |
1189 | |
1190 bignum_ceil (scratch_bignum, XRATIO_NUMERATOR (number), | |
1191 XRATIO_DENOMINATOR (number)); | |
1192 | |
1193 res0 = return_float ? make_float (bignum_to_double (scratch_bignum)) : | |
1194 Fcanonicalize_number (make_bignum_bg (scratch_bignum)); | |
1195 | |
1196 if (bignum_divisible_p (XRATIO_NUMERATOR (number), | |
1197 XRATIO_DENOMINATOR (number))) | |
1198 { | |
1199 res1 = Qzero; | |
1200 } | |
1201 else | |
1202 { | |
1203 ratio_set_bignum (scratch_ratio2, scratch_bignum); | |
1204 ratio_sub (scratch_ratio, XRATIO_DATA (number), scratch_ratio2); | |
1205 res1 = Fcanonicalize_number (make_ratio_rt (scratch_ratio)); | |
1206 } | |
1207 | |
1208 return values2 (res0, res1); | |
1209 } | |
1210 #endif /* HAVE_RATIO */ | |
1211 | |
1212 #ifdef HAVE_BIGFLOAT | |
1213 static Lisp_Object | |
1214 ceiling_one_bigfloat (Lisp_Object number, Lisp_Object UNUSED (divisor), | |
1215 int return_float) | |
1216 { | |
1217 Lisp_Object res0, res1; | |
1218 | |
1219 bigfloat_set_prec (scratch_bigfloat, XBIGFLOAT_GET_PREC (number)); | |
1220 bigfloat_ceil (scratch_bigfloat, XBIGFLOAT_DATA (number)); | |
1221 | |
1222 if (return_float) | |
1223 { | |
1224 res0 = make_bigfloat_bf (scratch_bigfloat); | |
1225 } | |
1226 else | |
1227 { | |
1228 #ifdef HAVE_BIGNUM | |
1229 bignum_set_bigfloat (scratch_bignum, scratch_bigfloat); | |
1230 res0 = Fcanonicalize_number (make_bignum_bg (scratch_bignum)); | |
1231 #else | |
1232 res0 = make_int ((EMACS_INT) bigfloat_to_long (scratch_bigfloat)); | |
1233 #endif /* HAVE_BIGNUM */ | |
1234 } | |
1235 | |
1236 bigfloat_sub (scratch_bigfloat2, XBIGFLOAT_DATA (number), scratch_bigfloat); | |
1237 | |
1238 res1 = make_bigfloat_bf (scratch_bigfloat2); | |
1239 return values2 (res0, res1); | |
1240 } | |
1241 #endif /* HAVE_BIGFLOAT */ | |
1242 | |
1243 static Lisp_Object | |
1244 ceiling_two_float (Lisp_Object number, Lisp_Object divisor, | |
1245 int return_float) | |
1246 { | |
1247 double f1 = extract_float (number); | |
1248 double f2 = extract_float (divisor); | |
1249 double f0, remain; | |
1250 Lisp_Object res0; | |
1251 | |
1252 if (f2 == 0.0) | |
1253 { | |
1254 Fsignal (Qarith_error, Qnil); | |
1255 } | |
1256 | |
1257 IN_FLOAT2 (f0 = ceil (f1 / f2), MAYBE_EFF("ceiling"), number, divisor); | |
1258 IN_FLOAT2 (remain = f1 - (f0 * f2), MAYBE_EFF("ceiling"), number, divisor); | |
1259 | |
1260 if (return_float) | |
1261 { | |
1262 res0 = make_float(f0); | |
1263 } | |
1264 else | |
1265 { | |
1266 res0 = float_to_int (f0, MAYBE_EFF("ceiling"), number, divisor); | |
1267 } | |
1268 | |
1269 return values2 (res0, make_float (remain)); | |
1270 } | |
1271 | |
1272 static Lisp_Object | |
1273 ceiling_one_float (Lisp_Object number, int return_float) | |
1274 { | |
1275 double d, remain; | |
1276 Lisp_Object res0; | |
1277 | |
1278 IN_FLOAT ((d = ceil (XFLOAT_DATA (number))), MAYBE_EFF("ceiling"), number); | |
1279 IN_FLOAT ((remain = XFLOAT_DATA (number) - d), MAYBE_EFF("ceiling"), number); | |
1280 | |
1281 if (return_float) | |
1282 { | |
1283 res0 = make_float (d); | |
1284 } | |
1285 else | |
1286 { | |
1287 res0 = float_to_int (d, MAYBE_EFF("ceiling"), number, Qunbound); | |
1288 } | |
1289 return values2 (res0, make_float (remain)); | |
1290 } | |
1291 | |
1292 EXFUN (Fceiling, 2); | |
1293 EXFUN (Ffceiling, 2); | |
1294 | |
1295 static Lisp_Object | |
1296 ceiling_one_mundane_arg (Lisp_Object number, Lisp_Object divisor, | |
1297 int return_float) | |
1298 { | |
1299 | |
1300 if (return_float) | |
1301 { | |
1302 if (INTP (number)) | |
1303 { | |
1304 return values2 (make_float ((double) XINT (number)), Qzero); | |
1305 } | |
1306 #ifdef HAVE_BIGNUM | |
1307 else if (BIGNUMP (number)) | |
1308 { | |
1309 return values2 (make_float | |
1310 (bignum_to_double (XBIGNUM_DATA (number))), | |
1311 Qzero); | |
1312 } | |
1313 #endif | |
1314 } | |
1315 else | |
1316 { | |
1317 #ifdef HAVE_BIGNUM | |
1318 if (INTEGERP (number)) | |
1319 #else | |
1320 if (INTP (number)) | |
1321 #endif | |
1322 { | |
1323 return values2 (number, Qzero); | |
1324 } | |
1325 } | |
1326 | |
1327 MAYBE_CHAR_OR_MARKER (ceiling); | |
1328 | |
1329 return Ffceiling (wrong_type_argument (Qnumberp, number), divisor); | |
1330 } | |
1331 | |
1332 static Lisp_Object | |
1333 floor_two_fixnum (Lisp_Object number, Lisp_Object divisor, | |
1334 int return_float) | |
1335 { | |
1336 EMACS_INT i1 = XREALINT (number); | |
1337 EMACS_INT i2 = XREALINT (divisor); | |
1338 EMACS_INT i3 = 0, i4 = 0; | |
1339 Lisp_Object res0; | |
1340 | |
1341 if (i2 == 0) | |
1342 { | |
1343 Fsignal (Qarith_error, Qnil); | |
1344 } | |
1345 | |
1346 /* With C89's integer /, the result is implementation-defined if either | |
1347 operand is negative, so use only nonnegative operands. Notice also that | |
1348 we're forcing the quotient of any negative numbers towards minus | |
1349 infinity. */ | |
1350 i3 = (i2 < 0 | |
1351 ? (i1 <= 0 ? -i1 / -i2 : -1 - ((i1 - 1) / -i2)) | |
1352 : (i1 < 0 ? -1 - ((-1 - i1) / i2) : i1 / i2)); | |
1353 | |
1354 i4 = i1 - (i3 * i2); | |
1355 | |
1356 if (return_float) | |
1357 { | |
1358 res0 = make_float ((double)i3); | |
1359 } | |
1360 else | |
1361 { | |
1362 res0 = make_int (i3); | |
1363 } | |
1364 | |
1365 return values2 (res0, make_int (i4)); | |
1366 } | |
1367 | |
1368 #ifdef HAVE_BIGNUM | |
1369 static Lisp_Object | |
1370 floor_two_bignum (Lisp_Object number, Lisp_Object divisor, | |
1371 int return_float) | |
1372 { | |
1373 Lisp_Object res0, res1; | |
1374 | |
1375 if (bignum_sign (XBIGNUM_DATA (divisor)) == 0) | |
1376 { | |
1377 Fsignal (Qarith_error, Qnil); | |
1378 } | |
1379 | |
1380 bignum_floor (scratch_bignum, XBIGNUM_DATA (number), | |
1381 XBIGNUM_DATA (divisor)); | |
1382 | |
1383 if (return_float) | |
1384 { | |
1385 res0 = make_float (bignum_to_double (scratch_bignum)); | |
1386 } | |
1387 else | |
1388 { | |
1389 res0 = Fcanonicalize_number (make_bignum_bg (scratch_bignum)); | |
1390 } | |
1391 | |
1392 if (bignum_divisible_p (XBIGNUM_DATA (number), XBIGNUM_DATA (divisor))) | |
1393 { | |
1394 res1 = Qzero; | |
1395 } | |
1396 else | |
1397 { | |
1398 bignum_mul (scratch_bignum, scratch_bignum, XBIGNUM_DATA (divisor)); | |
1399 bignum_sub (scratch_bignum, XBIGNUM_DATA (number), scratch_bignum); | |
1400 res1 = Fcanonicalize_number (make_bignum_bg (scratch_bignum)); | |
1401 } | |
1402 | |
1403 return values2 (res0, res1); | |
1404 } | |
1405 #endif /* HAVE_BIGNUM */ | |
1406 | |
1407 #ifdef HAVE_RATIO | |
1408 static Lisp_Object | |
1409 floor_two_ratio (Lisp_Object number, Lisp_Object divisor, | |
1410 int return_float) | |
1411 { | |
1412 Lisp_Object res0, res1; | |
1413 | |
1414 if (ratio_sign (XRATIO_DATA (divisor)) == 0) | |
1415 { | |
1416 Fsignal (Qarith_error, Qnil); | |
1417 } | |
1418 | |
1419 ratio_div (scratch_ratio, XRATIO_DATA (number), XRATIO_DATA (divisor)); | |
1420 | |
1421 bignum_floor (scratch_bignum, ratio_numerator (scratch_ratio), | |
1422 ratio_denominator (scratch_ratio)); | |
1423 | |
1424 res0 = return_float ? make_float (bignum_to_double (scratch_bignum)) : | |
1425 Fcanonicalize_number (make_bignum_bg (scratch_bignum)); | |
1426 | |
1427 if (bignum_divisible_p (ratio_numerator (scratch_ratio), | |
1428 ratio_denominator (scratch_ratio))) | |
1429 { | |
1430 res1 = Qzero; | |
1431 } | |
1432 else | |
1433 { | |
1434 ratio_set_bignum (scratch_ratio, scratch_bignum); | |
1435 ratio_mul (scratch_ratio, scratch_ratio, XRATIO_DATA (divisor)); | |
1436 ratio_sub (scratch_ratio, XRATIO_DATA (number), scratch_ratio); | |
1437 res1 = Fcanonicalize_number (make_ratio_rt (scratch_ratio)); | |
1438 } | |
1439 | |
1440 return values2 (res0, res1); | |
1441 } | |
1442 #endif /* HAVE_RATIO */ | |
1443 | |
1444 #ifdef HAVE_BIGFLOAT | |
1445 static Lisp_Object | |
1446 floor_two_bigfloat (Lisp_Object number, Lisp_Object divisor, | |
1447 int return_float) | |
1448 { | |
1449 Lisp_Object res0; | |
1450 | |
1451 if (bigfloat_sign (XBIGFLOAT_DATA (divisor)) == 0) | |
1452 { | |
1453 Fsignal (Qarith_error, Qnil); | |
1454 } | |
1455 | |
1456 bigfloat_set_prec (scratch_bigfloat, max (XBIGFLOAT_GET_PREC (number), | |
1457 XBIGFLOAT_GET_PREC (divisor))); | |
1458 bigfloat_div (scratch_bigfloat, XBIGFLOAT_DATA (number), | |
1459 XBIGFLOAT_DATA (divisor)); | |
1460 bigfloat_floor (scratch_bigfloat, scratch_bigfloat); | |
1461 | |
1462 if (return_float) | |
1463 { | |
1464 res0 = make_bigfloat_bf (scratch_bigfloat); | |
1465 } | |
1466 else | |
1467 { | |
1468 #ifdef HAVE_BIGNUM | |
1469 bignum_set_bigfloat (scratch_bignum, scratch_bigfloat); | |
1470 res0 = Fcanonicalize_number (make_bignum_bg (scratch_bignum)); | |
1471 #else | |
1472 res0 = make_int ((EMACS_INT) bigfloat_to_long (scratch_bigfloat)); | |
1473 #endif /* HAVE_BIGNUM */ | |
1474 } | |
1475 | |
1476 bigfloat_mul (scratch_bigfloat2, scratch_bigfloat, | |
1477 XBIGFLOAT_DATA (divisor)); | |
1478 bigfloat_sub (scratch_bigfloat, XBIGFLOAT_DATA (number), scratch_bigfloat2); | |
1479 | |
1480 return values2 (res0, make_bigfloat_bf (scratch_bigfloat)); | |
1481 } | |
1482 #endif /* HAVE_BIGFLOAT */ | |
1483 | |
1484 #ifdef HAVE_RATIO | |
1485 static Lisp_Object | |
1486 floor_one_ratio (Lisp_Object number, Lisp_Object UNUSED (divisor), | |
1487 int return_float) | |
1488 { | |
1489 Lisp_Object res0, res1; | |
1490 | |
1491 bignum_floor (scratch_bignum, XRATIO_NUMERATOR (number), | |
1492 XRATIO_DENOMINATOR (number)); | |
1493 | |
1494 res0 = return_float ? make_float (bignum_to_double (scratch_bignum)) : | |
1495 Fcanonicalize_number (make_bignum_bg (scratch_bignum)); | |
1496 | |
1497 if (bignum_divisible_p (XRATIO_NUMERATOR (number), | |
1498 XRATIO_DENOMINATOR (number))) | |
1499 { | |
1500 res1 = Qzero; | |
1501 } | |
1502 else | |
1503 { | |
1504 ratio_set_bignum (scratch_ratio2, scratch_bignum); | |
1505 ratio_sub (scratch_ratio, XRATIO_DATA (number), scratch_ratio2); | |
1506 res1 = Fcanonicalize_number (make_ratio_rt (scratch_ratio)); | |
1507 } | |
1508 | |
1509 return values2 (res0, res1); | |
1510 } | |
1511 #endif /* HAVE_RATIO */ | |
1512 | |
1513 #ifdef HAVE_BIGFLOAT | |
1514 static Lisp_Object | |
1515 floor_one_bigfloat (Lisp_Object number, Lisp_Object UNUSED (divisor), | |
1516 int return_float) | |
1517 { | |
1518 Lisp_Object res0; | |
1519 | |
1520 bigfloat_set_prec (scratch_bigfloat, XBIGFLOAT_GET_PREC (number)); | |
1521 bigfloat_floor (scratch_bigfloat, XBIGFLOAT_DATA (number)); | |
1522 | |
1523 if (return_float) | |
1524 { | |
1525 res0 = make_bigfloat_bf (scratch_bigfloat); | |
1526 } | |
1527 else | |
1528 { | |
1529 #ifdef HAVE_BIGNUM | |
1530 bignum_set_bigfloat (scratch_bignum, scratch_bigfloat); | |
1531 res0 = Fcanonicalize_number (make_bignum_bg (scratch_bignum)); | |
1532 #else | |
1533 res0 = make_int ((EMACS_INT) bigfloat_to_long (scratch_bigfloat)); | |
1534 #endif /* HAVE_BIGNUM */ | |
1535 } | |
1536 | |
1537 bigfloat_sub (scratch_bigfloat2, XBIGFLOAT_DATA (number), scratch_bigfloat); | |
1538 return values2 (res0, make_bigfloat_bf (scratch_bigfloat2)); | |
1539 } | |
1540 #endif /* HAVE_BIGFLOAT */ | |
1541 | |
1542 static Lisp_Object | |
1543 floor_two_float (Lisp_Object number, Lisp_Object divisor, | |
1544 int return_float) | |
1545 { | |
1546 double f1 = extract_float (number); | |
1547 double f2 = extract_float (divisor); | |
1548 double f0, remain; | |
1549 | |
1550 if (f2 == 0.0) | |
1551 { | |
1552 Fsignal (Qarith_error, Qnil); | |
1553 } | |
1554 | |
1555 IN_FLOAT2 (f0 = floor (f1 / f2), MAYBE_EFF ("floor"), number, divisor); | |
1556 IN_FLOAT2 (remain = f1 - (f0 * f2), MAYBE_EFF ("floor"), number, divisor); | |
1557 | |
1558 if (return_float) | |
1559 { | |
1560 return values2 (make_float (f0), make_float (remain)); | |
1561 } | |
1562 | |
1563 return values2 (float_to_int (f0, MAYBE_EFF ("floor"), number, divisor), | |
1564 make_float (remain)); | |
1565 } | |
1566 | |
1567 static Lisp_Object | |
1568 floor_one_float (Lisp_Object number, int return_float) | |
1569 { | |
1570 double d, d1; | |
1571 | |
1572 IN_FLOAT ((d = floor (XFLOAT_DATA (number))), MAYBE_EFF ("floor"), number); | |
1573 IN_FLOAT ((d1 = XFLOAT_DATA (number) - d), MAYBE_EFF ("floor"), number); | |
1574 | |
1575 if (return_float) | |
1576 { | |
1577 return values2 (make_float (d), make_float (d1)); | |
1578 } | |
1579 else | |
1580 { | |
1581 return values2 (float_to_int (d, MAYBE_EFF ("floor"), number, Qunbound), | |
1582 make_float (d1)); | |
1583 } | |
1584 } | |
1585 | |
1586 EXFUN (Ffloor, 2); | |
1587 EXFUN (Fffloor, 2); | |
1588 | |
1589 static Lisp_Object | |
1590 floor_one_mundane_arg (Lisp_Object number, Lisp_Object divisor, | |
1591 int return_float) | |
1592 { | |
863 #ifdef HAVE_BIGNUM | 1593 #ifdef HAVE_BIGNUM |
864 if (INTEGERP (number)) | 1594 if (INTEGERP (number)) |
865 #else | 1595 #else |
866 if (INTP (number)) | 1596 if (INTP (number)) |
867 #endif | 1597 #endif |
868 return number; | 1598 { |
1599 if (return_float) | |
1600 { | |
1601 return values2 (make_float (extract_float (number)), Qzero); | |
1602 } | |
1603 else | |
1604 { | |
1605 return values2 (number, Qzero); | |
1606 } | |
1607 } | |
1608 | |
1609 MAYBE_CHAR_OR_MARKER (floor); | |
1610 | |
1611 if (return_float) | |
1612 { | |
1613 return Fffloor (wrong_type_argument (Qnumberp, number), divisor); | |
1614 } | |
1615 else | |
1616 { | |
1617 return Ffloor (wrong_type_argument (Qnumberp, number), divisor); | |
1618 } | |
1619 } | |
1620 | |
1621 /* Algorithm taken from cl-extra.el, now to be found as cl-round in | |
1622 tests/automated/lisp-tests.el. */ | |
1623 static Lisp_Object | |
1624 round_two_fixnum (Lisp_Object number, Lisp_Object divisor, | |
1625 int return_float) | |
1626 { | |
1627 EMACS_INT i1 = XREALINT (number); | |
1628 EMACS_INT i2 = XREALINT (divisor); | |
1629 EMACS_INT i0, hi2, flooring, floored, flsecond; | |
1630 | |
1631 if (i2 == 0) | |
1632 { | |
1633 Fsignal (Qarith_error, Qnil); | |
1634 } | |
1635 | |
1636 hi2 = i2 < 0 ? -( -i2 / 2) : i2 / 2; | |
1637 | |
1638 flooring = hi2 + i1; | |
1639 | |
1640 floored = (i2 < 0 | |
1641 ? (flooring <= 0 ? -flooring / -i2 : -1 - ((flooring - 1) / -i2)) | |
1642 : (flooring < 0 ? -1 - ((-1 - flooring) / i2) : flooring / i2)); | |
1643 | |
1644 flsecond = flooring - (floored * i2); | |
1645 | |
1646 if (0 == flsecond | |
1647 && (i2 == (hi2 + hi2)) | |
1648 && (0 != (floored % 2))) | |
1649 { | |
1650 i0 = floored - 1; | |
1651 return values2 (return_float ? make_float ((double)i0) : | |
1652 make_int (i0), make_int (hi2)); | |
1653 } | |
1654 else | |
1655 { | |
1656 return values2 (return_float ? make_float ((double)floored) : | |
1657 make_int (floored), | |
1658 make_int (flsecond - hi2)); | |
1659 } | |
1660 } | |
1661 | |
1662 #ifdef HAVE_BIGNUM | |
1663 static void | |
1664 round_two_bignum_1 (bignum number, bignum divisor, | |
1665 Lisp_Object *res, Lisp_Object *remain) | |
1666 { | |
1667 bignum flooring, floored, hi2, flsecond; | |
1668 | |
1669 if (bignum_divisible_p (number, divisor)) | |
1670 { | |
1671 bignum_div (scratch_bignum, number, divisor); | |
1672 *res = make_bignum_bg (scratch_bignum); | |
1673 *remain = Qzero; | |
1674 return; | |
1675 } | |
1676 | |
1677 bignum_set_long (scratch_bignum, 2); | |
1678 | |
1679 bignum_div (scratch_bignum2, divisor, scratch_bignum); | |
1680 | |
1681 bignum_init (hi2); | |
1682 bignum_set (hi2, scratch_bignum2); | |
1683 | |
1684 bignum_add (scratch_bignum, scratch_bignum2, number); | |
1685 bignum_init (flooring); | |
1686 bignum_set (flooring, scratch_bignum); | |
1687 | |
1688 bignum_floor (scratch_bignum, flooring, divisor); | |
1689 bignum_init (floored); | |
1690 bignum_set (floored, scratch_bignum); | |
1691 | |
1692 bignum_mul (scratch_bignum2, scratch_bignum, divisor); | |
1693 bignum_sub (scratch_bignum, flooring, scratch_bignum2); | |
1694 bignum_init (flsecond); | |
1695 bignum_set (flsecond, scratch_bignum); | |
1696 | |
1697 bignum_set_long (scratch_bignum, 2); | |
1698 bignum_mul (scratch_bignum2, scratch_bignum, hi2); | |
1699 | |
1700 if (bignum_sign (flsecond) == 0 | |
1701 && bignum_eql (divisor, scratch_bignum2) | |
1702 && (1 == bignum_testbit (floored, 0))) | |
1703 { | |
1704 bignum_set_long (scratch_bignum, 1); | |
1705 bignum_sub (floored, floored, scratch_bignum); | |
1706 *res = make_bignum_bg (floored); | |
1707 *remain = make_bignum_bg (hi2); | |
1708 } | |
1709 else | |
1710 { | |
1711 bignum_sub (scratch_bignum, flsecond, | |
1712 hi2); | |
1713 *res = make_bignum_bg (floored); | |
1714 *remain = make_bignum_bg (scratch_bignum); | |
1715 } | |
1716 } | |
1717 | |
1718 static Lisp_Object | |
1719 round_two_bignum (Lisp_Object number, Lisp_Object divisor, | |
1720 int return_float) | |
1721 { | |
1722 Lisp_Object res0, res1; | |
1723 | |
1724 if (bignum_sign (XBIGNUM_DATA (divisor)) == 0) | |
1725 { | |
1726 Fsignal (Qarith_error, Qnil); | |
1727 } | |
1728 | |
1729 round_two_bignum_1 (XBIGNUM_DATA (number), XBIGNUM_DATA (divisor), | |
1730 &res0, &res1); | |
1731 | |
1732 if (return_float) | |
1733 { | |
1734 res0 = make_float (bignum_to_double (XBIGNUM_DATA (res0))); | |
1735 } | |
1736 else | |
1737 { | |
1738 res0 = Fcanonicalize_number (res0); | |
1739 } | |
1740 | |
1741 return values2 (res0, Fcanonicalize_number (res1)); | |
1742 } | |
1743 #endif /* HAVE_BIGNUM */ | |
869 | 1744 |
870 #ifdef HAVE_RATIO | 1745 #ifdef HAVE_RATIO |
871 if (RATIOP (number)) | 1746 static Lisp_Object |
872 { | 1747 round_two_ratio (Lisp_Object number, Lisp_Object divisor, |
873 bignum_ceil (scratch_bignum, XRATIO_NUMERATOR (number), | 1748 int return_float) |
874 XRATIO_DENOMINATOR (number)); | 1749 { |
875 return Fcanonicalize_number (make_bignum_bg (scratch_bignum)); | 1750 Lisp_Object res0, res1; |
876 } | 1751 |
877 #endif | 1752 if (ratio_sign (XRATIO_DATA (divisor)) == 0) |
1753 { | |
1754 Fsignal (Qarith_error, Qnil); | |
1755 } | |
1756 | |
1757 ratio_div (scratch_ratio, XRATIO_DATA (number), XRATIO_DATA (divisor)); | |
1758 | |
1759 round_two_bignum_1 (ratio_numerator (scratch_ratio), | |
1760 ratio_denominator (scratch_ratio), &res0, &res1); | |
1761 | |
1762 if (!ZEROP (res1)) | |
1763 { | |
1764 /* The numerator and denominator don't round exactly, calculate a | |
1765 ratio remainder: */ | |
1766 ratio_set_bignum (scratch_ratio2, XBIGNUM_DATA (res0)); | |
1767 ratio_mul (scratch_ratio, scratch_ratio2, XRATIO_DATA (divisor)); | |
1768 ratio_sub (scratch_ratio, XRATIO_DATA (number), scratch_ratio); | |
1769 | |
1770 res1 = Fcanonicalize_number (make_ratio_rt (scratch_ratio)); | |
1771 } | |
1772 | |
1773 res0 = return_float ? | |
1774 make_float ((double)bignum_to_double(XBIGNUM_DATA (res0))) : | |
1775 Fcanonicalize_number (res0); | |
1776 | |
1777 return values2 (res0, res1); | |
1778 } | |
1779 #endif /* HAVE_RATIO */ | |
878 | 1780 |
879 #ifdef HAVE_BIGFLOAT | 1781 #ifdef HAVE_BIGFLOAT |
880 if (BIGFLOATP (number)) | 1782 /* This is the logic of emacs_rint above, no more and no less. */ |
881 { | 1783 static Lisp_Object |
882 bigfloat_set_prec (scratch_bigfloat, XBIGFLOAT_GET_PREC (number)); | 1784 round_one_bigfloat_1 (bigfloat number) |
883 bigfloat_ceil (scratch_bigfloat, XBIGFLOAT_DATA (number)); | 1785 { |
1786 Lisp_Object res0; | |
1787 unsigned long prec = bigfloat_get_prec (number); | |
1788 | |
1789 assert ((bigfloat *)(&number) != (bigfloat *)&scratch_bigfloat | |
1790 && (bigfloat *)(&number) != (bigfloat *)(&scratch_bigfloat2)); | |
1791 | |
1792 bigfloat_set_prec (scratch_bigfloat, prec); | |
1793 bigfloat_set_prec (scratch_bigfloat2, prec); | |
1794 | |
1795 bigfloat_set_double (scratch_bigfloat, 0.5); | |
1796 bigfloat_add (scratch_bigfloat2, scratch_bigfloat, number); | |
1797 bigfloat_floor (scratch_bigfloat, scratch_bigfloat2); | |
1798 res0 = make_bigfloat_bf (scratch_bigfloat); | |
1799 | |
1800 bigfloat_sub (scratch_bigfloat2, scratch_bigfloat, number); | |
1801 bigfloat_abs (scratch_bigfloat, scratch_bigfloat2); | |
1802 | |
1803 bigfloat_set_double (scratch_bigfloat2, 0.5); | |
1804 | |
1805 do { | |
1806 if (!bigfloat_ge (scratch_bigfloat, scratch_bigfloat2)) | |
1807 { | |
1808 break; | |
1809 } | |
1810 | |
1811 if (!bigfloat_gt (scratch_bigfloat, scratch_bigfloat2)) | |
1812 { | |
1813 bigfloat_set_double (scratch_bigfloat2, 2.0); | |
1814 bigfloat_div (scratch_bigfloat, XBIGFLOAT_DATA (res0), | |
1815 scratch_bigfloat2); | |
1816 bigfloat_floor (scratch_bigfloat2, scratch_bigfloat); | |
1817 bigfloat_set_double (scratch_bigfloat, 2.0); | |
1818 bigfloat_mul (scratch_bigfloat2, scratch_bigfloat2, | |
1819 scratch_bigfloat); | |
1820 if (bigfloat_eql (scratch_bigfloat2, XBIGFLOAT_DATA (res0))) | |
1821 { | |
1822 break; | |
1823 } | |
1824 } | |
1825 | |
1826 if (bigfloat_lt (XBIGFLOAT_DATA (res0), number)) | |
1827 { | |
1828 bigfloat_set_double (scratch_bigfloat2, 1.0); | |
1829 } | |
1830 else | |
1831 { | |
1832 bigfloat_set_double (scratch_bigfloat2, -1.0); | |
1833 } | |
1834 | |
1835 bigfloat_set (scratch_bigfloat, XBIGFLOAT_DATA (res0)); | |
1836 | |
1837 bigfloat_add (XBIGFLOAT_DATA (res0), scratch_bigfloat2, | |
1838 scratch_bigfloat); | |
1839 | |
1840 } while (0); | |
1841 | |
1842 return res0; | |
1843 } | |
1844 | |
1845 static Lisp_Object | |
1846 round_two_bigfloat (Lisp_Object number, Lisp_Object divisor, | |
1847 int return_float) | |
1848 { | |
1849 Lisp_Object res0, res1; | |
1850 bigfloat divided; | |
1851 | |
1852 unsigned long prec = max (XBIGFLOAT_GET_PREC (number), | |
1853 XBIGFLOAT_GET_PREC (divisor)); | |
1854 | |
1855 if (bigfloat_sign (XBIGFLOAT_DATA (divisor)) == 0) | |
1856 { | |
1857 Fsignal (Qarith_error, Qnil); | |
1858 } | |
1859 | |
1860 bigfloat_init (divided); | |
1861 bigfloat_set_prec (divided, prec); | |
1862 | |
1863 bigfloat_div (divided, XBIGFLOAT_DATA (number), XBIGFLOAT_DATA (divisor)); | |
1864 | |
1865 res0 = round_one_bigfloat_1 (divided); | |
1866 | |
1867 bigfloat_set_prec (scratch_bigfloat, prec); | |
1868 bigfloat_set_prec (scratch_bigfloat2, prec); | |
1869 | |
1870 bigfloat_mul (scratch_bigfloat, XBIGFLOAT_DATA (res0), | |
1871 XBIGFLOAT_DATA (divisor)); | |
1872 bigfloat_sub (scratch_bigfloat2, XBIGFLOAT_DATA (number), | |
1873 scratch_bigfloat); | |
1874 | |
1875 res1 = make_bigfloat_bf (scratch_bigfloat2); | |
1876 | |
1877 if (!return_float) | |
1878 { | |
1879 #ifdef HAVE_BIGNUM | |
1880 bignum_set_bigfloat (scratch_bignum, XBIGFLOAT_DATA (res0)); | |
1881 res0 = Fcanonicalize_number (make_bignum_bg (scratch_bignum)); | |
1882 #else | |
1883 res0 = make_int ((EMACS_INT) bigfloat_to_long (XBIGFLOAT_DATA (res0))); | |
1884 #endif /* HAVE_BIGNUM */ | |
1885 } | |
1886 | |
1887 return values2 (res0, res1); | |
1888 } | |
1889 #endif /* HAVE_BIGFLOAT */ | |
1890 | |
1891 #ifdef HAVE_RATIO | |
1892 static Lisp_Object | |
1893 round_one_ratio (Lisp_Object number, Lisp_Object UNUSED (divisor), | |
1894 int return_float) | |
1895 { | |
1896 Lisp_Object res0, res1; | |
1897 | |
1898 round_two_bignum_1 (XRATIO_NUMERATOR (number), XRATIO_DENOMINATOR (number), | |
1899 &res0, &res1); | |
1900 | |
1901 if (!ZEROP (res1)) | |
1902 { | |
1903 ratio_set_bignum (scratch_ratio2, XBIGNUM_DATA (res0)); | |
1904 ratio_sub (scratch_ratio, XRATIO_DATA (number), scratch_ratio2); | |
1905 res1 = Fcanonicalize_number (make_ratio_rt (scratch_ratio)); | |
1906 } | |
1907 | |
1908 res0 = return_float ? | |
1909 make_float ((double)bignum_to_double(XBIGNUM_DATA (res0))) : | |
1910 Fcanonicalize_number (res0); | |
1911 | |
1912 return values2 (res0, res1); | |
1913 } | |
1914 #endif /* HAVE_RATIO */ | |
1915 | |
1916 #ifdef HAVE_BIGFLOAT | |
1917 static Lisp_Object | |
1918 round_one_bigfloat (Lisp_Object number, Lisp_Object UNUSED (divisor), | |
1919 int return_float) | |
1920 { | |
1921 Lisp_Object res0 = round_one_bigfloat_1 (XBIGFLOAT_DATA (number)); | |
1922 Lisp_Object res1; | |
1923 | |
1924 bigfloat_sub (scratch_bigfloat, XBIGFLOAT_DATA (number), | |
1925 XBIGFLOAT_DATA (res0)); | |
1926 | |
1927 res1 = make_bigfloat_bf (scratch_bigfloat); | |
1928 | |
1929 if (!return_float) | |
1930 { | |
1931 #ifdef HAVE_BIGNUM | |
1932 bignum_set_bigfloat (scratch_bignum, XBIGFLOAT_DATA (res0)); | |
1933 res0 = Fcanonicalize_number (make_bignum_bg (scratch_bignum)); | |
1934 #else | |
1935 res0 = make_int ((EMACS_INT) bigfloat_to_long | |
1936 (XBIGFLOAT_DATA (res0))); | |
1937 #endif /* HAVE_BIGNUM */ | |
1938 } | |
1939 | |
1940 return values2 (res0, res1); | |
1941 } | |
1942 #endif /* HAVE_BIGFLOAT */ | |
1943 | |
1944 static Lisp_Object | |
1945 round_two_float (Lisp_Object number, Lisp_Object divisor, | |
1946 int return_float) | |
1947 { | |
1948 double f1 = extract_float (number); | |
1949 double f2 = extract_float (divisor); | |
1950 double f0, remain; | |
1951 | |
1952 if (f2 == 0.0) | |
1953 Fsignal (Qarith_error, Qnil); | |
1954 | |
1955 IN_FLOAT2 ((f0 = emacs_rint (f1 / f2)), MAYBE_EFF ("round"), number, | |
1956 divisor); | |
1957 IN_FLOAT2 (remain = f1 - (f0 * f2), MAYBE_EFF ("round"), number, divisor); | |
1958 | |
1959 if (return_float) | |
1960 { | |
1961 return values2 (make_float (f0), make_float (remain)); | |
1962 } | |
1963 else | |
1964 { | |
1965 return values2 (float_to_int (f0, MAYBE_EFF("round"), number, divisor), | |
1966 make_float (remain)); | |
1967 } | |
1968 } | |
1969 | |
1970 static Lisp_Object | |
1971 round_one_float (Lisp_Object number, int return_float) | |
1972 { | |
1973 double d; | |
1974 /* Screw the prevailing rounding mode. */ | |
1975 IN_FLOAT ((d = emacs_rint (XFLOAT_DATA (number))), MAYBE_EFF ("round"), | |
1976 number); | |
1977 | |
1978 if (return_float) | |
1979 { | |
1980 return values2 (make_float (d), make_float (XFLOAT_DATA (number) - d)); | |
1981 } | |
1982 else | |
1983 { | |
1984 return values2 ((float_to_int (d, MAYBE_EFF ("round"), number, | |
1985 Qunbound)), | |
1986 make_float (XFLOAT_DATA (number) - d)); | |
1987 } | |
1988 } | |
1989 | |
1990 EXFUN (Fround, 2); | |
1991 EXFUN (Ffround, 2); | |
1992 | |
1993 static Lisp_Object | |
1994 round_one_mundane_arg (Lisp_Object number, Lisp_Object divisor, | |
1995 int return_float) | |
1996 { | |
1997 #ifdef HAVE_BIGNUM | |
1998 if (INTEGERP (number)) | |
1999 #else | |
2000 if (INTP (number)) | |
2001 #endif | |
2002 { | |
2003 if (return_float) | |
2004 { | |
2005 return values2 (make_float (extract_float (number)), Qzero); | |
2006 } | |
2007 else | |
2008 { | |
2009 return values2 (number, Qzero); | |
2010 } | |
2011 } | |
2012 | |
2013 MAYBE_CHAR_OR_MARKER (round); | |
2014 | |
2015 if (return_float) | |
2016 { | |
2017 return Ffround (wrong_type_argument (Qnumberp, number), divisor); | |
2018 } | |
2019 else | |
2020 { | |
2021 return Fround (wrong_type_argument (Qnumberp, number), divisor); | |
2022 } | |
2023 } | |
2024 | |
2025 static Lisp_Object | |
2026 truncate_two_fixnum (Lisp_Object number, Lisp_Object divisor, | |
2027 int return_float) | |
2028 { | |
2029 EMACS_INT i1 = XREALINT (number); | |
2030 EMACS_INT i2 = XREALINT (divisor); | |
2031 EMACS_INT i0; | |
2032 | |
2033 if (i2 == 0) | |
2034 Fsignal (Qarith_error, Qnil); | |
2035 | |
2036 /* We're truncating towards zero, so apart from avoiding the C89 | |
2037 implementation-defined behaviour with truncation and negative numbers, | |
2038 we don't need to do anything further: */ | |
2039 i0 = (i2 < 0 | |
2040 ? (i1 <= 0 ? -i1 / -i2 : -(i1 / -i2)) | |
2041 : (i1 < 0 ? -(-i1 / i2) : i1 / i2)); | |
2042 | |
2043 if (return_float) | |
2044 { | |
2045 return values2 (make_float ((double)i0), make_int (i1 - (i0 * i2))); | |
2046 } | |
2047 else | |
2048 { | |
2049 return values2 (make_int (i0), make_int (i1 - (i0 * i2))); | |
2050 } | |
2051 } | |
2052 | |
2053 #ifdef HAVE_BIGNUM | |
2054 static Lisp_Object | |
2055 truncate_two_bignum (Lisp_Object number, Lisp_Object divisor, | |
2056 int return_float) | |
2057 { | |
2058 Lisp_Object res0; | |
2059 | |
2060 if (bignum_sign (XBIGNUM_DATA (divisor)) == 0) | |
2061 { | |
2062 Fsignal (Qarith_error, Qnil); | |
2063 } | |
2064 | |
2065 bignum_div (scratch_bignum, XBIGNUM_DATA (number), | |
2066 XBIGNUM_DATA (divisor)); | |
2067 | |
2068 if (return_float) | |
2069 { | |
2070 res0 = make_float (bignum_to_double (scratch_bignum)); | |
2071 } | |
2072 else | |
2073 { | |
2074 res0 = make_bignum_bg (scratch_bignum); | |
2075 } | |
2076 | |
2077 if (bignum_divisible_p (XBIGNUM_DATA (number), | |
2078 XBIGNUM_DATA (divisor))) | |
2079 { | |
2080 return values2 (Fcanonicalize_number (res0), Qzero); | |
2081 } | |
2082 | |
2083 bignum_mul (scratch_bignum2, scratch_bignum, XBIGNUM_DATA (divisor)); | |
2084 bignum_sub (scratch_bignum, XBIGNUM_DATA (number), scratch_bignum2); | |
2085 | |
2086 return values2 (Fcanonicalize_number (res0), | |
2087 Fcanonicalize_number (make_bignum_bg (scratch_bignum))); | |
2088 } | |
2089 #endif /* HAVE_BIGNUM */ | |
2090 | |
2091 #ifdef HAVE_RATIO | |
2092 static Lisp_Object | |
2093 truncate_two_ratio (Lisp_Object number, Lisp_Object divisor, | |
2094 int return_float) | |
2095 { | |
2096 Lisp_Object res0; | |
2097 | |
2098 if (ratio_sign (XRATIO_DATA (divisor)) == 0) | |
2099 { | |
2100 Fsignal (Qarith_error, Qnil); | |
2101 } | |
2102 | |
2103 ratio_div (scratch_ratio, XRATIO_DATA (number), XRATIO_DATA (divisor)); | |
2104 | |
2105 bignum_div (scratch_bignum, ratio_numerator (scratch_ratio), | |
2106 ratio_denominator (scratch_ratio)); | |
2107 | |
2108 if (return_float) | |
2109 { | |
2110 res0 = make_float (bignum_to_double (scratch_bignum)); | |
2111 } | |
2112 else | |
2113 { | |
2114 res0 = Fcanonicalize_number (make_bignum_bg (scratch_bignum)); | |
2115 } | |
2116 | |
2117 if (bignum_divisible_p (ratio_numerator (scratch_ratio), | |
2118 ratio_denominator (scratch_ratio))) | |
2119 { | |
2120 return values2 (res0, Qzero); | |
2121 } | |
2122 | |
2123 ratio_set_bignum (scratch_ratio2, scratch_bignum); | |
2124 ratio_mul (scratch_ratio, scratch_ratio2, XRATIO_DATA (divisor)); | |
2125 ratio_sub (scratch_ratio2, XRATIO_DATA (number), scratch_ratio); | |
2126 | |
2127 return values2 (res0, Fcanonicalize_number (make_ratio_rt(scratch_ratio2))); | |
2128 } | |
2129 #endif | |
2130 | |
2131 #ifdef HAVE_BIGFLOAT | |
2132 static Lisp_Object | |
2133 truncate_two_bigfloat (Lisp_Object number, Lisp_Object divisor, | |
2134 int return_float) | |
2135 { | |
2136 Lisp_Object res0; | |
2137 unsigned long prec = max (XBIGFLOAT_GET_PREC (number), | |
2138 XBIGFLOAT_GET_PREC (divisor)); | |
2139 | |
2140 if (bigfloat_sign (XBIGFLOAT_DATA (divisor)) == 0) | |
2141 { | |
2142 Fsignal (Qarith_error, Qnil); | |
2143 } | |
2144 | |
2145 bigfloat_set_prec (scratch_bigfloat, prec); | |
2146 bigfloat_set_prec (scratch_bigfloat2, prec); | |
2147 | |
2148 bigfloat_div (scratch_bigfloat, XBIGFLOAT_DATA (number), | |
2149 XBIGFLOAT_DATA (divisor)); | |
2150 bigfloat_trunc (scratch_bigfloat, scratch_bigfloat); | |
2151 | |
2152 if (return_float) | |
2153 { | |
2154 res0 = make_bigfloat_bf (scratch_bigfloat); | |
2155 } | |
2156 else | |
2157 { | |
884 #ifdef HAVE_BIGNUM | 2158 #ifdef HAVE_BIGNUM |
885 bignum_set_bigfloat (scratch_bignum, scratch_bigfloat); | 2159 bignum_set_bigfloat (scratch_bignum, scratch_bigfloat); |
886 return Fcanonicalize_number (make_bignum_bg (scratch_bignum)); | 2160 res0 = Fcanonicalize_number (make_bignum_bg (scratch_bignum)); |
887 #else | 2161 #else |
888 return make_int ((EMACS_INT) bigfloat_to_long (scratch_bigfloat)); | 2162 res0 = make_int ((EMACS_INT) bigfloat_to_long (scratch_bigfloat)); |
889 #endif /* HAVE_BIGNUM */ | 2163 #endif /* HAVE_BIGNUM */ |
890 } | 2164 } |
2165 | |
2166 bigfloat_mul (scratch_bigfloat2, scratch_bigfloat, XBIGFLOAT_DATA (divisor)); | |
2167 bigfloat_sub (scratch_bigfloat, XBIGFLOAT_DATA (number), scratch_bigfloat2); | |
2168 | |
2169 return values2 (res0, make_bigfloat_bf (scratch_bigfloat)); | |
2170 } | |
891 #endif /* HAVE_BIGFLOAT */ | 2171 #endif /* HAVE_BIGFLOAT */ |
892 | 2172 |
893 return Fceiling (wrong_type_argument (Qnumberp, number)); | 2173 #ifdef HAVE_RATIO |
894 } | 2174 static Lisp_Object |
895 | 2175 truncate_one_ratio (Lisp_Object number, Lisp_Object UNUSED (divisor), |
2176 int return_float) | |
2177 { | |
2178 Lisp_Object res0; | |
2179 | |
2180 if (ratio_sign (XRATIO_DATA (number)) == 0) | |
2181 { | |
2182 Fsignal (Qarith_error, Qnil); | |
2183 } | |
2184 | |
2185 bignum_div (scratch_bignum, XRATIO_NUMERATOR (number), | |
2186 XRATIO_DENOMINATOR (number)); | |
2187 if (return_float) | |
2188 { | |
2189 res0 = make_float (bignum_to_double (scratch_bignum)); | |
2190 } | |
2191 else | |
2192 { | |
2193 res0 = Fcanonicalize_number (make_bignum_bg (scratch_bignum)); | |
2194 } | |
2195 | |
2196 if (bignum_divisible_p (XRATIO_NUMERATOR (number), | |
2197 XRATIO_DENOMINATOR (number))) | |
2198 { | |
2199 return values2 (res0, Qzero); | |
2200 } | |
2201 | |
2202 ratio_set_bignum (scratch_ratio2, scratch_bignum); | |
2203 ratio_sub (scratch_ratio, XRATIO_DATA (number), scratch_ratio2); | |
2204 | |
2205 return values2 (res0, Fcanonicalize_number (make_ratio_rt (scratch_ratio))); | |
2206 } | |
2207 #endif /* HAVE_RATIO */ | |
2208 | |
2209 #ifdef HAVE_BIGFLOAT | |
2210 static Lisp_Object | |
2211 truncate_one_bigfloat (Lisp_Object number, Lisp_Object UNUSED (divisor), | |
2212 int return_float) | |
2213 { | |
2214 Lisp_Object res0; | |
2215 | |
2216 bigfloat_set_prec (scratch_bigfloat, XBIGFLOAT_GET_PREC (number)); | |
2217 bigfloat_set_prec (scratch_bigfloat2, XBIGFLOAT_GET_PREC (number)); | |
2218 bigfloat_trunc (scratch_bigfloat, XBIGFLOAT_DATA (number)); | |
2219 | |
2220 if (return_float) | |
2221 { | |
2222 res0 = make_bigfloat_bf (scratch_bigfloat); | |
2223 } | |
2224 else | |
2225 { | |
2226 #ifdef HAVE_BIGNUM | |
2227 bignum_set_bigfloat (scratch_bignum, scratch_bigfloat); | |
2228 res0 = Fcanonicalize_number (make_bignum_bg (scratch_bignum)); | |
2229 #else | |
2230 res0 = make_int ((EMACS_INT) bigfloat_to_long (scratch_bigfloat)); | |
2231 #endif /* HAVE_BIGNUM */ | |
2232 } | |
2233 | |
2234 bigfloat_sub (scratch_bigfloat2, XBIGFLOAT_DATA (number), scratch_bigfloat); | |
2235 | |
2236 return | |
2237 values2 (res0, | |
2238 Fcanonicalize_number (make_bigfloat_bf (scratch_bigfloat2))); | |
2239 } | |
2240 #endif /* HAVE_BIGFLOAT */ | |
2241 | |
2242 static Lisp_Object | |
2243 truncate_two_float (Lisp_Object number, Lisp_Object divisor, | |
2244 int return_float) | |
2245 { | |
2246 double f1 = extract_float (number); | |
2247 double f2 = extract_float (divisor); | |
2248 double f0, remain; | |
2249 Lisp_Object res0; | |
2250 | |
2251 if (f2 == 0.0) | |
2252 { | |
2253 Fsignal (Qarith_error, Qnil); | |
2254 } | |
2255 | |
2256 res0 = float_to_int (f1 / f2, MAYBE_EFF ("truncate"), number, Qunbound); | |
2257 f0 = extract_float (res0); | |
2258 | |
2259 IN_FLOAT2 (remain = f1 - (f0 * f2), MAYBE_EFF ("truncate"), number, divisor); | |
2260 | |
2261 if (return_float) | |
2262 { | |
2263 res0 = make_float (f0); | |
2264 } | |
2265 | |
2266 return values2 (res0, make_float (remain)); | |
2267 } | |
2268 | |
2269 static Lisp_Object | |
2270 truncate_one_float (Lisp_Object number, int return_float) | |
2271 { | |
2272 Lisp_Object res0 | |
2273 = float_to_int (XFLOAT_DATA (number), MAYBE_EFF ("truncate"), | |
2274 number, Qunbound); | |
2275 if (return_float) | |
2276 { | |
2277 res0 = make_float ((double)XINT(res0)); | |
2278 return values2 (res0, make_float ((XFLOAT_DATA (number) | |
2279 - XFLOAT_DATA (res0)))); | |
2280 } | |
2281 else | |
2282 { | |
2283 return values2 (res0, make_float (XFLOAT_DATA (number) | |
2284 - XREALINT (res0))); | |
2285 } | |
2286 } | |
2287 | |
2288 EXFUN (Fftruncate, 2); | |
2289 | |
2290 static Lisp_Object | |
2291 truncate_one_mundane_arg (Lisp_Object number, Lisp_Object divisor, | |
2292 int return_float) | |
2293 { | |
2294 #ifdef HAVE_BIGNUM | |
2295 if (INTEGERP (number)) | |
2296 #else | |
2297 if (INTP (number)) | |
2298 #endif | |
2299 { | |
2300 if (return_float) | |
2301 { | |
2302 return values2 (make_float (extract_float (number)), Qzero); | |
2303 } | |
2304 else | |
2305 { | |
2306 return values2 (number, Qzero); | |
2307 } | |
2308 } | |
2309 | |
2310 MAYBE_CHAR_OR_MARKER (truncate); | |
2311 | |
2312 if (return_float) | |
2313 { | |
2314 return Fftruncate (wrong_type_argument (Qnumberp, number), divisor); | |
2315 } | |
2316 else | |
2317 { | |
2318 return Ftruncate (wrong_type_argument (Qnumberp, number), divisor); | |
2319 } | |
2320 } | |
2321 | |
2322 /* Rounding functions that will not necessarily return floats: */ | |
2323 | |
2324 DEFUN ("ceiling", Fceiling, 1, 2, 0, /* | |
2325 Return the smallest integer no less than NUMBER. (Round toward +inf.) | |
2326 | |
2327 With optional argument DIVISOR, return the smallest integer no less than | |
2328 the quotient of NUMBER and DIVISOR. | |
2329 | |
2330 This function returns multiple values; see `multiple-value-bind' and | |
2331 `multiple-value-call'. The second returned value is the remainder in the | |
2332 calculation, which will be one minus the fractional part of NUMBER if DIVISOR | |
2333 is omitted or one. | |
2334 */ | |
2335 (number, divisor)) | |
2336 { | |
2337 ROUNDING_CONVERT(ceiling, 0); | |
2338 } | |
896 | 2339 |
897 DEFUN ("floor", Ffloor, 1, 2, 0, /* | 2340 DEFUN ("floor", Ffloor, 1, 2, 0, /* |
898 Return the largest integer no greater than NUMBER. (Round towards -inf.) | 2341 Return the largest integer no greater than NUMBER. (Round towards -inf.) |
899 With optional second argument DIVISOR, return the largest integer no | 2342 With optional second argument DIVISOR, return the largest integer no |
900 greater than NUMBER/DIVISOR. | 2343 greater than the quotient of NUMBER and DIVISOR. |
2344 | |
2345 This function returns multiple values; see `multiple-value-call' and | |
2346 `multiple-value-bind'. The second returned value is the remainder in the | |
2347 calculation, which will just be the fractional part if DIVISOR is omitted or | |
2348 one. | |
901 */ | 2349 */ |
902 (number, divisor)) | 2350 (number, divisor)) |
903 { | 2351 { |
904 #ifdef WITH_NUMBER_TYPES | 2352 ROUNDING_CONVERT(floor, 0); |
905 CHECK_REAL (number); | 2353 } |
906 if (NILP (divisor)) | 2354 |
907 { | 2355 DEFUN ("round", Fround, 1, 2, 0, /* |
908 if (FLOATP (number)) | |
909 { | |
910 double d; | |
911 IN_FLOAT ((d = floor (XFLOAT_DATA (number))), "floor", number); | |
912 return (float_to_int (d, "floor", number, Qunbound)); | |
913 } | |
914 #ifdef HAVE_RATIO | |
915 else if (RATIOP (number)) | |
916 { | |
917 bignum_floor (scratch_bignum, XRATIO_NUMERATOR (number), | |
918 XRATIO_DENOMINATOR (number)); | |
919 return Fcanonicalize_number (make_bignum_bg (scratch_bignum)); | |
920 } | |
921 #endif | |
922 #ifdef HAVE_BIGFLOAT | |
923 else if (BIGFLOATP (number)) | |
924 { | |
925 bigfloat_set_prec (scratch_bigfloat, XBIGFLOAT_GET_PREC (number)); | |
926 bigfloat_floor (scratch_bigfloat, XBIGFLOAT_DATA (number)); | |
927 return make_bigfloat_bf (scratch_bigfloat); | |
928 } | |
929 #endif | |
930 return number; | |
931 } | |
932 else | |
933 { | |
934 CHECK_REAL (divisor); | |
935 switch (promote_args (&number, &divisor)) | |
936 { | |
937 case FIXNUM_T: | |
938 { | |
939 EMACS_INT i1 = XREALINT (number); | |
940 EMACS_INT i2 = XREALINT (divisor); | |
941 | |
942 if (i2 == 0) | |
943 Fsignal (Qarith_error, Qnil); | |
944 | |
945 /* With C's /, the result is implementation-defined if either | |
946 operand is negative, so use only nonnegative operands. */ | |
947 i1 = (i2 < 0 | |
948 ? (i1 <= 0 ? -i1 / -i2 : -1 - ((i1 - 1) / -i2)) | |
949 : (i1 < 0 ? -1 - ((-1 - i1) / i2) : i1 / i2)); | |
950 | |
951 return make_int (i1); | |
952 } | |
953 #ifdef HAVE_BIGNUM | |
954 case BIGNUM_T: | |
955 if (bignum_sign (XBIGNUM_DATA (divisor)) == 0) | |
956 Fsignal (Qarith_error, Qnil); | |
957 bignum_floor (scratch_bignum, XBIGNUM_DATA (number), | |
958 XBIGNUM_DATA (divisor)); | |
959 return Fcanonicalize_number (make_bignum_bg (scratch_bignum)); | |
960 #endif | |
961 #ifdef HAVE_RATIO | |
962 case RATIO_T: | |
963 if (ratio_sign (XRATIO_DATA (divisor)) == 0) | |
964 Fsignal (Qarith_error, Qnil); | |
965 ratio_div (scratch_ratio, XRATIO_DATA (number), | |
966 XRATIO_DATA (divisor)); | |
967 bignum_floor (scratch_bignum, ratio_numerator (scratch_ratio), | |
968 ratio_denominator (scratch_ratio)); | |
969 return Fcanonicalize_number (make_bignum_bg (scratch_bignum)); | |
970 #endif | |
971 #ifdef HAVE_BIGFLOAT | |
972 case BIGFLOAT_T: | |
973 if (bigfloat_sign (XBIGFLOAT_DATA (divisor)) == 0) | |
974 Fsignal (Qarith_error, Qnil); | |
975 bigfloat_set_prec (scratch_bigfloat, | |
976 max (XBIGFLOAT_GET_PREC (number), | |
977 XBIGFLOAT_GET_PREC (divisor))); | |
978 bigfloat_div (scratch_bigfloat, XBIGFLOAT_DATA (number), | |
979 XBIGFLOAT_DATA (divisor)); | |
980 bigfloat_floor (scratch_bigfloat, scratch_bigfloat); | |
981 return make_bigfloat_bf (scratch_bigfloat); | |
982 #endif | |
983 default: /* FLOAT_T */ | |
984 { | |
985 double f1 = extract_float (number); | |
986 double f2 = extract_float (divisor); | |
987 | |
988 if (f2 == 0.0) | |
989 Fsignal (Qarith_error, Qnil); | |
990 | |
991 IN_FLOAT2 (f1 = floor (f1 / f2), "floor", number, divisor); | |
992 return float_to_int (f1, "floor", number, divisor); | |
993 } | |
994 } | |
995 } | |
996 #else /* !WITH_NUMBER_TYPES */ | |
997 CHECK_INT_OR_FLOAT (number); | |
998 | |
999 if (! NILP (divisor)) | |
1000 { | |
1001 EMACS_INT i1, i2; | |
1002 | |
1003 CHECK_INT_OR_FLOAT (divisor); | |
1004 | |
1005 if (FLOATP (number) || FLOATP (divisor)) | |
1006 { | |
1007 double f1 = extract_float (number); | |
1008 double f2 = extract_float (divisor); | |
1009 | |
1010 if (f2 == 0) | |
1011 Fsignal (Qarith_error, Qnil); | |
1012 | |
1013 IN_FLOAT2 (f1 = floor (f1 / f2), "floor", number, divisor); | |
1014 return float_to_int (f1, "floor", number, divisor); | |
1015 } | |
1016 | |
1017 i1 = XINT (number); | |
1018 i2 = XINT (divisor); | |
1019 | |
1020 if (i2 == 0) | |
1021 Fsignal (Qarith_error, Qnil); | |
1022 | |
1023 /* With C's /, the result is implementation-defined if either operand | |
1024 is negative, so use only nonnegative operands. */ | |
1025 i1 = (i2 < 0 | |
1026 ? (i1 <= 0 ? -i1 / -i2 : -1 - ((i1 - 1) / -i2)) | |
1027 : (i1 < 0 ? -1 - ((-1 - i1) / i2) : i1 / i2)); | |
1028 | |
1029 return (make_int (i1)); | |
1030 } | |
1031 | |
1032 if (FLOATP (number)) | |
1033 { | |
1034 double d; | |
1035 IN_FLOAT ((d = floor (XFLOAT_DATA (number))), "floor", number); | |
1036 return (float_to_int (d, "floor", number, Qunbound)); | |
1037 } | |
1038 | |
1039 return number; | |
1040 #endif /* WITH_NUMBER_TYPES */ | |
1041 } | |
1042 | |
1043 DEFUN ("round", Fround, 1, 1, 0, /* | |
1044 Return the nearest integer to NUMBER. | 2356 Return the nearest integer to NUMBER. |
1045 */ | 2357 If NUMBER is exactly halfway between two integers, return the one that |
1046 (number)) | 2358 is even. |
1047 { | 2359 |
1048 if (FLOATP (number)) | 2360 Optional argument DIVISOR means return the nearest integer to NUMBER |
1049 { | 2361 divided by DIVISOR. |
1050 double d; | 2362 |
1051 /* Screw the prevailing rounding mode. */ | 2363 This function returns multiple values; see `multiple-value-call' and |
1052 IN_FLOAT ((d = emacs_rint (XFLOAT_DATA (number))), "round", number); | 2364 `multiple-value-bind'. The second returned value is the remainder |
1053 return (float_to_int (d, "round", number, Qunbound)); | 2365 in the calculation. |
1054 } | 2366 */ |
1055 | 2367 (number, divisor)) |
1056 #ifdef HAVE_BIGNUM | 2368 { |
1057 if (INTEGERP (number)) | 2369 ROUNDING_CONVERT(round, 0); |
1058 #else | 2370 } |
1059 if (INTP (number)) | 2371 |
1060 #endif | 2372 DEFUN ("truncate", Ftruncate, 1, 2, 0, /* |
1061 return number; | |
1062 | |
1063 #ifdef HAVE_RATIO | |
1064 if (RATIOP (number)) | |
1065 { | |
1066 if (bignum_divisible_p (XRATIO_NUMERATOR (number), | |
1067 XRATIO_DENOMINATOR (number))) | |
1068 { | |
1069 bignum_div (scratch_bignum, XRATIO_NUMERATOR (number), | |
1070 XRATIO_DENOMINATOR (number)); | |
1071 } | |
1072 else | |
1073 { | |
1074 bignum_add (scratch_bignum2, XRATIO_NUMERATOR (number), | |
1075 XRATIO_DENOMINATOR (number)); | |
1076 bignum_div (scratch_bignum, scratch_bignum2, | |
1077 XRATIO_DENOMINATOR (number)); | |
1078 } | |
1079 return Fcanonicalize_number (make_bignum_bg (scratch_bignum)); | |
1080 } | |
1081 #endif | |
1082 | |
1083 #ifdef HAVE_BIGFLOAT | |
1084 if (BIGFLOATP (number)) | |
1085 { | |
1086 unsigned long prec = XBIGFLOAT_GET_PREC (number); | |
1087 bigfloat_set_prec (scratch_bigfloat, prec); | |
1088 bigfloat_set_prec (scratch_bigfloat2, prec); | |
1089 bigfloat_set_double (scratch_bigfloat2, | |
1090 bigfloat_sign (XBIGFLOAT_DATA (number)) * 0.5); | |
1091 bigfloat_floor (scratch_bigfloat, scratch_bigfloat2); | |
1092 #ifdef HAVE_BIGNUM | |
1093 bignum_set_bigfloat (scratch_bignum, scratch_bigfloat); | |
1094 return Fcanonicalize_number (make_bignum_bg (scratch_bignum)); | |
1095 #else | |
1096 return make_int ((EMACS_INT) bigfloat_to_long (scratch_bigfloat)); | |
1097 #endif /* HAVE_BIGNUM */ | |
1098 } | |
1099 #endif /* HAVE_BIGFLOAT */ | |
1100 | |
1101 return Fround (wrong_type_argument (Qnumberp, number)); | |
1102 } | |
1103 | |
1104 DEFUN ("truncate", Ftruncate, 1, 1, 0, /* | |
1105 Truncate a floating point number to an integer. | 2373 Truncate a floating point number to an integer. |
1106 Rounds the value toward zero. | 2374 Rounds the value toward zero. |
1107 */ | 2375 |
1108 (number)) | 2376 Optional argument DIVISOR means truncate NUMBER divided by DIVISOR. |
1109 { | 2377 |
1110 if (FLOATP (number)) | 2378 This function returns multiple values; see `multiple-value-call' and |
1111 return float_to_int (XFLOAT_DATA (number), "truncate", number, Qunbound); | 2379 `multiple-value-bind'. The second returned value is the remainder. |
1112 | 2380 */ |
1113 #ifdef HAVE_BIGNUM | 2381 (number, divisor)) |
1114 if (INTEGERP (number)) | 2382 { |
1115 #else | 2383 ROUNDING_CONVERT(truncate, 0); |
1116 if (INTP (number)) | |
1117 #endif | |
1118 return number; | |
1119 | |
1120 #ifdef HAVE_RATIO | |
1121 if (RATIOP (number)) | |
1122 { | |
1123 bignum_div (scratch_bignum, XRATIO_NUMERATOR (number), | |
1124 XRATIO_DENOMINATOR (number)); | |
1125 return Fcanonicalize_number (make_bignum_bg (scratch_bignum)); | |
1126 } | |
1127 #endif | |
1128 | |
1129 #ifdef HAVE_BIGFLOAT | |
1130 if (BIGFLOATP (number)) | |
1131 { | |
1132 bigfloat_set_prec (scratch_bigfloat, XBIGFLOAT_GET_PREC (number)); | |
1133 bigfloat_trunc (scratch_bigfloat, XBIGFLOAT_DATA (number)); | |
1134 #ifdef HAVE_BIGNUM | |
1135 bignum_set_bigfloat (scratch_bignum, scratch_bigfloat); | |
1136 return Fcanonicalize_number (make_bignum_bg (scratch_bignum)); | |
1137 #else | |
1138 return make_int ((EMACS_INT) bigfloat_to_long (scratch_bigfloat)); | |
1139 #endif /* HAVE_BIGNUM */ | |
1140 } | |
1141 #endif /* HAVE_BIGFLOAT */ | |
1142 | |
1143 return Ftruncate (wrong_type_argument (Qnumberp, number)); | |
1144 } | 2384 } |
1145 | 2385 |
1146 /* Float-rounding functions. */ | 2386 /* Float-rounding functions. */ |
1147 | 2387 |
1148 DEFUN ("fceiling", Ffceiling, 1, 1, 0, /* | 2388 DEFUN ("fceiling", Ffceiling, 1, 2, 0, /* |
1149 Return the smallest integer no less than NUMBER, as a float. | 2389 Return the smallest integer no less than NUMBER, as a float. |
1150 \(Round toward +inf.\) | 2390 \(Round toward +inf.\) |
1151 */ | 2391 |
1152 (number)) | 2392 With optional argument DIVISOR, return the smallest integer no less than the |
1153 { | 2393 quotient of NUMBER and DIVISOR, as a float. |
1154 double d = extract_float (number); | 2394 |
1155 IN_FLOAT (d = ceil (d), "fceiling", number); | 2395 This function returns multiple values; the second value is the remainder in |
1156 return make_float (d); | 2396 the calculation. |
1157 } | 2397 */ |
1158 | 2398 (number, divisor)) |
1159 DEFUN ("ffloor", Fffloor, 1, 1, 0, /* | 2399 { |
2400 ROUNDING_CONVERT(ceiling, 1); | |
2401 } | |
2402 | |
2403 DEFUN ("ffloor", Fffloor, 1, 2, 0, /* | |
1160 Return the largest integer no greater than NUMBER, as a float. | 2404 Return the largest integer no greater than NUMBER, as a float. |
1161 \(Round towards -inf.\) | 2405 \(Round towards -inf.\) |
1162 */ | 2406 |
1163 (number)) | 2407 With optional argument DIVISOR, return the largest integer no greater than |
1164 { | 2408 the quotient of NUMBER and DIVISOR, as a float. |
1165 double d = extract_float (number); | 2409 |
1166 IN_FLOAT (d = floor (d), "ffloor", number); | 2410 This function returns multiple values; the second value is the remainder in |
1167 return make_float (d); | 2411 the calculation. |
1168 } | 2412 */ |
1169 | 2413 (number, divisor)) |
1170 DEFUN ("fround", Ffround, 1, 1, 0, /* | 2414 { |
2415 ROUNDING_CONVERT(floor, 1); | |
2416 } | |
2417 | |
2418 DEFUN ("fround", Ffround, 1, 2, 0, /* | |
1171 Return the nearest integer to NUMBER, as a float. | 2419 Return the nearest integer to NUMBER, as a float. |
1172 */ | 2420 If NUMBER is exactly halfway between two integers, return the one that is |
1173 (number)) | 2421 even. |
1174 { | 2422 |
1175 double d = extract_float (number); | 2423 With optional argument DIVISOR, return the nearest integer to the quotient |
1176 IN_FLOAT (d = emacs_rint (d), "fround", number); | 2424 of NUMBER and DIVISOR, as a float. |
1177 return make_float (d); | 2425 |
1178 } | 2426 This function returns multiple values; the second value is the remainder in |
1179 | 2427 the calculation. |
1180 DEFUN ("ftruncate", Fftruncate, 1, 1, 0, /* | 2428 */ |
2429 (number, divisor)) | |
2430 { | |
2431 ROUNDING_CONVERT(round, 1); | |
2432 } | |
2433 | |
2434 DEFUN ("ftruncate", Fftruncate, 1, 2, 0, /* | |
1181 Truncate a floating point number to an integral float value. | 2435 Truncate a floating point number to an integral float value. |
1182 Rounds the value toward zero. | 2436 Rounds the value toward zero. |
1183 */ | 2437 |
1184 (number)) | 2438 With optional argument DIVISOR, truncate the quotient of NUMBER and DIVISOR, |
1185 { | 2439 to an integral float value. |
1186 double d = extract_float (number); | 2440 |
1187 if (d >= 0.0) | 2441 This function returns multiple values; the second value is the remainder in |
1188 IN_FLOAT (d = floor (d), "ftruncate", number); | 2442 the calculation. |
1189 else | 2443 */ |
1190 IN_FLOAT (d = ceil (d), "ftruncate", number); | 2444 (number, divisor)) |
1191 return make_float (d); | 2445 { |
2446 ROUNDING_CONVERT(truncate, 1); | |
1192 } | 2447 } |
1193 | 2448 |
1194 #ifdef FLOAT_CATCH_SIGILL | 2449 #ifdef FLOAT_CATCH_SIGILL |
1195 static SIGTYPE | 2450 static SIGTYPE |
1196 float_error (int signo) | 2451 float_error (int signo) |