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: