1 /* $Header: //info.ravenbrook.com/project/jili/version/1.1/code/mnj/lua/MathLib.java#1 $
2 * Copyright (c) 2006 Nokia Corporation and/or its subsidiary(-ies).
5 * Permission is hereby granted, free of charge, to any person obtaining
6 * a copy of this software and associated documentation files (the
7 * "Software"), to deal in the Software without restriction, including
8 * without limitation the rights to use, copy, modify, merge, publish,
9 * distribute, sublicense, and/or sell copies of the Software, and to
10 * permit persons to whom the Software is furnished to do so, subject
11 * to the following conditions:
13 * The above copyright notice and this permission notice shall be
14 * included in all copies or substantial portions of the Software.
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
19 * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
20 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
21 * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
27 import java
.util
.Random
;
30 * Contains Lua's math library.
31 * The library can be opened using the {@link #open} method.
32 * Because this library is implemented on top of CLDC 1.1 it is not as
33 * complete as the PUC-Rio math library. Trigononmetric inverses
34 * (EG <code>acos</code>) and hyperbolic trigonometric functions (EG
35 * <code>cosh</code>) are not provided.
37 public final class MathLib
extends LuaJavaCallback
39 // Each function in the library corresponds to an instance of
40 // this class which is associated (the 'which' member) with an integer
41 // which is unique within this class. They are taken from the following
44 private static final int ABS
= 1;
45 private static final int ACOS
= 2;
46 private static final int ASIN
= 3;
47 private static final int ATAN2
= 4;
48 private static final int ATAN
= 5;
49 private static final int CEIL
= 6;
50 private static final int COSH
= 7;
51 private static final int COS
= 8;
52 private static final int DEG
= 9;
53 private static final int EXP
= 10;
54 private static final int FLOOR
= 11;
55 private static final int FMOD
= 12;
56 private static final int FREXP
= 13;
57 private static final int LDEXP
= 14;
58 private static final int LOG
= 15;
59 private static final int MAX
= 16;
60 private static final int MIN
= 17;
61 private static final int MODF
= 18;
62 private static final int POW
= 19;
63 private static final int RAD
= 20;
64 private static final int RANDOM
= 21;
65 private static final int RANDOMSEED
= 22;
66 private static final int SINH
= 23;
67 private static final int SIN
= 24;
68 private static final int SQRT
= 25;
69 private static final int TANH
= 26;
70 private static final int TAN
= 27;
71 private static final int LOG10
= 28;
72 private static final int L2MAGNITUDE
= 29;
74 private static final Random rng
= new Random();
77 * Which library function this object represents. This value should
78 * be one of the "enums" defined in the class.
82 /** Constructs instance, filling in the 'which' member. */
83 private MathLib(int which
)
89 * Implements all of the functions in the Lua math library. Do not
91 * @param L the Lua state in which to execute.
92 * @return number of returned parameters, as per convention.
94 public int luaFunction(Lua L
)
143 return randomseed(L
);
155 return l2magnitude(L
);
161 * Opens the library into the given Lua state. This registers
162 * the symbols of the library in the global table.
163 * @param L The Lua state into which to open.
165 public static void open(Lua L
)
167 LuaTable t
= L
.register("math");
173 r(L
, "atan2", ATAN2
);
179 r(L
, "floor", FLOOR
);
181 r(L
, "frexp", FREXP
);
182 r(L
, "ldexp", LDEXP
);
184 r(L
, "log10", LOG10
);
190 r(L
, "random", RANDOM
);
191 r(L
, "randomseed", RANDOMSEED
);
197 r(L
, "l2magnitude", L2MAGNITUDE
);
199 L
.setField(t
, "pi", Lua
.valueOfNumber(Math
.PI
));
200 L
.setField(t
, "huge", Lua
.valueOfNumber(Double
.POSITIVE_INFINITY
));
203 /** Register a function. */
204 private static void r(Lua L
, String name
, int which
)
206 MathLib f
= new MathLib(which
);
207 L
.setField(L
.getGlobal("math"), name
, f
);
210 private static int abs(Lua L
)
212 L
.pushNumber(Math
.abs(L
.checkNumber(1)));
216 private static int acos(Lua L
)
218 L
.pushNumber(Math
.acos(L
.checkNumber(1)));
222 private static int asin(Lua L
)
224 L
.pushNumber(Math
.asin(L
.checkNumber(1)));
228 private static int atan(Lua L
)
230 L
.pushNumber(Math
.atan(L
.checkNumber(1)));
234 private static int atan2(Lua L
)
236 L
.pushNumber(Math
.atan2(L
.checkNumber(1), L
.checkNumber(2)));
240 private static int ceil(Lua L
)
242 L
.pushNumber(Math
.ceil(L
.checkNumber(1)));
246 private static int cosh(Lua L
)
248 L
.pushNumber(Math
.cosh(L
.checkNumber(1)));
252 private static int cos(Lua L
)
254 L
.pushNumber(Math
.cos(L
.checkNumber(1)));
258 private static int deg(Lua L
)
260 L
.pushNumber(Math
.toDegrees(L
.checkNumber(1)));
264 private static int exp(Lua L
)
266 // CLDC 1.1 has Math.E but no exp, pow, or log. Bizarre.
267 L
.pushNumber(Lua
.iNumpow(Math
.E
, L
.checkNumber(1)));
271 private static int floor(Lua L
)
273 L
.pushNumber(Math
.floor(L
.checkNumber(1)));
277 private static int fmod(Lua L
)
279 L
.pushNumber(L
.checkNumber(1) % L
.checkNumber(2));
283 private static int frexp(Lua L
)
285 int scale
= 1 + Math
.getExponent(L
.checkNumber(1));
286 L
.pushNumber(Math
.scalb(L
.checkNumber(1), -scale
));
291 private static int ldexp(Lua L
)
293 L
.pushNumber(Math
.scalb(L
.checkNumber(1), (int)L
.checkNumber(2)));
297 private static int log(Lua L
)
299 L
.pushNumber(Math
.log(L
.checkNumber(1)));
303 private static int log10(Lua L
)
305 L
.pushNumber(Math
.log(L
.checkNumber(1)) / Math
.log(10));
309 private static int max(Lua L
)
311 int n
= L
.getTop(); // number of arguments
312 double dmax
= L
.checkNumber(1);
313 for (int i
=2; i
<=n
; ++i
)
315 double d
= L
.checkNumber(i
);
316 dmax
= Math
.max(dmax
, d
);
322 private static int min(Lua L
)
324 int n
= L
.getTop(); // number of arguments
325 double dmin
= L
.checkNumber(1);
326 for (int i
=2; i
<=n
; ++i
)
328 double d
= L
.checkNumber(i
);
329 dmin
= Math
.min(dmin
, d
);
335 private static int modf(Lua L
)
337 double x
= L
.checkNumber(1);
345 private static int pow(Lua L
)
347 L
.pushNumber(Lua
.iNumpow(L
.checkNumber(1), L
.checkNumber(2)));
351 private static int rad(Lua L
)
353 L
.pushNumber(Math
.toRadians(L
.checkNumber(1)));
357 private static int random(Lua L
)
359 // It would seem better style to associate the java.util.Random
360 // instance with the Lua instance (by implementing and using a
361 // registry for example). However, PUC-rio uses the ISO C library
362 // and so will share the same random number generator across all Lua
363 // states. So we do too.
364 switch (L
.getTop()) // check number of arguments
366 case 0: // no arguments
367 L
.pushNumber(rng
.nextDouble());
370 case 1: // only upper limit
372 int u
= L
.checkInt(1);
373 L
.argCheck(1<=u
, 1, "interval is empty");
374 L
.pushNumber(rng
.nextInt(u
) + 1);
378 case 2: // lower and upper limits
380 int l
= L
.checkInt(1);
381 int u
= L
.checkInt(2);
382 L
.argCheck(l
<=u
, 2, "interval is empty");
383 L
.pushNumber(rng
.nextInt(u
) + l
);
388 return L
.error("wrong number of arguments");
393 private static int randomseed(Lua L
)
395 rng
.setSeed((long)L
.checkNumber(1));
399 private static int sinh(Lua L
)
401 L
.pushNumber(Math
.sinh(L
.checkNumber(1)));
405 private static int sin(Lua L
)
407 L
.pushNumber(Math
.sin(L
.checkNumber(1)));
411 private static int sqrt(Lua L
)
413 L
.pushNumber(Math
.sqrt(L
.checkNumber(1)));
417 private static int tanh(Lua L
)
419 L
.pushNumber(Math
.tanh(L
.checkNumber(1)));
423 private static int tan(Lua L
)
425 L
.pushNumber(Math
.tan(L
.checkNumber(1)));
429 private static int l2magnitude(Lua L
)
431 L
.pushNumber(Math
.ceil(Math
.log(L
.checkNumber(1) + 1) / Math
.log(2)));