simple examples of how to

Showing posts with label source code. Show all posts
Showing posts with label source code. Show all posts

Thursday, October 20, 2011

[C++] Linear Regression Source Code

here it goes.

class LinearRegression
{
        public:
                // Constructor using an array of Point2D objects
                // This is also the default constructor
                LinearRegression(Point2D *p = 0, long size = 0);

                // Constructor using arrays of x values and y values
                LinearRegression(double *x, double *y, long size = 0);

                virtual void addXY(const double& x, const double& y);
                void clear() { sumX = sumY = sumXsquared = sumYsquared = sumXY = n = 0; }
                void addPoint(const Point2D& p) { addXY(p.getX(), p.getY()); }

                // Must have at least 3 points to calculate
                // standard error of estimate. Do we have enough data?
                int haveData() const { return (n > 2 ? 1 : 0); }
                long items() const { return n; }

                virtual double getA() const { return a; }
                virtual double getB() const { return b; }

                double getCoefDeterm() const { return coefD; }
                double getCoefCorrel() const { return coefC; }
                double getStdErrorEst() const { return stdError; }
                virtual double estimateY(double x) const { return (a + b * x); }

        protected:
                long n;       // number of data points input so far
                double sumX, sumY; // sums of x and y
                double sumXsquared, // sum of x squares
                    sumYsquared; // sum y squares
                double sumXY;    // sum of x*y

                double a, b;    // coefficients of f(x) = a + b*x
                double coefD,    // coefficient of determination
                    coefC,    // coefficient of correlation
                    stdError;  // standard error of estimate

                void Calculate();  // calculate coefficients
};

LinearRegression::LinearRegression(Point2D *p, long size)
{
  long i;
  a = b = sumX = sumY = sumXsquared = sumYsquared = sumXY = 0.0;
  n = 0L;

  if (size > 0L) // if size greater than zero there are data arrays
    for (n = 0, i = 0L; i < size; i++)
      addPoint(p[i]);
}

LinearRegression::LinearRegression(double *x, double *y, long size)
{
  long i;
  a = b = sumX = sumY = sumXsquared = sumYsquared = sumXY = 0.0;
  n = 0L;

  if (size > 0L) // if size greater than zero there are data arrays
    for (n = 0, i = 0L; i < size; i++)
      addXY(x[i], y[i]);
}

void LinearRegression::addXY(const double& x, const double& y)
{
  n++;
  sumX += x;
  sumY += y;
  sumXsquared += x * x;
  sumYsquared += y * y;
  sumXY += x * y;
  Calculate();
}

void LinearRegression::Calculate()
{
  if (haveData())
  {
    if (fabs( double(n) * sumXsquared - sumX * sumX) > DBL_EPSILON)
    {
      b = ( double(n) * sumXY - sumY * sumX) /
        ( double(n) * sumXsquared - sumX * sumX);
      a = (sumY - b * sumX) / double(n);

      double sx = b * ( sumXY - sumX * sumY / double(n) );
      double sy2 = sumYsquared - sumY * sumY / double(n);
      double sy = sy2 - sx;

      coefD = sx / sy2;
      coefC = sqrt(coefD);
      stdError = sqrt(sy / double(n - 2));
    }
    else
    {
      a = b = coefD = coefC = stdError = 0.0;
    }
  }
}

[C++] Post-fix Calculator Source Code (String-calculator)

Here goes the c++ source code of post-fix calculator, which appears a lot in data structure class.

here it goes

#include stdio.h>
#include stdlib.h>
#include string.h>
#include ctype.h>


#define T_EOL                ';'
#define T_CONST                'C'
#define T_SYMBOL        'S'
#define T_LPAR                '('
#define T_RPAR                ')'
#define T_COMMA                ','
#define T_ASSIGN        '='
#define T_POINT                '$'
#define T_MUL                '*'
#define T_DIV                '/'
#define T_MOD                '%'
#define T_ADD                '+'
#define T_SUB                '-'
#define T_NEG                '_'
#define T_NOT                '~'
#define T_SHL                'L'
#define T_SHR                'R'
#define T_AND                '&'

class StringCalculator {
        // I don't know why defining another class makes all messages of redefinitions...,
        // just put postfix calcualtor here
public:
        StringCalculator();        
        double push_eval( double val );
        double push( double val );
        double pop_eval();
        double pop();
        char getoken(int* v = NULL);
        int isbinop( char** cpp );
        int expression();
        double evaluate();
        int primary();
        int binop( char op );
        int op_prim( int precedence, int lvalue );
        void generate( char tkn, double val, int index=-1 );
        double calc( char* line );
        void setup_symbol(int index, double value);
#define STAKSZ 128
        struct OPSTK {
                char o_token;
                double o_value;
                int symbol_index;
        } Opstk[ STAKSZ ];
        int Opbase;
        int Opsp;

        double Valstk[ STAKSZ ];
        int Valbase;
        int Valsp;

        double Valstk_eval[ STAKSZ ];
        int Valbase_eval;
        int Valsp_eval;

        double Symbols[26];
        double Value;

        char buff[128];

#define MAXLEVEL 32
        char Level; /* current recursion level in calc() */
        char Token; /* current input token */
        char Eol; /* set when end of line encountered */
        char *Lineptr; /* points to next character in input line */
        char *Ofmt; /* current output format (set by "base" command) */
        int Error; /* set if parsing error occurred */
        char Nohelp; /* set if help was given already */

        int symbol_index;
};



StringCalculator::StringCalculator()
{
    Nohelp = 1;
    Level = 0;
    Token = 0;
    Eol = 0;
    Lineptr = NULL;
    Ofmt = NULL;
    Error = 0;
    Nohelp = 0;
    Opbase=0;
    Opsp=0;
    Valbase=0;
    Valsp=0;

    push( 10 );
        for( int i=0; i<26; i++ )
        {
                Symbols[i]=0;
        }

}

void StringCalculator::setup_symbol(int index, double value)
{
        Symbols[index] = value;
}


double StringCalculator::calc( char* line )
{
        char *savLineptr;
        int savValbase, savValsp, savOpbase, savOpsp;

        /* save in my buff */
        strncpy(buff, line, 128);
        line = buff;


        if ( ++Level > MAXLEVEL )
        {
                printf("recursion\n");
        }
        else
        {
                savLineptr = Lineptr;
                savValbase = Valbase;
                savValsp = Valsp;
                savOpbase = Opbase;
                savOpsp = Opsp;

                Valbase = Valsp;
                Opbase = Opsp;
                Lineptr = line;

                Eol = 0;

                if ( getoken() != T_EOL )
                {
                        expression();
                        if ( Error <= 0 )
                        {
                        }
                        else {
                                printf("parse error: %s\n", buff);
                        }
                }
        }
        return 0.0;
}

double StringCalculator::evaluate()
{
    int opsp;
    double val;
    char op;
    Valsp_eval = Valsp;
    Valbase_eval = Valbase;
    memcpy(Valstk_eval, Valstk, sizeof(Valstk));
#define TOS (Valstk_eval[Valsp_eval-1]) /* top of stack macro */

    for ( opsp=Opbase; opsp    {
        op = Opstk[ opsp ].o_token;

        if ( op == T_CONST )
                {
            push_eval( Opstk[ opsp ].o_value );
                }
        else if ( op == T_SYMBOL )
                {
            push_eval( Symbols[Opstk[ opsp ].symbol_index] );
                }
        else if ( op == T_ADD )
        {
            val = pop_eval();
            TOS += val;
        }
        else if ( op == T_SUB )
        {
            val = pop_eval();
            TOS -= val;
        }
        else if ( op == T_NEG )
            TOS = -TOS;
        else if ( op == T_MUL )
        {
            val = pop_eval();
            TOS *= val;
        }
        else if ( op == T_DIV )
        {
            val = pop_eval();
            TOS /= val;
        }
        else
            printf( "bad operator in stack: 0x%x (%c)\n", op, op );
    }
    return Valstk_eval[ Valbase_eval ];
}

double StringCalculator::push( double val )
{
        if ( Valsp >= STAKSZ )
                printf( "stack overflow" );
        return Valstk[ Valsp++ ] = val;
}

double StringCalculator::pop()
{
        if ( --Valsp < 0 )
                Valsp = 0;
        return Valstk[ Valsp ];
}

double StringCalculator::push_eval( double val )
{
        if ( Valsp_eval >= STAKSZ )
                printf( "stack overflow" );
        return Valstk_eval[ Valsp_eval++ ] = val;
}

double StringCalculator::pop_eval()
{
        if ( --Valsp_eval < 0 )
                Valsp_eval = 0;
        return Valstk_eval[ Valsp_eval ];
}
int StringCalculator::expression()
{
        int lvalue;
        if ( !(lvalue = primary()) )
        {
                printf( "bad expression" );
        }
        else if ( Eol )
        {
                if ( lvalue < 0 )
                        generate( T_POINT, 0 );
        }
        else
        {
                op_prim( 0, lvalue );
        }
        return 1;
}

int StringCalculator::op_prim( int precedence, int lvalue )
{
        char tkn;
        int pr, lv;

        while ( ! Eol )
        {

                pr = binop( Token );

                if (
                        (pr>precedence && pr>0) ||
                        (Token==T_ASSIGN && pr>=precedence)
                )
                {
                        if ( Token == T_ASSIGN )
                        {
                                if ( lvalue > 0 )
                                        printf( "= needs and lvalue" );
                        }
                        else if ( lvalue < 0 )
                                generate( T_POINT, 0 );
                        tkn = Token;
                        getoken();
                        if ( ! (lv = primary()) )
                                printf( "missing an operand" );
                        lvalue = op_prim( pr, lv );

                        if ( Token != T_ASSIGN && lvalue < 0 )
                        {
                                generate( T_POINT, 0 );
                                lvalue = 1;
                        }
                        else if ( tkn!=T_ASSIGN && Token==T_ASSIGN )
                        {
                                printf( "= needs an lvalue" );
                        }

                        generate( tkn, 0 );
                }
                else
                        break;
        }

        return lvalue;
}

int StringCalculator::primary()
{
        int rtn;

        if ( Eol )
                return 0;

        rtn = 1;

        switch ( Token )
        {
        case T_SYMBOL:        /* a symbol */
                generate( Token, Value, symbol_index );
                getoken();
                break;
        case T_CONST:        /* a constant */
                generate( Token, Value );
                getoken();
                break;
        case T_LPAR:        /* a parenthesized expression */
                getoken();
                expression();
                if ( Token != T_RPAR )
                {
                        printf( "missing ')'" );
                        rtn = 0;
                }
                else
                        getoken();
                break;
        case T_SUB:        /* unary - */
                getoken();
                expression();
                generate( T_NEG, 0 );
                break;
        case T_NOT:        /* unary ~ */
                getoken();
                expression();
                generate( T_NOT, 0 );
                break;
        case T_ADD:        /* unary + */
                getoken();
                expression();
                break;
        default:
                rtn = 0;
        }
        return rtn;
}

int StringCalculator::binop( char op )
{
        switch ( op )
        {
        case T_ADD:
        case T_SUB:
                return 7;
        case T_MUL:
        case T_DIV:
        case T_MOD:
                return 8;
        case T_NOT:
                return 9;
        }
        return 0;
}

void StringCalculator::generate( char tkn, double val, int index )
{
        if ( Opsp < STAKSZ )
        {
                Opstk[ Opsp ].o_token = tkn;
                Opstk[ Opsp ].o_value = val;
                Opstk[ Opsp ].symbol_index = index;
                ++Opsp;
        }
        else
                printf( "expression too complex" );
}
char StringCalculator::getoken(int* )
{
        char *cp, buf[ 128 ];

        if ( ! *Lineptr )
        {
                Eol = 1;
                Token = T_EOL;
        }
        else if ( isdigit( *Lineptr ) )
        {
                Token = T_CONST;
                for ( cp = buf; isdigit( *Lineptr ) || *Lineptr == '.'; )
                        *cp++ = *Lineptr++;
                *cp = 0;
                Value = atof(buf);
        }
        else if ( (Token = isbinop( &Lineptr )) )
        {
                ;
        }
        else if ( isalpha( *Lineptr ) )
        {
        Token = T_SYMBOL;
        symbol_index = toupper( *Lineptr ) - 'A';
        ++Lineptr;
        }
        else
        {
                printf( "bad syntax: %s", Lineptr );
                ++Lineptr;
        }


        return Token;
}

int StringCalculator::isbinop( char** cpp )
{
        int tkn=1;
        char c;

        c = **cpp;
        if ( c == ',' )
                tkn = T_COMMA;
        else if ( c == '=' )
                tkn = T_ASSIGN;
        else if ( c == '<' )
        {
                if ( *(++(*cpp)) == '<' )
                        tkn = T_SHL;
        }
        else if ( c == '>' )
        {
                if ( *(++(*cpp)) == '>' )
                        tkn = T_SHR;
        }
        else if ( c == '(' )
                tkn = T_LPAR;
        else if ( c == ')' )
                tkn = T_RPAR;
        else if ( c == '*' )
                tkn = T_MUL;
        else if ( c == '/' )
                tkn = T_DIV;
        else if ( c == '+' )
                tkn = T_ADD;
        else if ( c == '-' )
                tkn = T_SUB;
        else
                tkn = 0;

        if ( tkn )
                ++(*cpp);

        return tkn;
}