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