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