Fix joystick-related desync
[jpcrr.git] / mnj / lua / MathLib.java
blobe3622d622905aee09407ad2f1a4e238323335b44
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).
3 * All rights reserved.
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.
25 package mnj.lua;
27 import java.util.Random;
29 /**
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
42 // set.
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();
76 /**
77 * Which library function this object represents. This value should
78 * be one of the "enums" defined in the class.
80 private int which;
82 /** Constructs instance, filling in the 'which' member. */
83 private MathLib(int which)
85 this.which = which;
88 /**
89 * Implements all of the functions in the Lua math library. Do not
90 * call directly.
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)
96 switch (which)
98 case ABS:
99 return abs(L);
100 case ACOS:
101 return acos(L);
102 case ASIN:
103 return asin(L);
104 case ATAN:
105 return atan(L);
106 case ATAN2:
107 return atan2(L);
108 case CEIL:
109 return ceil(L);
110 case COSH:
111 return cosh(L);
112 case COS:
113 return cos(L);
114 case DEG:
115 return deg(L);
116 case EXP:
117 return exp(L);
118 case FLOOR:
119 return floor(L);
120 case FMOD:
121 return fmod(L);
122 case FREXP:
123 return frexp(L);
124 case LDEXP:
125 return ldexp(L);
126 case LOG:
127 return log(L);
128 case LOG10:
129 return log10(L);
130 case MAX:
131 return max(L);
132 case MIN:
133 return min(L);
134 case MODF:
135 return modf(L);
136 case POW:
137 return pow(L);
138 case RAD:
139 return rad(L);
140 case RANDOM:
141 return random(L);
142 case RANDOMSEED:
143 return randomseed(L);
144 case SINH:
145 return sinh(L);
146 case SIN:
147 return sin(L);
148 case SQRT:
149 return sqrt(L);
150 case TANH:
151 return tanh(L);
152 case TAN:
153 return tan(L);
154 case L2MAGNITUDE:
155 return l2magnitude(L);
157 return 0;
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");
169 r(L, "abs", ABS);
170 r(L, "acos", ACOS);
171 r(L, "asin", ASIN);
172 r(L, "atan", ATAN);
173 r(L, "atan2", ATAN2);
174 r(L, "ceil", CEIL);
175 r(L, "cosh", COSH);
176 r(L, "cos", COS);
177 r(L, "deg", DEG);
178 r(L, "exp", EXP);
179 r(L, "floor", FLOOR);
180 r(L, "fmod", FMOD);
181 r(L, "frexp", FREXP);
182 r(L, "ldexp", LDEXP);
183 r(L, "log", LOG);
184 r(L, "log10", LOG10);
185 r(L, "max", MAX);
186 r(L, "min", MIN);
187 r(L, "modf", MODF);
188 r(L, "pow", POW);
189 r(L, "rad", RAD);
190 r(L, "random", RANDOM);
191 r(L, "randomseed", RANDOMSEED);
192 r(L, "sinh", SINH);
193 r(L, "sin", SIN);
194 r(L, "sqrt", SQRT);
195 r(L, "tanh", TANH);
196 r(L, "tan", TAN);
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)));
213 return 1;
216 private static int acos(Lua L)
218 L.pushNumber(Math.acos(L.checkNumber(1)));
219 return 1;
222 private static int asin(Lua L)
224 L.pushNumber(Math.asin(L.checkNumber(1)));
225 return 1;
228 private static int atan(Lua L)
230 L.pushNumber(Math.atan(L.checkNumber(1)));
231 return 1;
234 private static int atan2(Lua L)
236 L.pushNumber(Math.atan2(L.checkNumber(1), L.checkNumber(2)));
237 return 1;
240 private static int ceil(Lua L)
242 L.pushNumber(Math.ceil(L.checkNumber(1)));
243 return 1;
246 private static int cosh(Lua L)
248 L.pushNumber(Math.cosh(L.checkNumber(1)));
249 return 1;
252 private static int cos(Lua L)
254 L.pushNumber(Math.cos(L.checkNumber(1)));
255 return 1;
258 private static int deg(Lua L)
260 L.pushNumber(Math.toDegrees(L.checkNumber(1)));
261 return 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)));
268 return 1;
271 private static int floor(Lua L)
273 L.pushNumber(Math.floor(L.checkNumber(1)));
274 return 1;
277 private static int fmod(Lua L)
279 L.pushNumber(L.checkNumber(1) % L.checkNumber(2));
280 return 1;
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));
287 L.pushNumber(scale);
288 return 2;
291 private static int ldexp(Lua L)
293 L.pushNumber(Math.scalb(L.checkNumber(1), (int)L.checkNumber(2)));
294 return 1;
297 private static int log(Lua L)
299 L.pushNumber(Math.log(L.checkNumber(1)));
300 return 1;
303 private static int log10(Lua L)
305 L.pushNumber(Math.log(L.checkNumber(1)) / Math.log(10));
306 return 1;
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);
318 L.pushNumber(dmax);
319 return 1;
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);
331 L.pushNumber(dmin);
332 return 1;
335 private static int modf(Lua L)
337 double x = L.checkNumber(1);
338 double fp = x % 1;
339 double ip = x - fp;
340 L.pushNumber(ip);
341 L.pushNumber(fp);
342 return 2;
345 private static int pow(Lua L)
347 L.pushNumber(Lua.iNumpow(L.checkNumber(1), L.checkNumber(2)));
348 return 1;
351 private static int rad(Lua L)
353 L.pushNumber(Math.toRadians(L.checkNumber(1)));
354 return 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());
368 break;
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);
376 break;
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);
385 break;
387 default:
388 return L.error("wrong number of arguments");
390 return 1;
393 private static int randomseed(Lua L)
395 rng.setSeed((long)L.checkNumber(1));
396 return 0;
399 private static int sinh(Lua L)
401 L.pushNumber(Math.sinh(L.checkNumber(1)));
402 return 1;
405 private static int sin(Lua L)
407 L.pushNumber(Math.sin(L.checkNumber(1)));
408 return 1;
411 private static int sqrt(Lua L)
413 L.pushNumber(Math.sqrt(L.checkNumber(1)));
414 return 1;
417 private static int tanh(Lua L)
419 L.pushNumber(Math.tanh(L.checkNumber(1)));
420 return 1;
423 private static int tan(Lua L)
425 L.pushNumber(Math.tan(L.checkNumber(1)));
426 return 1;
429 private static int l2magnitude(Lua L)
431 L.pushNumber(Math.ceil(Math.log(L.checkNumber(1) + 1) / Math.log(2)));
432 return 1;