All pastes #614567 Raw Edit

Someone

public text v1 · immutable
·published 2007-07-11 17:08 UTC
rendered paste body
// =====================================================================================================================================
// allen_cpu_base_arithmetic.c - Wed 13 jun 2007 00:09 CEST - Allen version 2.0
// ===================================================================================================================================== 

// Copyright (c) 2007, Archville, BSD License.
// A copy can be found here: http://www.opensource.org/licenses/bsd-license.php
// Initally based on Salvatore <antirez> 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 <stdio.h>                   // Standard input/output.
#include <stdlib.h>                  // Standard C libraries.
#include <string.h>                  // String libraries.
#include <math.h>                    // Math libraries.
#include <ctype.h>                   // Types and conversion libraries.

#include "allen_interpreter.h"       // Main interpreter library.
#include "allen_parser.h"            // Main parser library.

// =====================================================================================================================================
// Parameters.
// =====================================================================================================================================

#define TBASE_ARITH_BSIZE  1024                          // Buffer size.

// =====================================================================================================================================
// Possible errors.
// =====================================================================================================================================

#define TBASE_ARITH_EDIV  "division: parameter is zero"  // Error: Divide by zero returns inderminate result.
#define TBASE_ARITH_EMOD  "modulus: parameter is zero"   // Error: Modulus by zero returns indeterminate result.

// =====================================================================================================================================
// Tokens.
// =====================================================================================================================================

#define TBASE_ARITH_PLS    "+"   // Addition.
#define TBASE_ARITH_DPLS   "++"  // Increment.
#define TBASE_ARITH_MIN    "-"   // Substraction.
#define TBASE_ARITH_DMIN   "--"  // Decrement.
#define TBASE_ARITH_MUL    "*"   // Multiplication.
#define TBASE_ARITH_DMUL   "**"  // Square.
#define TBASE_ARITH_DIV    "/"   // Division.
#define TBASE_ARITH_DDIV   "//"  // Division without floating point.
#define TBASE_ARITH_MOD    "%"   // Modulus.
#define TBASE_ARITH_POW    "^"   // Pow.

// =====================================================================================================================================
// Basic arithmetic operators.
// =====================================================================================================================================

// Allows to perform regular arithmetic operations on value lists
// and return results based on their expresions.

// Index:                              Example:  Result:
// AllenVM_CPU_BASE_ARITH_PLS();  ::  + 2 3 - 4  1.000000
// AllenVM_CPU_BASE_ARITH_DPLS(); ::  ++ 2       3.000000
// AllenVM_CPU_BASE_ARITH_MIN();  ::  - 2 3 4   -5.000000
// AllenVM_CPU_BASE_ARITH_DMIN(); ::  -- 2       1.000000
// AllenVM_CPU_BASE_ARITH_MUL();  ::  * 2 3 4   24.000000
// AllenVM_CPU_BASE_ARITH_DMUL(); ::  ** 2       4.000000
// AllenVM_CPU_BASE_ARITH_DIV();  ::  / 2 3 4    0.166667
// AllenVM_CPU_BASE_ARITH_DDIV(); ::  // 2 3     0      
// AllenVM_CPU_BASE_ARITH_MOD();  ::  % 10 3     1.000000
// AllenVM_CPU_BASE_ARITH_POW();  ::  ^ 2 4 + 1  17.000000

// Total: 10.

// -------------------------------------------------------------------------------------------------------------------------------------
// Function:    AllenVM_CPU_BASE_ARITH_PLS();
// Purpose:     Addition.
// Returns:     Expression result.
// -------------------------------------------------------------------------------------------------------------------------------------

static int AllenVM_CPU_BASE_ARITH_PLS(struct AllenInterp *i, int argc, char **argv, void *pd) {
 char buf[TBASE_ARITH_BSIZE]; register int p,op; register float c=0;                     // Buffer and parameters.
 if(argc>=2) c=atof(argv[1]);                                                            // Conversion.
 for(op=1,p=2; p<argc; ++p) {                                                            // Loop through parameters.
 
  if(atof(argv[p])==0) {                                                                 // Check if we want to change.
   if(!strcmp(TBASE_ARITH_PLS,argv[p])) { op = 1; continue; }                            // Change operator: Addition.
   if(!strcmp(TBASE_ARITH_MIN,argv[p])) { op = 2; continue; }                            // Change operator: Substraction.
   if(!strcmp(TBASE_ARITH_MUL,argv[p])) { op = 3; continue; }                            // Change operator: Multiplication.
   if(!strcmp(TBASE_ARITH_DIV,argv[p])) { op = 4; continue; }                            // Change operator: Division.
   if(!strcmp(TBASE_ARITH_MOD,argv[p])) { op = 5; continue; }                            // Change operator: Modulus.
   if(!strcmp(TBASE_ARITH_POW,argv[p])) { op = 6; continue; }                            // Change operator: Pow.
  }

  switch(op) {                                                                           // Look current operator.
   case 1: c += atof(argv[p]); break;                                                    // Operate: Addition.
   case 2: c -= atof(argv[p]); break;                                                    // Operate: Substraction.
   case 3: c *= atof(argv[p]); break;                                                    // Operate: Multiplication.
   case 4: c /= atof(argv[p]); break;                                                    // Operate: Division.
   case 5: c = (int) c % atoi(argv[p]); break;                                           // Operate: Modulus.
   case 6: c = pow(c,atof(argv[p])); break;                                              // Operate: Pow.
  }}

 snprintf(buf,TBASE_ARITH_BSIZE,"%f",c);                                                 // Copy result to buffer as float.
 AllenVM_InterpSetResult(i,buf);                                                         // Set interpreter result.
 return Allen_VM_OK;                                                                     // Everything ok.
}

// -------------------------------------------------------------------------------------------------------------------------------------
// Function:    AllenVM_CPU_BASE_ARITH_DPLS();
// Purpose:     Increment.
// Returns:     Expression result.
// -------------------------------------------------------------------------------------------------------------------------------------

static int AllenVM_CPU_BASE_ARITH_DPLS(struct AllenInterp *i, int argc, char **argv, void *pd) {
 char buf[TBASE_ARITH_BSIZE]; register float c=0;                                        // Buffer and parameters.
 if(argc>=2) c=atof(argv[1])+1;                                                          // Increment.

 snprintf(buf,TBASE_ARITH_BSIZE,"%f",c);                                                 // Copy result to buffer as float.
 AllenVM_InterpSetResult(i,buf);                                                         // Set interpreter result.
 return Allen_VM_OK;                                                                     // Everything ok.
}

// -------------------------------------------------------------------------------------------------------------------------------------
// Function:    AllenVM_CPU_BASE_ARITH_MIN();
// Purpose:     Substraction.
// Returns:     Expression result.
// -------------------------------------------------------------------------------------------------------------------------------------

static int AllenVM_CPU_BASE_ARITH_MIN(struct AllenInterp *i, int argc, char **argv, void *pd) {
 char buf[TBASE_ARITH_BSIZE]; register int p,op; register float c=0;                     // Buffer and parameters.
 if(argc>=2) c=atof(argv[1]);                                                            // Conversion.
 for(op=2,p=2; p<argc; ++p) {                                                            // Loop through parameters.
 
  if(atof(argv[p])==0) {                                                                 // Check if we want to change.
   if(!strcmp(TBASE_ARITH_PLS,argv[p])) { op = 1; continue; }                            // Change operator: Addition.
   if(!strcmp(TBASE_ARITH_MIN,argv[p])) { op = 2; continue; }                            // Change operator: Substraction.
   if(!strcmp(TBASE_ARITH_MUL,argv[p])) { op = 3; continue; }                            // Change operator: Multiplication.
   if(!strcmp(TBASE_ARITH_DIV,argv[p])) { op = 4; continue; }                            // Change operator: Division.
   if(!strcmp(TBASE_ARITH_MOD,argv[p])) { op = 5; continue; }                            // Change operator: Modulus.
   if(!strcmp(TBASE_ARITH_POW,argv[p])) { op = 6; continue; }                            // Change operator: Pow.
  }

  switch(op) {                                                                           // Look current operator.
   case 1: c += atof(argv[p]); break;                                                    // Operate: Addition.
   case 2: c -= atof(argv[p]); break;                                                    // Operate: Substraction.
   case 3: c *= atof(argv[p]); break;                                                    // Operate: Multiplication.
   case 4: c /= atof(argv[p]); break;                                                    // Operate: Division.
   case 5: c = (int) c % atoi(argv[p]); break;                                           // Operate: Modulus.
   case 6: c = pow(c,atof(argv[p])); break;                                              // Operate: Pow.
  }}

 snprintf(buf,TBASE_ARITH_BSIZE,"%f",c);                                                 // Copy result to buffer as float.
 AllenVM_InterpSetResult(i,buf);                                                         // Set interpreter result.
 return Allen_VM_OK;                                                                     // Everything ok.
}

// -------------------------------------------------------------------------------------------------------------------------------------
// Function:    AllenVM_CPU_BASE_ARITH_DMIN();
// Purpose:     Decrement.
// Returns:     Expression result.
// -------------------------------------------------------------------------------------------------------------------------------------

static int AllenVM_CPU_BASE_ARITH_DMIN(struct AllenInterp *i, int argc, char **argv, void *pd) {
 char buf[TBASE_ARITH_BSIZE]; register float c=0;                                        // Buffer and parameters.
 if(argc>=2) c=atof(argv[1])-1;                                                          // Decrement.
 
 snprintf(buf,TBASE_ARITH_BSIZE,"%f",c);                                                 // Copy result to buffer as float.
 AllenVM_InterpSetResult(i,buf);                                                         // Set interpreter result.
 return Allen_VM_OK;                                                                     // Everything ok.
}

// -------------------------------------------------------------------------------------------------------------------------------------
// Function:    AllenVM_CPU_BASE_ARITH_MUL();
// Purpose:     Multiplication.
// Returns:     Expression result.
// -------------------------------------------------------------------------------------------------------------------------------------

static int AllenVM_CPU_BASE_ARITH_MUL(struct AllenInterp *i, int argc, char **argv, void *pd) {
 char buf[TBASE_ARITH_BSIZE]; register int p,op; register float c=0;                     // Buffer and parameters.
 if(argc>=2) c=atof(argv[1]);                                                            // Conversion.
 for(op=3,p=2; p<argc; ++p) {                                                            // Loop through parameters.
 
  if(atof(argv[p])==0) {                                                                 // Check if we want to change.
   if(!strcmp(TBASE_ARITH_PLS,argv[p])) { op = 1; continue; }                            // Change operator: Addition.
   if(!strcmp(TBASE_ARITH_MIN,argv[p])) { op = 2; continue; }                            // Change operator: Substraction.
   if(!strcmp(TBASE_ARITH_MUL,argv[p])) { op = 3; continue; }                            // Change operator: Multiplication.
   if(!strcmp(TBASE_ARITH_DIV,argv[p])) { op = 4; continue; }                            // Change operator: Division.
   if(!strcmp(TBASE_ARITH_MOD,argv[p])) { op = 5; continue; }                            // Change operator: Modulus.
   if(!strcmp(TBASE_ARITH_POW,argv[p])) { op = 6; continue; }                            // Change operator: Pow.
  }

  switch(op) {                                                                           // Look current operator.
   case 1: c += atof(argv[p]); break;                                                    // Operate: Addition.
   case 2: c -= atof(argv[p]); break;                                                    // Operate: Substraction.
   case 3: c *= atof(argv[p]); break;                                                    // Operate: Multiplication.
   case 4: c /= atof(argv[p]); break;                                                    // Operate: Division.
   case 5: c = (int) c % atoi(argv[p]); break;                                           // Operate: Modulus.
   case 6: c = pow(c,atof(argv[p])); break;                                              // Operate: Pow.
  }}

 snprintf(buf,TBASE_ARITH_BSIZE,"%f",c);                                                 // Copy result to buffer as float.
 AllenVM_InterpSetResult(i,buf);                                                         // Set interpreter result.
 return Allen_VM_OK;                                                                     // Everything ok.
}

// -------------------------------------------------------------------------------------------------------------------------------------
// Function:    AllenVM_CPU_BASE_ARITH_DMUL();
// Purpose:     Square.
// Returns:     Expression result.
// -------------------------------------------------------------------------------------------------------------------------------------

static int AllenVM_CPU_BASE_ARITH_DMUL(struct AllenInterp *i, int argc, char **argv, void *pd) {
 char buf[TBASE_ARITH_BSIZE]; register float c=0;                                        // Buffer and parameters.
 if(argc>=2) c=atof(argv[1])*atof(argv[1]);                                              // Square.

 snprintf(buf,TBASE_ARITH_BSIZE,"%f",c);                                                 // Copy result to buffer as float.
 AllenVM_InterpSetResult(i,buf);                                                         // Set interpreter result.
 return Allen_VM_OK;                                                                     // Everything ok.
}

// -------------------------------------------------------------------------------------------------------------------------------------
// Function:    AllenVM_CPU_BASE_ARITH_DIV();
// Purpose:     Division.
// Returns:     Expression result.
// -------------------------------------------------------------------------------------------------------------------------------------

static int AllenVM_CPU_BASE_ARITH_DIV(struct AllenInterp *i, int argc, char **argv, void *pd) {
 char buf[TBASE_ARITH_BSIZE]; register int p,op; register float c=0;                     // Buffer and parameters.
 if(argc>=2) c=atof(argv[1]);                                                            // Conversion.
 for(op=4,p=2; p<argc; ++p) {                                                            // Loop through parameters.
 
  if(atof(argv[p])==0) {                                                                 // Check if we want to change.
   if(!strcmp(TBASE_ARITH_PLS,argv[p])) { op = 1; continue; }                            // Change operator: Addition.
   if(!strcmp(TBASE_ARITH_MIN,argv[p])) { op = 2; continue; }                            // Change operator: Substraction.
   if(!strcmp(TBASE_ARITH_MUL,argv[p])) { op = 3; continue; }                            // Change operator: Multiplication.
   if(!strcmp(TBASE_ARITH_DIV,argv[p])) { op = 4; continue; }                            // Change operator: Division.
   if(!strcmp(TBASE_ARITH_MOD,argv[p])) { op = 5; continue; }                            // Change operator: Modulus.
   if(!strcmp(TBASE_ARITH_POW,argv[p])) { op = 6; continue; }                            // Change operator: Pow.
  }

  switch(op) {                                                                           // Look current operator.
   case 1: c += atof(argv[p]); break;                                                    // Operate: Addition.
   case 2: c -= atof(argv[p]); break;                                                    // Operate: Substraction.
   case 3: c *= atof(argv[p]); break;                                                    // Operate: Multiplication.
   case 4: c /= atof(argv[p]); break;                                                    // Operate: Division.
   case 5: c = (int) c % atoi(argv[p]); break;                                           // Operate: Modulus.
   case 6: c = pow(c,atof(argv[p])); break;                                              // Operate: Pow.
  }}

 snprintf(buf,TBASE_ARITH_BSIZE,"%f",c);                                                 // Copy result to buffer as float.
 AllenVM_InterpSetResult(i,buf);                                                         // Set interpreter result.
 return Allen_VM_OK;                                                                     // Everything ok.
}

// -------------------------------------------------------------------------------------------------------------------------------------
// Function:    AllenVM_CPU_BASE_ARITH_DDIV();
// Purpose:     Division without floating point.
// Returns:     Expression result.
// -------------------------------------------------------------------------------------------------------------------------------------

static int AllenVM_CPU_BASE_ARITH_DDIV(struct AllenInterp *i, int argc, char **argv, void *pd) {
 char buf[TBASE_ARITH_BSIZE]; register int p; register float c=0;                        // Buffer and parameters.
 if(argc>=2) c=atof(argv[1]);                                                            // Conversion.
 for(p=2; p<argc; ++p) {
   if(atof(argv[p]) == 0) return AllenVM_CPU_Error(i,TBASE_ARITH_EDIV);                  // Look for errors.
   c /= atof(argv[p]);                                                                   // Division.
 } 
 
 snprintf(buf,TBASE_ARITH_BSIZE,"%d",(int) c);                                           // Copy result to buffer as integer.
 AllenVM_InterpSetResult(i,buf);                                                         // Set interpreter result.
 return Allen_VM_OK;                                                                     // Everything ok.
}

// -------------------------------------------------------------------------------------------------------------------------------------
// Function:    AllenVM_CPU_BASE_ARITH_MOD();
// Purpose:     Modulus.
// Returns:     Expression result.
// -------------------------------------------------------------------------------------------------------------------------------------

static int AllenVM_CPU_BASE_ARITH_MOD(struct AllenInterp *i, int argc, char **argv, void *pd) {
 char buf[TBASE_ARITH_BSIZE]; register int p,op; register float c=0;                     // Buffer and parameters.
 if(argc>=2) c=atof(argv[1]);                                                            // Conversion.
 for(op=5,p=2; p<argc; ++p) {                                                            // Loop through parameters.
 
  if(atof(argv[p])==0) {                                                                 // Check if we want to change.
   if(!strcmp(TBASE_ARITH_PLS,argv[p])) { op = 1; continue; }                            // Change operator: Addition.
   if(!strcmp(TBASE_ARITH_MIN,argv[p])) { op = 2; continue; }                            // Change operator: Substraction.
   if(!strcmp(TBASE_ARITH_MUL,argv[p])) { op = 3; continue; }                            // Change operator: Multiplication.
   if(!strcmp(TBASE_ARITH_DIV,argv[p])) { op = 4; continue; }                            // Change operator: Division.
   if(!strcmp(TBASE_ARITH_MOD,argv[p])) { op = 5; continue; }                            // Change operator: Modulus.
   if(!strcmp(TBASE_ARITH_POW,argv[p])) { op = 6; continue; }                            // Change operator: Pow.
  }

  switch(op) {                                                                           // Look current operator.
   case 1: c += atof(argv[p]); break;                                                    // Operate: Addition.
   case 2: c -= atof(argv[p]); break;                                                    // Operate: Substraction.
   case 3: c *= atof(argv[p]); break;                                                    // Operate: Multiplication.
   case 4: c /= atof(argv[p]); break;                                                    // Operate: Division.
   case 5: c = (int) c % atoi(argv[p]); break;                                           // Operate: Modulus.
   case 6: c = pow(c,atof(argv[p])); break;                                              // Operate: Pow.
  }}

 snprintf(buf,TBASE_ARITH_BSIZE,"%f",c);                                                 // Copy result to buffer as float.
 AllenVM_InterpSetResult(i,buf);                                                         // Set interpreter result.
 return Allen_VM_OK;                                                                     // Everything ok.
}

// -------------------------------------------------------------------------------------------------------------------------------------
// Function:    AllenVM_CPU_BASE_ARITH_POW();
// Purpose:     Pow.
// Returns:     Expression result.
// -------------------------------------------------------------------------------------------------------------------------------------

static int AllenVM_CPU_BASE_ARITH_POW(struct AllenInterp *i, int argc, char **argv, void *pd) {
 char buf[TBASE_ARITH_BSIZE]; register int p,op; register float c=0;                     // Buffer and parameters.
 if(argc>=2) c=atof(argv[1]);                                                            // Conversion.
 for(op=6,p=2; p<argc; ++p) {                                                            // Loop through parameters.
 
  if(atof(argv[p])==0) {                                                                 // Check if we want to change.
   if(!strcmp(TBASE_ARITH_PLS,argv[p])) { op = 1; continue; }                            // Change operator: Addition.
   if(!strcmp(TBASE_ARITH_MIN,argv[p])) { op = 2; continue; }                            // Change operator: Substraction.
   if(!strcmp(TBASE_ARITH_MUL,argv[p])) { op = 3; continue; }                            // Change operator: Multiplication.
   if(!strcmp(TBASE_ARITH_DIV,argv[p])) { op = 4; continue; }                            // Change operator: Division.
   if(!strcmp(TBASE_ARITH_MOD,argv[p])) { op = 5; continue; }                            // Change operator: Modulus.
   if(!strcmp(TBASE_ARITH_POW,argv[p])) { op = 6; continue; }                            // Change operator: Pow.
  }

  switch(op) {                                                                           // Look current operator.
   case 1: c += atof(argv[p]); break;                                                    // Operate: Addition.
   case 2: c -= atof(argv[p]); break;                                                    // Operate: Substraction.
   case 3: c *= atof(argv[p]); break;                                                    // Operate: Multiplication.
   case 4: c /= atof(argv[p]); break;                                                    // Operate: Division.
   case 5: c = (int) c % atoi(argv[p]); break;                                           // Operate: Modulus.
   case 6: c = pow(c,atof(argv[p])); break;                                              // Operate: Pow.
  }}

 snprintf(buf,TBASE_ARITH_BSIZE,"%f",c);                                                 // Copy result to buffer as float.
 AllenVM_InterpSetResult(i,buf);                                                         // Set interpreter result.
 return Allen_VM_OK;                                                                     // Everything ok.
}

// -------------------------------------------------------------------------------------------------------------------------------------
// Function:    AllenVM_CPU_BASE_ARITH_ADD();
// Purpose:     Add instructions to the CPU.
// -------------------------------------------------------------------------------------------------------------------------------------
// Description: Register VM instructions for the interpreter.
// -------------------------------------------------------------------------------------------------------------------------------------

void AllenVM_CPU_BASE_ARITH_ADD(struct AllenInterp *i) {
 AllenVM_InterpSetCommand(i,TBASE_ARITH_PLS,   AllenVM_CPU_BASE_ARITH_PLS,    NULL);     // Addition.
 AllenVM_InterpSetCommand(i,TBASE_ARITH_DPLS,  AllenVM_CPU_BASE_ARITH_DPLS,   NULL);     // Increment.
 AllenVM_InterpSetCommand(i,TBASE_ARITH_MIN,   AllenVM_CPU_BASE_ARITH_MIN,    NULL);     // Substraction.
 AllenVM_InterpSetCommand(i,TBASE_ARITH_DMIN,  AllenVM_CPU_BASE_ARITH_DMIN,   NULL);     // Decrement.
 AllenVM_InterpSetCommand(i,TBASE_ARITH_MUL,   AllenVM_CPU_BASE_ARITH_MUL,    NULL);     // Multiplication.
 AllenVM_InterpSetCommand(i,TBASE_ARITH_DMUL,  AllenVM_CPU_BASE_ARITH_DMUL,   NULL);     // Square.
 AllenVM_InterpSetCommand(i,TBASE_ARITH_DIV,   AllenVM_CPU_BASE_ARITH_DIV,    NULL);     // Division.
 AllenVM_InterpSetCommand(i,TBASE_ARITH_DDIV,  AllenVM_CPU_BASE_ARITH_DDIV,   NULL);     // Division without floating point.
 AllenVM_InterpSetCommand(i,TBASE_ARITH_MOD,   AllenVM_CPU_BASE_ARITH_MOD,    NULL);     // Modulus.
 AllenVM_InterpSetCommand(i,TBASE_ARITH_POW,   AllenVM_CPU_BASE_ARITH_POW,    NULL);     // Pow.
}

// =====================================================================================================================================
// EOF
// =====================================================================================================================================
// Compiler parameters: Gcc -O2 -lm
// Recommended editor: Scite/Gedit/Vim.