2016-02-11 22:54:43 +01:00
|
|
|
/** @file
|
|
|
|
|
*
|
|
|
|
|
* @par History
|
|
|
|
|
* - 2005/09/10 Shinigami: added mf_Root - calculates y Root of x as a Real
|
|
|
|
|
* - 2006/10/07 Shinigami: GCC 3.4.x fix - added "template<>" to TmplExecutorModule
|
|
|
|
|
* removed obsolete gcvt, used sprintf
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#include "mathmod.h"
|
2018-01-29 21:55:48 +01:00
|
|
|
#include <cmath>
|
|
|
|
|
#include <stdio.h>
|
|
|
|
|
|
2016-02-11 22:54:43 +01:00
|
|
|
#include "../../bscript/berror.h"
|
2018-01-29 21:55:48 +01:00
|
|
|
#include "../../bscript/bobject.h"
|
2016-12-20 23:53:32 +01:00
|
|
|
#include "../../bscript/impstr.h"
|
2016-02-11 22:54:43 +01:00
|
|
|
|
2019-11-10 22:04:08 +01:00
|
|
|
#include <module_defs/math.h>
|
2016-02-11 22:54:43 +01:00
|
|
|
|
2016-02-19 19:26:35 +01:00
|
|
|
namespace Pol
|
|
|
|
|
{
|
|
|
|
|
namespace Module
|
|
|
|
|
{
|
|
|
|
|
using namespace Bscript;
|
|
|
|
|
|
|
|
|
|
static double const_pi;
|
|
|
|
|
static double const_e;
|
|
|
|
|
|
|
|
|
|
class initer
|
|
|
|
|
{
|
|
|
|
|
public:
|
|
|
|
|
initer();
|
|
|
|
|
};
|
|
|
|
|
initer::initer()
|
|
|
|
|
{
|
|
|
|
|
const_pi = acos( double( -1 ) );
|
|
|
|
|
const_e = exp( double( 1 ) );
|
|
|
|
|
}
|
|
|
|
|
initer _initer;
|
|
|
|
|
|
2016-12-14 21:50:23 +01:00
|
|
|
MathExecutorModule::MathExecutorModule( Bscript::Executor& exec )
|
2020-02-08 09:21:35 +01:00
|
|
|
: Bscript::TmplExecutorModule<MathExecutorModule, Bscript::ExecutorModule>( exec )
|
2016-12-14 21:50:23 +01:00
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
2016-02-19 19:26:35 +01:00
|
|
|
Bscript::BObjectImp* MathExecutorModule::mf_Sin()
|
|
|
|
|
{
|
|
|
|
|
double x;
|
|
|
|
|
if ( getRealParam( 0, x ) )
|
|
|
|
|
{
|
|
|
|
|
return new Double( sin( x ) );
|
2016-02-11 22:54:43 +01:00
|
|
|
}
|
2016-02-19 19:26:35 +01:00
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
return new BError( "Invalid parameter type" );
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
Bscript::BObjectImp* MathExecutorModule::mf_Cos()
|
|
|
|
|
{
|
|
|
|
|
double x;
|
|
|
|
|
if ( getRealParam( 0, x ) )
|
|
|
|
|
{
|
|
|
|
|
return new Double( cos( x ) );
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
return new BError( "Invalid parameter type" );
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
Bscript::BObjectImp* MathExecutorModule::mf_Tan()
|
|
|
|
|
{
|
|
|
|
|
double x;
|
|
|
|
|
if ( getRealParam( 0, x ) )
|
|
|
|
|
{
|
|
|
|
|
return new Double( tan( x ) );
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
return new BError( "Invalid parameter type" );
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
Bscript::BObjectImp* MathExecutorModule::mf_ASin()
|
|
|
|
|
{
|
|
|
|
|
double x;
|
|
|
|
|
if ( getRealParam( 0, x ) )
|
|
|
|
|
{
|
|
|
|
|
return new Double( asin( x ) );
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
return new BError( "Invalid parameter type" );
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
Bscript::BObjectImp* MathExecutorModule::mf_ACos()
|
|
|
|
|
{
|
|
|
|
|
double x;
|
|
|
|
|
if ( getRealParam( 0, x ) )
|
|
|
|
|
{
|
|
|
|
|
return new Double( acos( x ) );
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
return new BError( "Invalid parameter type" );
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
Bscript::BObjectImp* MathExecutorModule::mf_ATan()
|
|
|
|
|
{
|
|
|
|
|
double x;
|
|
|
|
|
if ( getRealParam( 0, x ) )
|
|
|
|
|
{
|
|
|
|
|
return new Double( atan( x ) );
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
return new BError( "Invalid parameter type" );
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
math::Pow(x : number, y : number ) : real
|
|
|
|
|
Function: calculates x raised to the power of y
|
|
|
|
|
Returns: x^y as a Real
|
|
|
|
|
Parameters: x and y can be Reals or Integers
|
|
|
|
|
|
|
|
|
|
math::Pow(2,5) = 2^5 = 32
|
|
|
|
|
*/
|
|
|
|
|
Bscript::BObjectImp* MathExecutorModule::mf_Pow()
|
|
|
|
|
{
|
|
|
|
|
double x, y;
|
|
|
|
|
if ( getRealParam( 0, x ) && getRealParam( 1, y ) )
|
|
|
|
|
{
|
|
|
|
|
return new Double( pow( x, y ) );
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
return new BError( "Invalid parameter type" );
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
math::Sqrt( x : number ) : real
|
|
|
|
|
Returns: Square Root of x as a Real
|
|
|
|
|
*/
|
|
|
|
|
Bscript::BObjectImp* MathExecutorModule::mf_Sqrt()
|
|
|
|
|
{
|
|
|
|
|
double x;
|
|
|
|
|
if ( getRealParam( 0, x ) )
|
|
|
|
|
{
|
|
|
|
|
return new Double( sqrt( x ) );
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
return new BError( "Invalid parameter type" );
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
math::Root( x : number, y : number ) : real
|
|
|
|
|
Function: calculates y Root of x as a Real
|
|
|
|
|
*/
|
|
|
|
|
Bscript::BObjectImp* MathExecutorModule::mf_Root()
|
|
|
|
|
{
|
|
|
|
|
double x, y;
|
|
|
|
|
if ( getRealParam( 0, x ) && getRealParam( 1, y ) )
|
|
|
|
|
{
|
|
|
|
|
return new Bscript::Double( pow( x, 1.0 / y ) );
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
return new Bscript::BError( "Invalid parameter type" );
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Bscript::BObjectImp* MathExecutorModule::mf_Min()
|
|
|
|
|
{
|
|
|
|
|
Bscript::BObjectImp* impX = getParamImp( 0 );
|
|
|
|
|
Bscript::BObjectImp* impY = getParamImp( 1 );
|
|
|
|
|
if ( ( ( impX->isa( Bscript::BObjectImp::OTDouble ) ) ||
|
|
|
|
|
( impX->isa( Bscript::BObjectImp::OTLong ) ) ) &&
|
|
|
|
|
( ( impY->isa( Bscript::BObjectImp::OTDouble ) ) ||
|
|
|
|
|
( impY->isa( Bscript::BObjectImp::OTLong ) ) ) )
|
|
|
|
|
{
|
|
|
|
|
if ( *impX < *impY )
|
|
|
|
|
return impX->copy();
|
|
|
|
|
else
|
|
|
|
|
return impY->copy();
|
|
|
|
|
}
|
|
|
|
|
else if ( impX->isa( Bscript::BObjectImp::OTArray ) )
|
|
|
|
|
{
|
|
|
|
|
Bscript::ObjArray* value = static_cast<Bscript::ObjArray*>( impX );
|
|
|
|
|
if ( value->ref_arr.empty() )
|
|
|
|
|
return new Bscript::BError( "Array empty" );
|
|
|
|
|
|
2018-07-31 14:30:29 +02:00
|
|
|
Bscript::BObjectImp* compare = nullptr;
|
2016-02-19 19:26:35 +01:00
|
|
|
for ( std::vector<Bscript::BObjectRef>::iterator itr = value->ref_arr.begin();
|
|
|
|
|
itr != value->ref_arr.end(); ++itr )
|
2016-02-11 22:54:43 +01:00
|
|
|
{
|
2016-02-19 19:26:35 +01:00
|
|
|
if ( itr->get() )
|
|
|
|
|
{
|
|
|
|
|
Bscript::BObject* bo = ( itr->get() );
|
|
|
|
|
|
2018-07-31 14:30:29 +02:00
|
|
|
if ( bo == nullptr )
|
2016-02-19 19:26:35 +01:00
|
|
|
continue;
|
|
|
|
|
if ( ( bo->isa( Bscript::BObjectImp::OTDouble ) ) ||
|
|
|
|
|
( bo->isa( Bscript::BObjectImp::OTLong ) ) )
|
|
|
|
|
{
|
2018-07-31 14:30:29 +02:00
|
|
|
if ( compare == nullptr )
|
2016-02-19 19:26:35 +01:00
|
|
|
compare = bo->impptr();
|
|
|
|
|
else if ( *( bo->impptr() ) < *compare )
|
|
|
|
|
compare = bo->impptr();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2018-07-31 14:30:29 +02:00
|
|
|
if ( compare != nullptr )
|
2016-02-19 19:26:35 +01:00
|
|
|
return ( compare->copy() );
|
|
|
|
|
else
|
|
|
|
|
return new Bscript::BError( "No Integer/Double elements" );
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
return new Bscript::BError( "Invalid parameter type" );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Bscript::BObjectImp* MathExecutorModule::mf_Max()
|
|
|
|
|
{
|
|
|
|
|
Bscript::BObjectImp* impX = getParamImp( 0 );
|
|
|
|
|
Bscript::BObjectImp* impY = getParamImp( 1 );
|
|
|
|
|
if ( ( ( impX->isa( Bscript::BObjectImp::OTDouble ) ) ||
|
|
|
|
|
( impX->isa( Bscript::BObjectImp::OTLong ) ) ) &&
|
|
|
|
|
( ( impY->isa( Bscript::BObjectImp::OTDouble ) ) ||
|
|
|
|
|
( impY->isa( Bscript::BObjectImp::OTLong ) ) ) )
|
|
|
|
|
{
|
|
|
|
|
if ( *impX < *impY )
|
|
|
|
|
return impY->copy();
|
|
|
|
|
else
|
|
|
|
|
return impX->copy();
|
|
|
|
|
}
|
|
|
|
|
else if ( impX->isa( Bscript::BObjectImp::OTArray ) )
|
|
|
|
|
{
|
|
|
|
|
Bscript::ObjArray* value = static_cast<Bscript::ObjArray*>( impX );
|
|
|
|
|
if ( value->ref_arr.empty() )
|
|
|
|
|
return new Bscript::BError( "Array empty" );
|
|
|
|
|
|
2018-07-31 14:30:29 +02:00
|
|
|
Bscript::BObjectImp* compare = nullptr;
|
2016-02-19 19:26:35 +01:00
|
|
|
for ( std::vector<BObjectRef>::iterator itr = value->ref_arr.begin();
|
|
|
|
|
itr != value->ref_arr.end(); ++itr )
|
2016-02-11 22:54:43 +01:00
|
|
|
{
|
2016-02-19 19:26:35 +01:00
|
|
|
if ( itr->get() )
|
|
|
|
|
{
|
|
|
|
|
Bscript::BObject* bo = ( itr->get() );
|
|
|
|
|
|
2018-07-31 14:30:29 +02:00
|
|
|
if ( bo == nullptr )
|
2016-02-19 19:26:35 +01:00
|
|
|
continue;
|
|
|
|
|
if ( ( bo->isa( Bscript::BObjectImp::OTDouble ) ) ||
|
|
|
|
|
( bo->isa( Bscript::BObjectImp::OTLong ) ) )
|
|
|
|
|
{
|
2018-07-31 14:30:29 +02:00
|
|
|
if ( compare == nullptr )
|
2016-02-19 19:26:35 +01:00
|
|
|
compare = bo->impptr();
|
|
|
|
|
else if ( *( bo->impptr() ) >= *compare )
|
|
|
|
|
compare = bo->impptr();
|
|
|
|
|
}
|
|
|
|
|
}
|
2016-02-11 22:54:43 +01:00
|
|
|
}
|
2018-07-31 14:30:29 +02:00
|
|
|
if ( compare != nullptr )
|
2016-02-19 19:26:35 +01:00
|
|
|
return ( compare->copy() );
|
|
|
|
|
else
|
|
|
|
|
return new Bscript::BError( "No Integer/Double elements" );
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
return new Bscript::BError( "Invalid parameter type" );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
math::Abs( x : number) : number
|
|
|
|
|
Returns: the absolute value of x
|
|
|
|
|
If a Real is passed, will return a Real
|
|
|
|
|
If an Integer is passed, will return an Integer
|
|
|
|
|
|
|
|
|
|
math::Abs(-2) = 2
|
|
|
|
|
math::Abs(-1.5) = 1.5
|
|
|
|
|
*/
|
|
|
|
|
Bscript::BObjectImp* MathExecutorModule::mf_Abs()
|
|
|
|
|
{
|
|
|
|
|
Bscript::BObjectImp* imp = getParamImp( 0 );
|
|
|
|
|
if ( imp->isa( Bscript::BObjectImp::OTDouble ) )
|
|
|
|
|
{
|
|
|
|
|
double value = static_cast<Double*>( imp )->value();
|
|
|
|
|
return new Double( fabs( value ) );
|
|
|
|
|
}
|
|
|
|
|
else if ( imp->isa( Bscript::BObjectImp::OTLong ) )
|
|
|
|
|
{
|
|
|
|
|
int value = static_cast<BLong*>( imp )->value();
|
|
|
|
|
return new BLong( labs( value ) );
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
double x;
|
|
|
|
|
// just for debug.log
|
|
|
|
|
(void)getRealParam( 0, x );
|
|
|
|
|
return new BError( "Invalid parameter type" );
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Bscript::BObjectImp* MathExecutorModule::mf_Log10()
|
|
|
|
|
{
|
|
|
|
|
double x;
|
|
|
|
|
if ( getRealParam( 0, x ) )
|
|
|
|
|
{
|
|
|
|
|
return new Double( log10( x ) );
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
return new BError( "Invalid parameter type" );
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
Bscript::BObjectImp* MathExecutorModule::mf_LogE()
|
|
|
|
|
{
|
|
|
|
|
double x;
|
|
|
|
|
if ( getRealParam( 0, x ) )
|
|
|
|
|
{
|
|
|
|
|
return new Double( log( x ) );
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
return new BError( "Invalid parameter type" );
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Bscript::BObjectImp* MathExecutorModule::mf_ConstPi()
|
|
|
|
|
{
|
|
|
|
|
return new Double( const_pi );
|
|
|
|
|
}
|
|
|
|
|
Bscript::BObjectImp* MathExecutorModule::mf_ConstE()
|
|
|
|
|
{
|
|
|
|
|
return new Double( const_e );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Bscript::BObjectImp* MathExecutorModule::mf_FormatRealToString()
|
|
|
|
|
{
|
|
|
|
|
double x;
|
|
|
|
|
int digits;
|
|
|
|
|
if ( getRealParam( 0, x ) && getParam( 1, digits ) )
|
|
|
|
|
{
|
|
|
|
|
char buffer[200];
|
|
|
|
|
/// @todo: sprintf produces different output on some doubles (eg. M_PI)
|
|
|
|
|
/// on Windows/Linux. Use something else? 2016-01-23 Bodom
|
2018-10-30 21:42:27 +01:00
|
|
|
/// Turley: as of now 2018-10-30 vs2017 on appveyor and travis show no difference with 64bit. Is
|
|
|
|
|
/// it just a difference between 64bit and 32bit?
|
2016-02-19 19:26:35 +01:00
|
|
|
sprintf( buffer, "%.*g", static_cast<int>( digits ), x );
|
|
|
|
|
return new String( buffer );
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
return new BError( "Invalid parameter type" );
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Bscript::BObjectImp* MathExecutorModule::mf_RadToDeg()
|
|
|
|
|
{
|
|
|
|
|
double rad;
|
|
|
|
|
if ( !getRealParam( 0, rad ) )
|
|
|
|
|
return new BError( "Invalid parameter type" );
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
360 degrees <~> 2*pi radians
|
|
|
|
|
<=> deg/360 = rad / 2*pi
|
|
|
|
|
<=> deg = 360*rad / 2*pi
|
|
|
|
|
<=> deg = 180*rad / pi
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
return new Double( ( rad * 180.0 ) / const_pi );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Bscript::BObjectImp* MathExecutorModule::mf_DegToRad()
|
|
|
|
|
{
|
|
|
|
|
double deg;
|
|
|
|
|
if ( !getRealParam( 0, deg ) )
|
|
|
|
|
return new BError( "Invalid parameter type" );
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
2*pi radians <~> 360 degrees
|
|
|
|
|
<=> rad / 2*pi = deg / 360
|
|
|
|
|
<=> rad = 2*pi*deg / 360
|
|
|
|
|
<=> rad = deg * pi / 180
|
|
|
|
|
*/
|
|
|
|
|
return new Double( ( deg * const_pi ) / 180.0 );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Bscript::BObjectImp* MathExecutorModule::mf_Ceil()
|
|
|
|
|
{
|
|
|
|
|
double x;
|
|
|
|
|
if ( getRealParam( 0, x ) )
|
|
|
|
|
{
|
|
|
|
|
return new Double( ceil( x ) );
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
return new BError( "Invalid parameter type" );
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
Bscript::BObjectImp* MathExecutorModule::mf_Floor()
|
|
|
|
|
{
|
|
|
|
|
double x;
|
|
|
|
|
if ( getRealParam( 0, x ) )
|
|
|
|
|
{
|
|
|
|
|
return new Double( floor( x ) );
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
return new BError( "Invalid parameter type" );
|
2016-02-11 22:54:43 +01:00
|
|
|
}
|
2016-02-19 19:26:35 +01:00
|
|
|
}
|
2018-10-30 21:42:27 +01:00
|
|
|
} // namespace Module
|
|
|
|
|
} // namespace Pol
|