root/trunk/minid/mathlib.d

Revision 398, 8.9 kB (checked in by JarrettBillingsley, 1 month ago)

Changed some 'int's to 'mdint's. Fixed a bug with mixing non-object and object parameter type constraints. Added modules.compile. Fixed a bug with array.apply and array.map.

Line 
1 /******************************************************************************
2 License:
3 Copyright (c) 2008 Jarrett Billingsley
4
5 This software is provided 'as-is', without any express or implied warranty.
6 In no event will the authors be held liable for any damages arising from the
7 use of this software.
8
9 Permission is granted to anyone to use this software for any purpose,
10 including commercial applications, and to alter it and redistribute it freely,
11 subject to the following restrictions:
12
13     1. The origin of this software must not be misrepresented; you must not
14     claim that you wrote the original software. If you use this software in a
15     product, an acknowledgment in the product documentation would be
16     appreciated but is not required.
17
18     2. Altered source versions must be plainly marked as such, and must not
19     be misrepresented as being the original software.
20
21     3. This notice may not be removed or altered from any source distribution.
22 ******************************************************************************/
23
24 module minid.mathlib;
25
26 import math = tango.math.Math;
27 import tango.math.GammaFunction;
28 import tango.math.IEEE;
29 import tango.math.random.Kiss;
30
31 import minid.ex;
32 import minid.interpreter;
33 import minid.types;
34
35 private void register(MDThread* t, char[] name, NativeFunc func, uword numUpvals = 0)
36 {
37     newFunction(t, func, name, numUpvals);
38     newGlobal(t, name);
39 }
40
41 struct MathLib
42 {
43 static:
44     public void init(MDThread* t)
45     {
46         pushGlobal(t, "modules");
47         field(t, -1, "customLoaders");
48
49         newFunction(t, function uword(MDThread* t, uword numParams)
50         {
51             pushFloat(t, math.E);              newGlobal(t, "e");
52             pushFloat(t, math.PI);             newGlobal(t, "pi");
53             pushFloat(t, mdfloat.nan);         newGlobal(t, "nan");
54             pushFloat(t, mdfloat.infinity);    newGlobal(t, "infinity");
55
56             pushInt(t, mdint.sizeof);          newGlobal(t, "intSize");
57             pushInt(t, mdint.min);             newGlobal(t, "intMin");
58             pushInt(t, mdint.max);             newGlobal(t, "intMax");
59
60             pushInt(t, mdfloat.sizeof);        newGlobal(t, "floatSize");
61             pushFloat(t, mdfloat.min);         newGlobal(t, "floatMin");
62             pushFloat(t, mdfloat.max);         newGlobal(t, "floatMax");
63            
64             register(t, "abs", &abs);
65             register(t, "sin", &sin);
66             register(t, "cos", &cos);
67             register(t, "tan", &tan);
68             register(t, "asin", &asin);
69             register(t, "acos", &acos);
70             register(t, "atan", &atan);
71             register(t, "atan2", &atan2);
72             register(t, "sqrt", &sqrt);
73             register(t, "cbrt", &cbrt);
74             register(t, "pow", &pow);
75             register(t, "exp", &exp);
76             register(t, "ln", &ln);
77             register(t, "log2", &log2);
78             register(t, "log10", &log10);
79             register(t, "hypot", &hypot);
80             register(t, "lgamma", &lgamma);
81             register(t, "gamma", &gamma);
82             register(t, "ceil", &ceil);
83             register(t, "floor", &floor);
84             register(t, "round", &round);
85             register(t, "trunc", &trunc);
86             register(t, "isNan", &isNan);
87             register(t, "isInf", &isInf);
88             register(t, "sign", &sign);
89             register(t, "rand", &rand);
90             register(t, "frand", &frand);
91             register(t, "max", &max);
92             register(t, "min", &min);
93
94             return 0;
95         }, "math");
96
97         fielda(t, -2, "math");
98         importModule(t, "math");
99         pop(t, 3);
100     }
101
102     mdfloat get_float(MDThread* t, word i)
103     {
104         if(isInt(t, i))
105             return getInt(t, i);
106         else if(isFloat(t, i))
107             return getFloat(t, i);
108         else
109         {
110             pushTypeString(t, i);
111             throwException(t, "Expected 'int' or 'float', not '{}'", getString(t, -1));
112         }
113        
114         assert(false);
115     }
116
117     uword abs(MDThread* t, uword numParams)
118     {
119         if(isInt(t, 1))
120             pushInt(t, math.abs(getInt(t, 1)));
121         else if(isFloat(t, 1))
122             pushFloat(t, math.abs(getFloat(t, 1)));
123         else
124         {
125             pushTypeString(t, 1);
126             throwException(t, "Expected 'int' or 'float', not '{}'", getString(t, -1));
127         }
128
129         return 1;
130     }
131
132     uword sin(MDThread* t, uword numParams)
133     {
134         pushFloat(t, math.sin(get_float(t, 1)));
135         return 1;
136     }
137
138     uword cos(MDThread* t, uword numParams)
139     {
140         pushFloat(t, math.cos(get_float(t, 1)));
141         return 1;
142     }
143
144     uword tan(MDThread* t, uword numParams)
145     {
146         pushFloat(t, math.tan(get_float(t, 1)));
147         return 1;
148     }
149
150     uword asin(MDThread* t, uword numParams)
151     {
152         pushFloat(t, math.asin(get_float(t, 1)));
153         return 1;
154     }
155
156     uword acos(MDThread* t, uword numParams)
157     {
158         pushFloat(t, math.acos(get_float(t, 1)));
159         return 1;
160     }
161
162     uword atan(MDThread* t, uword numParams)
163     {
164         pushFloat(t, math.atan(get_float(t, 1)));
165         return 1;
166     }
167
168     uword atan2(MDThread* t, uword numParams)
169     {
170         pushFloat(t, math.atan2(get_float(t, 1), get_float(t, 2)));
171         return 1;
172     }
173
174     uword sqrt(MDThread* t, uword numParams)
175     {
176         pushFloat(t, math.sqrt(get_float(t, 1)));
177         return 1;
178     }
179
180     uword cbrt(MDThread* t, uword numParams)
181     {
182         pushFloat(t, math.cbrt(get_float(t, 1)));
183         return 1;
184     }
185
186     uword exp(MDThread* t, uword numParams)
187     {
188         pushFloat(t, math.exp(get_float(t, 1)));
189         return 1;
190     }
191
192     uword ln(MDThread* t, uword numParams)
193     {
194         pushFloat(t, math.log(get_float(t, 1)));
195         return 1;
196     }
197
198     uword log2(MDThread* t, uword numParams)
199     {
200         pushFloat(t, math.log2(get_float(t, 1)));
201         return 1;
202     }
203
204     uword log10(MDThread* t, uword numParams)
205     {
206         pushFloat(t, math.log10(get_float(t, 1)));
207         return 1;
208     }
209
210     uword hypot(MDThread* t, uword numParams)
211     {
212         pushFloat(t, math.hypot(get_float(t, 1), get_float(t, 2)));
213         return 1;
214     }
215
216     uword lgamma(MDThread* t, uword numParams)
217     {
218         pushFloat(t, logGamma(get_float(t, 1)));
219         return 1;
220     }
221
222     uword gamma(MDThread* t, uword numParams)
223     {
224         pushFloat(t, .gamma(get_float(t, 1)));
225         return 1;
226     }
227
228     uword ceil(MDThread* t, uword numParams)
229     {
230         pushFloat(t, math.ceil(get_float(t, 1)));
231         return 1;
232     }
233
234     uword floor(MDThread* t, uword numParams)
235     {
236         pushFloat(t, math.floor(get_float(t, 1)));
237         return 1;
238     }
239
240     uword round(MDThread* t, uword numParams)
241     {
242         pushInt(t, cast(mdint)math.round(get_float(t, 1)));
243         return 1;
244     }
245
246     uword trunc(MDThread* t, uword numParams)
247     {
248         pushInt(t, cast(mdint)math.trunc(get_float(t, 1)));
249         return 1;
250     }
251
252     uword isNan(MDThread* t, uword numParams)
253     {
254         pushBool(t, cast(bool)math.isNaN(get_float(t, 1)));
255         return 1;
256     }
257
258     uword isInf(MDThread* t, uword numParams)
259     {
260         pushBool(t, cast(bool)math.isInfinity(get_float(t, 1)));
261         return 1;
262     }
263
264     uword sign(MDThread* t, uword numParams)
265     {
266         if(isInt(t, 1))
267         {
268             auto val = getInt(t, 1);
269
270             if(val < 0)
271                 pushInt(t, -1);
272             else if(val > 0)
273                 pushInt(t, 1);
274             else
275                 pushInt(t, 0);
276         }
277         else
278         {
279             auto val = getFloat(t, 1);
280
281             if(val < 0)
282                 pushInt(t, -1);
283             else if(val > 0)
284                 pushInt(t, 1);
285             else
286                 pushInt(t, 0);
287         }
288        
289         return 1;
290     }
291    
292     uword pow(MDThread* t, uword numParams)
293     {
294         auto base = get_float(t, 1);
295
296         if(isInt(t, 2))
297             pushFloat(t, math.pow(cast(real)base, cast(uint)getInt(t, 2)));
298         else
299             pushFloat(t, math.pow(base, get_float(t, 2)));
300
301         return 1;
302     }
303
304     uword rand(MDThread* t, uword numParams)
305     {
306         // uint is the return type of Kiss.toInt
307         static if(uint.sizeof < mdint.sizeof)
308         {
309             mdint num = Kiss.shared.toInt();
310             num |= (cast(ulong)Kiss.shared.toInt()) << 32;
311         }
312         else
313             mdint num = Kiss.shared.toInt();
314
315         switch(numParams)
316         {
317             case 0:
318                 pushInt(t, num);
319                 break;
320
321             case 1:
322                 auto max = getInt(t, 1);
323
324                 if(max == 0)
325                     throwException(t, "Maximum value may not be 0");
326
327                 pushInt(t, cast(uword)num % max);
328                 break;
329
330             default:
331                 auto lo = getInt(t, 1);
332                 auto hi = getInt(t, 2);
333
334                 if(hi == lo)
335                     throwException(t, "Low and high values must be different");
336
337                 pushInt(t, (cast(uword)num % (hi - lo)) + lo);
338                 break;
339         }
340
341         return 1;
342     }
343
344     uword frand(MDThread* t, uword numParams)
345     {
346         auto num = cast(mdfloat)Kiss.shared.toInt() / uint.max;
347
348         switch(numParams)
349         {
350             case 0:
351                 pushFloat(t, num);
352                 break;
353
354             case 1:
355                 pushFloat(t, num * getFloat(t, 1));
356                 break;
357
358             default:
359                 auto lo = getFloat(t, 1);
360                 auto hi = getFloat(t, 2);
361
362                 pushFloat(t, (num * (hi - lo)) + lo);
363                 break;
364         }
365
366         return 1;
367     }
368
369     uword max(MDThread* t, uword numParams)
370     {
371         switch(numParams)
372         {
373             case 0:
374                 throwException(t, "At least one parameter required");
375
376             case 1:
377                 break;
378
379             case 2:
380                 if(cmp(t, 1, 2) > 0)
381                     pop(t);
382                 break;
383
384             default:
385                 word m = 1;
386
387                 for(uword i = 2; i <= numParams; i++)
388                     if(cmp(t, i, m) > 0)
389                         m = i;
390
391                 dup(t, m);
392                 break;
393         }
394
395         return 1;
396     }
397
398     uword min(MDThread* t, uword numParams)
399     {
400         switch(numParams)
401         {
402             case 0:
403                 throwException(t, "At least one parameter required");
404
405             case 1:
406                 break;
407
408             case 2:
409                 if(cmp(t, 1, 2) < 0)
410                     pop(t);
411                 break;
412
413             default:
414                 word m = 1;
415
416                 for(uword i = 2; i <= numParams; i++)
417                     if(cmp(t, i, m) < 0)
418                         m = i;
419
420                 dup(t, m);
421                 break;
422         }
423
424
425         return 1;
426     }
427 }
Note: See TracBrowser for help on using the browser.