Annotation of parser3/src/classes/math.C, revision 1.5
1.1 parser 1: /** @file
2: Parser: @b math parser class.
3:
4: Copyright (c) 2001 ArtLebedev Group (http://www.artlebedev.com)
5:
6: Author: Alexander Petrosyan <paf@design.ru> (http://design.ru/paf)
7: */
1.5 ! parser 8: static const char *RCSId="$Id: math.C,v 1.4 2001/07/18 10:06:04 parser Exp $";
1.1 parser 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)
44: PTHROW(0, 0,
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: