Initialize Tizen 2.3
[framework/uifw/embryo.git] / wearable / src / lib / embryo_float.c
1 /*  Float arithmetic for the Small AMX engine
2  *
3  *  Copyright (c) Artran, Inc. 1999
4  *  Written by Greg Garner (gmg@artran.com)
5  *  Portions Copyright (c) Carsten Haitzler, 2004 <raster@rasterman.com>
6  *
7  *  This software is provided "as-is", without any express or implied warranty.
8  *  In no event will the authors be held liable for any damages arising from
9  *  the use of this software.
10  *
11  *  Permission is granted to anyone to use this software for any purpose,
12  *  including commercial applications, and to alter it and redistribute it
13  *  freely, subject to the following restrictions:
14  *
15  *  1.  The origin of this software must not be misrepresented; you must not
16  *      claim that you wrote the original software. If you use this software in
17  *      a product, an acknowledgment in the product documentation would be
18  *      appreciated but is not required.
19  *  2.  Altered source versions must be plainly marked as such, and must not be
20  *      misrepresented as being the original software.
21  *  3.  This notice may not be removed or altered from any source distribution.
22  */
23
24 /* CHANGES -
25  * 2002-08-27: Basic conversion of source from C++ to C by Adam D. Moss
26  *             <adam@gimp.org> <aspirin@icculus.org>
27  * 2003-08-29: Removal of the dynamic memory allocation and replacing two
28  *             type conversion functions by macros, by Thiadmer Riemersma
29  * 2003-09-22: Moved the type conversion macros to AMX.H, and simplifications
30  *             of some routines, by Thiadmer Riemersma
31  * 2003-11-24: A few more native functions (geometry), plus minor modifications,
32  *             mostly to be compatible with dynamically loadable extension
33  *             modules, by Thiadmer Riemersma
34  * 2004-03-20: Cleaned up and reduced size for Embryo, Modified to conform to
35  *             E coding style. Added extra parameter checks.
36  *             Carsten Haitzler, <raster@rasterman.com>
37  */
38
39
40 #ifdef HAVE_CONFIG_H
41 # include "config.h"
42 #endif
43
44 #include <stdlib.h>
45 #include <math.h>
46
47 #include "Embryo.h"
48 #include "embryo_private.h"
49
50 #define PI  3.1415926535897932384626433832795f
51 #ifndef MAXFLOAT
52 #define MAXFLOAT 3.40282347e+38f
53 #endif
54
55 /* internally useful calls */
56
57 static float
58 _embryo_fp_degrees_to_radians(float angle, int radix)
59 {
60    switch (radix)
61      {
62       case 1: /* degrees, sexagesimal system (technically: degrees/minutes/seconds) */
63         return (angle * PI / 180.0f);
64       case 2: /* grades, centesimal system */
65         return (angle * PI / 200.0f);
66       default: /* assume already radian */
67         break;
68      }
69    return angle;
70 }
71
72 /* exported float api */
73
74 static Embryo_Cell
75 _embryo_fp(Embryo_Program *ep __UNUSED__, Embryo_Cell *params)
76 {
77    /* params[1] = long value to convert to a float */
78    float f;
79
80    if (params[0] != (1 * sizeof(Embryo_Cell))) return 0;
81    f = (float)params[1];
82    return EMBRYO_FLOAT_TO_CELL(f);
83 }
84
85 static Embryo_Cell
86 _embryo_fp_str(Embryo_Program *ep, Embryo_Cell *params)
87 {
88    /* params[1] = virtual string address to convert to a float */
89    char buf[64];
90    Embryo_Cell *str;
91    float f;
92    int len;
93
94    if (params[0] != (1 * sizeof(Embryo_Cell))) return 0;
95    str = embryo_data_address_get(ep, params[1]);
96    len = embryo_data_string_length_get(ep, str);
97    if ((len == 0) || (len >= (int)sizeof(buf))) return 0;
98    embryo_data_string_get(ep, str, buf);
99    f = (float)atof(buf);
100    return EMBRYO_FLOAT_TO_CELL(f);
101 }
102
103 static Embryo_Cell
104 _embryo_fp_mul(Embryo_Program *ep __UNUSED__, Embryo_Cell *params)
105 {
106    /* params[1] = float operand 1 */
107    /* params[2] = float operand 2 */
108    float f;
109
110    if (params[0] != (2 * sizeof(Embryo_Cell))) return 0;
111    f = EMBRYO_CELL_TO_FLOAT(params[1]) * EMBRYO_CELL_TO_FLOAT(params[2]);
112    return EMBRYO_FLOAT_TO_CELL(f);
113 }
114
115 static Embryo_Cell
116 _embryo_fp_div(Embryo_Program *ep __UNUSED__, Embryo_Cell *params)
117 {
118    /* params[1] = float dividend (top) */
119    /* params[2] = float divisor (bottom) */
120    float f, ff;
121
122    if (params[0] != (2 * sizeof(Embryo_Cell))) return 0;
123    f = EMBRYO_CELL_TO_FLOAT(params[1]);
124    ff = EMBRYO_CELL_TO_FLOAT(params[2]);
125    if (ff == 0.0)
126      {
127         if (f == 0.0)
128           return EMBRYO_FLOAT_TO_CELL(0.0f);
129         else if (f < 0.0)
130           return EMBRYO_FLOAT_TO_CELL(-MAXFLOAT);
131         else
132           return EMBRYO_FLOAT_TO_CELL(MAXFLOAT);
133      }
134    f = f / ff;
135    return EMBRYO_FLOAT_TO_CELL(f);
136 }
137
138 static Embryo_Cell
139 _embryo_fp_add(Embryo_Program *ep __UNUSED__, Embryo_Cell *params)
140 {
141    /* params[1] = float operand 1 */
142    /* params[2] = float operand 2 */
143    float f;
144
145    if (params[0] != (2 * sizeof(Embryo_Cell))) return 0;
146    f = EMBRYO_CELL_TO_FLOAT(params[1]) + EMBRYO_CELL_TO_FLOAT(params[2]);
147    return EMBRYO_FLOAT_TO_CELL(f);
148 }
149
150 static Embryo_Cell
151 _embryo_fp_sub(Embryo_Program *ep __UNUSED__, Embryo_Cell *params)
152 {
153    /* params[1] = float operand 1 */
154    /* params[2] = float operand 2 */
155    float f;
156
157    if (params[0] != (2 * sizeof(Embryo_Cell))) return 0;
158    f = EMBRYO_CELL_TO_FLOAT(params[1]) - EMBRYO_CELL_TO_FLOAT(params[2]);
159    return EMBRYO_FLOAT_TO_CELL(f);
160 }
161
162 /* Return fractional part of float */
163 static Embryo_Cell
164 _embryo_fp_fract(Embryo_Program *ep __UNUSED__, Embryo_Cell *params)
165 {
166    /* params[1] = float operand */
167    float f;
168
169    if (params[0] != (1 * sizeof(Embryo_Cell))) return 0;
170    f = EMBRYO_CELL_TO_FLOAT(params[1]);
171    f -= (floorf(f));
172    return EMBRYO_FLOAT_TO_CELL(f);
173 }
174
175 /* Return integer part of float, rounded */
176 static Embryo_Cell
177 _embryo_fp_round(Embryo_Program *ep __UNUSED__, Embryo_Cell *params)
178 {
179    /* params[1] = float operand */
180    /* params[2] = Type of rounding (cell) */
181    float f;
182
183    if (params[0] != (2 * sizeof(Embryo_Cell))) return 0;
184    f = EMBRYO_CELL_TO_FLOAT(params[1]);
185    switch (params[2])
186      {
187       case 1: /* round downwards (truncate) */
188         f = (floorf(f));
189         break;
190       case 2: /* round upwards */
191         f = (ceilf(f));
192         break;
193       case 3: /* round towards zero */
194         if (f >= 0.0) f = (floorf(f));
195         else          f = (ceilf(f));
196         break;
197       default: /* standard, round to nearest */
198         f = (floorf(f + 0.5));
199         break;
200      }
201     return (Embryo_Cell)f;
202 }
203
204 static Embryo_Cell
205 _embryo_fp_cmp(Embryo_Program *ep __UNUSED__, Embryo_Cell *params)
206 {
207    /* params[1] = float operand 1 */
208    /* params[2] = float operand 2 */
209    float f, ff;
210
211    if (params[0] != (2 * sizeof(Embryo_Cell))) return 0;
212    f = EMBRYO_CELL_TO_FLOAT(params[1]);
213    ff = EMBRYO_CELL_TO_FLOAT(params[2]);
214    if (f == ff) return 0;
215    else if (f > ff) return 1;
216    return -1;
217 }
218
219 static Embryo_Cell
220 _embryo_fp_sqroot(Embryo_Program *ep, Embryo_Cell *params)
221 {
222    /* params[1] = float operand */
223    float f;
224
225    if (params[0] != (1 * sizeof(Embryo_Cell))) return 0;
226    f = EMBRYO_CELL_TO_FLOAT(params[1]);
227    f = sqrtf(f);
228    if (f < 0)
229      {
230         embryo_program_error_set(ep, EMBRYO_ERROR_DOMAIN);
231         return 0;
232      }
233    return EMBRYO_FLOAT_TO_CELL(f);
234 }
235
236 static Embryo_Cell
237 _embryo_fp_power(Embryo_Program *ep __UNUSED__, Embryo_Cell *params)
238 {
239    /* params[1] = float operand 1 */
240    /* params[2] = float operand 2 */
241    float f, ff;
242
243    if (params[0] != (2 * sizeof(Embryo_Cell))) return 0;
244    f = EMBRYO_CELL_TO_FLOAT(params[1]);
245    ff = EMBRYO_CELL_TO_FLOAT(params[2]);
246    f = powf(f, ff);
247    return EMBRYO_FLOAT_TO_CELL(f);
248 }
249
250 static Embryo_Cell
251 _embryo_fp_log(Embryo_Program *ep, Embryo_Cell *params)
252 {
253    /* params[1] = float operand 1 (value) */
254    /* params[2] = float operand 2 (base) */
255    float f, ff, tf;
256
257    if (params[0] != (2 * sizeof(Embryo_Cell))) return 0;
258    f = EMBRYO_CELL_TO_FLOAT(params[1]);
259    ff = EMBRYO_CELL_TO_FLOAT(params[2]);
260    if ((f <= 0.0) || (ff <= 0.0))
261      {
262         embryo_program_error_set(ep, EMBRYO_ERROR_DOMAIN);
263         return 0;
264      }
265     if (ff == 10.0) f = log10f(f);
266     else if (ff == 2.0) f = log2f(f);
267     else
268      {
269         tf = logf(ff);
270         if (tf == 0.0) f = 0.0;
271         else f = (logf(f) / tf);
272      }
273     return EMBRYO_FLOAT_TO_CELL(f);
274 }
275
276 static Embryo_Cell
277 _embryo_fp_sin(Embryo_Program *ep __UNUSED__, Embryo_Cell *params)
278 {
279    /* params[1] = float operand 1 (angle) */
280    /* params[2] = float operand 2 (radix) */
281    float f;
282
283    if (params[0] != (2 * sizeof(Embryo_Cell))) return 0;
284    f = EMBRYO_CELL_TO_FLOAT(params[1]);
285    f = _embryo_fp_degrees_to_radians(f, params[2]);
286    f = sinf(f);
287    return EMBRYO_FLOAT_TO_CELL(f);
288 }
289
290 static Embryo_Cell
291 _embryo_fp_cos(Embryo_Program *ep __UNUSED__, Embryo_Cell *params)
292 {
293    /* params[1] = float operand 1 (angle) */
294    /* params[2] = float operand 2 (radix) */
295    float f;
296
297    if (params[0] != (2 * sizeof(Embryo_Cell))) return 0;
298    f = EMBRYO_CELL_TO_FLOAT(params[1]);
299    f = _embryo_fp_degrees_to_radians(f, params[2]);
300    f = cosf(f);
301    return EMBRYO_FLOAT_TO_CELL(f);
302 }
303
304 static Embryo_Cell
305 _embryo_fp_tan(Embryo_Program *ep __UNUSED__, Embryo_Cell *params)
306 {
307    /* params[1] = float operand 1 (angle) */
308    /* params[2] = float operand 2 (radix) */
309    float f;
310
311    if (params[0] != (2 * sizeof(Embryo_Cell))) return 0;
312    f = EMBRYO_CELL_TO_FLOAT(params[1]);
313    f = _embryo_fp_degrees_to_radians(f, params[2]);
314    f = tanf(f);
315    return EMBRYO_FLOAT_TO_CELL(f);
316 }
317
318 static Embryo_Cell
319 _embryo_fp_abs(Embryo_Program *ep __UNUSED__, Embryo_Cell *params)
320 {
321    /* params[1] = float operand */
322    float f;
323
324    if (params[0] != (1 * sizeof(Embryo_Cell))) return 0;
325    f = EMBRYO_CELL_TO_FLOAT(params[1]);
326    f = (f >= 0) ? f : -f;
327    return EMBRYO_FLOAT_TO_CELL(f);
328 }
329
330 static Embryo_Cell
331 _embryo_fp_asin(Embryo_Program *ep __UNUSED__, Embryo_Cell *params)
332 {
333    /* params[1] = float operand 1 (angle) */
334    /* params[2] = float operand 2 (radix) */
335    float f;
336
337    if (params[0] != (2 * sizeof(Embryo_Cell))) return 0;
338    f = EMBRYO_CELL_TO_FLOAT(params[1]);
339    f = sinf(f);
340    f = _embryo_fp_degrees_to_radians(f, params[2]);
341    return EMBRYO_FLOAT_TO_CELL(f);
342 }
343
344 static Embryo_Cell
345 _embryo_fp_acos(Embryo_Program *ep __UNUSED__, Embryo_Cell *params)
346 {
347    /* params[1] = float operand 1 (angle) */
348    /* params[2] = float operand 2 (radix) */
349    float f;
350
351    if (params[0] != (2 * sizeof(Embryo_Cell))) return 0;
352    f = EMBRYO_CELL_TO_FLOAT(params[1]);
353    f = cosf(f);
354    f = _embryo_fp_degrees_to_radians(f, params[2]);
355    return EMBRYO_FLOAT_TO_CELL(f);
356 }
357
358 static Embryo_Cell
359 _embryo_fp_atan(Embryo_Program *ep __UNUSED__, Embryo_Cell *params)
360 {
361    /* params[1] = float operand 1 (angle) */
362    /* params[2] = float operand 2 (radix) */
363    float f;
364
365    if (params[0] != (2 * sizeof(Embryo_Cell))) return 0;
366    f = EMBRYO_CELL_TO_FLOAT(params[1]);
367    f = tanf(f);
368    f = _embryo_fp_degrees_to_radians(f, params[2]);
369    return EMBRYO_FLOAT_TO_CELL(f);
370 }
371
372 static Embryo_Cell
373 _embryo_fp_atan2(Embryo_Program *ep __UNUSED__, Embryo_Cell *params)
374 {
375    /* params[1] = float operand 1 (y) */
376    /* params[2] = float operand 2 (x) */
377    /* params[3] = float operand 3 (radix) */
378    float f, ff;
379
380    if (params[0] != (3 * sizeof(Embryo_Cell))) return 0;
381    f = EMBRYO_CELL_TO_FLOAT(params[1]);
382    ff = EMBRYO_CELL_TO_FLOAT(params[2]);
383    f = atan2f(f, ff);
384    f = _embryo_fp_degrees_to_radians(f, params[3]);
385    return EMBRYO_FLOAT_TO_CELL(f);
386 }
387
388 static Embryo_Cell
389 _embryo_fp_log1p(Embryo_Program *ep __UNUSED__, Embryo_Cell *params)
390 {
391    /* params[1] = float operand */
392    float f;
393
394    if (params[0] != (1 * sizeof(Embryo_Cell))) return 0;
395    f = EMBRYO_CELL_TO_FLOAT(params[1]);
396    f = log1pf(f);
397    return EMBRYO_FLOAT_TO_CELL(f);
398 }
399
400 static Embryo_Cell
401 _embryo_fp_cbrt(Embryo_Program *ep __UNUSED__, Embryo_Cell *params)
402 {
403    /* params[1] = float operand */
404    float f;
405
406    if (params[0] != (1 * sizeof(Embryo_Cell))) return 0;
407    f = EMBRYO_CELL_TO_FLOAT(params[1]);
408    f = cbrtf(f);
409    return EMBRYO_FLOAT_TO_CELL(f);
410 }
411
412 static Embryo_Cell
413 _embryo_fp_exp(Embryo_Program *ep __UNUSED__, Embryo_Cell *params)
414 {
415    /* params[1] = float operand */
416    float f;
417
418    if (params[0] != (1 * sizeof(Embryo_Cell))) return 0;
419    f = EMBRYO_CELL_TO_FLOAT(params[1]);
420    f = expf(f);
421    return EMBRYO_FLOAT_TO_CELL(f);
422 }
423
424 static Embryo_Cell
425 _embryo_fp_exp2(Embryo_Program *ep __UNUSED__, Embryo_Cell *params)
426 {
427    /* params[1] = float operand */
428    float f;
429
430    if (params[0] != (1 * sizeof(Embryo_Cell))) return 0;
431    f = EMBRYO_CELL_TO_FLOAT(params[1]);
432    f = exp2f(f);
433    return EMBRYO_FLOAT_TO_CELL(f);
434 }
435
436 static Embryo_Cell
437 _embryo_fp_hypot(Embryo_Program *ep __UNUSED__, Embryo_Cell *params)
438 {
439    /* params[1] = float operand */
440    float f, ff;
441
442    if (params[0] != (2 * sizeof(Embryo_Cell))) return 0;
443    f = EMBRYO_CELL_TO_FLOAT(params[1]);
444    ff = EMBRYO_CELL_TO_FLOAT(params[2]);
445    f = hypotf(f, ff);
446    return EMBRYO_FLOAT_TO_CELL(f);
447 }
448
449 /* functions used by the rest of embryo */
450
451 void
452 _embryo_fp_init(Embryo_Program *ep)
453 {
454    embryo_program_native_call_add(ep, "float",     _embryo_fp);
455    embryo_program_native_call_add(ep, "atof",      _embryo_fp_str);
456    embryo_program_native_call_add(ep, "float_mul", _embryo_fp_mul);
457    embryo_program_native_call_add(ep, "float_div", _embryo_fp_div);
458    embryo_program_native_call_add(ep, "float_add", _embryo_fp_add);
459    embryo_program_native_call_add(ep, "float_sub", _embryo_fp_sub);
460    embryo_program_native_call_add(ep, "fract",     _embryo_fp_fract);
461    embryo_program_native_call_add(ep, "round",     _embryo_fp_round);
462    embryo_program_native_call_add(ep, "float_cmp", _embryo_fp_cmp);
463    embryo_program_native_call_add(ep, "sqrt",      _embryo_fp_sqroot);
464    embryo_program_native_call_add(ep, "pow",       _embryo_fp_power);
465    embryo_program_native_call_add(ep, "log",       _embryo_fp_log);
466    embryo_program_native_call_add(ep, "sin",       _embryo_fp_sin);
467    embryo_program_native_call_add(ep, "cos",       _embryo_fp_cos);
468    embryo_program_native_call_add(ep, "tan",       _embryo_fp_tan);
469    embryo_program_native_call_add(ep, "abs",       _embryo_fp_abs);
470    /* Added in embryo 1.2 */
471    embryo_program_native_call_add(ep, "asin",      _embryo_fp_asin);
472    embryo_program_native_call_add(ep, "acos",      _embryo_fp_acos);
473    embryo_program_native_call_add(ep, "atan",      _embryo_fp_atan);
474    embryo_program_native_call_add(ep, "atan2",     _embryo_fp_atan2);
475    embryo_program_native_call_add(ep, "log1p",     _embryo_fp_log1p);
476    embryo_program_native_call_add(ep, "cbrt",      _embryo_fp_cbrt);
477    embryo_program_native_call_add(ep, "exp",       _embryo_fp_exp);
478    embryo_program_native_call_add(ep, "exp2",      _embryo_fp_exp2);
479    embryo_program_native_call_add(ep, "hypot",     _embryo_fp_hypot);
480 }