1 21 22 package org.armedbear.lisp; 23 24 import java.lang.reflect.Method ; 25 26 public final class MathFunctions extends Lisp 27 { 28 private static final boolean isJava15; 30 static { 31 isJava15 = System.getProperty("java.version").startsWith("1.5"); 32 } 33 34 private static final Primitive1 SIN = new Primitive1("sin", "radians") 36 { 37 public LispObject execute(LispObject arg) throws ConditionThrowable 38 { 39 return sin(arg); 40 } 41 }; 42 43 private static LispObject sin(LispObject arg) throws ConditionThrowable 44 { 45 if (arg.realp()) 46 return new LispFloat(Math.sin(LispFloat.coerceToFloat(arg).getValue())); 47 if (arg instanceof Complex) { 48 LispObject n = arg.multiplyBy(Complex.getInstance(Fixnum.ZERO, 49 Fixnum.ONE)); 50 LispObject result = exp(n); 51 result = result.subtract(exp(n.multiplyBy(Fixnum.MINUS_ONE))); 52 return result.divideBy(Fixnum.TWO.multiplyBy(Complex.getInstance(Fixnum.ZERO, 53 Fixnum.ONE))); 54 } 55 return signal(new TypeError(arg, Symbol.NUMBER)); 56 } 57 58 private static final Primitive1 COS = new Primitive1("cos", "radians") 60 { 61 public LispObject execute(LispObject arg) throws ConditionThrowable 62 { 63 return cos(arg); 64 } 65 }; 66 67 private static LispObject cos(LispObject arg) throws ConditionThrowable 68 { 69 if (arg.realp()) 70 return new LispFloat(Math.cos(LispFloat.coerceToFloat(arg).getValue())); 71 if (arg instanceof Complex) { 72 LispObject n = arg.multiplyBy(Complex.getInstance(Fixnum.ZERO, 73 Fixnum.ONE)); 74 LispObject result = exp(n); 75 result = result.add(exp(n.multiplyBy(Fixnum.MINUS_ONE))); 76 return result.divideBy(Fixnum.TWO); 77 } 78 return signal(new TypeError(arg, "number")); 79 } 80 81 private static final Primitive1 TAN = new Primitive1("tan", "radians") 83 { 84 public LispObject execute(LispObject arg) throws ConditionThrowable 85 { 86 if (arg.realp()) 87 return new LispFloat(Math.tan(LispFloat.coerceToFloat(arg).value)); 88 return sin(arg).divideBy(cos(arg)); 89 } 90 }; 91 92 private static final Primitive1 ASIN = new Primitive1("asin", "number") 94 { 95 public LispObject execute(LispObject arg) throws ConditionThrowable 96 { 97 return asin(arg); 98 } 99 }; 100 101 private static LispObject asin(LispObject arg) throws ConditionThrowable 102 { 103 if (arg instanceof Complex) { 104 LispObject im = ((Complex)arg).getImaginaryPart(); 105 if (im.zerop()) 106 return Complex.getInstance(asin(((Complex)arg).getRealPart()), 107 im); 108 } 109 if (arg instanceof LispFloat) 110 return new LispFloat(Math.asin(((LispFloat)arg).value)); 111 LispObject result = arg.multiplyBy(arg); 112 result = Fixnum.ONE.subtract(result); 113 result = sqrt(result); 114 LispObject n = Complex.getInstance(Fixnum.ZERO, Fixnum.ONE); 115 n = n.multiplyBy(arg); 116 result = n.add(result); 117 result = log(result); 118 result = result.multiplyBy(Complex.getInstance(Fixnum.ZERO, Fixnum.MINUS_ONE)); 119 if (result instanceof Complex) { 120 if (arg instanceof Complex) 121 return result; 122 LispObject im = ((Complex)result).getImaginaryPart(); 123 if (im.zerop()) 124 return ((Complex)result).getRealPart(); 125 } 126 return result; 127 } 128 129 private static final Primitive1 ACOS = new Primitive1("acos", "number") 131 { 132 public LispObject execute(LispObject arg) throws ConditionThrowable 133 { 134 return acos(arg); 135 } 136 }; 137 138 private static LispObject acos(LispObject arg) throws ConditionThrowable 139 { 140 if (arg instanceof Complex) { 141 LispObject im = ((Complex)arg).getImaginaryPart(); 142 if (im.zerop()) 143 return Complex.getInstance(acos(((Complex)arg).getRealPart()), 144 im); 145 } 146 if (arg instanceof LispFloat) 147 return new LispFloat(Math.acos(((LispFloat)arg).value)); 148 LispObject result = LispFloat.PI.divideBy(Fixnum.TWO); 149 result = result.subtract(asin(arg)); 150 if (result instanceof Complex) { 151 if (arg instanceof Complex) 152 return result; 153 LispObject im = ((Complex)result).getImaginaryPart(); 154 if (im.zerop()) 155 return ((Complex)result).getRealPart(); 156 } 157 return result; 158 } 159 160 private static final Primitive ATAN = 162 new Primitive("atan", "number1 &optional number2") 163 { 164 public LispObject execute(LispObject arg) throws ConditionThrowable 165 { 166 return atan(arg); 167 } 168 169 public LispObject execute(LispObject first, LispObject second) 170 throws ConditionThrowable 171 { 172 return atan(first.divideBy(second)); 173 } 174 }; 175 176 private static LispObject atan(LispObject arg) throws ConditionThrowable 177 { 178 if (arg instanceof Complex) { 179 LispObject im = ((Complex)arg).getImaginaryPart(); 180 if (im.zerop()) 181 return Complex.getInstance(atan(((Complex)arg).getRealPart()), 182 im); 183 LispObject result = arg.multiplyBy(arg); 184 result = result.add(Fixnum.ONE); 185 result = Fixnum.ONE.divideBy(result); 186 result = sqrt(result); 187 LispObject n = Complex.getInstance(Fixnum.ZERO, Fixnum.ONE); 188 n = n.multiplyBy(arg); 189 n = n.add(Fixnum.ONE); 190 result = n.multiplyBy(result); 191 result = log(result); 192 result = result.multiplyBy(Complex.getInstance(Fixnum.ZERO, Fixnum.MINUS_ONE)); 193 return result; 194 } 195 return new LispFloat(Math.atan(LispFloat.coerceToFloat(arg).getValue())); 196 } 197 198 private static final Primitive1 SINH = new Primitive1("sinh", "number") 200 { 201 public LispObject execute(LispObject arg) throws ConditionThrowable 202 { 203 return sinh(arg); 204 } 205 }; 206 207 private static Method sinhMethod = null; 208 209 private static LispObject sinh(LispObject arg) throws ConditionThrowable 210 { 211 if (arg instanceof Complex) { 212 LispObject im = ((Complex)arg).getImaginaryPart(); 213 if (im.zerop()) 214 return Complex.getInstance(sinh(((Complex)arg).getRealPart()), 215 im); 216 } 217 if (isJava15 && arg instanceof LispFloat) { 218 try { 219 if (sinhMethod == null) { 220 Class c = Class.forName("java.lang.Math"); 221 Class [] parameterTypes = new Class [1]; 222 parameterTypes[0] = Double.TYPE; 223 sinhMethod = c.getMethod("sinh", parameterTypes); 224 } 225 if (sinhMethod != null) { 226 Object [] args; 227 args = new Object [1]; 228 args[0] = new Double (((LispFloat)arg).value); 229 Double d = (Double ) sinhMethod.invoke(null, args); 230 return new LispFloat(d.doubleValue()); 231 } 232 } 233 catch (Throwable t) { 234 Debug.trace(t); 235 } 237 } 238 LispObject result = exp(arg); 239 result = result.subtract(exp(arg.multiplyBy(Fixnum.MINUS_ONE))); 240 result = result.divideBy(Fixnum.TWO); 241 if (result instanceof Complex) { 242 if (arg instanceof Complex) 243 return result; 244 LispObject im = ((Complex)result).getImaginaryPart(); 245 if (im.zerop()) 246 return ((Complex)result).getRealPart(); 247 } 248 return result; 249 } 250 251 private static final Primitive1 COSH = new Primitive1("cosh", "number") 253 { 254 public LispObject execute(LispObject arg) throws ConditionThrowable 255 { 256 return cosh(arg); 257 } 258 }; 259 260 private static Method coshMethod = null; 261 262 private static LispObject cosh(LispObject arg) throws ConditionThrowable 263 { 264 if (arg instanceof Complex) { 265 LispObject im = ((Complex)arg).getImaginaryPart(); 266 if (im.zerop()) 267 return Complex.getInstance(cosh(((Complex)arg).getRealPart()), 268 im); 269 } 270 if (isJava15 && arg instanceof LispFloat) { 271 try { 272 if (coshMethod == null) { 273 Class c = Class.forName("java.lang.Math"); 274 Class [] parameterTypes = new Class [1]; 275 parameterTypes[0] = Double.TYPE; 276 coshMethod = c.getMethod("cosh", parameterTypes); 277 } 278 if (coshMethod != null) { 279 Object [] args; 280 args = new Object [1]; 281 args[0] = new Double (((LispFloat)arg).value); 282 Double d = (Double ) coshMethod.invoke(null, args); 283 return new LispFloat(d.doubleValue()); 284 } 285 } 286 catch (Throwable t) { 287 Debug.trace(t); 288 } 290 } 291 LispObject result = exp(arg); 292 result = result.add(exp(arg.multiplyBy(Fixnum.MINUS_ONE))); 293 result = result.divideBy(Fixnum.TWO); 294 if (result instanceof Complex) { 295 if (arg instanceof Complex) 296 return result; 297 LispObject im = ((Complex)result).getImaginaryPart(); 298 if (im.zerop()) 299 return ((Complex)result).getRealPart(); 300 } 301 return result; 302 } 303 304 private static Method tanhMethod = null; 305 306 private static final Primitive1 TANH = new Primitive1("tanh", "number") 308 { 309 public LispObject execute(LispObject arg) throws ConditionThrowable 310 { 311 if (isJava15 && arg instanceof LispFloat) { 312 try { 313 if (tanhMethod == null) { 314 Class c = Class.forName("java.lang.Math"); 315 Class [] parameterTypes = new Class [1]; 316 parameterTypes[0] = Double.TYPE; 317 tanhMethod = c.getMethod("tanh", parameterTypes); 318 } 319 if (tanhMethod != null) { 320 Object [] args; 321 args = new Object [1]; 322 args[0] = new Double (((LispFloat)arg).value); 323 Double d = (Double ) tanhMethod.invoke(null, args); 324 return new LispFloat(d.doubleValue()); 325 } 326 } 327 catch (Throwable t) { 328 Debug.trace(t); 329 } 331 } 332 return sinh(arg).divideBy(cosh(arg)); 333 } 334 }; 335 336 private static final Primitive1 ASINH = new Primitive1("asinh", "number") 338 { 339 public LispObject execute(LispObject arg) throws ConditionThrowable 340 { 341 return asinh(arg); 342 } 343 }; 344 345 private static LispObject asinh(LispObject arg) throws ConditionThrowable 346 { 347 if (arg instanceof Complex) { 348 LispObject im = ((Complex)arg).getImaginaryPart(); 349 if (im.zerop()) 350 return Complex.getInstance(asinh(((Complex)arg).getRealPart()), 351 im); 352 } 353 LispObject result = arg.multiplyBy(arg); 354 result = Fixnum.ONE.add(result); 355 result = sqrt(result); 356 result = result.add(arg); 357 result = log(result); 358 if (result instanceof Complex) { 359 if (arg instanceof Complex) 360 return result; 361 LispObject im = ((Complex)result).getImaginaryPart(); 362 if (im.zerop()) 363 return ((Complex)result).getRealPart(); 364 } 365 return result; 366 } 367 368 private static final Primitive1 ACOSH = new Primitive1("acosh", "number") 370 { 371 public LispObject execute(LispObject arg) throws ConditionThrowable 372 { 373 return acosh(arg); 374 } 375 }; 376 377 private static LispObject acosh(LispObject arg) throws ConditionThrowable 378 { 379 if (arg instanceof Complex) { 380 LispObject im = ((Complex)arg).getImaginaryPart(); 381 if (im.zerop()) 382 return Complex.getInstance(acosh(((Complex)arg).getRealPart()), 383 im); 384 } 385 LispObject n1 = arg.add(Fixnum.ONE); 386 n1 = n1.divideBy(Fixnum.TWO); 387 n1 = sqrt(n1); 388 LispObject n2 = arg.subtract(Fixnum.ONE); 389 n2 = n2.divideBy(Fixnum.TWO); 390 n2 = sqrt(n2); 391 LispObject result = n1.add(n2); 392 result = log(result); 393 result = result.multiplyBy(Fixnum.TWO); 394 if (result instanceof Complex) { 395 if (arg instanceof Complex) 396 return result; 397 LispObject im = ((Complex)result).getImaginaryPart(); 398 if (im.zerop()) 399 return ((Complex)result).getRealPart(); 400 } 401 return result; 402 } 403 404 private static final Primitive1 ATANH = new Primitive1("atanh", "number") 406 { 407 public LispObject execute(LispObject arg) throws ConditionThrowable 408 { 409 return atanh(arg); 410 } 411 }; 412 413 private static LispObject atanh(LispObject arg) throws ConditionThrowable 414 { 415 if (arg instanceof Complex) { 416 LispObject im = ((Complex)arg).getImaginaryPart(); 417 if (im.zerop()) 418 return Complex.getInstance(atanh(((Complex)arg).getRealPart()), 419 im); 420 } 421 LispObject n1 = log(Fixnum.ONE.add(arg)); 422 LispObject n2 = log(Fixnum.ONE.subtract(arg)); 423 LispObject result = n1.subtract(n2); 424 result = result.divideBy(Fixnum.TWO); 425 if (result instanceof Complex) { 426 if (arg instanceof Complex) 427 return result; 428 LispObject im = ((Complex)result).getImaginaryPart(); 429 if (im.zerop()) 430 return ((Complex)result).getRealPart(); 431 } 432 return result; 433 } 434 435 private static final Primitive1 EXP = new Primitive1("exp", "number") 437 { 438 public LispObject execute(LispObject arg) throws ConditionThrowable 439 { 440 return exp(arg); 441 } 442 }; 443 444 private static LispObject exp(LispObject arg) throws ConditionThrowable 445 { 446 if (arg instanceof LispFloat) 447 return new LispFloat(Math.exp(((LispFloat)arg).value)); 448 if (arg.realp()) 449 return new LispFloat(Math.exp(LispFloat.coerceToFloat(arg).value)); 450 if (arg instanceof Complex) { 451 Complex argc = (Complex)arg; 452 double re = LispFloat.coerceToFloat(argc.getRealPart()).getValue(); 453 double im = LispFloat.coerceToFloat(argc.getImaginaryPart()).getValue(); 454 LispFloat resX = new LispFloat(Math.exp(re) * Math.cos(im)); 455 LispFloat resY = new LispFloat(Math.exp(re) * Math.sin(im)); 456 return Complex.getInstance(resX, resY); 457 } 458 return signal(new TypeError(arg, Symbol.NUMBER)); 459 } 460 461 private static final Primitive1 SQRT = new Primitive1("sqrt", "number") 463 { 464 public LispObject execute(LispObject arg) throws ConditionThrowable 465 { 466 return sqrt(arg); 467 } 468 }; 469 470 private static final LispObject sqrt(LispObject obj) throws ConditionThrowable 471 { 472 if (obj.realp() && !obj.minusp()) { LispFloat f = LispFloat.coerceToFloat(obj); 474 return new LispFloat(Math.sqrt(f.getValue())); 475 } else { if (obj.realp()) { 477 return Complex.getInstance(new LispFloat(0), 478 sqrt(Fixnum.ZERO.subtract(obj))); 479 } else if (obj instanceof Complex) { 480 return exp(log(obj).divideBy(Fixnum.TWO)); 481 } 482 } 483 signal(new TypeError(obj, "number")); 484 return NIL; 485 } 486 487 private static final Primitive LOG = new Primitive("log", "number &optional base") 489 { 490 public LispObject execute(LispObject arg) throws ConditionThrowable 491 { 492 return log(arg); 493 } 494 public LispObject execute(LispObject number, LispObject base) 495 throws ConditionThrowable 496 { 497 return log(number).divideBy(log(base)); 498 } 499 }; 500 501 private static final LispObject log(LispObject obj) throws ConditionThrowable 502 { 503 if (obj.realp() && !obj.minusp()) { if (obj instanceof Fixnum) 505 return new LispFloat(Math.log(((Fixnum)obj).getValue())); 506 if (obj instanceof Bignum) 507 return new LispFloat(Math.log(((Bignum)obj).floatValue())); 508 if (obj instanceof Ratio) 509 return new LispFloat(Math.log(((Ratio)obj).floatValue())); 510 if (obj instanceof LispFloat) 511 return new LispFloat(Math.log(((LispFloat)obj).getValue())); 512 } else { LispFloat re, im, phase, abs; 514 if (obj.realp() && obj.minusp()) { 515 re = LispFloat.coerceToFloat(obj); 516 abs = new LispFloat(Math.abs(re.getValue())); 517 phase = new LispFloat(Math.PI); 518 return Complex.getInstance(new LispFloat(Math.log(abs.getValue())), phase); 519 } else if (obj instanceof Complex) { 520 re = LispFloat.coerceToFloat(((Complex)obj).getRealPart()); 521 im = LispFloat.coerceToFloat(((Complex)obj).getImaginaryPart()); 522 phase = new LispFloat(Math.atan2(im.getValue(), re.getValue())); abs = (LispFloat)((Complex)obj).ABS(); 524 return Complex.getInstance(new LispFloat(Math.log(abs.getValue())), phase); 525 } 526 } 527 signal(new TypeError(obj, "number")); 528 return NIL; 529 } 530 } 531 | Popular Tags |