mirror of https://github.com/cutefishos/calculator
				
				
				
			
			You cannot select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
	
	
		
			1111 lines
		
	
	
		
			32 KiB
		
	
	
	
		
			C++
		
	
			
		
		
	
	
			1111 lines
		
	
	
		
			32 KiB
		
	
	
	
		
			C++
		
	
/* Copyright (C) 2004-2006 Ariya Hidayat <ariya@kde.org>
 | 
						|
   2007 Helder Correia <helder.pereira.correia@gmail.com>
 | 
						|
 | 
						|
   This program is free software; you can redistribute it and/or
 | 
						|
   modify it under the terms of the GNU General Public License
 | 
						|
   as published by the Free Software Foundation; either version 2
 | 
						|
   of the License, or (at your option) any later version.
 | 
						|
 | 
						|
   This program is distributed in the hope that it will be useful,
 | 
						|
   but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
						|
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
						|
   GNU General Public License for more details.
 | 
						|
 | 
						|
   You should have received a copy of the GNU General Public License
 | 
						|
   along with this program; see the file COPYING.  If not, write to
 | 
						|
   the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
 | 
						|
   Boston, MA 02110-1301, USA.
 | 
						|
*/
 | 
						|
 | 
						|
#include "evaluator.h"
 | 
						|
#include "functions.h"
 | 
						|
#include "hmath.h"
 | 
						|
 | 
						|
#include <QCoreApplication>
 | 
						|
#include <QHash>
 | 
						|
#include <QObject>
 | 
						|
#include <QStringList>
 | 
						|
#include <QVector>
 | 
						|
 | 
						|
#include <float.h>
 | 
						|
#include <math.h>
 | 
						|
 | 
						|
#define qApp QCoreApplication::instance()
 | 
						|
 | 
						|
HNumber deg2rad( HNumber x )
 | 
						|
{
 | 
						|
    return x * HMath::pi() / HNumber(180);
 | 
						|
}
 | 
						|
 | 
						|
HNumber rad2deg( HNumber x )
 | 
						|
{
 | 
						|
    return HNumber(180) * x / HMath::pi();
 | 
						|
}
 | 
						|
 | 
						|
HNumber function_abs( const Evaluator*, Function*, const FunctionArguments& args )
 | 
						|
{
 | 
						|
    if( args.count() != 1 )
 | 
						|
        return HNumber::nan();
 | 
						|
 | 
						|
    HNumber num = args[0];
 | 
						|
    return HMath::abs( num );
 | 
						|
}
 | 
						|
 | 
						|
HNumber function_int( const Evaluator*, Function*, const FunctionArguments& args )
 | 
						|
{
 | 
						|
    if( args.count() != 1 )
 | 
						|
        return HNumber::nan();
 | 
						|
 | 
						|
    HNumber num = args[0];
 | 
						|
    return HMath::integer( num );
 | 
						|
}
 | 
						|
 | 
						|
HNumber function_trunc( const Evaluator         * evaluator,
 | 
						|
                        Function                * function,
 | 
						|
                        const FunctionArguments & arguments )
 | 
						|
{
 | 
						|
    int nArgs = arguments.count();
 | 
						|
 | 
						|
    if( nArgs != 1 && nArgs != 2 )
 | 
						|
    {
 | 
						|
        function->setError( function->name(), QString( "function requires 1 or 2 arguments" ) );
 | 
						|
        return HNumber::nan();
 | 
						|
    }
 | 
						|
 | 
						|
    HNumber num = arguments[0];
 | 
						|
    HNumber prec;
 | 
						|
    HNumber zero(0);
 | 
						|
    if( nArgs == 2)
 | 
						|
        prec = arguments[1];
 | 
						|
    else prec = zero;
 | 
						|
 | 
						|
    if( !prec.isInteger() )
 | 
						|
    {
 | 
						|
        function->setError( function->name(), QString( "function undefined for specified arguments" ) );
 | 
						|
        return HNumber::nan();
 | 
						|
    }
 | 
						|
 | 
						|
    HNumber limit(150);
 | 
						|
    if( prec > limit )
 | 
						|
        prec = limit;
 | 
						|
    else if( prec < zero )
 | 
						|
        prec = zero;
 | 
						|
 | 
						|
    if( nArgs == 1 )
 | 
						|
        return HMath::trunc( num );
 | 
						|
    else // nArgs == 2
 | 
						|
        return HMath::trunc( num, prec.toInt() );
 | 
						|
}
 | 
						|
 | 
						|
HNumber function_frac( const Evaluator         * evaluator,
 | 
						|
                       Function                * function,
 | 
						|
                       const FunctionArguments & arguments )
 | 
						|
{
 | 
						|
    if ( arguments.count() != 1 )
 | 
						|
        return HNumber::nan();
 | 
						|
 | 
						|
    HNumber x = arguments[0];
 | 
						|
    return HMath::frac( x );
 | 
						|
}
 | 
						|
 | 
						|
HNumber function_floor( const Evaluator*, Function*, const FunctionArguments& args )
 | 
						|
{
 | 
						|
    if( args.count() != 1 )
 | 
						|
        return HNumber::nan();
 | 
						|
 | 
						|
    HNumber num = args[0];
 | 
						|
    return HMath::floor( num );
 | 
						|
}
 | 
						|
 | 
						|
HNumber function_ceil( const Evaluator*, Function*, const FunctionArguments& args )
 | 
						|
{
 | 
						|
    if( args.count() != 1 )
 | 
						|
        return HNumber::nan();
 | 
						|
 | 
						|
    HNumber num = args[0];
 | 
						|
    return HMath::ceil( num );
 | 
						|
}
 | 
						|
 | 
						|
