Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Details | Last modification | View Log | RSS feed

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