// ===================================================================================================================================== // allen_cpu_lib_arithmetics.c - Allen version 2.0 // ===================================================================================================================================== // // This file is part of the Allen Library. // Last modified: Saturday July 14, 2007. // // Copyright (c) 2007, Archville, BSD License. // A copy can be found here: http://www.opensource.org/licenses/bsd-license.php // Initally based on Salvatore Sanfilippo within Picol 0.1.0 // // All rights reserved. // // Redistribution and use in source and binary forms, with or without modification, // are permitted provided that the following conditions are met: // // * Redistributions of source code must retain the above copyright notice, // this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above copyright notice, // this list of conditions and the following disclaimer in the documentation // and/or other materials provided with the distribution. // * Neither the name of the Garabatos de licor nor the names of its contributors may // be used to endorse or promote products derived from this software // without specific prior written permission. // // This software is provided by the copyright holders and contributors // "as is" and any express or implied warranties, including, but not // limited to, the implied warranties of merchantability and fitness for // a particular purpose are disclaimed. in no event shall the copyright owner or // contributors be liable for any direct, indirect, incidental, special, // exemplary, or consequential damages (including, but not limited to, // procurement of substitute goods or services; loss of use, data, or // profits; or business interruption) however caused and on any theory of // liability, whether in contract, strict liability, or tort (including // negligence or otherwise) arising in any way out of the use of this // software, even if advised of the possibility of such damage. // ===================================================================================================================================== // Include libraries. // ===================================================================================================================================== #include // Standard input/output. #include // Standard C libraries. #include // String libraries. #include // Math libraries. #include // Types and conversion libraries. #include "allen_interpreter.h" // Main interpreter library. #include "allen_parser.h" // Main parser library. // ===================================================================================================================================== // Parameters. // ===================================================================================================================================== #define TLIB_ARITH_BSIZE 1024 // Buffer size. // ===================================================================================================================================== // Possible errors. // ===================================================================================================================================== #define TLIB_ARITH_EDIV "arith.*: division parameter is zero." // Error: Division by zero returns indeterminate results. #define TLIB_ARITH_EMOD "arith.*: modulus parameter is zero." // Error: Modulus by zero returns indeterminate results. #define TLIB_ARITH_EPAR "arith.*: unexpected or wrong parameters." // Error: Parameters are not satisfied for the command. #define TLIB_ARITH_EVAL "arith.*: variable does not exist." // Error: Variable does not exist in the interpreter. #define TLIB_ARITH_EHLP "arith.*: command not found in library." // Error: Command not found in arithmetic library. // ===================================================================================================================================== // Tokens. // ===================================================================================================================================== #define TLIB_ARITH_PLS "+" // Addition. #define TLIB_ARITH_DPLS "++" // Increment. #define TLIB_ARITH_MIN "-" // Substraction. #define TLIB_ARITH_DMIN "--" // Decrement. #define TLIB_ARITH_MUL "*" // Multiplication. #define TLIB_ARITH_DMUL "**" // Square. #define TLIB_ARITH_DIV "/" // Division. #define TLIB_ARITH_DDIV "//" // Division without floating point. #define TLIB_ARITH_MOD "mod" // Modulus. #define TLIB_ARITH_POW "pow" // Pow. #define TLIB_ARITH_VPLS "+:" // Addition in variable. #define TLIB_ARITH_VDPLS "++:" // Increment in variable. #define TLIB_ARITH_VMIN "-:" // Substraction in variable. #define TLIB_ARITH_VDMIN "--:" // Decrement in variable. #define TLIB_ARITH_VMUL "*:" // Multiplication in variable. #define TLIB_ARITH_VDMUL "**:" // Square in variable. #define TLIB_ARITH_VDIV "/:" // Division in variable. #define TLIB_ARITH_VDDIV "//:" // Division without floating point in variable. #define TLIB_ARITH_VMOD "mod:" // Modulus in variable. #define TLIB_ARITH_VPOW "pow:" // Pow in variable. // ===================================================================================================================================== // Helper Function. // ===================================================================================================================================== #define TLIB_ARITH_HLP "arith.?" // Helper function. #define TLIB_ARITH_NIL "nil" // Null value. // ===================================================================================================================================== // Basic arithmetic operators. // ===================================================================================================================================== // Allows to perform regular arithmetic operations on value lists // and return results based on their expressions. // Index: Example: Result: // AllenVM_CPU_LIB_ARITH_PLS(); :: + 2 3 4 9.000000 // AllenVM_CPU_LIB_ARITH_DPLS(); :: ++ 2 3.000000 // AllenVM_CPU_LIB_ARITH_MIN(); :: - 2 3 4 -5.000000 // AllenVM_CPU_LIB_ARITH_DMIN(); :: -- 2 1.000000 // AllenVM_CPU_LIB_ARITH_MUL(); :: * 2 3 4 24.000000 // AllenVM_CPU_LIB_ARITH_DMUL(); :: ** 2 4.000000 // AllenVM_CPU_LIB_ARITH_DIV(); :: / 2 3 4 0.166667 // AllenVM_CPU_LIB_ARITH_DDIV(); :: // 2 3 0 // AllenVM_CPU_LIB_ARITH_MOD(); :: mod 10 3 1.000000 // AllenVM_CPU_LIB_ARITH_POW(); :: pow 2 4 16.000000 // Index: Example: Result: // AllenVM_CPU_LIB_ARITH_VPLS(); :: +: x 10 var.def x [+ $x 10] // AllenVM_CPU_LIB_ARITH_VDPLS(); :: ++: x var.def x [++ $x] // AllenVM_CPU_LIB_ARITH_VMIN(); :: -: x 10 var.def x [- $x 10] // AllenVM_CPU_LIB_ARITH_VDMIN(); :: --: x var.def x [-- $x] // AllenVM_CPU_LIB_ARITH_VMUL(); :: *: x 10 var.def x [* $x 10] // AllenVM_CPU_LIB_ARITH_VDMUL(); :: **: x var.def x [** $x] // AllenVM_CPU_LIB_ARITH_VDIV(); :: /: x 10 var.def x [/ $x 10] // AllenVM_CPU_LIB_ARITH_VDDIV(); :: //: x 10 var.def x [// $x 10] // AllenVM_CPU_LIB_ARITH_VMOD(); :: mod: x 10 var.def x [mod $x 10] // AllenVM_CPU_LIB_ARITH_VPOW(); :: pow: x 10 var.def x [pow $x 10] // Total: 20. // ------------------------------------------------------------------------------------------------------------------------------------- // Function: AllenVM_CPU_LIB_ARITH_PLS(); // Purpose: Addition. // Returns: Expression result. // ------------------------------------------------------------------------------------------------------------------------------------- static int AllenVM_CPU_LIB_ARITH_PLS(struct AllenInterp *i, int argc, char **argv, void *pd) { if(argc < 2) return AllenVM_CPU_Error(i,TLIB_ARITH_EPAR); // Check parameters. register int p, op=1; register float c=atof(argv[1]); // Parameters. for(p=2; pc_val); // Parameters. for(p=2; pc_val)+1; // Operate. register int p; // Variable assignement result. char buf[TLIB_ARITH_BSIZE]; // Create buffer. snprintf(buf,TLIB_ARITH_BSIZE,"%f",c); // Copy result to buffer as float. if((p=AllenVM_InterpSetVar(i,argv[1],buf,0)) != Allen_VM_OK) return p; // Set the new variable value. AllenVM_InterpSetResult(i,buf); // Set interpreter result. return Allen_VM_OK; // Everything ok. } // ------------------------------------------------------------------------------------------------------------------------------------- // Function: AllenVM_CPU_LIB_ARITH_VMIN(); // Purpose: Substraction in variable. // Returns: Expression result. // ------------------------------------------------------------------------------------------------------------------------------------- static int AllenVM_CPU_LIB_ARITH_VMIN(struct AllenInterp *i, int argc, char **argv, void *pd) { if(argc < 3) return AllenVM_CPU_Error(i,TLIB_ARITH_EPAR); // Check parameters. struct AllenVar *v; // Variable struct. if((v = (void*) AllenVM_InterpGetVar(i,argv[1])) == NULL) // Check variable for existence. return AllenVM_CPU_Error(i,TLIB_ARITH_EVAL); // Does not exist, error. register int p, op=2; register float c=atof(v->c_val); // Parameters. for(p=2; pc_val)-1; // Operate. register int p; // Variable assignement result. char buf[TLIB_ARITH_BSIZE]; // Create buffer. snprintf(buf,TLIB_ARITH_BSIZE,"%f",c); // Copy result to buffer as float. if((p=AllenVM_InterpSetVar(i,argv[1],buf,0)) != Allen_VM_OK) return p; // Set the new variable value. AllenVM_InterpSetResult(i,buf); // Set interpreter result. return Allen_VM_OK; // Everything ok. } // ------------------------------------------------------------------------------------------------------------------------------------- // Function: AllenVM_CPU_LIB_ARITH_VMUL(); // Purpose: Multiplication in variable. // Returns: Expression result. // ------------------------------------------------------------------------------------------------------------------------------------- static int AllenVM_CPU_LIB_ARITH_VMUL(struct AllenInterp *i, int argc, char **argv, void *pd) { if(argc < 3) return AllenVM_CPU_Error(i,TLIB_ARITH_EPAR); // Check parameters. struct AllenVar *v; // Variable struct. if((v = (void*) AllenVM_InterpGetVar(i,argv[1])) == NULL) // Check variable for existence. return AllenVM_CPU_Error(i,TLIB_ARITH_EVAL); // Does not exist, error. register int p, op=3; register float c=atof(v->c_val); // Parameters. for(p=2; pc_val) * atof(v->c_val); // Operate. register int p; // Variable assignement result. char buf[TLIB_ARITH_BSIZE]; // Create buffer. snprintf(buf,TLIB_ARITH_BSIZE,"%f",c); // Copy result to buffer as float. if((p=AllenVM_InterpSetVar(i,argv[1],buf,0)) != Allen_VM_OK) return p; // Set the new variable value. AllenVM_InterpSetResult(i,buf); // Set interpreter result. return Allen_VM_OK; // Everything ok. } // ------------------------------------------------------------------------------------------------------------------------------------- // Function: AllenVM_CPU_LIB_ARITH_VDIV(); // Purpose: Division in variable. // Returns: Expression result. // ------------------------------------------------------------------------------------------------------------------------------------- static int AllenVM_CPU_LIB_ARITH_VDIV(struct AllenInterp *i, int argc, char **argv, void *pd) { if(argc < 3) return AllenVM_CPU_Error(i,TLIB_ARITH_EPAR); // Check parameters. struct AllenVar *v; // Variable struct. if((v = (void*) AllenVM_InterpGetVar(i,argv[1])) == NULL) // Check variable for existence. return AllenVM_CPU_Error(i,TLIB_ARITH_EVAL); // Does not exist, error. register int p, op=4; register float c=atof(v->c_val); // Parameters. for(p=2; pc_val); // Parameters. for(p=2; pc_val); // Parameters. for(p=2; pc_val); // Parameters. for(p=2; p 11.000000"); // Sample function. puts("Parameters: min: 1 max: ANY"); // Parameters needed. AllenVM_InterpSetResult(i,TLIB_ARITH_PLS); // Set interpreter result. return Allen_VM_OK; } // Everything ok. if(!strcmp(TLIB_ARITH_DPLS,argv[1])) { // Compare parameters. puts("Description: Increments it's parameter by one."); // Description. puts("Returns: Float number from expression result. "); // Returns. puts("Sample: ++ 5 => 6.000000"); // Sample function. puts("Parameters: min: 1 max: 1"); // Parameters needed. AllenVM_InterpSetResult(i,TLIB_ARITH_DPLS); // Set interpreter result. return Allen_VM_OK; } // Everything ok. if(!strcmp(TLIB_ARITH_MIN,argv[1])) { // Compare parameters. puts("Description: Substracts a list of numbers."); // Description. puts("Returns: Float number from expression result. "); // Returns. puts("Sample: - 5 10 21 => - 26.000000"); // Sample function. puts("Parameters: min: 1 max: ANY"); // Parameters needed. AllenVM_InterpSetResult(i,TLIB_ARITH_MIN); // Set interpreter result. return Allen_VM_OK; } // Everything ok. if(!strcmp(TLIB_ARITH_DMIN,argv[1])) { // Compare parameters. puts("Description: Decrements it's parameter by one."); // Description. puts("Returns: Float number from expression result. "); // Returns. puts("Sample: -- 5 => 4.000000"); // Sample function. puts("Parameters: min: 1 max: 1"); // Parameters needed. AllenVM_InterpSetResult(i,TLIB_ARITH_DMIN); // Set interpreter result. return Allen_VM_OK; } // Everything ok. if(!strcmp(TLIB_ARITH_MUL,argv[1])) { // Compare parameters. puts("Description: Multiplies a list of numbers."); // Description. puts("Returns: Float number from expression result. "); // Returns. puts("Sample: * 5 4 2 => 40.000000"); // Sample function. puts("Parameters: min: 1 max: ANY"); // Parameters needed. AllenVM_InterpSetResult(i,TLIB_ARITH_MUL); // Set interpreter result. return Allen_VM_OK; } // Everything ok. if(!strcmp(TLIB_ARITH_DMUL,argv[1])) { // Compare parameters. puts("Description: Calculates the square of a number."); // Description. puts("Returns: Float number from expression result. "); // Returns. puts("Sample: ** 10 => 100.000000"); // Sample function. puts("Parameters: min: 1 max: 1"); // Parameters needed. AllenVM_InterpSetResult(i,TLIB_ARITH_DMUL); // Set interpreter result. return Allen_VM_OK; } // Everything ok. if(!strcmp(TLIB_ARITH_DIV,argv[1])) { // Compare parameters. puts("Description: Divides a list of numbers."); // Description. puts("Returns: Float number from expression result. "); // Returns. puts("Sample: / 5 2 1 => 2.500000"); // Sample function. puts("Parameters: min: 1 max: ANY"); // Parameters needed. AllenVM_InterpSetResult(i,TLIB_ARITH_DIV); // Set interpreter result. return Allen_VM_OK; } // Everything ok. if(!strcmp(TLIB_ARITH_DDIV,argv[1])) { // Compare parameters. puts("Description: Divides a list of numbers."); // Description. puts("Returns: Integer number from expression result. "); // Returns. puts("Sample: // 5 2 1 => 2.000000"); // Sample function. puts("Parameters: min: 1 max: ANY"); // Parameters needed. AllenVM_InterpSetResult(i,TLIB_ARITH_DDIV); // Set interpreter result. return Allen_VM_OK; } // Everything ok. if(!strcmp(TLIB_ARITH_MOD,argv[1])) { // Compare parameters. puts("Description: Calculates modulus of a division."); // Description. puts("Returns: Float number from expression result. "); // Returns. puts("Sample: mod 10 3 => 1.000000"); // Sample function. puts("Parameters: min: 1 max: ANY"); // Parameters needed. AllenVM_InterpSetResult(i,TLIB_ARITH_MOD); // Set interpreter result. return Allen_VM_OK; } // Everything ok. if(!strcmp(TLIB_ARITH_POW,argv[1])) { // Compare parameters. puts("Description: Calculates the pow of a list of numbers."); // Description. puts("Returns: Float number from expression result. "); // Returns. puts("Sample: pow 2 3 => 8.000000"); // Sample function. puts("Parameters: min: 1 max: ANY"); // Parameters needed. AllenVM_InterpSetResult(i,TLIB_ARITH_POW); // Set interpreter result. return Allen_VM_OK; } // Everything ok. if(!strcmp(TLIB_ARITH_VPLS,argv[1])) { // Compare parameters. puts("Description: Adds a list of numbers to a variable."); // Description. puts("Returns: Float number from expression result. "); // Returns. puts("Sample: +: x 10 => var.def x [+ $x 10]"); // Sample function. puts("Parameters: min: 2 max: ANY"); // Parameters needed. AllenVM_InterpSetResult(i,TLIB_ARITH_VPLS); // Set interpreter result. return Allen_VM_OK; } // Everything ok. if(!strcmp(TLIB_ARITH_VDPLS,argv[1])) { // Compare parameters. puts("Description: Increments a variable."); // Description. puts("Returns: Float number from expression result. "); // Returns. puts("Sample: ++: x => var.def x [++ $x];"); // Sample function. puts("Parameters: min: 1 max: 1"); // Parameters needed. AllenVM_InterpSetResult(i,TLIB_ARITH_VDPLS); // Set interpreter result. return Allen_VM_OK; } // Everything ok. if(!strcmp(TLIB_ARITH_VMIN,argv[1])) { // Compare parameters. puts("Description: Substracts a list of numbers from a variable."); // Description. puts("Returns: Float number from expression result. "); // Returns. puts("Sample: -: x 10 => var.def x [- $x 10]"); // Sample function. puts("Parameters: min: 2 max: ANY"); // Parameters needed. AllenVM_InterpSetResult(i,TLIB_ARITH_VMIN); // Set interpreter result. return Allen_VM_OK; } // Everything ok. if(!strcmp(TLIB_ARITH_VDMIN,argv[1])) { // Compare parameters. puts("Description: Decrements a variable."); // Description. puts("Returns: Float number from expression result. "); // Returns. puts("Sample: --: x => var.def x [-- $x]"); // Sample function. puts("Parameters: min: 1 max: 1"); // Parameters needed. AllenVM_InterpSetResult(i,TLIB_ARITH_VDMIN); // Set interpreter result. return Allen_VM_OK; } // Everything ok. if(!strcmp(TLIB_ARITH_VMUL,argv[1])) { // Compare parameters. puts("Description: Multiplies a variable by a list of numbers."); // Description. puts("Returns: Float number from expression result. "); // Returns. puts("Sample: *: x 5 => var.def x [* $x 5]"); // Sample function. puts("Parameters: min: 2 max: ANY"); // Parameters needed. AllenVM_InterpSetResult(i,TLIB_ARITH_VMUL); // Set interpreter result. return Allen_VM_OK; } // Everything ok. if(!strcmp(TLIB_ARITH_VDMUL,argv[1])) { // Compare parameters. puts("Description: Multiplies a variable by self."); // Description. puts("Returns: Float number from expression result. "); // Returns. puts("Sample: **: x => var.def x [** $x]"); // Sample function. puts("Parameters: min: 1 max: 1"); // Parameters needed. AllenVM_InterpSetResult(i,TLIB_ARITH_VDMUL); // Set interpreter result. return Allen_VM_OK; } // Everything ok. if(!strcmp(TLIB_ARITH_VDIV,argv[1])) { // Compare parameters. puts("Description: Divides a variable by a list of numbers."); // Description. puts("Returns: Float number from expression result. "); // Returns. puts("Sample: /: x 10 => var.def x [/ $x 10]"); // Sample function. puts("Parameters: min: 2 max: ANY"); // Parameters needed. AllenVM_InterpSetResult(i,TLIB_ARITH_VDIV); // Set interpreter result. return Allen_VM_OK; } // Everything ok. if(!strcmp(TLIB_ARITH_VDDIV,argv[1])) { // Compare parameters. puts("Description: Divides a variable by a list of numbers."); // Description. puts("Returns: Integer number from expression result. "); // Returns. puts("Sample: //: x 2 => var.def x [// $x 2]"); // Sample function. puts("Parameters: min: 1 max: ANY"); // Parameters needed. AllenVM_InterpSetResult(i,TLIB_ARITH_VDDIV); // Set interpreter result. return Allen_VM_OK; } // Everything ok. if(!strcmp(TLIB_ARITH_VMOD,argv[1])) { // Compare parameters. puts("Description: Calculates modulus of a division in a variable."); // Description. puts("Returns: Float number from expression result. "); // Returns. puts("Sample: mod: x 3 => var.def x [mod $x 3]"); // Sample function. puts("Parameters: min: 2 max: ANY"); // Parameters needed. AllenVM_InterpSetResult(i,TLIB_ARITH_VMOD); // Set interpreter result. return Allen_VM_OK; } // Everything ok. if(!strcmp(TLIB_ARITH_VPOW,argv[1])) { // Compare parameters. puts("Description: Calculates the pow of a variable by a list of numbers."); // Description. puts("Returns: Float number from expression result. "); // Returns. puts("Sample: pow: x 3 => var.def x [pow $x 3]"); // Sample function. puts("Parameters: min: 2 max: ANY"); // Parameters needed. AllenVM_InterpSetResult(i,TLIB_ARITH_VPOW); // Set interpreter result. return Allen_VM_OK; } // Everything ok. AllenVM_InterpSetResult(i,TLIB_ARITH_NIL); // Set interpreter result. return AllenVM_CPU_Error(i,TLIB_ARITH_EHLP); // Command not found. } // ------------------------------------------------------------------------------------------------------------------------------------- // Function: AllenVM_CPU_LIB_ARITH_ADD(); // Purpose: Add instructions to the CPU. // Returns: Void (nothing). // ------------------------------------------------------------------------------------------------------------------------------------- void AllenVM_CPU_LIB_ARITH_ADD(struct AllenInterp *i) { AllenVM_InterpSetCommand(i,TLIB_ARITH_PLS, AllenVM_CPU_LIB_ARITH_PLS, NULL); // Addition. AllenVM_InterpSetCommand(i,TLIB_ARITH_DPLS, AllenVM_CPU_LIB_ARITH_DPLS, NULL); // Increment. AllenVM_InterpSetCommand(i,TLIB_ARITH_MIN, AllenVM_CPU_LIB_ARITH_MIN, NULL); // Substraction. AllenVM_InterpSetCommand(i,TLIB_ARITH_DMIN, AllenVM_CPU_LIB_ARITH_DMIN, NULL); // Decrement. AllenVM_InterpSetCommand(i,TLIB_ARITH_MUL, AllenVM_CPU_LIB_ARITH_MUL, NULL); // Multiplication. AllenVM_InterpSetCommand(i,TLIB_ARITH_DMUL, AllenVM_CPU_LIB_ARITH_DMUL, NULL); // Square. AllenVM_InterpSetCommand(i,TLIB_ARITH_DIV, AllenVM_CPU_LIB_ARITH_DIV, NULL); // Division. AllenVM_InterpSetCommand(i,TLIB_ARITH_DDIV, AllenVM_CPU_LIB_ARITH_DDIV, NULL); // Division without floating point. AllenVM_InterpSetCommand(i,TLIB_ARITH_MOD, AllenVM_CPU_LIB_ARITH_MOD, NULL); // Modulus. AllenVM_InterpSetCommand(i,TLIB_ARITH_POW, AllenVM_CPU_LIB_ARITH_POW, NULL); // Pow. AllenVM_InterpSetCommand(i,TLIB_ARITH_VPLS, AllenVM_CPU_LIB_ARITH_VPLS, NULL); // Addition in variable. AllenVM_InterpSetCommand(i,TLIB_ARITH_VDPLS, AllenVM_CPU_LIB_ARITH_VDPLS, NULL); // Increment in variable. AllenVM_InterpSetCommand(i,TLIB_ARITH_VMIN, AllenVM_CPU_LIB_ARITH_VMIN, NULL); // Substraction in variable. AllenVM_InterpSetCommand(i,TLIB_ARITH_VDMIN, AllenVM_CPU_LIB_ARITH_VDMIN, NULL); // Decrement in variable. AllenVM_InterpSetCommand(i,TLIB_ARITH_VMUL, AllenVM_CPU_LIB_ARITH_VMUL, NULL); // Multiplication in variable. AllenVM_InterpSetCommand(i,TLIB_ARITH_VDMUL, AllenVM_CPU_LIB_ARITH_VDMUL, NULL); // Square in variable. AllenVM_InterpSetCommand(i,TLIB_ARITH_VDIV, AllenVM_CPU_LIB_ARITH_VDIV, NULL); // Division in variable AllenVM_InterpSetCommand(i,TLIB_ARITH_VDDIV, AllenVM_CPU_LIB_ARITH_VDDIV, NULL); // Division without fp in variable. AllenVM_InterpSetCommand(i,TLIB_ARITH_VMOD, AllenVM_CPU_LIB_ARITH_VMOD, NULL); // Modulus in variable. AllenVM_InterpSetCommand(i,TLIB_ARITH_VPOW, AllenVM_CPU_LIB_ARITH_VPOW, NULL); // Pow in variable. AllenVM_InterpSetCommand(i,TLIB_ARITH_HLP, AllenVM_CPU_LIB_ARITH_HLP, NULL); // Helper function. } // ===================================================================================================================================== // EOF // ===================================================================================================================================== // Compiler parameters: Gcc -O2 -lm // Recommended editor: Scite/Gedit/Vim.