HNumber function_gcd( const Evaluator*, Function* fn, const FunctionArguments& args )
 | 
						|
{
 | 
						|
    int nArgs = args.count();
 | 
						|
 | 
						|
    if ( nArgs < 2 )
 | 
						|
    {
 | 
						|
        fn->setError( fn->name(), QString( "function requires at least 2 arguments" ) );
 | 
						|
        return HNumber::nan();
 | 
						|
    }
 | 
						|
 | 
						|
    for ( int i = 0; i < args.count(); i++ )
 | 
						|
        if ( !args[i].isInteger() )
 | 
						|
        {
 | 
						|
            fn->setError( fn->name(), QString( "function requires integer arguments" ) );
 | 
						|
            return HNumber::nan();
 | 
						|
        }
 | 
						|
 | 
						|
    HNumber result = HMath::gcd( args[0], args[1] );
 | 
						|
    for ( int i = 2; i < nArgs; i++ )
 | 
						|
    {
 | 
						|
        result = HMath::gcd( result, args[i] );
 | 
						|
    }
 | 
						|
    return result;
 | 
						|
}
 | 
						|
 | 
						|
HNumber function_round( const Evaluator*, Function* fn, const FunctionArguments& args )
 | 
						|
{
 | 
						|
    int nArgs = args.count();
 | 
						|
 | 
						|
    if( nArgs != 1 && nArgs != 2 )
 | 
						|
    {
 | 
						|
        fn->setError( fn->name(), QString( "function requires 1 or 2 arguments" ) );
 | 
						|
        return HNumber::nan();
 | 
						|
    }
 | 
						|
 | 
						|
    HNumber num = args[0];
 | 
						|
    HNumber prec;
 | 
						|
    HNumber zero(0);
 | 
						|
    if( nArgs == 2)
 | 
						|
        prec = args[1];
 | 
						|
    else
 | 
						|
        prec = zero;
 | 
						|
 | 
						|
    if( !prec.isInteger() )
 | 
						|
    {
 | 
						|
        fn->setError( fn->name(), QString( "function requires integer P2" ) );
 | 
						|
        return HNumber::nan();
 | 
						|
    }
 | 
						|
 | 
						|
    HNumber limit(150);
 | 
						|
    if( prec > limit )
 | 
						|
        prec = limit;
 | 
						|
    else if( prec < zero )
 | 
						|
        prec = zero;
 | 
						|
 | 
						|
    if( nArgs == 1 )
 | 
						|
        return HMath::round( num );
 | 
						|
    else // nArgs == 2
 | 
						|
        return HMath::round( num, prec.toInt() );
 | 
						|
}
 | 
						|
 | 
						|
HNumber function_sqrt( const Evaluator*, Function* fn, const FunctionArguments& args )
 | 
						|
{
 | 
						|
    if( args.count() != 1 )
 | 
						|
        return HNumber::nan();
 | 
						|
 | 
						|
    HNumber num = args[0];
 | 
						|
    if( num < HNumber(0) )
 | 
						|
    {
 | 
						|
        fn->setError( fn->name(), QString( "function undefined for specified argument" ) );
 | 
						|
        return HNumber::nan();
 | 
						|
    }
 | 
						|
 | 
						|
    return HMath::sqrt( num );
 | 
						|
}
 | 
						|
 | 
						|
HNumber function_cbrt( const Evaluator*, Function*, const FunctionArguments& args )
 | 
						|
{
 | 
						|
    if( args.count() != 1 )
 | 
						|
        return HNumber::nan();
 | 
						|
 | 
						|
    HNumber num = args[0];
 | 
						|
    return HMath::cbrt( num );
 | 
						|
}
 | 
						|
 | 
						|
HNumber function_exp( const Evaluator*, Function*, const FunctionArguments& args )
 | 
						|
{
 | 
						|
    if( args.count() != 1 )
 | 
						|
        return HNumber::nan();
 | 
						|
 | 
						|
    HNumber num = args[0];
 | 
						|
    return HMath::exp( num );
 | 
						|
}
 | 
						|
 | 
						|
HNumber function_ln( const Evaluator*, Function* fn, const FunctionArguments& args )
 | 
						|
{
 | 
						|
    if( args.count() != 1 )
 | 
						|
        return HNumber::nan();
 | 
						|
 | 
						|
    HNumber x = args[0];
 | 
						|
    HNumber result = HMath::ln( x );
 | 
						|
 | 
						|
    if( result.isNan() )
 | 
						|
        fn->setError( fn->name(), QString( "function undefined for specified argument" ) );
 | 
						|
 | 
						|
    return result;
 | 
						|
}
 | 
						|
 | 
						|
HNumber function_log( const Evaluator*, Function* fn, const FunctionArguments& args )
 | 
						|
{
 | 
						|
    if( args.count() != 1 )
 | 
						|
        return HNumber::nan();
 | 
						|
 | 
						|
    HNumber x = args[0];
 | 
						|
    HNumber result = HMath::log( x );
 | 
						|
 | 
						|
    if( result.isNan() )
 | 
						|
        fn->setError( fn->name(), QString( "function undefined for specified argument" ) );
 | 
						|
 | 
						|
    return result;
 | 
						|
}
 | 
						|
 | 
						|
HNumber function_lg( const Evaluator*, Function* fn, const FunctionArguments& args )
 | 
						|
{
 | 
						|
    if( args.count() != 1 )
 | 
						|
        return HNumber::nan();
 | 
						|
 | 
						|
    HNumber x = args[0];
 | 
						|
    HNumber result = HMath::lg( x );
 | 
						|
 | 
						|
    if( result.isNan() )
 | 
						|
        fn->setError( fn->name(), QString( "function undefined for specified argument" ) );
 | 
						|
 | 
						|
    return result;
 | 
						|
}
 | 
						|
 | 
						|
HNumber function_sin( const Evaluator* eval, Function*, const FunctionArguments& args )
 | 
						|
{
 | 
						|
    if( args.count() != 1 )
 | 
						|
        return HNumber::nan();
 | 
						|
 | 
						|
    HNumber angle = args[0];
 | 
						|
    if( eval->angleMode() == Evaluator::Degree )
 | 
						|
        angle = deg2rad( angle );
 | 
						|
 | 
						|
    return HMath::sin( angle );
 | 
						|
}
 | 
						|
 | 
						|
HNumber function_cos( const Evaluator* eval, Function*, const FunctionArguments& args )
 | 
						|
{
 | 
						|
    if( args.count() != 1 )
 | 
						|
        return HNumber::nan();
 | 
						|
 | 
						|
    HNumber angle = args[0];
 | 
						|
    if( eval->angleMode() == Evaluator::Degree )
 | 
						|
        angle = deg2rad( angle );
 | 
						|
 | 
						|
    return HMath::cos( angle );
 | 
						|
}
 | 
						|
 | 
						|
HNumber function_tan( const Evaluator* eval, Function* fn, const FunctionArguments& args )
 | 
						|
{
 | 
						|
    if( args.count() != 1 )
 | 
						|
        return HNumber::nan();
 | 
						|
 | 
						|
    HNumber angle = args[0];
 | 
						|
    if( eval->angleMode() == Evaluator::Degree )
 | 
						|
        angle = deg2rad( angle );
 | 
						|
 | 
						|
    HNumber result = HMath::tan( angle );
 | 
						|
    if ( result.isNan() )
 | 
						|
    {
 | 
						|
        fn->setError( fn->name(), QString( "function undefined for specified argument" ) );
 | 
						|
        return HNumber::nan();
 | 
						|
    }
 | 
						|
 | 
						|
    return result;
 | 
						|
}
 | 
						|
 | 
						|
HNumber function_cot( const Evaluator* eval, Function* fn, const FunctionArguments& args )
 | 
						|
{
 | 
						|
    if( args.count() != 1 )
 | 
						|
        return HNumber::nan();
 | 
						|
 | 
						|
    HNumber angle = args[0];
 | 
						|
    if( eval->angleMode() == Evaluator::Degree )
 | 
						|
        angle = deg2rad( angle );
 | 
						|
 | 
						|
    HNumber result = HMath::cot( angle );
 | 
						|
    if ( result.isNan() )
 | 
						|
    {
 | 
						|
        fn->setError( fn->name(), QString( "function undefined for specified argument" ) );
 | 
						|
        return HNumber::nan();
 | 
						|
    }
 | 
						|
 | 
						|
    return result;
 | 
						|
}
 | 
						|
 | 
						|
HNumber function_sec( const Evaluator* eval, Function* fn, const FunctionArguments& args )
 | 
						|
{
 | 
						|
    if( args.count() != 1 )
 | 
						|
        return HNumber::nan();
 | 
						|
 | 
						|
    HNumber angle = args[0];
 | 
						|
    if( eval->angleMode() == Evaluator::Degree )
 | 
						|
        angle = deg2rad( angle );
 | 
						|
 | 
						|
    HNumber result = HMath::sec( angle );
 | 
						|
    if ( result.isNan() )
 | 
						|
    {
 | 
						|
        fn->setError( fn->name(), QString( "function undefined for specified argument" ) );
 | 
						|
        return HNumber::nan();
 | 
						|
    }
 | 
						|
 | 
						|
    return result;
 | 
						|
}
 | 
						|
 | 
						|
HNumber function_csc( const Evaluator* eval, Function* fn, const FunctionArguments& args )
 | 
						|
{
 | 
						|
    if( args.count() != 1 )
 | 
						|
        return HNumber::nan();
 | 
						|
 | 
						|
    HNumber angle = args[0];
 | 
						|
    if( eval->angleMode() == Evaluator::Degree )
 | 
						|
        angle = deg2rad( angle );
 | 
						|
 | 
						|
    HNumber result = HMath::csc( angle );
 | 
						|
    if ( result.isNan() )
 | 
						|
    {
 | 
						|
        fn->setError( fn->name(), QString( "function undefined for specified argument" ) );
 | 
						|
        return HNumber::nan();
 | 
						|
    }
 | 
						|
 | 
						|
    return result;
 | 
						|
}
 | 
						|
 | 
						|
HNumber function_asin( const Evaluator         * evaluator,
 | 
						|
                       Function          * function,
 | 
						|
                       const FunctionArguments & arguments )
 | 
						|
{
 | 
						|
    if ( arguments.count() != 1 )
 | 
						|
        return HNumber::nan();
 | 
						|
 | 
						|
    HNumber x = arguments[0];
 | 
						|
 | 
						|
    HNumber result = HMath::asin( x );
 | 
						|
 | 
						|
    if ( result.isNan() )
 | 
						|
    {
 | 
						|
        function->setError( function->name(), QString( "function undefined for specified argument" ) );
 | 
						|
        return HNumber::nan();
 | 
						|
    }
 | 
						|
 | 
						|
    if ( evaluator->angleMode() == Evaluator::Degree )
 | 
						|
        result = rad2deg( result );
 | 
						|
 | 
						|
    return result;
 | 
						|
}
 | 
						|
 | 
						|
HNumber function_acos( const Evaluator         * evaluator,
 | 
						|
                       Function          * function,
 | 
						|
                       const FunctionArguments & arguments )
 | 
						|
{
 | 
						|
    if ( arguments.count() != 1 )
 | 
						|
        return HNumber::nan();
 | 
						|
 | 
						|
    HNumber x = arguments[0];
 | 
						|
 | 
						|
    HNumber result = HMath::acos( x );
 | 
						|
 | 
						|
    if ( result.isNan() )
 | 
						|
    {
 | 
						|
        function->setError( function->name(), QString( "function undefined for specified argument" ) );
 | 
						|
        return HNumber::nan();
 | 
						|
    }
 | 
						|
 | 
						|
    if ( evaluator->angleMode() == Evaluator::Degree )
 | 
						|
        result = rad2deg( result );
 | 
						|
 | 
						|
    return result;
 | 
						|
}
 | 
						|
 | 
						|
HNumber function_atan( const Evaluator* eval, Function*, const FunctionArguments& args )
 | 
						|
{
 | 
						|
    if( args.count() != 1 )
 | 
						|
        return HNumber::nan();
 | 
						|
 | 
						|
    HNumber num = args[0];
 | 
						|
    HNumber angle = HMath::atan( num );
 | 
						|
    if( eval->angleMode() == Evaluator::Degree )
 | 
						|
        angle = rad2deg( angle );
 | 
						|
 | 
						|
    return angle;
 | 
						|
}
 | 
						|
 | 
						|
HNumber function_sinh( const Evaluator* eval, Function*, const FunctionArguments& args )
 | 
						|
{
 | 
						|
    if( args.count() != 1 )
 | 
						|
        return HNumber::nan();
 | 
						|
 | 
						|
    HNumber angle = args[0];
 | 
						|
    if( eval->angleMode() == Evaluator::Degree )
 | 
						|
        angle = deg2rad( angle );
 | 
						|
    return HMath::sinh( angle );
 | 
						|
}
 | 
						|
 | 
						|
HNumber function_cosh( const Evaluator* eval, Function*, const FunctionArguments& args )
 | 
						|
{
 | 
						|
    if( args.count() != 1 )
 | 
						|
        return HNumber::nan();
 | 
						|
 | 
						|
    HNumber angle = args[0];
 | 
						|
    if( eval->angleMode() == Evaluator::Degree )
 | 
						|
        angle = deg2rad( angle );
 | 
						|
    return HMath::cosh( angle );
 | 
						|
}
 | 
						|
 | 
						|
HNumber function_tanh( const Evaluator* eval, Function*, const FunctionArguments& args )
 | 
						|
{
 | 
						|
    if( args.count() != 1 )
 | 
						|
        return HNumber::nan();
 | 
						|
 | 
						|
    HNumber angle = args[0];
 | 
						|
    if( eval->angleMode() == Evaluator::Degree )
 | 
						|
        angle = deg2rad( angle );
 | 
						|
    return HMath::tanh( angle );
 | 
						|
}
 | 
						|
 | 
						|
HNumber function_sign( const Evaluator*, Function*, const FunctionArguments& args )
 | 
						|
{
 | 
						|
    if( args.count() != 1 )
 | 
						|
        return HNumber::nan();
 | 
						|
    return HMath::sign( args[0] );
 | 
						|
}
 | 
						|
 | 
						|
HNumber function_nCr( const Evaluator         * evaluator,
 | 
						|
                      Function          * function,
 | 
						|
                      const FunctionArguments & arguments )
 | 
						|
{
 | 
						|
    // check number of arguments
 | 
						|
    if ( arguments.count() != 2 )
 | 
						|
        return HNumber::nan();
 | 
						|
 | 
						|
    // compute result
 | 
						|
    // n = arguments[0]
 | 
						|
    // r = arguments[1]
 | 
						|
    HNumber result = HMath::nCr( arguments[0], arguments[1] );
 | 
						|
 | 
						|
    // check invalid usage and set error accordingly
 | 
						|
    if ( result.isNan() )
 | 
						|
        function->setError( function->name(), QString( "function undefined for specified arguments" ) );
 | 
						|
 | 
						|
    return result;
 | 
						|
}
 | 
						|
 | 
						|
HNumber function_nPr( const Evaluator         * evaluator,
 | 
						|
                      Function          * function,
 | 
						|
                      const FunctionArguments & arguments )
 | 
						|
{
 | 
						|
    // check number of arguments
 | 
						|
    if ( arguments.count() != 2 )
 | 
						|
        return HNumber::nan();
 | 
						|
 | 
						|
    // compute result
 | 
						|
    // n = arguments[0]
 | 
						|
    // r = arguments[1]
 | 
						|
    HNumber result = HMath::nPr( arguments[0], arguments[1] );
 | 
						|
 | 
						|
    // check invalid usage and set error accordingly
 | 
						|
    if ( result.isNan() )
 | 
						|
        function->setError( function->name(), QString( "function undefined for specified arguments" ) );
 | 
						|
 | 
						|
    return result;
 | 
						|
}
 | 
						|
 | 
						|
HNumber function_degrees( const Evaluator*, Function*, const FunctionArguments& args )
 | 
						|
{
 | 
						|
    if ( args.count() != 1 )
 | 
						|
        return HNumber::nan();
 | 
						|
 | 
						|
    HNumber angle = args[0];
 | 
						|
    return angle * HNumber(180) / HMath::pi();
 | 
						|
}
 | 
						|
 | 
						|
HNumber function_radians( const Evaluator*, Function*, const FunctionArguments& args )
 | 
						|
{
 | 
						|
    if ( args.count() != 1 )
 | 
						|
        return HNumber::nan();
 | 
						|
 | 
						|
    HNumber angle = args[0];
 | 
						|
    return angle * HMath::pi() / HNumber(180);
 | 
						|
}
 | 
						|
 | 
						|
HNumber function_max( const Evaluator         * evaluator,
 | 
						|
                      Function                * function,
 | 
						|
                      const FunctionArguments & arguments )
 | 
						|
{
 | 
						|
    if ( arguments.count() < 1 )
 | 
						|
    {
 | 
						|
        function->setError( function->name(), QString( "function requires at least 1 argument" ) );
 | 
						|
        return HNumber::nan();
 | 
						|
    }
 | 
						|
 | 
						|
    int totalParams = arguments.count();
 | 
						|
    HNumber result = arguments[0];
 | 
						|
    if(totalParams > 1)
 | 
						|
        for ( int i = 1; i < totalParams; i++ )
 | 
						|
            result = HMath::max( result, arguments[i] );
 | 
						|
 | 
						|
    return result;
 | 
						|
}
 | 
						|
 | 
						|
HNumber function_min( const Evaluator         * evaluator,
 | 
						|
                      Function                * function,
 | 
						|
                      const FunctionArguments & arguments )
 | 
						|
{
 | 
						|
    if ( arguments.count() < 1 )
 | 
						|
    {
 | 
						|
        function->setError( function->name(), QString( "function requires at least 1 argument" ) );
 | 
						|
        return HNumber::nan();
 | 
						|
    }
 | 
						|
 | 
						|
    int totalParams = arguments.count();
 | 
						|
    HNumber result = arguments[0];
 | 
						|
    if(totalParams > 1)
 | 
						|
        for ( int i = 1; i < totalParams; i++ )
 | 
						|
            result = HMath::min( result, arguments[i] );
 | 
						|
 | 
						|
    return result;
 | 
						|
}
 | 
						|
 | 
						|
HNumber function_sum( const Evaluator*, Function*, const FunctionArguments& args )
 | 
						|
{
 | 
						|
    if( args.count() <= 0 )
 | 
						|
        return HNumber(0);
 | 
						|
 | 
						|
    HNumber result = args[0];
 | 
						|
    for( int c = 1; c < args.count(); c++ )
 | 
						|
        result = result + args[c];
 | 
						|
 | 
						|
    return result;
 | 
						|
}
 | 
						|
 | 
						|
HNumber function_product( const Evaluator*, Function*, const FunctionArguments& args )
 | 
						|
{
 | 
						|
    if( args.count() <= 0 )
 | 
						|
        return HNumber(0);
 | 
						|
 | 
						|
    HNumber result = args[0];
 | 
						|
    for( int c = 1; c < args.count(); c++ )
 | 
						|
        result = result * args[c];
 | 
						|
 | 
						|
    return result;
 | 
						|
}
 | 
						|
 | 
						|
HNumber function_average( const Evaluator*, Function*, const FunctionArguments& args )
 | 
						|
{
 | 
						|
    if( args.count() <= 0 )
 | 
						|
        return HNumber("NaN");
 | 
						|
 | 
						|
    HNumber result = args[0];
 | 
						|
    for( int c = 1; c < args.count(); c++ )
 | 
						|
        result = result + args[c];
 | 
						|
 | 
						|
    result = result / HNumber(args.count());
 | 
						|
 | 
						|
    return result;
 | 
						|
}
 | 
						|
 | 
						|
HNumber function_geomean( const Evaluator*, Function*, const FunctionArguments& args )
 | 
						|
{
 | 
						|
    if( args.count() <= 0 )
 | 
						|
        return HNumber("NaN");
 | 
						|
 | 
						|
    HNumber result = args[0];
 | 
						|
    for( int c = 1; c < args.count(); c++ )
 | 
						|
        result = result * args[c];
 | 
						|
 | 
						|
    result = result / HNumber(args.count());
 | 
						|
 | 
						|
    if( result <= HNumber(0))
 | 
						|
        return HNumber("NaN");
 | 
						|
 | 
						|
    return result;
 | 
						|
}
 | 
						|
 | 
						|
HNumber function_dec( const Evaluator*, Function*, const FunctionArguments& args )
 | 
						|
{
 | 
						|
    if( args.count() < 1 )
 | 
						|
        return HNumber("NaN");
 | 
						|
    HNumber result = args[0];
 | 
						|
    result.setFormat('g');
 | 
						|
    return result;
 | 
						|
}
 | 
						|
 | 
						|
HNumber function_hex( const Evaluator*, Function*, const FunctionArguments& args )
 | 
						|
{
 | 
						|
    if( args.count() < 1 )
 | 
						|
        return HNumber("NaN");
 | 
						|
    HNumber result = args[0];
 | 
						|
    result.setFormat('h');
 | 
						|
    return result;
 | 
						|
}
 | 
						|
 | 
						|
HNumber function_oct( const Evaluator*, Function*, const FunctionArguments& args )
 | 
						|
{
 | 
						|
    if( args.count() < 1 )
 | 
						|
        return HNumber("NaN");
 | 
						|
    HNumber result = args[0];
 | 
						|
    result.setFormat('o');
 | 
						|
    return result;
 | 
						|
}
 | 
						|
 | 
						|
HNumber function_bin( const Evaluator*, Function*, const FunctionArguments& args )
 | 
						|
{
 | 
						|
    if( args.count() < 1 )
 | 
						|
        return HNumber("NaN");
 | 
						|
    HNumber result = args[0];
 | 
						|
    result.setFormat('b');
 | 
						|
    return result;
 | 
						|
}
 | 
						|
 | 
						|
HNumber function_binompmf( const Evaluator         * evaluator,
 | 
						|
                           Function                * function,
 | 
						|
                           const FunctionArguments & arguments )
 | 
						|
{
 | 
						|
    if ( arguments.count() != 3 )
 | 
						|
        return HNumber::nan();
 | 
						|
 | 
						|
    HNumber k = arguments[0];
 | 
						|
    HNumber n = arguments[1];
 | 
						|
    HNumber p = arguments[2];
 | 
						|
    HNumber result = HMath::binomialPmf( k, n, p );
 | 
						|
 | 
						|
    if ( result.isNan() )
 | 
						|
        function->setError( function->name(), QString( "function undefined for specified arguments" ) );
 | 
						|
 | 
						|
    return result;
 | 
						|
}
 | 
						|
 | 
						|
HNumber function_binomcdf( const Evaluator         * evaluator,
 | 
						|
                           Function          * function,
 | 
						|
                           const FunctionArguments & arguments )
 | 
						|
{
 | 
						|
    if ( arguments.count() != 3 )
 | 
						|
        return HNumber::nan();
 | 
						|
 | 
						|
    HNumber k = arguments[0];
 | 
						|
    HNumber n = arguments[1];
 | 
						|
    HNumber p = arguments[2];
 | 
						|
    HNumber result = HMath::binomialCdf( k, n, p );
 | 
						|
 | 
						|
    if ( result.isNan() )
 | 
						|
        function->setError( function->name(), QString( "function undefined for specified arguments" ) );
 | 
						|
 | 
						|
    return result;
 | 
						|
}
 | 
						|
 | 
						|
HNumber function_binommean( const Evaluator         * evaluator,
 | 
						|
                            Function                * function,
 | 
						|
                            const FunctionArguments & arguments )
 | 
						|
{
 | 
						|
    if ( arguments.count() != 2 )
 | 
						|
        return HNumber::nan();
 | 
						|
 | 
						|
    HNumber n = arguments[0];
 | 
						|
    HNumber p = arguments[1];
 | 
						|
    HNumber result = HMath::binomialMean( n, p );
 | 
						|
 | 
						|
    if ( result.isNan() )
 | 
						|
        function->setError( function->name(), QString( "function undefined for specified arguments" ) );
 | 
						|
 | 
						|
    return result;
 | 
						|
}
 | 
						|
 | 
						|
HNumber function_binomvar( const Evaluator         * evaluator,
 | 
						|
                           Function                * function,
 | 
						|
                           const FunctionArguments & arguments )
 | 
						|
{
 | 
						|
    if ( arguments.count() != 2 )
 | 
						|
        return HNumber::nan();
 | 
						|
 | 
						|
    HNumber n = arguments[0];
 | 
						|
    HNumber p = arguments[1];
 | 
						|
    HNumber result = HMath::binomialVariance( n, p );
 | 
						|
 | 
						|
    if ( result.isNan() )
 | 
						|
        function->setError( function->name(), QString( "function undefined for specified arguments" ) );
 | 
						|
 | 
						|
    return result;
 | 
						|
}
 | 
						|
 | 
						|
HNumber function_hyperpmf( const Evaluator         * evaluator,
 | 
						|
                           Function                * function,
 | 
						|
                           const FunctionArguments & arguments )
 | 
						|
{
 | 
						|
    if ( arguments.count() != 4 )
 | 
						|
        return HNumber::nan();
 | 
						|
 | 
						|
    HNumber k = arguments[0];
 | 
						|
    HNumber N = arguments[1];
 | 
						|
    HNumber M = arguments[2];
 | 
						|
    HNumber n = arguments[3];
 | 
						|
    HNumber result = HMath::hypergeometricPmf( k, N, M, n );
 | 
						|
 | 
						|
    if ( result.isNan() )
 | 
						|
        function->setError( function->name(), QString( "function undefined for specified arguments" ) );
 | 
						|
 | 
						|
    return result;
 | 
						|
}
 | 
						|
 | 
						|
HNumber function_hypercdf( const Evaluator         * evaluator,
 | 
						|
                           Function                * function,
 | 
						|
                           const FunctionArguments & arguments )
 | 
						|
{
 | 
						|
    if ( arguments.count() != 4 )
 | 
						|
        return HNumber::nan();
 | 
						|
 | 
						|
    HNumber k = arguments[0];
 | 
						|
    HNumber N = arguments[1];
 | 
						|
    HNumber M = arguments[2];
 | 
						|
    HNumber n = arguments[3];
 | 
						|
    HNumber result = HMath::hypergeometricCdf( k, N, M, n );
 | 
						|
 | 
						|
    if ( result.isNan() )
 | 
						|
        function->setError( function->name(), QString( "function undefined for specified arguments" ) );
 | 
						|
 | 
						|
    return result;
 | 
						|
}
 | 
						|
 | 
						|
HNumber function_hypermean( const Evaluator         * evaluator,
 | 
						|
                            Function                * function,
 | 
						|
                            const FunctionArguments & arguments )
 | 
						|
{
 | 
						|
    if ( arguments.count() != 3 )
 | 
						|
        return HNumber::nan();
 | 
						|
 | 
						|
    HNumber N = arguments[0];
 | 
						|
    HNumber M = arguments[1];
 | 
						|
    HNumber n = arguments[2];
 | 
						|
    HNumber result = HMath::hypergeometricMean( N, M, n );
 | 
						|
 | 
						|
    if ( result.isNan() )
 | 
						|
        function->setError( function->name(), QString( "function undefined for specified arguments" ) );
 | 
						|
 | 
						|
    return result;
 | 
						|
}
 | 
						|
 | 
						|
HNumber function_hypervar( const Evaluator         * evaluator,
 | 
						|
                           Function                * function,
 | 
						|
                           const FunctionArguments & arguments )
 | 
						|
{
 | 
						|
    if ( arguments.count() != 3 )
 | 
						|
        return HNumber::nan();
 | 
						|
 | 
						|
    HNumber N = arguments[0];
 | 
						|
    HNumber M = arguments[1];
 | 
						|
    HNumber n = arguments[2];
 | 
						|
    HNumber result = HMath::hypergeometricVariance( N, M, n );
 | 
						|
 | 
						|
    if ( result.isNan() )
 | 
						|
        function->setError( function->name(), QString( "function undefined for specified arguments" ) );
 | 
						|
 | 
						|
    return result;
 | 
						|
}
 | 
						|
 | 
						|
HNumber function_poipmf( const Evaluator         * evaluator,
 | 
						|
                         Function                * function,
 | 
						|
                         const FunctionArguments & arguments )
 | 
						|
{
 | 
						|
    if ( arguments.count() != 2 )
 | 
						|
        return HNumber::nan();
 | 
						|
 | 
						|
    HNumber k = arguments[0];
 | 
						|
    HNumber l = arguments[1];
 | 
						|
    HNumber result = HMath::poissonPmf( k, l );
 | 
						|
 | 
						|
    if ( result.isNan() )
 | 
						|
        function->setError( function->name(), QString( "function undefined for specified arguments" ) );
 | 
						|
 | 
						|
    return result;
 | 
						|
}
 | 
						|
 | 
						|
HNumber function_poicdf( const Evaluator         * evaluator,
 | 
						|
                         Function                * function,
 | 
						|
                         const FunctionArguments & arguments )
 | 
						|
{
 | 
						|
    if ( arguments.count() != 2 )
 | 
						|
        return HNumber::nan();
 | 
						|
 | 
						|
    HNumber k = arguments[0];
 | 
						|
    HNumber l = arguments[1];
 | 
						|
    HNumber result = HMath::poissonCdf( k, l );
 | 
						|
 | 
						|
    if ( result.isNan() )
 | 
						|
        function->setError( function->name(), QString( "function undefined for specified arguments" ) );
 | 
						|
 | 
						|
    return result;
 | 
						|
}
 | 
						|
 | 
						|
HNumber function_poimean( const Evaluator         * evaluator,
 | 
						|
                          Function                * function,
 | 
						|
                          const FunctionArguments & arguments )
 | 
						|
{
 | 
						|
    if ( arguments.count() != 1 )
 | 
						|
        return HNumber::nan();
 | 
						|
 | 
						|
    HNumber l = arguments[0];
 | 
						|
    HNumber result = HMath::poissonMean( l );
 | 
						|
 | 
						|
    if ( result.isNan() )
 | 
						|
        function->setError( function->name(), QString( "function undefined for specified arguments" ) );
 | 
						|
 | 
						|
    return result;
 | 
						|
}
 | 
						|
 | 
						|
HNumber function_poivar( const Evaluator         * evaluator,
 | 
						|
                         Function                * function,
 | 
						|
                         const FunctionArguments & arguments )
 | 
						|
{
 | 
						|
    if ( arguments.count() != 1 )
 | 
						|
        return HNumber::nan();
 | 
						|
 | 
						|
    HNumber l = arguments[0];
 | 
						|
    HNumber result = HMath::poissonVariance( l );
 | 
						|
 | 
						|
    if ( result.isNan() )
 | 
						|
        function->setError( function->name(), QString( "function undefined for specified arguments" ) );
 | 
						|
 | 
						|
    return result;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
class FunctionPrivate
 | 
						|
{
 | 
						|
public:
 | 
						|
    QString name;
 | 
						|
    int argc;
 | 
						|
    QString desc;
 | 
						|
    QString error;
 | 
						|
    FunctionPtr ptr;
 | 
						|
 | 
						|
    FunctionPrivate(): name(), argc(0), desc(), error(), ptr(0) {}
 | 
						|
};
 | 
						|
 | 
						|
class FunctionRepositoryPrivate
 | 
						|
{
 | 
						|
public:
 | 
						|
    QHash<QString, Function*> functions;
 | 
						|
};
 | 
						|
 | 
						|
Function::Function( const QString& name, int argc, FunctionPtr ptr, const QString& desc ):
 | 
						|
    d( new FunctionPrivate )
 | 
						|
{
 | 
						|
    d->name = name;
 | 
						|
    d->argc = argc;
 | 
						|
    d->desc = QString( desc.toLatin1() );
 | 
						|
    d->ptr = ptr;
 | 
						|
}
 | 
						|
 | 
						|
Function::Function( const QString& name, FunctionPtr ptr, const QString& desc ):
 | 
						|
    d( new FunctionPrivate )
 | 
						|
{
 | 
						|
    d->name = name;
 | 
						|
    d->argc = -1;
 | 
						|
    d->desc = QString( desc.toLatin1() );
 | 
						|
    d->ptr = ptr;
 | 
						|
}
 | 
						|
 | 
						|
Function::~Function()
 | 
						|
{
 | 
						|
    delete d;
 | 
						|
}
 | 
						|
 | 
						|
QString Function::name() const
 | 
						|
{
 | 
						|
    return d->name;
 | 
						|
}
 | 
						|
 | 
						|
QString Function::description() const
 | 
						|
{
 | 
						|
    return d->desc;
 | 
						|
}
 | 
						|
 | 
						|
QString Function::error() const
 | 
						|
{
 | 
						|
    return d->error;
 | 
						|
}
 | 
						|
 | 
						|
void Function::setError( const QString& context, const QString& error )
 | 
						|
{
 | 
						|
    d->error = context + ": " + error;
 | 
						|
}
 | 
						|
 | 
						|
HNumber Function::exec( const Evaluator* eval, const FunctionArguments& args )
 | 
						|
{
 | 
						|
    d->error = QString();
 | 
						|
    if( !d->ptr )
 | 
						|
    {
 | 
						|
        setError( QString("error"), QString( QString( "cannot execute function %1") ).arg( name() ) );
 | 
						|
        return HNumber(0);
 | 
						|
    }
 | 
						|
 | 
						|
    if( d->argc >= 0 )
 | 
						|
        if( args.count() != d->argc )
 | 
						|
        {
 | 
						|
            if ( d->argc == 1 )
 | 
						|
                setError( d->name, QString( QString( "function accepts 1 argument" ) ) );
 | 
						|
            else
 | 
						|
                setError( d->name, QString( QString( "function accepts %1 arguments" ) ).arg( d->argc ) );
 | 
						|
            return HNumber(0);
 | 
						|
        }
 | 
						|
 | 
						|
    return (*d->ptr)( eval, this, args );
 | 
						|
}
 | 
						|
 | 
						|
FunctionRepository* FunctionRepository::s_self = 0;
 | 
						|
 | 
						|
FunctionRepository* FunctionRepository::self()
 | 
						|
{
 | 
						|
    if( !s_self )
 | 
						|
        s_self = new FunctionRepository();
 | 
						|
    return s_self;
 | 
						|
}
 | 
						|
 | 
						|
FunctionRepository::FunctionRepository()
 | 
						|
{
 | 
						|
    d = new FunctionRepositoryPrivate;
 | 
						|
 | 
						|
    /*
 | 
						|
      ANALYSIS
 | 
						|
    */
 | 
						|
    add( new Function( "abs",     1, function_abs,
 | 
						|
                       QString("Absolute Value")             ) );
 | 
						|
    add( new Function( "average",    function_average,
 | 
						|
                       QString("Average (Arithmetic Mean)")  ) );
 | 
						|
    add( new Function( "log",     1, function_log,
 | 
						|
                       QString("Base-10 Logarithm")          ) );
 | 
						|
    add( new Function( "lg",      1, function_lg,
 | 
						|
                       QString("Base-2 Logarithm")           ) );
 | 
						|
    add( new Function( "bin",        function_bin,
 | 
						|
                       QString("Binary Representation")      ) );
 | 
						|
    add( new Function( "ceil",    1, function_ceil,
 | 
						|
                       QString("Ceiling")                    ) );
 | 
						|
    add( new Function( "cbrt",    1, function_cbrt,
 | 
						|
                       QString("Cube Root")                  ) );
 | 
						|
    add( new Function( "dec",        function_dec,
 | 
						|
                       QString("Decimal Representation")     ) );
 | 
						|
    add( new Function( "exp",     1, function_exp,
 | 
						|
                       QString("Exponential")                ) );
 | 
						|
    add( new Function( "floor",   1, function_floor,
 | 
						|
                       QString("Floor")                      ) );
 | 
						|
    add( new Function( "frac",    1, function_frac,
 | 
						|
                       QString("Fractional Part")            ) );
 | 
						|
    add( new Function( "geomean",    function_geomean,
 | 
						|
                       QString("Geometric Mean")             ) );
 | 
						|
    add( new Function( "hex",        function_hex,
 | 
						|
                       QString("Hexadecimal Representation") ) );
 | 
						|
    add( new Function( "int",     1, function_int,
 | 
						|
                       QString("Integer Part")               ) );
 | 
						|
    add( new Function( "max",        function_max,
 | 
						|
                       QString("Maximum")                    ) );
 | 
						|
    add( new Function( "min",        function_min,
 | 
						|
                       QString("Minimum")                    ) );
 | 
						|
    add( new Function( "ln",      1, function_ln,
 | 
						|
                       QString("Natural Logarithm")          ) );
 | 
						|
    add( new Function( "oct",        function_oct,
 | 
						|
                       QString("Octal Representation")       ) );
 | 
						|
    add( new Function( "product",    function_product,
 | 
						|
                       QString("Product")                    ) );
 | 
						|
    add( new Function( "round",      function_round,
 | 
						|
                       QString("Rounding")                   ) );
 | 
						|
    add( new Function( "sign",    1, function_sign,
 | 
						|
                       QString("Signum")                     ) );
 | 
						|
    add( new Function( "sqrt",    1, function_sqrt,
 | 
						|
                       QString("Square Root")                ) );
 | 
						|
    add( new Function( "sum",        function_sum,
 | 
						|
                       QString("Sum")                        ) );
 | 
						|
    add( new Function( "trunc",      function_trunc,
 | 
						|
                       QString("Truncation")                 ) );
 | 
						|
    /*
 | 
						|
      DISCRETE
 | 
						|
    */
 | 
						|
    add( new Function( "gcd",     function_gcd,
 | 
						|
                       QString("Greatest Common Divisor")            ) );
 | 
						|
    add( new Function( "ncr",  2, function_nCr,
 | 
						|
                       QString("Combination (Binomial Coefficient)") ) );
 | 
						|
    add( new Function( "npr",  2, function_nPr,
 | 
						|
                       QString("Permutation (Arrangement)")          ) );
 | 
						|
    /*
 | 
						|
      PROBABILITY
 | 
						|
    */
 | 
						|
    add( new Function( "binompmf",  3, function_binompmf,
 | 
						|
                       QString("Binomial Probability Mass Function")        ));
 | 
						|
    add( new Function( "binomcdf",  3, function_binomcdf,
 | 
						|
                       QString("Binomial Cumulative Distribution Function") ));
 | 
						|
    add( new Function( "binommean", 2, function_binommean,
 | 
						|
                       QString("Binomial Distribution Mean")                ));
 | 
						|
    add( new Function( "binomvar",  2, function_binomvar,
 | 
						|
                       QString("Binomial Distribution Variance")            ));
 | 
						|
    add( new Function( "hyperpmf",  4, function_hyperpmf,
 | 
						|
                       QString("Hypergeometric Probability Mass Function")  ));
 | 
						|
    add( new Function( "hypercdf",  4, function_hypercdf,
 | 
						|
                       QString("Hypergeometric Cumulative Distribution Function")));
 | 
						|
    add( new Function( "hypermean", 3, function_hypermean,
 | 
						|
                       QString("Hypergeometric Distribution Mean")          ));
 | 
						|
    add( new Function( "hypervar",  3, function_hypervar,
 | 
						|
                       QString("Hypergeometric Distribution Variance")      ));
 | 
						|
    add( new Function( "poipmf",    2, function_poipmf,
 | 
						|
                       QString("Poissonian Probability Mass Function")      ));
 | 
						|
    add( new Function( "poicdf",    2, function_poicdf,
 | 
						|
                       QString("Poissonian Cumulative Distribution Function")));
 | 
						|
    add( new Function( "poimean",   1, function_poimean,
 | 
						|
                       QString("Poissonian Distribution Mean")              ));
 | 
						|
    add( new Function( "poivar",    1, function_poivar,
 | 
						|
                       QString("Poissonian Distribution Variance")          ));
 | 
						|
    /*
 | 
						|
      TRIGONOMETRY
 | 
						|
    */
 | 
						|
    add( new Function( "acos",    1, function_acos,
 | 
						|
                       QString("Arc Cosine")         ) );
 | 
						|
    add( new Function( "asin",    1, function_asin,
 | 
						|
                       QString("Arc Sine")           ) );
 | 
						|
    add( new Function( "atan",    1, function_atan,
 | 
						|
                       QString("Arc Tangent")        ) );
 | 
						|
    add( new Function( "csc",     1, function_csc,
 | 
						|
                       QString("Cosecant")           ) );
 | 
						|
    add( new Function( "cos",     1, function_cos,
 | 
						|
                       QString("Cosine")             ) );
 | 
						|
    add( new Function( "cot",     1, function_cot,
 | 
						|
                       QString("Cotangent")          ) );
 | 
						|
    add( new Function( "cosh",    1, function_cosh,
 | 
						|
                       QString("Hyperbolic Cosine")  ) );
 | 
						|
    add( new Function( "degrees", 1, function_degrees,
 | 
						|
                       QString("Degrees Of Arc")     ) );
 | 
						|
    add( new Function( "radians", 1, function_radians,
 | 
						|
                       QString("Radians")            ) );
 | 
						|
    add( new Function( "sinh",    1, function_sinh,
 | 
						|
                       QString("Hyperbolic Sine")    ) );
 | 
						|
    add( new Function( "tanh",    1, function_tanh,
 | 
						|
                       QString("Hyperbolic Tangent") ) );
 | 
						|
    add( new Function( "sec",     1, function_sec,
 | 
						|
                       QString("Secant")             ) );
 | 
						|
    add( new Function( "sin",     1, function_sin,
 | 
						|
                       QString("Sine")               ) );
 | 
						|
    add( new Function( "tan",     1, function_tan,
 | 
						|
                       QString("Tangent")            ) );
 | 
						|
}
 | 
						|
 | 
						|
FunctionRepository::~FunctionRepository()
 | 
						|
{
 | 
						|
    while( d->functions.size() > 0 )
 | 
						|
    {
 | 
						|
        delete d->functions[ 0 ];
 | 
						|
        d->functions.remove( 0 );
 | 
						|
    }
 | 
						|
 | 
						|
    delete d;
 | 
						|
}
 | 
						|
 | 
						|
void FunctionRepository::add( Function* function )
 | 
						|
{
 | 
						|
    if( !function ) return;
 | 
						|
    d->functions.insert( function->name().toUpper(), function );
 | 
						|
}
 | 
						|
 | 
						|
Function* FunctionRepository::function( const QString& name )
 | 
						|
{
 | 
						|
    return d->functions.value( name.toUpper() );
 | 
						|
}
 | 
						|
 | 
						|
QStringList FunctionRepository::functionNames() const
 | 
						|
{
 | 
						|
    QStringList result;
 | 
						|
    QHashIterator<QString, Function*> it( d->functions );
 | 
						|
    while( it.hasNext() )
 | 
						|
    {
 | 
						|
        it.next();
 | 
						|
        result.append( it.key().toLower() );
 | 
						|
    }
 | 
						|
    return result;
 | 
						|
}
 |