Annotation of parser3/src/classes/math.C, revision 1.12
1.1 parser 1: /** @file
2: Parser: @b math parser class.
3:
1.12 ! paf 4: Copyright (c) 2001, 2002 ArtLebedev Group (http://www.artlebedev.com)
1.9 paf 5: Author: Alexander Petrosyan <paf@design.ru> (http://paf.design.ru)
1.1 parser 6:
1.12 ! paf 7: $Id: math.C,v 1.11 2001/12/15 21:28:17 paf Exp $
1.1 parser 8: */
9:
10: #include "pa_common.h"
11: #include "pa_vint.h"
1.2 parser 12: #include "pa_vmath.h"
1.1 parser 13: #include "pa_request.h"
14:
1.5 parser 15: #ifdef WIN32
16: # include <windows.h>
17: #endif
18:
1.1 parser 19: // defines
20:
1.3 parser 21: #define PI 3.1415926535
1.1 parser 22: #define MATH_CLASS_NAME "math"
23:
24: // class
25:
26: class MMath : public Methoded {
27: public:
28: MMath(Pool& pool);
1.5 parser 29: void configure_admin(Request& r);
30:
1.1 parser 31: public: // Methoded
32: bool used_directly() { return true; }
33: };
34:
35: // methods
1.5 parser 36: static unsigned int randomizer=0;
1.1 parser 37: static void _random(Request& r, const String& method_name, MethodParams *params) {
38: Pool& pool=r.pool();
39:
1.3 parser 40: Value& range=params->as_junction(0, "range must be expression");
1.1 parser 41: uint max=(uint)r.process(range).as_double();
42: if(max<=1)
1.7 parser 43: throw Exception(0, 0,
1.1 parser 44: &method_name,
45: "bad range [0..%u]", max);
46:
1.5 parser 47: Value& result=*new(pool) VInt(pool, (int)(
1.10 paf 48: ((double)((randomizer=rand())% RAND_MAX)) / RAND_MAX * max ));
1.4 parser 49: result.set_name(method_name);
50: r.write_no_lang(result);
1.1 parser 51: }
52:
53:
54: typedef double (*math1_func_ptr)(double);
1.3 parser 55: static double frac(double param) { return param-trunc(param); }
56: static double degrees(double param) { return param /PI *180; }
57: static double radians(double param) { return param /180 *PI; }
1.1 parser 58:
59: static void math1(Request& r,
60: const String& method_name, MethodParams *params,
61: math1_func_ptr func) {
62: Pool& pool=r.pool();
1.3 parser 63: Value& param=params->as_junction(0, "parameter must be expression");
1.1 parser 64:
65: Value& result=*new(pool) VDouble(pool, (*func)(r.process(param).as_double()));
66: result.set_name(method_name);
67: r.write_no_lang(result);
68: }
69:
70: #define MATH1(name) \
71: static void _##name(Request& r, const String& method_name, MethodParams *params) {\
72: math1(r, method_name, params, &name);\
73: }
74: #define MATH1P(name_parser, name_c) \
75: static void _##name_parser(Request& r, const String& method_name, MethodParams *params) {\
76: math1(r, method_name, params, &name_c);\
77: }
78: MATH1(round); MATH1(floor); MATH1P(ceiling, ceil);
1.3 parser 79: MATH1(trunc); MATH1(frac);
1.1 parser 80: MATH1P(abs, fabs); MATH1(sign);
81: MATH1(exp); MATH1(log);
82: MATH1(sin); MATH1(asin);
83: MATH1(cos); MATH1(acos);
84: MATH1(tan); MATH1(atan);
1.3 parser 85: MATH1(degrees); MATH1(radians);
1.1 parser 86: MATH1(sqrt);
87:
88:
89: typedef double (*math2_func_ptr)(double, double);
90: static void math2(Request& r,
91: const String& method_name, MethodParams *params,
92: math2_func_ptr func) {
93: Pool& pool=r.pool();
1.3 parser 94: Value& a=params->as_junction(0, "parameter must be expression");
95: Value& b=params->as_junction(1, "parameter must be expression");
1.1 parser 96:
97: Value& result=*new(pool) VDouble(pool, (*func)(
98: r.process(a).as_double(),
99: r.process(b).as_double()));
100: result.set_name(method_name);
101: r.write_no_lang(result);
102: }
103:
104: #define MATH2(name) \
105: static void _##name(Request& r, const String& method_name, MethodParams *params) {\
106: math2(r, method_name, params, &name);\
107: }
108: MATH2(pow);
109:
110: // constructor
111:
112: MMath::MMath(Pool& apool) : Methoded(apool) {
113: set_name(*NEW String(pool(), MATH_CLASS_NAME));
114:
115: // ^FUNC(expr)
116: #define ADD1(name) \
117: add_native_method(#name, Method::CT_STATIC, _##name, 1, 1)
118:
119: ADD1(round); ADD1(floor); ADD1(ceiling);
1.3 parser 120: ADD1(trunc); ADD1(frac);
1.1 parser 121: ADD1(abs); ADD1(sign);
122: ADD1(exp); ADD1(log);
123: ADD1(sin); ADD1(asin);
124: ADD1(cos); ADD1(acos);
125: ADD1(tan); ADD1(atan);
1.3 parser 126: ADD1(degrees); ADD1(radians);
1.1 parser 127: ADD1(sqrt);
1.3 parser 128: ADD1(random);
1.1 parser 129:
130: #define ADD2(name) \
131: add_native_method(#name, Method::CT_STATIC, _##name, 2, 2)
132:
133: // ^pow(x;y)
134: ADD2(pow);
135:
1.5 parser 136: }
137:
138: // in MSVC each thread has it's own pseudo-random sequence
139: // in win32 apache each thread can handle multiple requests
140: // so to get proper randoms we remember random generated in one thread
141: void MMath::configure_admin(Request&) {
142: // setting seed
143: srand(
144: randomizer ^
145: #ifdef WIN32
146: GetCurrentThreadId() ^
147: #else
148: getpid() ^
149: #endif
150: (unsigned int)time(NULL)
151: );
152: if(!randomizer)
153: randomizer=rand();
1.1 parser 154: }
155:
1.2 parser 156: // global variables
157:
158: Methoded *math_base_class;
159: Hash *math_consts;
160:
1.1 parser 161: // creator
162:
163: Methoded *MMath_create(Pool& pool) {
1.2 parser 164: math_consts=new(pool) Hash(pool);
165: math_consts->put(
166: *new(pool) String(pool, "PI"),
1.3 parser 167: new(pool) VDouble(pool, PI));
1.2 parser 168:
169: return math_base_class=new(pool) MMath(pool);
1.1 parser 170: }
E-mail: