diff options
| author | Richard M. Stallman | 1993-03-10 05:33:40 +0000 |
|---|---|---|
| committer | Richard M. Stallman | 1993-03-10 05:33:40 +0000 |
| commit | 4b6baf5f451a0b5225bd158734efbc3d61af7c98 (patch) | |
| tree | 80cd8cb1161ea5710cb3d391fbc315534a0135b6 /src/floatfns.c | |
| parent | 0b8fc2d4519e687bf3b011e276666c1417826997 (diff) | |
| download | emacs-4b6baf5f451a0b5225bd158734efbc3d61af7c98.tar.gz emacs-4b6baf5f451a0b5225bd158734efbc3d61af7c98.zip | |
(FLOAT_CHECK_ERRNO): Define unless NO_FLOAT_CHECK_ERRNO.
Changes from Lucid:
(HAVE_MATHERR, FLOAT_CHECK_ERRNO, FLOAT_CATCH_SIGILL): New parm macros.
(FLOAT_CHECK_DOMAIN, HAVE_RINT): New parm macros.
(HAVE_INVERSE_HYPERBOLIC, HAVE_CBRT): New parm macros.
[!HAVE_RINT]: Define rint as macro.
(IN_FLOAT): Major rewrite; several alternate versions.
(IN_FLOAT2): New macro.
(arith_error, range_error, domain_error, domain_error2): New macros.
(Facos, Fasin, Fatan, Fcos, Fsin, Ftan, Fexp, Fexpt, Flog): Changed.
(Flog10, Fsqrt, Fabs, Ffloat, Flogb): Changed.
(Ffloor, Fceiling, Fround, Ftruncate): Changed.
(Fcube_root): Renamed from Fcbrt.
(matherr): New function.
(float_error): Only if FLOAT_CATCH_SIGILL.
Diffstat (limited to 'src/floatfns.c')
| -rw-r--r-- | src/floatfns.c | 631 |
1 files changed, 447 insertions, 184 deletions
diff --git a/src/floatfns.c b/src/floatfns.c index 7968d1207d7..760b7449387 100644 --- a/src/floatfns.c +++ b/src/floatfns.c | |||
| @@ -18,6 +18,31 @@ along with GNU Emacs; see the file COPYING. If not, write to | |||
| 18 | the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ | 18 | the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ |
| 19 | 19 | ||
| 20 | 20 | ||
| 21 | /* ANSI C requires only these float functions: | ||
| 22 | acos, asin, atan, atan2, ceil, cos, cosh, exp, fabs, floor, fmod, | ||
| 23 | frexp, ldexp, log, log10, modf, pow, sin, sinh, sqrt, tan, tanh. | ||
| 24 | |||
| 25 | Define HAVE_INVERSE_HYPERBOLIC if you have acosh, asinh, and atanh. | ||
| 26 | Define HAVE_CBRT if you have cbrt. | ||
| 27 | Define HAVE_RINT if you have rint. | ||
| 28 | If you don't define these, then the appropriate routines will be simulated. | ||
| 29 | |||
| 30 | Define HAVE_MATHERR if on a system supporting the SysV matherr callback. | ||
| 31 | (This should happen automatically.) | ||
| 32 | |||
| 33 | Define FLOAT_CHECK_ERRNO if the float library routines set errno. | ||
| 34 | This has no effect if HAVE_MATHERR is defined. | ||
| 35 | |||
| 36 | Define FLOAT_CATCH_SIGILL if the float library routines signal SIGILL. | ||
| 37 | (What systems actually do this? Please let us know.) | ||
| 38 | |||
| 39 | Define FLOAT_CHECK_DOMAIN if the float library doesn't handle errors by | ||
| 40 | either setting errno, or signalling SIGFPE/SIGILL. Otherwise, domain and | ||
| 41 | range checking will happen before calling the float routines. This has | ||
| 42 | no effect if HAVE_MATHERR is defined (since matherr will be called when | ||
| 43 | a domain error occurs.) | ||
| 44 | */ | ||
| 45 | |||
| 21 | #include <signal.h> | 46 | #include <signal.h> |
| 22 | 47 | ||
| 23 | #include "config.h" | 48 | #include "config.h" |
| @@ -29,9 +54,32 @@ Lisp_Object Qarith_error; | |||
| 29 | #ifdef LISP_FLOAT_TYPE | 54 | #ifdef LISP_FLOAT_TYPE |
| 30 | 55 | ||
| 31 | #include <math.h> | 56 | #include <math.h> |
| 32 | #include <errno.h> | 57 | |
| 58 | #if defined(DOMAIN) && defined(SING) && defined(OVERFLOW) | ||
| 59 | /* If those are defined, then this is probably a `matherr' machine. */ | ||
| 60 | # ifndef HAVE_MATHERR | ||
| 61 | # define HAVE_MATHERR | ||
| 62 | # endif | ||
| 63 | #endif | ||
| 64 | |||
| 65 | #ifdef HAVE_MATHERR | ||
| 66 | # ifdef FLOAT_CHECK_ERRNO | ||
| 67 | # undef FLOAT_CHECK_ERRNO | ||
| 68 | # endif | ||
| 69 | # ifdef FLOAT_CHECK_DOMAIN | ||
| 70 | # undef FLOAT_CHECK_DOMAIN | ||
| 71 | # endif | ||
| 72 | #endif | ||
| 73 | |||
| 74 | #ifndef NO_FLOAT_CHECK_ERRNO | ||
| 75 | #define FLOAT_CHECK_ERRNO | ||
| 76 | #endif | ||
| 77 | |||
| 78 | #ifdef FLOAT_CHECK_ERRNO | ||
| 79 | # include <errno.h> | ||
| 33 | 80 | ||
| 34 | extern int errno; | 81 | extern int errno; |
| 82 | #endif | ||
| 35 | 83 | ||
| 36 | /* Avoid traps on VMS from sinh and cosh. | 84 | /* Avoid traps on VMS from sinh and cosh. |
| 37 | All the other functions set errno instead. */ | 85 | All the other functions set errno instead. */ |
| @@ -43,6 +91,10 @@ extern int errno; | |||
| 43 | #define sinh(x) ((exp(x)-exp(-x))*0.5) | 91 | #define sinh(x) ((exp(x)-exp(-x))*0.5) |
| 44 | #endif /* VMS */ | 92 | #endif /* VMS */ |
| 45 | 93 | ||
| 94 | #ifndef HAVE_RINT | ||
| 95 | #define rint(x) (floor((x)+0.5)) | ||
| 96 | #endif | ||
| 97 | |||
| 46 | static SIGTYPE float_error (); | 98 | static SIGTYPE float_error (); |
| 47 | 99 | ||
| 48 | /* Nonzero while executing in floating point. | 100 | /* Nonzero while executing in floating point. |
| @@ -53,7 +105,9 @@ static int in_float; | |||
| 53 | /* If an argument is out of range for a mathematical function, | 105 | /* If an argument is out of range for a mathematical function, |
| 54 | here is the actual argument value to use in the error message. */ | 106 | here is the actual argument value to use in the error message. */ |
| 55 | 107 | ||
| 56 | static Lisp_Object float_error_arg; | 108 | static Lisp_Object float_error_arg, float_error_arg2; |
| 109 | |||
| 110 | static char *float_error_fn_name; | ||
| 57 | 111 | ||
| 58 | /* Evaluate the floating point expression D, recording NUM | 112 | /* Evaluate the floating point expression D, recording NUM |
| 59 | as the original argument for error messages. | 113 | as the original argument for error messages. |
| @@ -64,10 +118,44 @@ static Lisp_Object float_error_arg; | |||
| 64 | just cast the zero after the colon to (SIGTYPE) to make the types | 118 | just cast the zero after the colon to (SIGTYPE) to make the types |
| 65 | check properly. */ | 119 | check properly. */ |
| 66 | 120 | ||
| 67 | #define IN_FLOAT(D, NUM) \ | 121 | #ifdef FLOAT_CHECK_ERRNO |
| 68 | (in_float = 1, errno = 0, float_error_arg = NUM, (D), \ | 122 | #define IN_FLOAT(d, name, num) \ |
| 69 | (errno == ERANGE || errno == EDOM ? (float_error (),0) : 0), \ | 123 | do { \ |
| 70 | in_float = 0) | 124 | float_error_arg = num; \ |
| 125 | float_error_fn_name = name; \ | ||
| 126 | in_float = 1; errno = 0; (d); in_float = 0; \ | ||
| 127 | switch (errno) { \ | ||
| 128 | case 0: break; \ | ||
| 129 | case EDOM: domain_error (float_error_fn_name, float_error_arg); \ | ||
| 130 | case ERANGE: range_error (float_error_fn_name, float_error_arg); \ | ||
| 131 | default: arith_error (float_error_fn_name, float_error_arg); \ | ||
| 132 | } \ | ||
| 133 | } while (0) | ||
| 134 | #define IN_FLOAT2(d, name, num, num2) \ | ||
| 135 | do { \ | ||
| 136 | float_error_arg = num; \ | ||
| 137 | float_error_arg2 = num2; \ | ||
| 138 | float_error_fn_name = name; \ | ||
| 139 | in_float = 1; errno = 0; (d); in_float = 0; \ | ||
| 140 | switch (errno) { \ | ||
| 141 | case 0: break; \ | ||
| 142 | case EDOM: domain_error (float_error_fn_name, float_error_arg); \ | ||
| 143 | case ERANGE: range_error (float_error_fn_name, float_error_arg); \ | ||
| 144 | default: arith_error (float_error_fn_name, float_error_arg); \ | ||
| 145 | } \ | ||
| 146 | } while (0) | ||
| 147 | #else | ||
| 148 | #define IN_FLOAT2(d, name, num, num2) (in_float = 1, (d), in_float = 0) | ||
| 149 | #endif | ||
| 150 | |||
| 151 | #define arith_error(op,arg) \ | ||
| 152 | Fsignal (Qarith_error, Fcons (build_string ((op)), Fcons ((arg), Qnil))) | ||
| 153 | #define range_error(op,arg) \ | ||
| 154 | Fsignal (Qrange_error, Fcons (build_string ((op)), Fcons ((arg), Qnil))) | ||
| 155 | #define domain_error(op,arg) \ | ||
| 156 | Fsignal (Qdomain_error, Fcons (build_string ((op)), Fcons ((arg), Qnil))) | ||
| 157 | #define domain_error2(op,a1,a2) \ | ||
| 158 | Fsignal (Qdomain_error, Fcons (build_string ((op)), Fcons ((a1), Fcons ((a2), Qnil)))) | ||
| 71 | 159 | ||
| 72 | /* Extract a Lisp number as a `double', or signal an error. */ | 160 | /* Extract a Lisp number as a `double', or signal an error. */ |
| 73 | 161 | ||
| @@ -86,61 +174,74 @@ extract_float (num) | |||
| 86 | 174 | ||
| 87 | DEFUN ("acos", Facos, Sacos, 1, 1, 0, | 175 | DEFUN ("acos", Facos, Sacos, 1, 1, 0, |
| 88 | "Return the inverse cosine of ARG.") | 176 | "Return the inverse cosine of ARG.") |
| 89 | (num) | 177 | (arg) |
| 90 | register Lisp_Object num; | 178 | register Lisp_Object arg; |
| 91 | { | 179 | { |
| 92 | double d = extract_float (num); | 180 | double d = extract_float (arg); |
| 93 | IN_FLOAT (d = acos (d), num); | 181 | #ifdef FLOAT_CHECK_DOMAIN |
| 182 | if (d > 1.0 || d < -1.0) | ||
| 183 | domain_error ("acos", arg); | ||
| 184 | #endif | ||
| 185 | IN_FLOAT (d = acos (d), "acos", arg); | ||
| 94 | return make_float (d); | 186 | return make_float (d); |
| 95 | } | 187 | } |
| 96 | 188 | ||
| 97 | DEFUN ("asin", Fasin, Sasin, 1, 1, 0, | 189 | DEFUN ("asin", Fasin, Sasin, 1, 1, 0, |
| 98 | "Return the inverse sine of ARG.") | 190 | "Return the inverse sine of ARG.") |
| 99 | (num) | 191 | (arg) |
| 100 | register Lisp_Object num; | 192 | register Lisp_Object arg; |
| 101 | { | 193 | { |
| 102 | double d = extract_float (num); | 194 | double d = extract_float (arg); |
| 103 | IN_FLOAT (d = asin (d), num); | 195 | #ifdef FLOAT_CHECK_DOMAIN |
| 196 | if (d > 1.0 || d < -1.0) | ||
| 197 | domain_error ("asin", arg); | ||
| 198 | #endif | ||
| 199 | IN_FLOAT (d = asin (d), "asin", arg); | ||
| 104 | return make_float (d); | 200 | return make_float (d); |
| 105 | } | 201 | } |
| 106 | 202 | ||
| 107 | DEFUN ("atan", Fatan, Satan, 1, 1, 0, | 203 | DEFUN ("atan", Fatan, Satan, 1, 1, 0, |
| 108 | "Return the inverse tangent of ARG.") | 204 | "Return the inverse tangent of ARG.") |
| 109 | (num) | 205 | (arg) |
| 110 | register Lisp_Object num; | 206 | register Lisp_Object arg; |
| 111 | { | 207 | { |
| 112 | double d = extract_float (num); | 208 | double d = extract_float (arg); |
| 113 | IN_FLOAT (d = atan (d), num); | 209 | IN_FLOAT (d = atan (d), "atan", arg); |
| 114 | return make_float (d); | 210 | return make_float (d); |
| 115 | } | 211 | } |
| 116 | 212 | ||
| 117 | DEFUN ("cos", Fcos, Scos, 1, 1, 0, | 213 | DEFUN ("cos", Fcos, Scos, 1, 1, 0, |
| 118 | "Return the cosine of ARG.") | 214 | "Return the cosine of ARG.") |
| 119 | (num) | 215 | (arg) |
| 120 | register Lisp_Object num; | 216 | register Lisp_Object arg; |
| 121 | { | 217 | { |
| 122 | double d = extract_float (num); | 218 | double d = extract_float (arg); |
| 123 | IN_FLOAT (d = cos (d), num); | 219 | IN_FLOAT (d = cos (d), "cos", arg); |
| 124 | return make_float (d); | 220 | return make_float (d); |
| 125 | } | 221 | } |
| 126 | 222 | ||
| 127 | DEFUN ("sin", Fsin, Ssin, 1, 1, 0, | 223 | DEFUN ("sin", Fsin, Ssin, 1, 1, 0, |
| 128 | "Return the sine of ARG.") | 224 | "Return the sine of ARG.") |
| 129 | (num) | 225 | (arg) |
| 130 | register Lisp_Object num; | 226 | register Lisp_Object arg; |
| 131 | { | 227 | { |
| 132 | double d = extract_float (num); | 228 | double d = extract_float (arg); |
| 133 | IN_FLOAT (d = sin (d), num); | 229 | IN_FLOAT (d = sin (d), "sin", arg); |
| 134 | return make_float (d); | 230 | return make_float (d); |
| 135 | } | 231 | } |
| 136 | 232 | ||
| 137 | DEFUN ("tan", Ftan, Stan, 1, 1, 0, | 233 | DEFUN ("tan", Ftan, Stan, 1, 1, 0, |
| 138 | "Return the tangent of ARG.") | 234 | "Return the tangent of ARG.") |
| 139 | (num) | 235 | (arg) |
| 140 | register Lisp_Object num; | 236 | register Lisp_Object arg; |
| 141 | { | 237 | { |
| 142 | double d = extract_float (num); | 238 | double d = extract_float (arg); |
| 143 | IN_FLOAT (d = tan (d), num); | 239 | double c = cos (d); |
| 240 | #ifdef FLOAT_CHECK_DOMAIN | ||
| 241 | if (c == 0.0) | ||
| 242 | domain_error ("tan", arg); | ||
| 243 | #endif | ||
| 244 | IN_FLOAT (d = sin (d) / c, "tan", arg); | ||
| 144 | return make_float (d); | 245 | return make_float (d); |
| 145 | } | 246 | } |
| 146 | 247 | ||
| @@ -148,67 +249,67 @@ DEFUN ("tan", Ftan, Stan, 1, 1, 0, | |||
| 148 | 249 | ||
| 149 | DEFUN ("bessel-j0", Fbessel_j0, Sbessel_j0, 1, 1, 0, | 250 | DEFUN ("bessel-j0", Fbessel_j0, Sbessel_j0, 1, 1, 0, |
| 150 | "Return the bessel function j0 of ARG.") | 251 | "Return the bessel function j0 of ARG.") |
| 151 | (num) | 252 | (arg) |
| 152 | register Lisp_Object num; | 253 | register Lisp_Object arg; |
| 153 | { | 254 | { |
| 154 | double d = extract_float (num); | 255 | double d = extract_float (arg); |
| 155 | IN_FLOAT (d = j0 (d), num); | 256 | IN_FLOAT (d = j0 (d), "bessel-j0", arg); |
| 156 | return make_float (d); | 257 | return make_float (d); |
| 157 | } | 258 | } |
| 158 | 259 | ||
| 159 | DEFUN ("bessel-j1", Fbessel_j1, Sbessel_j1, 1, 1, 0, | 260 | DEFUN ("bessel-j1", Fbessel_j1, Sbessel_j1, 1, 1, 0, |
| 160 | "Return the bessel function j1 of ARG.") | 261 | "Return the bessel function j1 of ARG.") |
| 161 | (num) | 262 | (arg) |
| 162 | register Lisp_Object num; | 263 | register Lisp_Object arg; |
| 163 | { | 264 | { |
| 164 | double d = extract_float (num); | 265 | double d = extract_float (arg); |
| 165 | IN_FLOAT (d = j1 (d), num); | 266 | IN_FLOAT (d = j1 (d), "bessel-j1", arg); |
| 166 | return make_float (d); | 267 | return make_float (d); |
| 167 | } | 268 | } |
| 168 | 269 | ||
| 169 | DEFUN ("bessel-jn", Fbessel_jn, Sbessel_jn, 2, 2, 0, | 270 | DEFUN ("bessel-jn", Fbessel_jn, Sbessel_jn, 2, 2, 0, |
| 170 | "Return the order N bessel function output jn of ARG.\n\ | 271 | "Return the order N bessel function output jn of ARG.\n\ |
| 171 | The first arg (the order) is truncated to an integer.") | 272 | The first arg (the order) is truncated to an integer.") |
| 172 | (num1, num2) | 273 | (arg1, arg2) |
| 173 | register Lisp_Object num1, num2; | 274 | register Lisp_Object arg1, arg2; |
| 174 | { | 275 | { |
| 175 | int i1 = extract_float (num1); | 276 | int i1 = extract_float (arg1); |
| 176 | double f2 = extract_float (num2); | 277 | double f2 = extract_float (arg2); |
| 177 | 278 | ||
| 178 | IN_FLOAT (f2 = jn (i1, f2), num1); | 279 | IN_FLOAT (f2 = jn (i1, f2), "bessel-jn", arg1); |
| 179 | return make_float (f2); | 280 | return make_float (f2); |
| 180 | } | 281 | } |
| 181 | 282 | ||
| 182 | DEFUN ("bessel-y0", Fbessel_y0, Sbessel_y0, 1, 1, 0, | 283 | DEFUN ("bessel-y0", Fbessel_y0, Sbessel_y0, 1, 1, 0, |
| 183 | "Return the bessel function y0 of ARG.") | 284 | "Return the bessel function y0 of ARG.") |
| 184 | (num) | 285 | (arg) |
| 185 | register Lisp_Object num; | 286 | register Lisp_Object arg; |
| 186 | { | 287 | { |
| 187 | double d = extract_float (num); | 288 | double d = extract_float (arg); |
| 188 | IN_FLOAT (d = y0 (d), num); | 289 | IN_FLOAT (d = y0 (d), "bessel-y0", arg); |
| 189 | return make_float (d); | 290 | return make_float (d); |
| 190 | } | 291 | } |
| 191 | 292 | ||
| 192 | DEFUN ("bessel-y1", Fbessel_y1, Sbessel_y1, 1, 1, 0, | 293 | DEFUN ("bessel-y1", Fbessel_y1, Sbessel_y1, 1, 1, 0, |
| 193 | "Return the bessel function y1 of ARG.") | 294 | "Return the bessel function y1 of ARG.") |
| 194 | (num) | 295 | (arg) |
| 195 | register Lisp_Object num; | 296 | register Lisp_Object arg; |
| 196 | { | 297 | { |
| 197 | double d = extract_float (num); | 298 | double d = extract_float (arg); |
| 198 | IN_FLOAT (d = y1 (d), num); | 299 | IN_FLOAT (d = y1 (d), "bessel-y0", arg); |
| 199 | return make_float (d); | 300 | return make_float (d); |
| 200 | } | 301 | } |
| 201 | 302 | ||
| 202 | DEFUN ("bessel-yn", Fbessel_yn, Sbessel_yn, 2, 2, 0, | 303 | DEFUN ("bessel-yn", Fbessel_yn, Sbessel_yn, 2, 2, 0, |
| 203 | "Return the order N bessel function output yn of ARG.\n\ | 304 | "Return the order N bessel function output yn of ARG.\n\ |
| 204 | The first arg (the order) is truncated to an integer.") | 305 | The first arg (the order) is truncated to an integer.") |
| 205 | (num1, num2) | 306 | (arg1, arg2) |
| 206 | register Lisp_Object num1, num2; | 307 | register Lisp_Object arg1, arg2; |
| 207 | { | 308 | { |
| 208 | int i1 = extract_float (num1); | 309 | int i1 = extract_float (arg1); |
| 209 | double f2 = extract_float (num2); | 310 | double f2 = extract_float (arg2); |
| 210 | 311 | ||
| 211 | IN_FLOAT (f2 = yn (i1, f2), num1); | 312 | IN_FLOAT (f2 = yn (i1, f2), "bessel-yn", arg1); |
| 212 | return make_float (f2); | 313 | return make_float (f2); |
| 213 | } | 314 | } |
| 214 | 315 | ||
| @@ -218,41 +319,48 @@ The first arg (the order) is truncated to an integer.") | |||
| 218 | 319 | ||
| 219 | DEFUN ("erf", Ferf, Serf, 1, 1, 0, | 320 | DEFUN ("erf", Ferf, Serf, 1, 1, 0, |
| 220 | "Return the mathematical error function of ARG.") | 321 | "Return the mathematical error function of ARG.") |
| 221 | (num) | 322 | (arg) |
| 222 | register Lisp_Object num; | 323 | register Lisp_Object arg; |
| 223 | { | 324 | { |
| 224 | double d = extract_float (num); | 325 | double d = extract_float (arg); |
| 225 | IN_FLOAT (d = erf (d), num); | 326 | IN_FLOAT (d = erf (d), "erf", arg); |
| 226 | return make_float (d); | 327 | return make_float (d); |
| 227 | } | 328 | } |
| 228 | 329 | ||
| 229 | DEFUN ("erfc", Ferfc, Serfc, 1, 1, 0, | 330 | DEFUN ("erfc", Ferfc, Serfc, 1, 1, 0, |
| 230 | "Return the complementary error function of ARG.") | 331 | "Return the complementary error function of ARG.") |
| 231 | (num) | 332 | (arg) |
| 232 | register Lisp_Object num; | 333 | register Lisp_Object arg; |
| 233 | { | 334 | { |
| 234 | double d = extract_float (num); | 335 | double d = extract_float (arg); |
| 235 | IN_FLOAT (d = erfc (d), num); | 336 | IN_FLOAT (d = erfc (d), "erfc", arg); |
| 236 | return make_float (d); | 337 | return make_float (d); |
| 237 | } | 338 | } |
| 238 | 339 | ||
| 239 | DEFUN ("log-gamma", Flog_gamma, Slog_gamma, 1, 1, 0, | 340 | DEFUN ("log-gamma", Flog_gamma, Slog_gamma, 1, 1, 0, |
| 240 | "Return the log gamma of ARG.") | 341 | "Return the log gamma of ARG.") |
| 241 | (num) | 342 | (arg) |
| 242 | register Lisp_Object num; | 343 | register Lisp_Object arg; |
| 243 | { | 344 | { |
| 244 | double d = extract_float (num); | 345 | double d = extract_float (arg); |
| 245 | IN_FLOAT (d = lgamma (d), num); | 346 | IN_FLOAT (d = lgamma (d), "log-gamma", arg); |
| 246 | return make_float (d); | 347 | return make_float (d); |
| 247 | } | 348 | } |
| 248 | 349 | ||
| 249 | DEFUN ("cbrt", Fcbrt, Scbrt, 1, 1, 0, | 350 | DEFUN ("cube-root", Fcube_root, Scube_root, 1, 1, 0, |
| 250 | "Return the cube root of ARG.") | 351 | "Return the cube root of ARG.") |
| 251 | (num) | 352 | (arg) |
| 252 | register Lisp_Object num; | 353 | register Lisp_Object arg; |
| 253 | { | 354 | { |
| 254 | double d = extract_float (num); | 355 | double d = extract_float (arg); |
| 255 | IN_FLOAT (d = cbrt (d), num); | 356 | #ifdef HAVE_CBRT |
| 357 | IN_FLOAT (d = cbrt (d), "cube-root", arg); | ||
| 358 | #else | ||
| 359 | if (d >= 0.0) | ||
| 360 | IN_FLOAT (d = pow (d, 1.0/3.0), "cube-root", arg); | ||
| 361 | else | ||
| 362 | IN_FLOAT (d = -pow (-d, 1.0/3.0), "cube-root", arg); | ||
| 363 | #endif | ||
| 256 | return make_float (d); | 364 | return make_float (d); |
| 257 | } | 365 | } |
| 258 | 366 | ||
| @@ -260,87 +368,130 @@ DEFUN ("cbrt", Fcbrt, Scbrt, 1, 1, 0, | |||
| 260 | 368 | ||
| 261 | DEFUN ("exp", Fexp, Sexp, 1, 1, 0, | 369 | DEFUN ("exp", Fexp, Sexp, 1, 1, 0, |
| 262 | "Return the exponential base e of ARG.") | 370 | "Return the exponential base e of ARG.") |
| 263 | (num) | 371 | (arg) |
| 264 | register Lisp_Object num; | 372 | register Lisp_Object arg; |
| 265 | { | 373 | { |
| 266 | double d = extract_float (num); | 374 | double d = extract_float (arg); |
| 267 | IN_FLOAT (d = exp (d), num); | 375 | #ifdef FLOAT_CHECK_DOMAIN |
| 376 | if (d > 709.7827) /* Assume IEEE doubles here */ | ||
| 377 | range_error ("exp", arg); | ||
| 378 | else if (d < -709.0) | ||
| 379 | return make_float (0.0); | ||
| 380 | else | ||
| 381 | #endif | ||
| 382 | IN_FLOAT (d = exp (d), "exp", arg); | ||
| 268 | return make_float (d); | 383 | return make_float (d); |
| 269 | } | 384 | } |
| 270 | 385 | ||
| 271 | DEFUN ("expt", Fexpt, Sexpt, 2, 2, 0, | 386 | DEFUN ("expt", Fexpt, Sexpt, 2, 2, 0, |
| 272 | "Return the exponential X ** Y.") | 387 | "Return the exponential X ** Y.") |
| 273 | (num1, num2) | 388 | (arg1, arg2) |
| 274 | register Lisp_Object num1, num2; | 389 | register Lisp_Object arg1, arg2; |
| 275 | { | 390 | { |
| 276 | double f1, f2; | 391 | double f1, f2; |
| 277 | 392 | ||
| 278 | CHECK_NUMBER_OR_FLOAT (num1, 0); | 393 | CHECK_NUMBER_OR_FLOAT (arg1, 0); |
| 279 | CHECK_NUMBER_OR_FLOAT (num2, 0); | 394 | CHECK_NUMBER_OR_FLOAT (arg2, 0); |
| 280 | if ((XTYPE (num1) == Lisp_Int) && /* common lisp spec */ | 395 | if ((XTYPE (arg1) == Lisp_Int) && /* common lisp spec */ |
| 281 | (XTYPE (num2) == Lisp_Int)) /* don't promote, if both are ints */ | 396 | (XTYPE (arg2) == Lisp_Int)) /* don't promote, if both are ints */ |
| 282 | { /* this can be improved by pre-calculating */ | 397 | { /* this can be improved by pre-calculating */ |
| 283 | int acc, x, y; /* some binary powers of x then acumulating */ | 398 | int acc, x, y; /* some binary powers of x then acumulating */ |
| 284 | /* these, therby saving some time. -wsr */ | 399 | /* these, therby saving some time. -wsr */ |
| 285 | x = XINT (num1); | 400 | x = XINT (arg1); |
| 286 | y = XINT (num2); | 401 | y = XINT (arg2); |
| 287 | acc = 1; | 402 | acc = 1; |
| 288 | 403 | ||
| 289 | if (y < 0) | 404 | if (y < 0) |
| 290 | { | 405 | { |
| 291 | for (; y < 0; y++) | 406 | if (x == 1) |
| 292 | acc /= x; | 407 | acc = 1; |
| 408 | else if (x == -1) | ||
| 409 | acc = (y & 1) ? -1 : 1; | ||
| 410 | else | ||
| 411 | acc = 0; | ||
| 293 | } | 412 | } |
| 294 | else | 413 | else |
| 295 | { | 414 | { |
| 296 | for (; y > 0; y--) | 415 | for (; y > 0; y--) |
| 297 | acc *= x; | 416 | while (y > 0) |
| 417 | { | ||
| 418 | if (y & 1) | ||
| 419 | acc *= x; | ||
| 420 | x *= x; | ||
| 421 | y = (unsigned)y >> 1; | ||
| 422 | } | ||
| 298 | } | 423 | } |
| 299 | XFASTINT (x) = acc; | 424 | XSET (x, Lisp_Int, acc); |
| 300 | return x; | 425 | return x; |
| 301 | } | 426 | } |
| 302 | f1 = (XTYPE (num1) == Lisp_Float) ? XFLOAT (num1)->data : XINT (num1); | 427 | f1 = (XTYPE (arg1) == Lisp_Float) ? XFLOAT (arg1)->data : XINT (arg1); |
| 303 | f2 = (XTYPE (num2) == Lisp_Float) ? XFLOAT (num2)->data : XINT (num2); | 428 | f2 = (XTYPE (arg2) == Lisp_Float) ? XFLOAT (arg2)->data : XINT (arg2); |
| 304 | IN_FLOAT (f1 = pow (f1, f2), num1); | 429 | /* Really should check for overflow, too */ |
| 430 | if (f1 == 0.0 && f2 == 0.0) | ||
| 431 | f1 = 1.0; | ||
| 432 | #ifdef FLOAT_CHECK_DOMAIN | ||
| 433 | else if ((f1 == 0.0 && f2 < 0.0) || (f1 < 0 && f2 != floor(f2))) | ||
| 434 | domain_error2 ("expt", arg1, arg2); | ||
| 435 | #endif | ||
| 436 | IN_FLOAT (f1 = pow (f1, f2), "expt", arg1); | ||
| 305 | return make_float (f1); | 437 | return make_float (f1); |
| 306 | } | 438 | } |
| 307 | 439 | ||
| 308 | DEFUN ("log", Flog, Slog, 1, 2, 0, | 440 | DEFUN ("log", Flog, Slog, 1, 2, 0, |
| 309 | "Return the natural logarithm of NUM.\n\ | 441 | "Return the natural logarithm of ARG.\n\ |
| 310 | If second optional argument BASE is given, return log NUM using that base.") | 442 | If second optional argument BASE is given, return log ARG using that base.") |
| 311 | (num, base) | 443 | (arg, base) |
| 312 | register Lisp_Object num, base; | 444 | register Lisp_Object arg, base; |
| 313 | { | 445 | { |
| 314 | double d = extract_float (num); | 446 | double d = extract_float (arg); |
| 315 | 447 | ||
| 448 | #ifdef FLOAT_CHECK_DOMAIN | ||
| 449 | if (d <= 0.0) | ||
| 450 | domain_error2 ("log", arg, base); | ||
| 451 | #endif | ||
| 316 | if (NILP (base)) | 452 | if (NILP (base)) |
| 317 | IN_FLOAT (d = log (d), num); | 453 | IN_FLOAT (d = log (d), "log", arg); |
| 318 | else | 454 | else |
| 319 | { | 455 | { |
| 320 | double b = extract_float (base); | 456 | double b = extract_float (base); |
| 321 | 457 | ||
| 322 | IN_FLOAT (d = log (num) / log (b), num); | 458 | #ifdef FLOAT_CHECK_DOMAIN |
| 459 | if (b <= 0.0 || b == 1.0) | ||
| 460 | domain_error2 ("log", arg, base); | ||
| 461 | #endif | ||
| 462 | if (b == 10.0) | ||
| 463 | IN_FLOAT2 (d = log10 (d), "log", arg, base); | ||
| 464 | else | ||
| 465 | IN_FLOAT2 (d = log (arg) / log (b), "log", arg, base); | ||
| 323 | } | 466 | } |
| 324 | return make_float (d); | 467 | return make_float (d); |
| 325 | } | 468 | } |
| 326 | 469 | ||
| 327 | DEFUN ("log10", Flog10, Slog10, 1, 1, 0, | 470 | DEFUN ("log10", Flog10, Slog10, 1, 1, 0, |
| 328 | "Return the logarithm base 10 of ARG.") | 471 | "Return the logarithm base 10 of ARG.") |
| 329 | (num) | 472 | (arg) |
| 330 | register Lisp_Object num; | 473 | register Lisp_Object arg; |
| 331 | { | 474 | { |
| 332 | double d = extract_float (num); | 475 | double d = extract_float (arg); |
| 333 | IN_FLOAT (d = log10 (d), num); | 476 | #ifdef FLOAT_CHECK_DOMAIN |
| 477 | if (d <= 0.0) | ||
| 478 | domain_error ("log10", arg); | ||
| 479 | #endif | ||
| 480 | IN_FLOAT (d = log10 (d), "log10", arg); | ||
| 334 | return make_float (d); | 481 | return make_float (d); |
| 335 | } | 482 | } |
| 336 | 483 | ||
| 337 | DEFUN ("sqrt", Fsqrt, Ssqrt, 1, 1, 0, | 484 | DEFUN ("sqrt", Fsqrt, Ssqrt, 1, 1, 0, |
| 338 | "Return the square root of ARG.") | 485 | "Return the square root of ARG.") |
| 339 | (num) | 486 | (arg) |
| 340 | register Lisp_Object num; | 487 | register Lisp_Object arg; |
| 341 | { | 488 | { |
| 342 | double d = extract_float (num); | 489 | double d = extract_float (arg); |
| 343 | IN_FLOAT (d = sqrt (d), num); | 490 | #ifdef FLOAT_CHECK_DOMAIN |
| 491 | if (d < 0.0) | ||
| 492 | domain_error ("sqrt", arg); | ||
| 493 | #endif | ||
| 494 | IN_FLOAT (d = sqrt (d), "sqrt", arg); | ||
| 344 | return make_float (d); | 495 | return make_float (d); |
| 345 | } | 496 | } |
| 346 | 497 | ||
| @@ -348,169 +499,240 @@ DEFUN ("sqrt", Fsqrt, Ssqrt, 1, 1, 0, | |||
| 348 | 499 | ||
| 349 | DEFUN ("acosh", Facosh, Sacosh, 1, 1, 0, | 500 | DEFUN ("acosh", Facosh, Sacosh, 1, 1, 0, |
| 350 | "Return the inverse hyperbolic cosine of ARG.") | 501 | "Return the inverse hyperbolic cosine of ARG.") |
| 351 | (num) | 502 | (arg) |
| 352 | register Lisp_Object num; | 503 | register Lisp_Object arg; |
| 353 | { | 504 | { |
| 354 | double d = extract_float (num); | 505 | double d = extract_float (arg); |
| 355 | IN_FLOAT (d = acosh (d), num); | 506 | #ifdef FLOAT_CHECK_DOMAIN |
| 507 | if (d < 1.0) | ||
| 508 | domain_error ("acosh", arg); | ||
| 509 | #endif | ||
| 510 | #ifdef HAVE_INVERSE_HYPERBOLIC | ||
| 511 | IN_FLOAT (d = acosh (d), "acosh", arg); | ||
| 512 | #else | ||
| 513 | IN_FLOAT (d = log (d + sqrt (d*d - 1.0)), "acosh", arg); | ||
| 514 | #endif | ||
| 356 | return make_float (d); | 515 | return make_float (d); |
| 357 | } | 516 | } |
| 358 | 517 | ||
| 359 | DEFUN ("asinh", Fasinh, Sasinh, 1, 1, 0, | 518 | DEFUN ("asinh", Fasinh, Sasinh, 1, 1, 0, |
| 360 | "Return the inverse hyperbolic sine of ARG.") | 519 | "Return the inverse hyperbolic sine of ARG.") |
| 361 | (num) | 520 | (arg) |
| 362 | register Lisp_Object num; | 521 | register Lisp_Object arg; |
| 363 | { | 522 | { |
| 364 | double d = extract_float (num); | 523 | double d = extract_float (arg); |
| 365 | IN_FLOAT (d = asinh (d), num); | 524 | #ifdef HAVE_INVERSE_HYPERBOLIC |
| 525 | IN_FLOAT (d = asinh (d), "asinh", arg); | ||
| 526 | #else | ||
| 527 | IN_FLOAT (d = log (d + sqrt (d*d + 1.0)), "asinh", arg); | ||
| 528 | #endif | ||
| 366 | return make_float (d); | 529 | return make_float (d); |
| 367 | } | 530 | } |
| 368 | 531 | ||
| 369 | DEFUN ("atanh", Fatanh, Satanh, 1, 1, 0, | 532 | DEFUN ("atanh", Fatanh, Satanh, 1, 1, 0, |
| 370 | "Return the inverse hyperbolic tangent of ARG.") | 533 | "Return the inverse hyperbolic tangent of ARG.") |
| 371 | (num) | 534 | (arg) |
| 372 | register Lisp_Object num; | 535 | register Lisp_Object arg; |
| 373 | { | 536 | { |
| 374 | double d = extract_float (num); | 537 | double d = extract_float (arg); |
| 375 | IN_FLOAT (d = atanh (d), num); | 538 | #ifdef FLOAT_CHECK_DOMAIN |
| 539 | if (d >= 1.0 || d <= -1.0) | ||
| 540 | domain_error ("atanh", arg); | ||
| 541 | #endif | ||
| 542 | #ifdef HAVE_INVERSE_HYPERBOLIC | ||
| 543 | IN_FLOAT (d = atanh (d), "atanh", arg); | ||
| 544 | #else | ||
| 545 | IN_FLOAT (d = 0.5 * log ((1.0 + d) / (1.0 - d)), "atanh", arg); | ||
| 546 | #endif | ||
| 376 | return make_float (d); | 547 | return make_float (d); |
| 377 | } | 548 | } |
| 378 | 549 | ||
| 379 | DEFUN ("cosh", Fcosh, Scosh, 1, 1, 0, | 550 | DEFUN ("cosh", Fcosh, Scosh, 1, 1, 0, |
| 380 | "Return the hyperbolic cosine of ARG.") | 551 | "Return the hyperbolic cosine of ARG.") |
| 381 | (num) | 552 | (arg) |
| 382 | register Lisp_Object num; | 553 | register Lisp_Object arg; |
| 383 | { | 554 | { |
| 384 | double d = extract_float (num); | 555 | double d = extract_float (arg); |
| 385 | IN_FLOAT (d = cosh (d), num); | 556 | #ifdef FLOAT_CHECK_DOMAIN |
| 557 | if (d > 710.0 || d < -710.0) | ||
| 558 | range_error ("cosh", arg); | ||
| 559 | #endif | ||
| 560 | IN_FLOAT (d = cosh (d), "cosh", arg); | ||
| 386 | return make_float (d); | 561 | return make_float (d); |
| 387 | } | 562 | } |
| 388 | 563 | ||
| 389 | DEFUN ("sinh", Fsinh, Ssinh, 1, 1, 0, | 564 | DEFUN ("sinh", Fsinh, Ssinh, 1, 1, 0, |
| 390 | "Return the hyperbolic sine of ARG.") | 565 | "Return the hyperbolic sine of ARG.") |
| 391 | (num) | 566 | (arg) |
| 392 | register Lisp_Object num; | 567 | register Lisp_Object arg; |
| 393 | { | 568 | { |
| 394 | double d = extract_float (num); | 569 | double d = extract_float (arg); |
| 395 | IN_FLOAT (d = sinh (d), num); | 570 | #ifdef FLOAT_CHECK_DOMAIN |
| 571 | if (d > 710.0 || d < -710.0) | ||
| 572 | range_error ("sinh", arg); | ||
| 573 | #endif | ||
| 574 | IN_FLOAT (d = sinh (d), "sinh", arg); | ||
| 396 | return make_float (d); | 575 | return make_float (d); |
| 397 | } | 576 | } |
| 398 | 577 | ||
| 399 | DEFUN ("tanh", Ftanh, Stanh, 1, 1, 0, | 578 | DEFUN ("tanh", Ftanh, Stanh, 1, 1, 0, |
| 400 | "Return the hyperbolic tangent of ARG.") | 579 | "Return the hyperbolic tangent of ARG.") |
| 401 | (num) | 580 | (arg) |
| 402 | register Lisp_Object num; | 581 | register Lisp_Object arg; |
| 403 | { | 582 | { |
| 404 | double d = extract_float (num); | 583 | double d = extract_float (arg); |
| 405 | IN_FLOAT (d = tanh (d), num); | 584 | IN_FLOAT (d = tanh (d), "tanh", arg); |
| 406 | return make_float (d); | 585 | return make_float (d); |
| 407 | } | 586 | } |
| 408 | #endif | 587 | #endif |
| 409 | 588 | ||
| 410 | DEFUN ("abs", Fabs, Sabs, 1, 1, 0, | 589 | DEFUN ("abs", Fabs, Sabs, 1, 1, 0, |
| 411 | "Return the absolute value of ARG.") | 590 | "Return the absolute value of ARG.") |
| 412 | (num) | 591 | (arg) |
| 413 | register Lisp_Object num; | 592 | register Lisp_Object arg; |
| 414 | { | 593 | { |
| 415 | CHECK_NUMBER_OR_FLOAT (num, 0); | 594 | CHECK_NUMBER_OR_FLOAT (arg, 0); |
| 416 | 595 | ||
| 417 | if (XTYPE (num) == Lisp_Float) | 596 | if (XTYPE (arg) == Lisp_Float) |
| 418 | IN_FLOAT (num = make_float (fabs (XFLOAT (num)->data)), num); | 597 | IN_FLOAT (arg = make_float (fabs (XFLOAT (arg)->data)), "abs", arg); |
| 419 | else if (XINT (num) < 0) | 598 | else if (XINT (arg) < 0) |
| 420 | XSETINT (num, - XFASTINT (num)); | 599 | XSETINT (arg, - XFASTINT (arg)); |
| 421 | 600 | ||
| 422 | return num; | 601 | return arg; |
| 423 | } | 602 | } |
| 424 | 603 | ||
| 425 | DEFUN ("float", Ffloat, Sfloat, 1, 1, 0, | 604 | DEFUN ("float", Ffloat, Sfloat, 1, 1, 0, |
| 426 | "Return the floating point number equal to ARG.") | 605 | "Return the floating point number equal to ARG.") |
| 427 | (num) | 606 | (arg) |
| 428 | register Lisp_Object num; | 607 | register Lisp_Object arg; |
| 429 | { | 608 | { |
| 430 | CHECK_NUMBER_OR_FLOAT (num, 0); | 609 | CHECK_NUMBER_OR_FLOAT (arg, 0); |
| 431 | 610 | ||
| 432 | if (XTYPE (num) == Lisp_Int) | 611 | if (XTYPE (arg) == Lisp_Int) |
| 433 | return make_float ((double) XINT (num)); | 612 | return make_float ((double) XINT (arg)); |
| 434 | else /* give 'em the same float back */ | 613 | else /* give 'em the same float back */ |
| 435 | return num; | 614 | return arg; |
| 436 | } | 615 | } |
| 437 | 616 | ||
| 438 | DEFUN ("logb", Flogb, Slogb, 1, 1, 0, | 617 | DEFUN ("logb", Flogb, Slogb, 1, 1, 0, |
| 439 | "Returns the integer that is the base 2 log of ARG.\n\ | 618 | "Returns the integer that is the base 2 log of ARG.\n\ |
| 440 | This is the same as the exponent of a float.") | 619 | This is the same as the exponent of a float.") |
| 441 | (num) | 620 | (arg) |
| 442 | Lisp_Object num; | 621 | Lisp_Object arg; |
| 443 | { | 622 | { |
| 444 | /* System V apparently doesn't have a `logb' function. It might be | 623 | /* System V apparently doesn't have a `logb' function. It might be |
| 445 | better to use it on systems that have it, but Ultrix (at least) | 624 | better to use it on systems that have it, but Ultrix (at least) |
| 446 | doesn't declare it properly in <math.h>; does anyone really care? */ | 625 | doesn't declare it properly in <math.h>; does anyone really care? */ |
| 447 | return Flog (num, make_number (2)); | 626 | return Flog (arg, make_number (2)); |
| 448 | } | 627 | } |
| 449 | 628 | ||
| 450 | /* the rounding functions */ | 629 | /* the rounding functions */ |
| 451 | 630 | ||
| 452 | DEFUN ("ceiling", Fceiling, Sceiling, 1, 1, 0, | 631 | DEFUN ("ceiling", Fceiling, Sceiling, 1, 1, 0, |
| 453 | "Return the smallest integer no less than ARG. (Round toward +inf.)") | 632 | "Return the smallest integer no less than ARG. (Round toward +inf.)") |
| 454 | (num) | 633 | (arg) |
| 455 | register Lisp_Object num; | 634 | register Lisp_Object arg; |
| 456 | { | 635 | { |
| 457 | CHECK_NUMBER_OR_FLOAT (num, 0); | 636 | CHECK_NUMBER_OR_FLOAT (arg, 0); |
| 458 | 637 | ||
| 459 | if (XTYPE (num) == Lisp_Float) | 638 | if (XTYPE (arg) == Lisp_Float) |
| 460 | IN_FLOAT (XSET (num, Lisp_Int, ceil (XFLOAT (num)->data)), num); | 639 | IN_FLOAT (XSET (arg, Lisp_Int, ceil (XFLOAT (arg)->data)), "celing", arg); |
| 461 | 640 | ||
| 462 | return num; | 641 | return arg; |
| 463 | } | 642 | } |
| 464 | 643 | ||
| 465 | DEFUN ("floor", Ffloor, Sfloor, 1, 1, 0, | 644 | DEFUN ("floor", Ffloor, Sfloor, 1, 1, 0, |
| 466 | "Return the largest integer no greater than ARG. (Round towards -inf.)") | 645 | "Return the largest integer no greater than ARG. (Round towards -inf.)") |
| 467 | (num) | 646 | (arg) |
| 468 | register Lisp_Object num; | 647 | register Lisp_Object arg; |
| 469 | { | 648 | { |
| 470 | CHECK_NUMBER_OR_FLOAT (num, 0); | 649 | CHECK_NUMBER_OR_FLOAT (arg, 0); |
| 471 | 650 | ||
| 472 | if (XTYPE (num) == Lisp_Float) | 651 | if (XTYPE (arg) == Lisp_Float) |
| 473 | IN_FLOAT (XSET (num, Lisp_Int, floor (XFLOAT (num)->data)), num); | 652 | IN_FLOAT (XSET (arg, Lisp_Int, floor (XFLOAT (arg)->data)), "floor", arg); |
| 474 | 653 | ||
| 475 | return num; | 654 | return arg; |
| 476 | } | 655 | } |
| 477 | 656 | ||
| 478 | DEFUN ("round", Fround, Sround, 1, 1, 0, | 657 | DEFUN ("round", Fround, Sround, 1, 1, 0, |
| 479 | "Return the nearest integer to ARG.") | 658 | "Return the nearest integer to ARG.") |
| 480 | (num) | 659 | (arg) |
| 481 | register Lisp_Object num; | 660 | register Lisp_Object arg; |
| 482 | { | 661 | { |
| 483 | CHECK_NUMBER_OR_FLOAT (num, 0); | 662 | CHECK_NUMBER_OR_FLOAT (arg, 0); |
| 484 | 663 | ||
| 485 | if (XTYPE (num) == Lisp_Float) | 664 | if (XTYPE (arg) == Lisp_Float) |
| 486 | { | 665 | /* Screw the prevailing rounding mode. */ |
| 487 | /* Screw the prevailing rounding mode. */ | 666 | IN_FLOAT (XSET (arg, Lisp_Int, rint (XFLOAT (arg)->data)), "round", arg); |
| 488 | IN_FLOAT (XSET (num, Lisp_Int, floor (XFLOAT (num)->data + 0.5)), num); | ||
| 489 | |||
| 490 | /* It used to be that on non-USG systems we'd use the `rint' | ||
| 491 | function. But that seems not to be declared properly in | ||
| 492 | <math.h> on Ultrix, I don't want to declare it myself because | ||
| 493 | that might conflict with <math.h> on other systems, and I | ||
| 494 | don't see what's wrong with the code above anyway. */ | ||
| 495 | } | ||
| 496 | 667 | ||
| 497 | return num; | 668 | return arg; |
| 498 | } | 669 | } |
| 499 | 670 | ||
| 500 | DEFUN ("truncate", Ftruncate, Struncate, 1, 1, 0, | 671 | DEFUN ("truncate", Ftruncate, Struncate, 1, 1, 0, |
| 501 | "Truncate a floating point number to an int.\n\ | 672 | "Truncate a floating point number to an int.\n\ |
| 502 | Rounds the value toward zero.") | 673 | Rounds the value toward zero.") |
| 503 | (num) | 674 | (arg) |
| 504 | register Lisp_Object num; | 675 | register Lisp_Object arg; |
| 505 | { | 676 | { |
| 506 | CHECK_NUMBER_OR_FLOAT (num, 0); | 677 | CHECK_NUMBER_OR_FLOAT (arg, 0); |
| 507 | 678 | ||
| 508 | if (XTYPE (num) == Lisp_Float) | 679 | if (XTYPE (arg) == Lisp_Float) |
| 509 | XSET (num, Lisp_Int, (int) XFLOAT (num)->data); | 680 | XSET (arg, Lisp_Int, (int) XFLOAT (arg)->data); |
| 681 | |||
| 682 | return arg; | ||
| 683 | } | ||
| 684 | |||
| 685 | #if 0 | ||
| 686 | /* It's not clear these are worth adding. */ | ||
| 687 | |||
| 688 | DEFUN ("fceiling", Ffceiling, Sfceiling, 1, 1, 0, | ||
| 689 | "Return the smallest integer no less than ARG, as a float.\n\ | ||
| 690 | \(Round toward +inf.\)") | ||
| 691 | (arg) | ||
| 692 | register Lisp_Object arg; | ||
| 693 | { | ||
| 694 | double d = extract_float (arg); | ||
| 695 | IN_FLOAT (d = ceil (d), "fceiling", arg); | ||
| 696 | return make_float (d); | ||
| 697 | } | ||
| 698 | |||
| 699 | DEFUN ("ffloor", Fffloor, Sffloor, 1, 1, 0, | ||
| 700 | "Return the largest integer no greater than ARG, as a float.\n\ | ||
| 701 | \(Round towards -inf.\)") | ||
| 702 | (arg) | ||
| 703 | register Lisp_Object arg; | ||
| 704 | { | ||
| 705 | double d = extract_float (arg); | ||
| 706 | IN_FLOAT (d = floor (d), "ffloor", arg); | ||
| 707 | return make_float (d); | ||
| 708 | } | ||
| 510 | 709 | ||
| 511 | return num; | 710 | DEFUN ("fround", Ffround, Sfround, 1, 1, 0, |
| 711 | "Return the nearest integer to ARG, as a float.") | ||
| 712 | (arg) | ||
| 713 | register Lisp_Object arg; | ||
| 714 | { | ||
| 715 | double d = extract_float (arg); | ||
| 716 | IN_FLOAT (d = rint (XFLOAT (arg)->data), "fround", arg); | ||
| 717 | return make_float (d); | ||
| 718 | } | ||
| 719 | |||
| 720 | DEFUN ("ftruncate", Fftruncate, Sftruncate, 1, 1, 0, | ||
| 721 | "Truncate a floating point number to an integral float value.\n\ | ||
| 722 | Rounds the value toward zero.") | ||
| 723 | (arg) | ||
| 724 | register Lisp_Object arg; | ||
| 725 | { | ||
| 726 | double d = extract_float (arg); | ||
| 727 | if (d >= 0.0) | ||
| 728 | IN_FLOAT (d = floor (d), "ftruncate", arg); | ||
| 729 | else | ||
| 730 | IN_FLOAT (d = ceil (d), arg); | ||
| 731 | return make_float (d); | ||
| 512 | } | 732 | } |
| 733 | #endif | ||
| 513 | 734 | ||
| 735 | #ifdef FLOAT_CATCH_SIGILL | ||
| 514 | static SIGTYPE | 736 | static SIGTYPE |
| 515 | float_error (signo) | 737 | float_error (signo) |
| 516 | int signo; | 738 | int signo; |
| @@ -534,9 +756,46 @@ float_error (signo) | |||
| 534 | Fsignal (Qarith_error, Fcons (float_error_arg, Qnil)); | 756 | Fsignal (Qarith_error, Fcons (float_error_arg, Qnil)); |
| 535 | } | 757 | } |
| 536 | 758 | ||
| 759 | /* Another idea was to replace the library function `infnan' | ||
| 760 | where SIGILL is signaled. */ | ||
| 761 | |||
| 762 | #endif /* FLOAT_CATCH_SIGILL */ | ||
| 763 | |||
| 764 | #ifdef HAVE_MATHERR | ||
| 765 | int | ||
| 766 | matherr (x) | ||
| 767 | struct exception *x; | ||
| 768 | { | ||
| 769 | Lisp_Object args; | ||
| 770 | if (! in_float) | ||
| 771 | /* Not called from emacs-lisp float routines; do the default thing. */ | ||
| 772 | return 0; | ||
| 773 | if (!strcmp (x->name, "pow")) | ||
| 774 | x->name = "expt"; | ||
| 775 | |||
| 776 | args | ||
| 777 | = Fcons (build_string (x->name), | ||
| 778 | Fcons (make_float (x->arg1), | ||
| 779 | ((!strcmp (x->name, "log") || !strcmp (x->name, "pow")) | ||
| 780 | ? Fcons (make_float (x->arg2), Qnil) | ||
| 781 | : Qnil))); | ||
| 782 | switch (x->type) | ||
| 783 | { | ||
| 784 | case DOMAIN: Fsignal (Qdomain_error, args); break; | ||
| 785 | case SING: Fsignal (Qsingularity_error, args); break; | ||
| 786 | case OVERFLOW: Fsignal (Qoverflow_error, args); break; | ||
| 787 | case UNDERFLOW: Fsignal (Qunderflow_error, args); break; | ||
| 788 | default: Fsignal (Qarith_error, args); break; | ||
| 789 | } | ||
| 790 | return (1); /* don't set errno or print a message */ | ||
| 791 | } | ||
| 792 | #endif /* HAVE_MATHERR */ | ||
| 793 | |||
| 537 | init_floatfns () | 794 | init_floatfns () |
| 538 | { | 795 | { |
| 796 | #ifdef FLOAT_CATCH_SIGILL | ||
| 539 | signal (SIGILL, float_error); | 797 | signal (SIGILL, float_error); |
| 798 | #endif | ||
| 540 | in_float = 0; | 799 | in_float = 0; |
| 541 | } | 800 | } |
| 542 | 801 | ||
| @@ -564,7 +823,11 @@ syms_of_floatfns () | |||
| 564 | defsubr (&Serf); | 823 | defsubr (&Serf); |
| 565 | defsubr (&Serfc); | 824 | defsubr (&Serfc); |
| 566 | defsubr (&Slog_gamma); | 825 | defsubr (&Slog_gamma); |
| 567 | defsubr (&Scbrt); | 826 | defsubr (&Scube_root); |
| 827 | defsubr (&Sfceiling); | ||
| 828 | defsubr (&Sffloor); | ||
| 829 | defsubr (&Sfround); | ||
| 830 | defsubr (&Sftruncate); | ||
| 568 | #endif | 831 | #endif |
| 569 | defsubr (&Sexp); | 832 | defsubr (&Sexp); |
| 570 | defsubr (&Sexpt); | 833 | defsubr (&Sexpt); |