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: