%{ /* Auto: smake MCalc */ static void __yy_bcopy(char *from, char *to, int count); #undef alloca #define alloca(x) AllocVecPool(ParsePool, x) #undef malloc #define malloc(x) AllocVecPool(ParsePool, x) #undef free #define free(x) FreeVecPool(ParsePool, x) #undef YYINITDEPTH #define YYINITDEPTH 512 #undef _STDC_ #define _STDC_ #undef error #define error extern APTR ParsePool; extern double Value; extern double IMem, JMem, KMem, LMem, MMem, NMem, OMem, PMem, QMem, RMem, SMem, TMem, UMem, VMem, WMem, XMem, YMem, ZMem; extern struct List StandardList; extern struct List LinearList; #define outputr(x) {Value = x;} #define outputmem(x, y) {Value = *(x) = y;} #define errout(x) ; #define erroutm(x, y) ; /**********************************************************************/ /* Chars read and read-position */ /**********************************************************************/ extern UWORD PColumn; extern UWORD PCharRead; // This is for the wanted angle extern UWORD IntAngle; /**********************************************************************/ /* Error-Value */ /**********************************************************************/ UWORD PError; %} /**********************************************************************/ /* Possible Return-Value */ /**********************************************************************/ %union { double Real; double *MemPtr; } /**********************************************************************/ /* Token which returns Real */ /**********************************************************************/ %token INT_CONSTANT /**********************************************************************/ /* Non-Priority functions */ /**********************************************************************/ %token EQU_OP OPEN_OP CLOSE_OP COMMA SEMICOLON /**********************************************************************/ /* Set priorities */ /**********************************************************************/ %left AND_OP OR_OP XOR_OP ASL ASR LSL LSR ROL ROR %left ADD_OP SUB_OP %left MUL_OP DIV_OP MOD_OP %left NEG_OP NOT_OP PERCENT CHPERCENT TPERCENT %left POW %nonassoc MY_ABS COS SIN TAN ACOS ASIN ATAN EXP LOG LOG10 SQRT SINH COSH TANH FAK COT N_OVER_K YROOT REZ SD_INIT SD_AVERAGE SD_DEVIATION1 SD_DEVIATION2 SD_QSUM SD_SUM SD_NUM LR_INIT LR_XAVERAGE LR_YAVERAGE LR_XDEVIATION1 LR_YDEVIATION1 LR_XDEVIATION2 LR_YDEVIATION2 LR_XQSUM LR_YQSUM LR_XSUM LR_YSUM LR_XNUM LR_YNUM LR_XYSUM LR_ALPHA LR_BETA LR_ASSESSX LR_ASSESSY LR_CORR LR_CRITCORR LR_COVAR EXG_OP %nonassoc I_MEM J_MEM K_MEM L_MEM M_MEM N_MEM O_MEM P_MEM Q_MEM R_MEM S_MEM T_MEM U_MEM V_MEM W_MEM X_MEM Y_MEM Z_MEM /**********************************************************************/ /* Return-Value of my terminal */ /**********************************************************************/ %type int_expr %type standard_deviation %type linear_regression %type memory_name %% /**********************************************************************/ /* Main "sentence" */ /**********************************************************************/ eingabe : int_expr {outputr($1);} | standard_deviation {UpdateHistoryWindow(FALSE); outputr(0.0);} | linear_regression {UpdateHistoryWindow(TRUE); outputr(0.0);} | memory_name EQU_OP int_expr {outputmem($1, $3);} | error ; /**********************************************************************/ /* Do the grammar */ /**********************************************************************/ int_expr : OPEN_OP int_expr CLOSE_OP {$$ = $2;} | int_expr AND_OP int_expr {$$ = (make_ulong($1)) & (make_ulong($3));} | int_expr OR_OP int_expr {$$ = (make_ulong($1)) | (make_ulong($3));} | int_expr XOR_OP int_expr {$$ = MyXOR(make_ulong($1),make_ulong($3));} | int_expr NOT_OP AND_OP int_expr {$$ = MyNAND(make_ulong($1), make_ulong($4));} | int_expr NOT_OP OR_OP int_expr {$$ = MyNOR(make_ulong($1), make_ulong($4));} | int_expr NOT_OP XOR_OP int_expr {$$ = MyNXOR(make_ulong($1), make_ulong($4));} | int_expr ADD_OP int_expr PERCENT {$$ = ($1 + (($1 * $3) / 100));} | int_expr SUB_OP int_expr PERCENT {$$ = ($1 - (($1 * $3) / 100));} | int_expr MUL_OP int_expr PERCENT {$$ = (($1 * $3) / 100);} | int_expr CHPERCENT int_expr {$$ = ((($3 - $1) * 100) / $1);} | int_expr TPERCENT int_expr {$$ = (($3 * 100) / $1);} | int_expr ADD_OP int_expr {$$ = $1 + $3;} | int_expr SUB_OP int_expr {$$ = $1 - $3;} | int_expr MUL_OP int_expr {$$ = $1 * $3;} | int_expr DIV_OP int_expr {if($3 == 0.0) {PError = ERR_DIVBY0; yyerror(NULL); } else $$ = $1 / $3;} | int_expr MOD_OP int_expr {if($3 == 0.0) {PError = ERR_DIVBY0; yyerror(NULL); } else $$ = fmod($1,$3);} | SUB_OP int_expr %prec NEG_OP {$$ = -$2; } | NOT_OP int_expr {$$ = (~make_ulong($2)); } | int_expr ASL int_expr {$$ = (double)MyASL(make_ulong($1),make_ulong($3)); } | int_expr ASR int_expr {$$ = (double)MyASR(make_ulong($1),make_ulong($3)); } | int_expr LSL int_expr {$$ = (double)MyLSL(make_ulong($1),make_ulong($3)); } | int_expr LSR int_expr {$$ = (double)MyLSR(make_ulong($1),make_ulong($3)); } | int_expr ROL int_expr {$$ = (double)MyROL(make_ulong($1),make_ulong($3)); } | int_expr ROR int_expr {$$ = (double)MyROR(make_ulong($1),make_ulong($3)); } | int_expr POW int_expr {$$ = pow($1,$3); } | SIN int_expr {$$ = sin(calc_angle($2)); } | COS int_expr {$$ = cos(calc_angle($2)); } | TAN int_expr {$$ = tan(calc_angle($2)); } | ASIN int_expr {$$ = asin(calc_angle($2)); } | ACOS int_expr {$$ = acos(calc_angle($2)); } | ATAN int_expr {$$ = atan(calc_angle($2)); } | COT int_expr {$$ = cot(calc_angle($2)); } | SINH int_expr {$$ = sinh(calc_angle($2)); } | COSH int_expr {$$ = cosh(calc_angle($2)); } | TANH int_expr {$$ = tanh(calc_angle($2)); } | EXP int_expr {$$ = exp($2); } | LOG int_expr {$$ = log($2); } | LOG10 int_expr {$$ = log10($2); } | MY_ABS int_expr {$$ = fabs($2); } | SQRT int_expr {if($2 < 0.0) {PError = ERR_OVERFLOW; yyerror(NULL); } else $$ = sqrt($2);} | int_expr N_OVER_K int_expr {if($1 < 0.0 || ($1 - $3) < 0.0 || $1 > 170.0 || ($1 - $3) > 170.0) {PError = ERR_OVERFLOW; yyerror(NULL); } else $$ = (calc_fak($1) / calc_fak($1 - $3));} | int_expr YROOT int_expr {if($1 < 0.0) {PError = ERR_DIVBY0; yyerror(NULL);} else $$ = pow($3, (1/$1));} | REZ int_expr {if($2 < 0.0) {PError = ERR_DIVBY0; yyerror(NULL);} else $$ = (1.0 / $2);} | FAK int_expr {if($2 > 170.0) { PError = ERR_OVERFLOW; yyerror(NULL); } else $$ = calc_fak($2);} | int_expr FAK {if($1 > 170.0) { PError = ERR_OVERFLOW; yyerror(NULL); } else $$ = calc_fak($1);} | SD_AVERAGE {if(numbers_in_list(&StandardList) < 1) {PError = ERR_UNDERFLOW; yyerror(NULL);} else {$$ = calc_average(&StandardList, FALSE);}} | SD_DEVIATION1 {if(numbers_in_list(&StandardList) < 1) {PError = ERR_UNDERFLOW; yyerror(NULL);} else {$$ = calc_population(&StandardList, FALSE);}} | SD_DEVIATION2 {if(numbers_in_list(&StandardList) < 2) {PError = ERR_UNDERFLOW; yyerror(NULL);} else {$$ = calc_sample(&StandardList, FALSE);}} | SD_QSUM {$$ = calc_powsum(&StandardList, FALSE);} | SD_SUM {$$ = calc_sum(&StandardList, FALSE);} | SD_NUM {$$ = (double)numbers_in_list(&StandardList);} | LR_XAVERAGE {if(numbers_in_list(&LinearList) < 1) {PError = ERR_UNDERFLOW; yyerror(NULL);} else {$$ = calc_average(&LinearList, FALSE);}} | LR_XDEVIATION1 {if(numbers_in_list(&LinearList) < 1) {PError = ERR_UNDERFLOW; yyerror(NULL);} else {$$ = calc_population(&LinearList, FALSE);}} | LR_XDEVIATION2 {if(numbers_in_list(&LinearList) < 2) {PError = ERR_UNDERFLOW; yyerror(NULL);} else {$$ = calc_sample(&LinearList, FALSE);}} | LR_XQSUM {$$ = calc_powsum(&LinearList, FALSE);} | LR_XSUM {$$ = calc_sum(&LinearList, FALSE);} | LR_XNUM {$$ = (double)numbers_in_list(&LinearList);} | LR_YAVERAGE {if(numbers_in_list(&LinearList) < 1) {PError = ERR_UNDERFLOW; yyerror(NULL);} else {$$ = calc_average(&LinearList, TRUE);}} | LR_YDEVIATION1 {if(numbers_in_list(&LinearList) < 1) {PError = ERR_UNDERFLOW; yyerror(NULL);} else {$$ = calc_population(&LinearList, TRUE);}} | LR_YDEVIATION2 {if(numbers_in_list(&LinearList) < 2) {PError = ERR_UNDERFLOW; yyerror(NULL);} else {$$ = calc_sample(&LinearList, TRUE);}} | LR_YQSUM {$$ = calc_powsum(&LinearList, TRUE);} | LR_YSUM {$$ = calc_sum(&LinearList, TRUE);} | LR_YNUM {$$ = (double)numbers_in_list(&LinearList);} | LR_XYSUM {$$ = calc_xysum();} | LR_ALPHA {$$ = calc_lralpha(); if(PError) yyerror(NULL);} | LR_BETA {$$ = calc_lrbeta(); if(PError) yyerror(NULL);} | LR_ASSESSX int_expr {$$ = calc_lrassessx($2); if(PError) yyerror(NULL);} | LR_ASSESSY int_expr {$$ = calc_lrassessy($2); if(PError) yyerror(NULL);} | LR_CORR {$$ = calc_lrcorr(); if(PError) yyerror(NULL);} | LR_CRITCORR {$$ = pow(calc_lrcorr(), 2.0); if(PError) yyerror(NULL);} | LR_COVAR {$$ = calc_lrcovar(); if(PError) yyerror(NULL);} | memory_name {$$ = (*($1));} | INT_CONSTANT | EXG_OP OPEN_OP memory_name COMMA memory_name CLOSE_OP {double Spare; $$ = 0.0; Spare = *($3); *($3) = *($5); *($5) = Spare;} ; standard_deviation : SD_INIT OPEN_OP standard_input CLOSE_OP {$$ = 0.0;} standard_input : int_expr {if(!add_standard_value($1)) { PError = ERR_NOMEM; yyerror(NULL); }} | int_expr COMMA standard_input {if(!add_standard_value($1)) { PError = ERR_NOMEM; yyerror(NULL); }} ; linear_regression : LR_INIT OPEN_OP linear_input CLOSE_OP {$$ = 0.0;} linear_input : int_expr SEMICOLON int_expr {if(!add_linear_value($1, $3)) { PError = ERR_NOMEM; yyerror(NULL); }} | int_expr SEMICOLON int_expr COMMA linear_input {if(!add_linear_value($1, $3)) { PError = ERR_NOMEM; yyerror(NULL); }} ; memory_name : I_MEM {$$ = &IMem;} | J_MEM {$$ = &JMem;} | K_MEM {$$ = &KMem;} | L_MEM {$$ = &LMem;} | M_MEM {$$ = &MMem;} | N_MEM {$$ = &NMem;} | O_MEM {$$ = &OMem;} | P_MEM {$$ = &PMem;} | Q_MEM {$$ = &QMem;} | R_MEM {$$ = &RMem;} | S_MEM {$$ = &SMem;} | T_MEM {$$ = &TMem;} | U_MEM {$$ = &UMem;} | V_MEM {$$ = &VMem;} | W_MEM {$$ = &WMem;} | X_MEM {$$ = &XMem;} | Y_MEM {$$ = &YMem;} | Z_MEM {$$ = &ZMem;} ; %% /**********************************************************************/ /* Convert a double to a long (the hard way) */ /**********************************************************************/ ULONG make_ulong(double OldVal) { char Buffer[26]; ULONG Dummy; sprintf(Buffer, "%f", OldVal); stcd_l(Buffer, (LONG *)&Dummy); return(Dummy); } /**********************************************************************/ /* Calculate Fak */ /**********************************************************************/ double calc_fak(double Fak) { double RetVal = 1.0, i = 1.0; while(i <= Fak) { RetVal *= i; i++; } return(RetVal); } /**********************************************************************/ /* Calculate correct angle value (rad, deg, gra) */ /**********************************************************************/ double calc_angle(double Value) { switch(IntAngle) { case ID_GRAD : { Value = (Value * (9.0 / 10.0)); } case ID_DEG : { Value = (Value / 180.0) * Pi; break; } } return(Value); } /**********************************************************************/ /* Error-Routine ;) */ /**********************************************************************/ int yyerror(char *s) { return(0); } /**********************************************************************/ /* Add a value to the standard regression array */ /**********************************************************************/ BOOL add_standard_value(double Value) { struct DoubleNode *NewNode; if((NewNode = AllocVec(sizeof(struct DoubleNode), MEMF_CLEAR))) { AddHead(&StandardList, (struct Node *)NewNode); NewNode->ValueX = Value; return(TRUE); } else return(FALSE); } /**********************************************************************/ /* Add a value to linear regression array */ /**********************************************************************/ BOOL add_linear_value(double ValueX, double ValueY) { struct DoubleNode *NewNode; if((NewNode = AllocVec(sizeof(struct DoubleNode), MEMF_CLEAR))) { AddHead(&LinearList, (struct Node *)NewNode); NewNode->ValueX = ValueX; NewNode->ValueY = ValueY; return(TRUE); } else return(FALSE); } /**********************************************************************/ /* Return the number of entries in a list */ /**********************************************************************/ int numbers_in_list(struct List *Lst) { struct Node *CheckNode = Lst->lh_Head; int Number = 0; while(CheckNode->ln_Succ) { Number++; CheckNode = CheckNode->ln_Succ; } return(Number); } /**********************************************************************/ /* Calc average of a list */ /**********************************************************************/ double calc_average(struct List *Lst, BOOL LinearValueY) { struct DoubleNode *CheckNode = (struct DoubleNode *)Lst->lh_Head; int Number = numbers_in_list(Lst); double Sum = 0; if(!Number) return(0.0); while(CheckNode->Link.ln_Succ) { if(!LinearValueY) Sum += CheckNode->ValueX; else Sum += CheckNode->ValueY; CheckNode = (struct DoubleNode *)CheckNode->Link.ln_Succ; } return((Sum / (double)Number)); } /**********************************************************************/ /* Calc std-deviation of population */ /**********************************************************************/ double calc_population(struct List *Lst, BOOL LinearValueY) { struct DoubleNode *CheckNode = (struct DoubleNode *)Lst->lh_Head; int Number = numbers_in_list(Lst); double Poss, Pop = 0, Ave = calc_average(Lst, LinearValueY), Value; Poss = 1.0 / (double)Number; while(CheckNode->Link.ln_Succ) { if(!LinearValueY) Value = CheckNode->ValueX; else Value = CheckNode->ValueY; Pop += (pow((Value - Ave), 2.0) * Poss); CheckNode = (struct DoubleNode *)CheckNode->Link.ln_Succ; } return(sqrt(Pop)); } /**********************************************************************/ /* Calc std-deviation of sample */ /**********************************************************************/ double calc_sample(struct List *Lst, BOOL LinearValueY) { struct DoubleNode *CheckNode = (struct DoubleNode *)Lst->lh_Head; int Number = numbers_in_list(Lst); double Poss, Pop = 0, Ave = calc_average(Lst, LinearValueY), Value; Poss = 1.0 / ((double)Number - 1); while(CheckNode->Link.ln_Succ) { if(!LinearValueY) Value = CheckNode->ValueX; else Value = CheckNode->ValueY; Pop += (pow((Value - Ave), 2.0) * Poss); CheckNode = (struct DoubleNode *)CheckNode->Link.ln_Succ; } return(sqrt(Pop)); } /**********************************************************************/ /* Calc sum of powers of two of entries within list */ /**********************************************************************/ double calc_powsum(struct List *Lst, BOOL LinearValueY) { struct DoubleNode *CheckNode = (struct DoubleNode *)Lst->lh_Head; double Number, Value = 0; while(CheckNode->Link.ln_Succ) { if(!LinearValueY) Number = CheckNode->ValueX; else Number = CheckNode->ValueY; Value += (pow(Number, 2.0)); CheckNode = (struct DoubleNode *)CheckNode->Link.ln_Succ; } return(Value); } /**********************************************************************/ /* Calc sum of entries within list */ /**********************************************************************/ double calc_sum(struct List *Lst, BOOL LinearValueY) { struct DoubleNode *CheckNode = (struct DoubleNode *)Lst->lh_Head; double Number, Value = 0; while(CheckNode->Link.ln_Succ) { if(!LinearValueY) Number = CheckNode->ValueX; else Number = CheckNode->ValueY; Value += Number; CheckNode = (struct DoubleNode *)CheckNode->Link.ln_Succ; } return(Value); } /**********************************************************************/ /* Calc sum of x and y members */ /**********************************************************************/ double calc_xysum(void) { struct DoubleNode *CheckNode = (struct DoubleNode *)LinearList.lh_Head; double Value = 0; while(CheckNode->Link.ln_Succ) { Value += (CheckNode->ValueX * CheckNode->ValueY); CheckNode = (struct DoubleNode *)CheckNode->Link.ln_Succ; } return(Value); } /**********************************************************************/ /* Calc alpha part of formular of regression */ /**********************************************************************/ double calc_lralpha(void) { double XSum = calc_sum(&LinearList, FALSE), XYSum = calc_xysum(), YSum = calc_sum(&LinearList, TRUE), XQSum = calc_powsum(&LinearList, FALSE), Number = (double)numbers_in_list(&LinearList); if((pow(XSum, 2.0) - (Number * XQSum)) == 0.0) { PError = ERR_DIVBY0; return(0.0); } return( (((XSum * XYSum) - (YSum * XQSum)) / (pow(XSum, 2.0) - (Number * XQSum))) ); } /**********************************************************************/ /* Calc alpha part of formular of regression */ /**********************************************************************/ double calc_lrbeta(void) { double XSum = calc_sum(&LinearList, FALSE), YSum = calc_sum(&LinearList, TRUE), XYSum = calc_xysum(), XQSum = calc_powsum(&LinearList, FALSE), Number = (double)numbers_in_list(&LinearList); if((pow(XSum, 2.0) - (Number * XQSum)) == 0.0) { PError = ERR_DIVBY0; return(0.0); } return( (((XSum * YSum) - (Number * XYSum)) / (pow(XSum, 2.0) - (Number * XQSum))) ); } /**********************************************************************/ /* Assess x value of linear regression given a y */ /**********************************************************************/ double calc_lrassessx(double y) { double Alpha = calc_lralpha(), Beta = calc_lrbeta(); if(Beta == 0.0) { PError = ERR_DIVBY0; return(0.0); } return( ((y - Alpha) / Beta) ); } /**********************************************************************/ /* Assess y value of linear regression given an x */ /**********************************************************************/ double calc_lrassessy(double x) { double Alpha = calc_lralpha(), Beta = calc_lrbeta(); return( (Alpha + (Beta * x)) ); } /**********************************************************************/ /* Calc correlation coefficient */ /**********************************************************************/ double calc_lrcorr(void) { double XSum = calc_sum(&LinearList, FALSE), YSum = calc_sum(&LinearList, TRUE), XYSum = calc_xysum(), Number = numbers_in_list(&LinearList), XDev = calc_population(&LinearList, FALSE), YDev = calc_population(&LinearList, TRUE); if(Number == 0.0 || XDev == 0.0 || YDev == 0.0) { PError = ERR_DIVBY0; return(0.0); } return( ( ((XYSum / Number) - ((XSum / Number) * (YSum / Number))) / (XDev * YDev) ) ); } /**********************************************************************/ /* Calc covariant of linear regression */ /**********************************************************************/ double calc_lrcovar(void) { double XYSum = calc_xysum(), Number = (double)numbers_in_list(&LinearList), XAve = calc_average(&LinearList, FALSE), YAve = calc_average(&LinearList, TRUE); if(Number == 1.0) { PError = ERR_DIVBY0; return(0.0); } return( ( (XYSum - (Number * XAve * YAve)) / (Number - 1) ) ); }