Mercurial > emacs
comparison src/floatfns.c @ 2094:c77607f8e32d
(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.
| author | Richard M. Stallman <rms@gnu.org> |
|---|---|
| date | Wed, 10 Mar 1993 05:33:40 +0000 |
| parents | 699ae3079c09 |
| children | 4077ef8ad483 |
comparison
equal
deleted
inserted
replaced
| 2093:ce8bad247b1a | 2094:c77607f8e32d |
|---|---|
| 16 You should have received a copy of the GNU General Public License | 16 You should have received a copy of the GNU General Public License |
| 17 along with GNU Emacs; see the file COPYING. If not, write to | 17 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" |
| 24 #include "lisp.h" | 49 #include "lisp.h" |
| 25 #include "syssignal.h" | 50 #include "syssignal.h" |
| 27 Lisp_Object Qarith_error; | 52 Lisp_Object Qarith_error; |
| 28 | 53 |
| 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. */ |
| 38 | 86 |
| 39 #ifdef VMS | 87 #ifdef VMS |
| 41 #undef sinh | 89 #undef sinh |
| 42 #define cosh(x) ((exp(x)+exp(-x))*0.5) | 90 #define cosh(x) ((exp(x)+exp(-x))*0.5) |
| 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. |
| 49 This tells float_error what to do. */ | 101 This tells float_error what to do. */ |
| 50 | 102 |
| 51 static int in_float; | 103 static int in_float; |
| 52 | 104 |
| 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. |
| 60 D is normally an assignment expression. | 114 D is normally an assignment expression. |
| 61 Handle errors which may result in signals or may set errno. | 115 Handle errors which may result in signals or may set errno. |
| 62 | 116 |
| 63 Note that float_error may be declared to return void, so you can't | 117 Note that float_error may be declared to return void, so you can't |
| 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 |
| 74 double | 162 double |
| 75 extract_float (num) | 163 extract_float (num) |
| 84 | 172 |
| 85 /* Trig functions. */ | 173 /* Trig functions. */ |
| 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 |
| 147 #if 0 /* Leave these out unless we find there's a reason for them. */ | 248 #if 0 /* Leave these out unless we find there's a reason for them. */ |
| 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 |
| 215 #endif | 316 #endif |
| 216 | 317 |
| 217 #if 0 /* Leave these out unless we see they are worth having. */ | 318 #if 0 /* Leave these out unless we see they are worth having. */ |
| 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 |
| 259 #endif | 367 #endif |
| 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 |
| 347 #if 0 /* Not clearly worth adding. */ | 498 #if 0 /* Not clearly worth adding. */ |
| 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); | 667 |
| 489 | 668 return arg; |
| 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 | |
| 497 return num; | |
| 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); |
| 510 | 681 |
| 511 return num; | 682 return arg; |
| 512 } | 683 } |
| 513 | 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 } | |
| 709 | |
| 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); | |
| 732 } | |
| 733 #endif | |
| 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; |
| 517 { | 739 { |
| 518 if (! in_float) | 740 if (! in_float) |
| 532 in_float = 0; | 754 in_float = 0; |
| 533 | 755 |
| 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 |
| 543 syms_of_floatfns () | 802 syms_of_floatfns () |
| 544 { | 803 { |
| 562 defsubr (&Sbessel_j1); | 821 defsubr (&Sbessel_j1); |
| 563 defsubr (&Sbessel_jn); | 822 defsubr (&Sbessel_jn); |
| 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); |
| 571 defsubr (&Slog); | 834 defsubr (&Slog); |
| 572 defsubr (&Slog10); | 835 defsubr (&Slog10); |
