Subversion Repositories Kolibri OS

Rev

Rev 8535 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
8535 superturbo 1
#include 
8578 superturbo 2
#include 
8535 superturbo 3
 
4
#ifndef M_E
5
 #define M_E     2.7182818284590452354
6
#endif
7
#ifndef M_PI
8
 #define M_PI    3.14159265358979323846
9
#endif
10
 
11
#include 
12
 
13
/*
14
 * template for tinypy math functions
15
 * with one parameter.
16
 *
17
 * @cfunc is the coresponding function name in C
18
 * math library.
19
 */
20
#define TP_MATH_FUNC1(cfunc)                        \
21
    static tp_obj math_##cfunc(TP) {                \
22
        double x = TP_NUM();                        \
23
        double r = 0.0;                             \
24
                                                    \
25
        errno = 0;                                  \
26
        r = cfunc(x);                               \
27
        if (errno == EDOM || errno == ERANGE) {     \
28
            tp_raise(tp_None, tp_printf(tp, "%s(x): x=%f "		\
29
                                        "out of range", __func__, x));	\
30
        }                                           \
31
                                                    \
32
        return (tp_number(r));                      \
33
    }
34
 
35
/*
36
 * template for tinypy math functions
37
 * with two parameters.
38
 *
39
 * @cfunc is the coresponding function name in C
40
 * math library.
41
 */
42
#define TP_MATH_FUNC2(cfunc)                        \
43
    static tp_obj math_##cfunc(TP) {                \
44
        double x = TP_NUM();                        \
45
        double y = TP_NUM();                        \
46
        double r = 0.0;                             \
47
                                                    \
48
        errno = 0;                                  \
49
        r = cfunc(x, y);                            \
50
        if (errno == EDOM || errno == ERANGE) {     \
51
            tp_raise(tp_None, tp_printf(tp, "%s(x, y): x=%f,y=%f "	\
52
                                        "out of range", __func__, x, y)); \
53
        }                                           \
54
                                                    \
55
        return (tp_number(r));                      \
56
    }
57
 
58
 
59
/*
60
 * PI definition: 3.1415926535897931
61
 */
62
static tp_obj   math_pi;
63
 
64
/*
65
 * E definition: 2.7182818284590451
66
 */
67
static tp_obj   math_e;
68
 
69
/*
70
 * acos(x)
71
 *
72
 * return arc cosine of x, return value is measured in radians.
73
 * if x falls out -1 to 1, raise out-of-range exception.
74
 */
75
TP_MATH_FUNC1(acos)
76
 
77
/*
78
 * asin(x)
79
 *
80
 * return arc sine of x, measured in radians, actually [-PI/2, PI/2]
81
 * if x falls out of -1 to 1, raise out-of-range exception
82
 */
83
TP_MATH_FUNC1(asin)
84
 
85
/*
86
 * atan(x)
87
 *
88
 * return arc tangent of x, measured in radians,
89
 */
90
TP_MATH_FUNC1(atan)
91
 
92
/*
93
 * atan2(x, y)
94
 *
95
 * return arc tangent of x/y, measured in radians.
96
 * unlike atan(x/y), both the signs of x and y
97
 * are considered to determine the quaderant of
98
 * the result.
99
 */
100
TP_MATH_FUNC2(atan2)
101
 
102
/*
103
 * ceil(x)
104
 *
105
 * return the ceiling of x, i.e, the smallest
106
 * integer >= x.
107
 */
108
TP_MATH_FUNC1(ceil)
109
 
110
/*
111
 * cos(x)
112
 *
113
 * return cosine of x. x is measured in radians.
114
 */
115
TP_MATH_FUNC1(cos)
116
 
117
/*
118
 * cosh(x)
119
 *
120
 * return hyperbolic cosine of x.
121
 */
122
TP_MATH_FUNC1(cosh)
123
 
124
/*
125
 * degrees(x)
126
 *
127
 * converts angle x from radians to degrees.
128
 * NOTE: this function is introduced by python,
129
 * so we cannot wrap it directly in TP_MATH_FUNC1(),
130
 * here the solution is defining a new
131
 * C function - degrees().
132
 */
133
static const double degToRad =
134
                3.141592653589793238462643383 / 180.0;
135
static double degrees(double x)
136
{
137
    return (x / degToRad);
138
}
139
 
140
TP_MATH_FUNC1(degrees)
141
 
142
/*
143
 * exp(x)
144
 *
145
 * return the value e raised to power of x.
146
 * e is the base of natural logarithms.
147
 */
148
TP_MATH_FUNC1(exp)
149
 
150
/*
151
 * fabs(x)
152
 *
153
 * return the absolute value of x.
154
 */
155
TP_MATH_FUNC1(fabs)
156
 
157
/*
158
 * floor(x)
159
 *
160
 * return the floor of x, i.e, the largest integer <= x
161
 */
162
TP_MATH_FUNC1(floor)
163
 
164
/*
165
 * fmod(x, y)
166
 *
167
 * return the remainder of dividing x by y. that is,
168
 * return x - n * y, where n is the quotient of x/y.
169
 * NOTE: this function relies on the underlying platform.
170
 */
171
TP_MATH_FUNC2(fmod)
172
 
173
/*
174
 * frexp(x)
175
 *
176
 * return a pair (r, y), which satisfies:
177
 * x = r * (2 ** y), and r is normalized fraction
178
 * which is laid between 1/2 <= abs(r) < 1.
179
 * if x = 0, the (r, y) = (0, 0).
180
 */
181
static tp_obj math_frexp(TP) {
182
    double x = TP_NUM();
183
    int    y = 0;
184
    double r = 0.0;
185
    tp_obj rList = tp_list(tp);
186
 
187
    errno = 0;
188
    r = frexp(x, &y);
189
    if (errno == EDOM || errno == ERANGE) {
190
        tp_raise(tp_None, tp_printf(tp, "%s(x): x=%f, "
191
                                    "out of range", __func__, x));
192
    }
193
 
194
    _tp_list_append(tp, rList.list.val, tp_number(r));
195
    _tp_list_append(tp, rList.list.val, tp_number((tp_num)y));
196
    return (rList);
197
}
198
 
199
 
200
/*
201
 * hypot(x, y)
202
 *
203
 * return Euclidean distance, namely,
204
 * sqrt(x*x + y*y)
205
 */
206
TP_MATH_FUNC2(hypot)
207
 
208
 
209
/*
210
 * ldexp(x, y)
211
 *
212
 * return the result of multiplying x by 2
213
 * raised to y.
214
 */
215
TP_MATH_FUNC2(ldexp)
216
 
217
/*
218
 * log(x, [base])
219
 *
220
 * return logarithm of x to given base. If base is
221
 * not given, return the natural logarithm of x.
222
 * Note: common logarithm(log10) is used to compute
223
 * the denominator and numerator. based on fomula:
224
 * log(x, base) = log10(x) / log10(base).
225
 */
226
static tp_obj math_log(TP) {
227
    double x = TP_NUM();
228
    tp_obj b = TP_DEFAULT(tp_None);
229
    double y = 0.0;
230
    double den = 0.0;   /* denominator */
231
    double num = 0.0;   /* numinator */
232
    double r = 0.0;     /* result */
233
 
234
    if (b.type == TP_NONE)
235
        y = M_E;
236
    else if (b.type == TP_NUMBER)
237
        y = (double)b.number.val;
238
    else
239
        tp_raise(tp_None, tp_printf(tp, "%s(x, [base]): base invalid", __func__));
240
 
241
    errno = 0;
242
    num = log10(x);
243
    if (errno == EDOM || errno == ERANGE)
244
        goto excep;
245
 
246
    errno = 0;
247
    den = log10(y);
248
    if (errno == EDOM || errno == ERANGE)
249
        goto excep;
250
 
251
    r = num / den;
252
 
253
    return (tp_number(r));
254
 
255
excep:
256
    tp_raise(tp_None, tp_printf(tp, "%s(x, y): x=%f,y=%f "
257
                                "out of range", __func__, x, y));
258
}
259
 
260
/*
261
 * log10(x)
262
 *
263
 * return 10-based logarithm of x.
264
 */
265
TP_MATH_FUNC1(log10)
266
 
267
/*
268
 * modf(x)
269
 *
270
 * return a pair (r, y). r is the integral part of
271
 * x and y is the fractional part of x, both holds
272
 * the same sign as x.
273
 */
274
static tp_obj math_modf(TP) {
275
    double x = TP_NUM();
276
    double y = 0.0;
277
    double r = 0.0;
278
    tp_obj rList = tp_list(tp);
279
 
280
    errno = 0;
281
    r = modf(x, &y);
282
    if (errno == EDOM || errno == ERANGE) {
283
        tp_raise(tp_None, tp_printf(tp, "%s(x): x=%f, "
284
                                    "out of range", __func__, x));
285
    }
286
 
287
    _tp_list_append(tp, rList.list.val, tp_number(r));
288
    _tp_list_append(tp, rList.list.val, tp_number(y));
289
    return (rList);
290
}
291
 
292
/*
293
 * pow(x, y)
294
 *
295
 * return value of x raised to y. equivalence of x ** y.
296
 * NOTE: conventionally, tp_pow() is the implementation
297
 * of builtin function pow(); whilst, math_pow() is an
298
 * alternative in math module.
299
 */
300
static tp_obj math_pow(TP) {
301
    double x = TP_NUM();
302
    double y = TP_NUM();
303
    double r = 0.0;
304
 
305
    errno = 0;
306
    r = pow(x, y);
307
    if (errno == EDOM || errno == ERANGE) {
308
        tp_raise(tp_None, tp_printf(tp, "%s(x, y): x=%f,y=%f "
309
                                    "out of range", __func__, x, y));
310
    }
311
 
312
    return (tp_number(r));
313
}
314
 
315
 
316
/*
317
 * radians(x)
318
 *
319
 * converts angle x from degrees to radians.
320
 * NOTE: this function is introduced by python,
321
 * adopt same solution as degrees(x).
322
 */
323
static double radians(double x)
324
{
325
    return (x * degToRad);
326
}
327
 
328
TP_MATH_FUNC1(radians)
329
 
330
/*
331
 * sin(x)
332
 *
333
 * return sine of x, x is measured in radians.
334
 */
335
TP_MATH_FUNC1(sin)
336
 
337
/*
338
 * sinh(x)
339
 *
340
 * return hyperbolic sine of x.
341
 * mathematically, sinh(x) = (exp(x) - exp(-x)) / 2.
342
 */
343
TP_MATH_FUNC1(sinh)
344
 
345
/*
346
 * sqrt(x)
347
 *
348
 * return square root of x.
349
 * if x is negtive, raise out-of-range exception.
350
 */
351
TP_MATH_FUNC1(sqrt)
352
 
353
/*
354
 * tan(x)
355
 *
356
 * return tangent of x, x is measured in radians.
357
 */
358
TP_MATH_FUNC1(tan)
359
 
360
/*
361
 * tanh(x)
362
 *
363
 * return hyperbolic tangent of x.
364
 * mathematically, tanh(x) = sinh(x) / cosh(x).
365
 */
366
TP_MATH_FUNC1(tanh)