mirror of
https://github.com/fish-shell/fish-shell.git
synced 2026-06-02 22:21:15 -03:00
[muparser] Remove cmFUNC_BULK
fish does not need bulk functions, which are used to enable parallel computations.
This commit is contained in:
@@ -99,7 +99,6 @@ class ParserBase {
|
||||
|
||||
value_type Eval() const;
|
||||
value_type *Eval(int &nStackSize) const;
|
||||
void Eval(value_type *results, int nBulkSize);
|
||||
|
||||
int GetNumResults() const;
|
||||
|
||||
|
||||
@@ -111,7 +111,6 @@ class ParserByteCode {
|
||||
void AddIfElse(ECmdCode a_Oprt);
|
||||
void AddAssignOp(value_type *a_pVar);
|
||||
void AddFun(generic_fun_type a_pFun, int a_iArgc);
|
||||
void AddBulkFun(generic_fun_type a_pFun, int a_iArgc);
|
||||
void AddStrFun(generic_fun_type a_pFun, int a_iArgc, int a_iIdx);
|
||||
|
||||
void EnableOptimizer(bool bStat);
|
||||
|
||||
@@ -63,18 +63,6 @@ class ParserCallback {
|
||||
ParserCallback(fun_type9 a_pFun, bool a_bAllowOpti);
|
||||
ParserCallback(fun_type10 a_pFun, bool a_bAllowOpti);
|
||||
|
||||
ParserCallback(bulkfun_type0 a_pFun, bool a_bAllowOpti);
|
||||
ParserCallback(bulkfun_type1 a_pFun, bool a_bAllowOpti);
|
||||
ParserCallback(bulkfun_type2 a_pFun, bool a_bAllowOpti);
|
||||
ParserCallback(bulkfun_type3 a_pFun, bool a_bAllowOpti);
|
||||
ParserCallback(bulkfun_type4 a_pFun, bool a_bAllowOpti);
|
||||
ParserCallback(bulkfun_type5 a_pFun, bool a_bAllowOpti);
|
||||
ParserCallback(bulkfun_type6 a_pFun, bool a_bAllowOpti);
|
||||
ParserCallback(bulkfun_type7 a_pFun, bool a_bAllowOpti);
|
||||
ParserCallback(bulkfun_type8 a_pFun, bool a_bAllowOpti);
|
||||
ParserCallback(bulkfun_type9 a_pFun, bool a_bAllowOpti);
|
||||
ParserCallback(bulkfun_type10 a_pFun, bool a_bAllowOpti);
|
||||
|
||||
ParserCallback(multfun_type a_pFun, bool a_bAllowOpti);
|
||||
ParserCallback(strfun_type1 a_pFun, bool a_bAllowOpti);
|
||||
ParserCallback(strfun_type2 a_pFun, bool a_bAllowOpti);
|
||||
|
||||
@@ -73,24 +73,6 @@ typedef muFloat_t (*muFun9_t)(muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloa
|
||||
typedef muFloat_t (*muFun10_t)(muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t,
|
||||
muFloat_t, muFloat_t, muFloat_t, muFloat_t);
|
||||
|
||||
// Function prototypes for bulkmode functions
|
||||
typedef muFloat_t (*muBulkFun0_t)(int, int);
|
||||
typedef muFloat_t (*muBulkFun1_t)(int, int, muFloat_t);
|
||||
typedef muFloat_t (*muBulkFun2_t)(int, int, muFloat_t, muFloat_t);
|
||||
typedef muFloat_t (*muBulkFun3_t)(int, int, muFloat_t, muFloat_t, muFloat_t);
|
||||
typedef muFloat_t (*muBulkFun4_t)(int, int, muFloat_t, muFloat_t, muFloat_t, muFloat_t);
|
||||
typedef muFloat_t (*muBulkFun5_t)(int, int, muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t);
|
||||
typedef muFloat_t (*muBulkFun6_t)(int, int, muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t,
|
||||
muFloat_t);
|
||||
typedef muFloat_t (*muBulkFun7_t)(int, int, muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t,
|
||||
muFloat_t, muFloat_t);
|
||||
typedef muFloat_t (*muBulkFun8_t)(int, int, muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t,
|
||||
muFloat_t, muFloat_t, muFloat_t);
|
||||
typedef muFloat_t (*muBulkFun9_t)(int, int, muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t,
|
||||
muFloat_t, muFloat_t, muFloat_t, muFloat_t);
|
||||
typedef muFloat_t (*muBulkFun10_t)(int, int, muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t,
|
||||
muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t);
|
||||
|
||||
typedef muFloat_t (*muMultFun_t)(const muFloat_t *, muInt_t);
|
||||
typedef muFloat_t (*muStrFun1_t)(const muChar_t *);
|
||||
typedef muFloat_t (*muStrFun2_t)(const muChar_t *, muFloat_t);
|
||||
@@ -130,7 +112,6 @@ mupSetVarFactory(muParserHandle_t a_hParser, muFacFun_t a_pFactory, void *pUserD
|
||||
API_EXPORT(const muChar_t *) mupGetVersion(muParserHandle_t a_hParser);
|
||||
API_EXPORT(muFloat_t) mupEval(muParserHandle_t a_hParser);
|
||||
API_EXPORT(muFloat_t *) mupEvalMulti(muParserHandle_t a_hParser, int *nNum);
|
||||
API_EXPORT(void) mupEvalBulk(muParserHandle_t a_hParser, muFloat_t *a_fResult, int nSize);
|
||||
|
||||
// Defining callbacks / variables / constants
|
||||
API_EXPORT(void)
|
||||
@@ -167,30 +148,6 @@ API_EXPORT(void)
|
||||
mupDefineFun10(muParserHandle_t a_hParser, const muChar_t *a_szName, muFun10_t a_pFun,
|
||||
muBool_t a_bOptimize);
|
||||
|
||||
// Defining bulkmode functions
|
||||
API_EXPORT(void)
|
||||
mupDefineBulkFun0(muParserHandle_t a_hParser, const muChar_t *a_szName, muBulkFun0_t a_pFun);
|
||||
API_EXPORT(void)
|
||||
mupDefineBulkFun1(muParserHandle_t a_hParser, const muChar_t *a_szName, muBulkFun1_t a_pFun);
|
||||
API_EXPORT(void)
|
||||
mupDefineBulkFun2(muParserHandle_t a_hParser, const muChar_t *a_szName, muBulkFun2_t a_pFun);
|
||||
API_EXPORT(void)
|
||||
mupDefineBulkFun3(muParserHandle_t a_hParser, const muChar_t *a_szName, muBulkFun3_t a_pFun);
|
||||
API_EXPORT(void)
|
||||
mupDefineBulkFun4(muParserHandle_t a_hParser, const muChar_t *a_szName, muBulkFun4_t a_pFun);
|
||||
API_EXPORT(void)
|
||||
mupDefineBulkFun5(muParserHandle_t a_hParser, const muChar_t *a_szName, muBulkFun5_t a_pFun);
|
||||
API_EXPORT(void)
|
||||
mupDefineBulkFun6(muParserHandle_t a_hParser, const muChar_t *a_szName, muBulkFun6_t a_pFun);
|
||||
API_EXPORT(void)
|
||||
mupDefineBulkFun7(muParserHandle_t a_hParser, const muChar_t *a_szName, muBulkFun7_t a_pFun);
|
||||
API_EXPORT(void)
|
||||
mupDefineBulkFun8(muParserHandle_t a_hParser, const muChar_t *a_szName, muBulkFun8_t a_pFun);
|
||||
API_EXPORT(void)
|
||||
mupDefineBulkFun9(muParserHandle_t a_hParser, const muChar_t *a_szName, muBulkFun9_t a_pFun);
|
||||
API_EXPORT(void)
|
||||
mupDefineBulkFun10(muParserHandle_t a_hParser, const muChar_t *a_szName, muBulkFun10_t a_pFun);
|
||||
|
||||
// string functions
|
||||
API_EXPORT(void)
|
||||
mupDefineStrFun1(muParserHandle_t a_hParser, const muChar_t *a_szName, muStrFun1_t a_pFun);
|
||||
@@ -216,9 +173,6 @@ mupDefineStrConst(muParserHandle_t a_hParser, const muChar_t *a_szName, const mu
|
||||
API_EXPORT(void)
|
||||
mupDefineVar(muParserHandle_t a_hParser, const muChar_t *a_szName, muFloat_t *a_fVar);
|
||||
|
||||
API_EXPORT(void)
|
||||
mupDefineBulkVar(muParserHandle_t a_hParser, const muChar_t *a_szName, muFloat_t *a_fVar);
|
||||
|
||||
API_EXPORT(void)
|
||||
mupDefinePostfixOprt(muParserHandle_t a_hParser, const muChar_t *a_szName, muFun1_t a_pOprt,
|
||||
muBool_t a_bOptimize);
|
||||
|
||||
@@ -179,8 +179,6 @@ enum ECmdCode {
|
||||
// operators and functions
|
||||
cmFUNC, ///< Code for a generic function item
|
||||
cmFUNC_STR, ///< Code for a function with a string parameter
|
||||
cmFUNC_BULK, ///< Special callbacks for Bulk mode with an additional parameter for the bulk
|
||||
/// index
|
||||
cmSTRING, ///< Code for a string token
|
||||
cmOPRT_BIN, ///< user defined binary operator
|
||||
cmOPRT_POSTFIX, ///< code for postfix operators
|
||||
@@ -397,46 +395,6 @@ typedef value_type (*fun_type9)(value_type, value_type, value_type, value_type,
|
||||
typedef value_type (*fun_type10)(value_type, value_type, value_type, value_type, value_type,
|
||||
value_type, value_type, value_type, value_type, value_type);
|
||||
|
||||
/** \brief Callback type used for functions without arguments. */
|
||||
typedef value_type (*bulkfun_type0)(int, int);
|
||||
|
||||
/** \brief Callback type used for functions with a single arguments. */
|
||||
typedef value_type (*bulkfun_type1)(int, int, value_type);
|
||||
|
||||
/** \brief Callback type used for functions with two arguments. */
|
||||
typedef value_type (*bulkfun_type2)(int, int, value_type, value_type);
|
||||
|
||||
/** \brief Callback type used for functions with three arguments. */
|
||||
typedef value_type (*bulkfun_type3)(int, int, value_type, value_type, value_type);
|
||||
|
||||
/** \brief Callback type used for functions with four arguments. */
|
||||
typedef value_type (*bulkfun_type4)(int, int, value_type, value_type, value_type, value_type);
|
||||
|
||||
/** \brief Callback type used for functions with five arguments. */
|
||||
typedef value_type (*bulkfun_type5)(int, int, value_type, value_type, value_type, value_type,
|
||||
value_type);
|
||||
|
||||
/** \brief Callback type used for functions with five arguments. */
|
||||
typedef value_type (*bulkfun_type6)(int, int, value_type, value_type, value_type, value_type,
|
||||
value_type, value_type);
|
||||
|
||||
/** \brief Callback type used for functions with five arguments. */
|
||||
typedef value_type (*bulkfun_type7)(int, int, value_type, value_type, value_type, value_type,
|
||||
value_type, value_type, value_type);
|
||||
|
||||
/** \brief Callback type used for functions with five arguments. */
|
||||
typedef value_type (*bulkfun_type8)(int, int, value_type, value_type, value_type, value_type,
|
||||
value_type, value_type, value_type, value_type);
|
||||
|
||||
/** \brief Callback type used for functions with five arguments. */
|
||||
typedef value_type (*bulkfun_type9)(int, int, value_type, value_type, value_type, value_type,
|
||||
value_type, value_type, value_type, value_type, value_type);
|
||||
|
||||
/** \brief Callback type used for functions with five arguments. */
|
||||
typedef value_type (*bulkfun_type10)(int, int, value_type, value_type, value_type, value_type,
|
||||
value_type, value_type, value_type, value_type, value_type,
|
||||
value_type);
|
||||
|
||||
/** \brief Callback type used for functions with a variable argument list. */
|
||||
typedef value_type (*multfun_type)(const value_type *, int);
|
||||
|
||||
|
||||
@@ -172,7 +172,6 @@ class ParserTester // final
|
||||
int TestException();
|
||||
int TestStrArg();
|
||||
int TestIfThenElse();
|
||||
int TestBulkMode();
|
||||
|
||||
void Abort() const;
|
||||
|
||||
@@ -194,9 +193,6 @@ class ParserTester // final
|
||||
|
||||
// Test Int Parser
|
||||
int EqnTestInt(const string_type& a_str, double a_fRes, bool a_fPass);
|
||||
|
||||
// Test Bulkmode
|
||||
int EqnTestBulk(const string_type& a_str, double a_fRes[4], bool a_fPass);
|
||||
};
|
||||
} // namespace Test
|
||||
} // namespace mu
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
//---------------------------------------------------------------------------
|
||||
//
|
||||
// __________
|
||||
// _____ __ __\______ \_____ _______ ______ ____ _______
|
||||
// __________
|
||||
// _____ __ __\______ \_____ _______ ______ ____ _______
|
||||
// / \ | | \| ___/\__ \ \_ __ \/ ___/_/ __ \\_ __ \
|
||||
// | Y Y \| | /| | / __ \_| | \/\___ \ \ ___/ | | \/
|
||||
// |__|_| /|____/ |____| (____ /|__| /____ > \___ >|__|
|
||||
// \/ \/ \/ \/
|
||||
// |__|_| /|____/ |____| (____ /|__| /____ > \___ >|__|
|
||||
// \/ \/ \/ \/
|
||||
// (C) 2015 Ingo Berg
|
||||
//
|
||||
// example1.cpp - using the parser as a static library
|
||||
@@ -15,209 +15,178 @@
|
||||
#include "muParserTest.h"
|
||||
|
||||
#if defined(_WIN32) && defined(_DEBUG)
|
||||
#define _CRTDBG_MAP_ALLOC
|
||||
#include <stdlib.h>
|
||||
#include <crtdbg.h>
|
||||
#define CREATE_LEAKAGE_REPORT
|
||||
#define _CRTDBG_MAP_ALLOC
|
||||
#include <crtdbg.h>
|
||||
#include <stdlib.h>
|
||||
#define CREATE_LEAKAGE_REPORT
|
||||
#endif
|
||||
|
||||
#if defined( USINGDLL ) && defined( _WIN32 )
|
||||
#if defined(USINGDLL) && defined(_WIN32)
|
||||
#error This sample can be used only with STATIC builds of muParser (on win32)
|
||||
#endif
|
||||
|
||||
/** \brief This macro will enable mathematical constants like M_PI. */
|
||||
#define _USE_MATH_DEFINES
|
||||
#define _USE_MATH_DEFINES
|
||||
|
||||
#include <cmath>
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
#include <cmath>
|
||||
#include <string>
|
||||
#include <iostream>
|
||||
#include <locale>
|
||||
#include <limits>
|
||||
#include <ios>
|
||||
#include <iomanip>
|
||||
#include <ios>
|
||||
#include <iostream>
|
||||
#include <limits>
|
||||
#include <locale>
|
||||
#include <numeric>
|
||||
#include <string>
|
||||
|
||||
#include "muParser.h"
|
||||
|
||||
using namespace std;
|
||||
using namespace mu;
|
||||
|
||||
|
||||
#if defined(CREATE_LEAKAGE_REPORT)
|
||||
|
||||
// Dumping memory leaks in the destructor of the static guard
|
||||
// guarantees i won't get false positives from the ParserErrorMsg
|
||||
// guarantees i won't get false positives from the ParserErrorMsg
|
||||
// class wich is a singleton with a static instance.
|
||||
struct DumpLeaks
|
||||
{
|
||||
~DumpLeaks()
|
||||
{
|
||||
_CrtDumpMemoryLeaks();
|
||||
}
|
||||
struct DumpLeaks {
|
||||
~DumpLeaks() { _CrtDumpMemoryLeaks(); }
|
||||
} static LeakDumper;
|
||||
|
||||
#endif
|
||||
|
||||
// Forward declarations
|
||||
void CalcBulk();
|
||||
|
||||
// Operator callback functions
|
||||
value_type Mega(value_type a_fVal) { return a_fVal * 1e6; }
|
||||
value_type Milli(value_type a_fVal) { return a_fVal / (value_type)1e3; }
|
||||
value_type Rnd(value_type v) { return v*std::rand()/(value_type)(RAND_MAX+1.0); }
|
||||
value_type Not(value_type v) { return v==0; }
|
||||
value_type Add(value_type v1, value_type v2) { return v1+v2; }
|
||||
value_type Mul(value_type v1, value_type v2) { return v1*v2; }
|
||||
value_type Rnd(value_type v) { return v * std::rand() / (value_type)(RAND_MAX + 1.0); }
|
||||
value_type Not(value_type v) { return v == 0; }
|
||||
value_type Add(value_type v1, value_type v2) { return v1 + v2; }
|
||||
value_type Mul(value_type v1, value_type v2) { return v1 * v2; }
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
value_type ThrowAnException(value_type)
|
||||
{
|
||||
throw std::runtime_error("This function does throw an exception.");
|
||||
value_type ThrowAnException(value_type) {
|
||||
throw std::runtime_error("This function does throw an exception.");
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
value_type BulkFun1(int nBulkIdx, int nThreadIdx, value_type v1)
|
||||
{
|
||||
// Note: I'm just doing something with all three parameters to shut
|
||||
// compiler warnings up!
|
||||
return nBulkIdx + nThreadIdx + v1;
|
||||
value_type Ping() {
|
||||
mu::console() << "ping\n";
|
||||
return 0;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
value_type Ping()
|
||||
{
|
||||
mu::console() << "ping\n";
|
||||
return 0;
|
||||
value_type StrFun0(const char_type *szMsg) {
|
||||
if (szMsg) mu::console() << szMsg << std::endl;
|
||||
|
||||
return 999;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
value_type StrFun0(const char_type *szMsg)
|
||||
{
|
||||
if (szMsg)
|
||||
mu::console() << szMsg << std::endl;
|
||||
|
||||
return 999;
|
||||
value_type StrFun2(const char_type *v1, value_type v2, value_type v3) {
|
||||
mu::console() << v1 << std::endl;
|
||||
return v2 + v3;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
value_type StrFun2(const char_type *v1, value_type v2,value_type v3)
|
||||
{
|
||||
mu::console() << v1 << std::endl;
|
||||
return v2+v3;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
value_type Debug(mu::value_type v1, mu::value_type v2)
|
||||
{
|
||||
ParserBase::EnableDebugDump(v1!=0, v2!=0);
|
||||
mu::console() << _T("Bytecode dumping ") << ((v1!=0) ? _T("active") : _T("inactive")) << _T("\n");
|
||||
return 1;
|
||||
value_type Debug(mu::value_type v1, mu::value_type v2) {
|
||||
ParserBase::EnableDebugDump(v1 != 0, v2 != 0);
|
||||
mu::console() << _T("Bytecode dumping ") << ((v1 != 0) ? _T("active") : _T("inactive"))
|
||||
<< _T("\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
// Factory function for creating new parser variables
|
||||
// This could as well be a function performing database queries.
|
||||
value_type* AddVariable(const char_type *a_szName, void *a_pUserData)
|
||||
{
|
||||
// I don't want dynamic allocation here, so i used this static buffer
|
||||
// If you want dynamic allocation you must allocate all variables dynamically
|
||||
// in order to delete them later on. Or you find other ways to keep track of
|
||||
// variables that have been created implicitely.
|
||||
static value_type afValBuf[100];
|
||||
static int iVal = -1;
|
||||
value_type *AddVariable(const char_type *a_szName, void *a_pUserData) {
|
||||
// I don't want dynamic allocation here, so i used this static buffer
|
||||
// If you want dynamic allocation you must allocate all variables dynamically
|
||||
// in order to delete them later on. Or you find other ways to keep track of
|
||||
// variables that have been created implicitely.
|
||||
static value_type afValBuf[100];
|
||||
static int iVal = -1;
|
||||
|
||||
++iVal;
|
||||
++iVal;
|
||||
|
||||
mu::console() << _T("Generating new variable \"")
|
||||
<< a_szName << std::dec << _T("\" (slots left: ")
|
||||
<< 99-iVal << _T(")")
|
||||
<< _T(" User data pointer is:")
|
||||
<< std::hex << a_pUserData <<endl;
|
||||
afValBuf[iVal] = 0;
|
||||
mu::console() << _T("Generating new variable \"") << a_szName << std::dec
|
||||
<< _T("\" (slots left: ") << 99 - iVal << _T(")")
|
||||
<< _T(" User data pointer is:") << std::hex << a_pUserData << endl;
|
||||
afValBuf[iVal] = 0;
|
||||
|
||||
if (iVal>=99)
|
||||
throw mu::ParserError( _T("Variable buffer overflow.") );
|
||||
else
|
||||
return &afValBuf[iVal];
|
||||
if (iVal >= 99)
|
||||
throw mu::ParserError(_T("Variable buffer overflow."));
|
||||
else
|
||||
return &afValBuf[iVal];
|
||||
}
|
||||
|
||||
int IsHexValue(const char_type *a_szExpr, int *a_iPos, value_type *a_fVal)
|
||||
{
|
||||
if (a_szExpr[1]==0 || (a_szExpr[0]!='0' || a_szExpr[1]!='x') )
|
||||
return 0;
|
||||
int IsHexValue(const char_type *a_szExpr, int *a_iPos, value_type *a_fVal) {
|
||||
if (a_szExpr[1] == 0 || (a_szExpr[0] != '0' || a_szExpr[1] != 'x')) return 0;
|
||||
|
||||
unsigned iVal(0);
|
||||
unsigned iVal(0);
|
||||
|
||||
// New code based on streams for UNICODE compliance:
|
||||
stringstream_type::pos_type nPos(0);
|
||||
stringstream_type ss(a_szExpr + 2);
|
||||
ss >> std::hex >> iVal;
|
||||
nPos = ss.tellg();
|
||||
// New code based on streams for UNICODE compliance:
|
||||
stringstream_type::pos_type nPos(0);
|
||||
stringstream_type ss(a_szExpr + 2);
|
||||
ss >> std::hex >> iVal;
|
||||
nPos = ss.tellg();
|
||||
|
||||
if (nPos == (stringstream_type::pos_type)0) return 1;
|
||||
|
||||
*a_iPos += (int)(2 + nPos);
|
||||
*a_fVal = (value_type)iVal;
|
||||
|
||||
if (nPos==(stringstream_type::pos_type)0)
|
||||
return 1;
|
||||
|
||||
*a_iPos += (int)(2 + nPos);
|
||||
*a_fVal = (value_type)iVal;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
void Splash()
|
||||
{
|
||||
mu::console() << _T(" __________ \n");
|
||||
mu::console() << _T(" _____ __ __\\______ \\_____ _______ ______ ____ _______\n");
|
||||
mu::console() << _T(" / \\ | | \\| ___/\\__ \\ \\_ __ \\/ ___/_/ __ \\\\_ __ \\ \n");
|
||||
mu::console() << _T(" | Y Y \\| | /| | / __ \\_| | \\/\\___ \\ \\ ___/ | | \\/ \n");
|
||||
mu::console() << _T(" |__|_| /|____/ |____| (____ /|__| /____ > \\___ >|__| \n");
|
||||
mu::console() << _T(" \\/ \\/ \\/ \\/ \n");
|
||||
mu::console() << _T(" Version ") << Parser().GetVersion(pviFULL) << _T("\n");
|
||||
mu::console() << _T(" (C) 2015 Ingo Berg\n");
|
||||
void Splash() {
|
||||
mu::console() << _T(" __________ \n");
|
||||
mu::console() << _T(" _____ __ __\\______ \\_____ _______ ______ ____ _______\n");
|
||||
mu::console()
|
||||
<< _T(" / \\ | | \\| ___/\\__ \\ \\_ __ \\/ ___/_/ __ \\\\_ __ \\ \n");
|
||||
mu::console()
|
||||
<< _T(" | Y Y \\| | /| | / __ \\_| | \\/\\___ \\ \\ ___/ | | \\/ \n");
|
||||
mu::console() << _T(" |__|_| /|____/ |____| (____ /|__| /____ > \\___ >|__| \n");
|
||||
mu::console() << _T(" \\/ \\/ \\/ \\/ \n");
|
||||
mu::console() << _T(" Version ") << Parser().GetVersion(pviFULL) << _T("\n");
|
||||
mu::console() << _T(" (C) 2015 Ingo Berg\n");
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
value_type SelfTest()
|
||||
{
|
||||
mu::console() << _T( "-----------------------------------------------------------\n");
|
||||
mu::console() << _T( "Running test suite:\n\n");
|
||||
value_type SelfTest() {
|
||||
mu::console() << _T( "-----------------------------------------------------------\n");
|
||||
mu::console() << _T( "Running test suite:\n\n");
|
||||
|
||||
// Skip the self test if the value type is set to an integer type.
|
||||
if (mu::TypeInfo<mu::value_type>::IsInteger())
|
||||
{
|
||||
mu::console() << _T( " Test skipped: integer data type are not compatible with the unit test!\n\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
mu::Test::ParserTester pt;
|
||||
pt.Run();
|
||||
}
|
||||
// Skip the self test if the value type is set to an integer type.
|
||||
if (mu::TypeInfo<mu::value_type>::IsInteger()) {
|
||||
mu::console()
|
||||
<< _T( " Test skipped: integer data type are not compatible with the unit test!\n\n");
|
||||
} else {
|
||||
mu::Test::ParserTester pt;
|
||||
pt.Run();
|
||||
}
|
||||
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
value_type Help()
|
||||
{
|
||||
mu::console() << _T( "-----------------------------------------------------------\n");
|
||||
mu::console() << _T( "Commands:\n\n");
|
||||
mu::console() << _T( " list var - list parser variables\n");
|
||||
mu::console() << _T( " list exprvar - list expression variables\n");
|
||||
mu::console() << _T( " list const - list all numeric parser constants\n");
|
||||
mu::console() << _T( " opt on - enable optimizer (default)\n");
|
||||
mu::console() << _T( " opt off - disable optimizer\n");
|
||||
mu::console() << _T( " locale de - switch to german locale\n");
|
||||
mu::console() << _T( " locale en - switch to english locale\n");
|
||||
mu::console() << _T( " locale reset - reset locale\n");
|
||||
mu::console() << _T( " test bulk - test bulk mode\n");
|
||||
mu::console() << _T( " quit - exits the parser\n");
|
||||
mu::console() << _T( "\nConstants:\n\n");
|
||||
mu::console() << _T( " \"_e\" 2.718281828459045235360287\n");
|
||||
mu::console() << _T( " \"_pi\" 3.141592653589793238462643\n");
|
||||
mu::console() << _T( "-----------------------------------------------------------\n");
|
||||
return 0;
|
||||
value_type Help() {
|
||||
mu::console() << _T( "-----------------------------------------------------------\n");
|
||||
mu::console() << _T( "Commands:\n\n");
|
||||
mu::console() << _T( " list var - list parser variables\n");
|
||||
mu::console() << _T( " list exprvar - list expression variables\n");
|
||||
mu::console() << _T( " list const - list all numeric parser constants\n");
|
||||
mu::console() << _T( " opt on - enable optimizer (default)\n");
|
||||
mu::console() << _T( " opt off - disable optimizer\n");
|
||||
mu::console() << _T( " locale de - switch to german locale\n");
|
||||
mu::console() << _T( " locale en - switch to english locale\n");
|
||||
mu::console() << _T( " locale reset - reset locale\n");
|
||||
mu::console() << _T( " quit - exits the parser\n");
|
||||
mu::console() << _T( "\nConstants:\n\n");
|
||||
mu::console() << _T( " \"_e\" 2.718281828459045235360287\n");
|
||||
mu::console() << _T( " \"_pi\" 3.141592653589793238462643\n");
|
||||
mu::console() << _T( "-----------------------------------------------------------\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
@@ -233,11 +202,16 @@ void CheckLocale()
|
||||
{
|
||||
std::locale loc("German_germany");
|
||||
console() << _T("Locale settings:\n");
|
||||
console() << _T(" Decimal point: '") << std::use_facet<numpunct<char_type> >(loc).decimal_point() << _T("'\n");
|
||||
console() << _T(" Thousands sep: '") << std::use_facet<numpunct<char_type> >(loc).thousands_sep() << _T("'\n");
|
||||
console() << _T(" Grouping: '") << std::use_facet<numpunct<char_type> >(loc).grouping() << _T("'\n");
|
||||
console() << _T(" True is named: '") << std::use_facet<numpunct<char_type> >(loc).truename() << _T("'\n");
|
||||
console() << _T(" False is named: '") << std::use_facet<numpunct<char_type> >(loc).falsename() << _T("'\n");
|
||||
console() << _T(" Decimal point: '") << std::use_facet<numpunct<char_type>
|
||||
>(loc).decimal_point() << _T("'\n");
|
||||
console() << _T(" Thousands sep: '") << std::use_facet<numpunct<char_type>
|
||||
>(loc).thousands_sep() << _T("'\n");
|
||||
console() << _T(" Grouping: '") << std::use_facet<numpunct<char_type> >(loc).grouping()
|
||||
<< _T("'\n");
|
||||
console() << _T(" True is named: '") << std::use_facet<numpunct<char_type> >(loc).truename()
|
||||
<< _T("'\n");
|
||||
console() << _T(" False is named: '") << std::use_facet<numpunct<char_type> >(loc).falsename()
|
||||
<< _T("'\n");
|
||||
console() << _T("-----------------------------------------------------------\n");
|
||||
}
|
||||
catch(...)
|
||||
@@ -252,17 +226,18 @@ void CheckLocale()
|
||||
void CheckDiff()
|
||||
{
|
||||
mu::Parser parser;
|
||||
value_type x = 1,
|
||||
value_type x = 1,
|
||||
v1,
|
||||
v2,
|
||||
v3,
|
||||
eps(pow(std::numeric_limits<value_type>::epsilon(), 0.2));
|
||||
parser.DefineVar(_T("x"), &x);
|
||||
parser.SetExpr(_T("_e^-x*sin(x)"));
|
||||
|
||||
|
||||
v1 = parser.Diff(&x, 1),
|
||||
v2 = parser.Diff(&x, 1, eps);
|
||||
v3 = cos((value_type)1.0)/exp((value_type)1) - sin((value_type)1.0)/exp((value_type)1); //-0.110793765307;
|
||||
v3 = cos((value_type)1.0)/exp((value_type)1) - sin((value_type)1.0)/exp((value_type)1);
|
||||
//-0.110793765307;
|
||||
mu::console() << parser.GetExpr() << _T("\n");
|
||||
mu::console() << _T("v1 = ") << v1 << _T("; v1-v3 = ") << v1-v3 << _T("\n");
|
||||
mu::console() << _T("v2 = ") << v2 << _T("; v2-v3 = ") << v2-v3 << _T("\n");
|
||||
@@ -270,323 +245,238 @@ void CheckDiff()
|
||||
*/
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
void ListVar(const mu::ParserBase &parser)
|
||||
{
|
||||
// Query the used variables (must be done after calc)
|
||||
mu::varmap_type variables = parser.GetVar();
|
||||
if (!variables.size())
|
||||
return;
|
||||
void ListVar(const mu::ParserBase &parser) {
|
||||
// Query the used variables (must be done after calc)
|
||||
mu::varmap_type variables = parser.GetVar();
|
||||
if (!variables.size()) return;
|
||||
|
||||
cout << "\nParser variables:\n";
|
||||
cout << "-----------------\n";
|
||||
cout << "Number: " << (int)variables.size() << "\n";
|
||||
varmap_type::const_iterator item = variables.begin();
|
||||
for (; item!=variables.end(); ++item)
|
||||
mu::console() << _T("Name: ") << item->first << _T(" Address: [0x") << item->second << _T("]\n");
|
||||
cout << "\nParser variables:\n";
|
||||
cout << "-----------------\n";
|
||||
cout << "Number: " << (int)variables.size() << "\n";
|
||||
varmap_type::const_iterator item = variables.begin();
|
||||
for (; item != variables.end(); ++item)
|
||||
mu::console() << _T("Name: ") << item->first << _T(" Address: [0x") << item->second
|
||||
<< _T("]\n");
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
void ListConst(const mu::ParserBase &parser)
|
||||
{
|
||||
mu::console() << _T("\nParser constants:\n");
|
||||
mu::console() << _T("-----------------\n");
|
||||
void ListConst(const mu::ParserBase &parser) {
|
||||
mu::console() << _T("\nParser constants:\n");
|
||||
mu::console() << _T("-----------------\n");
|
||||
|
||||
mu::valmap_type cmap = parser.GetConst();
|
||||
if (!cmap.size())
|
||||
{
|
||||
mu::console() << _T("Expression does not contain constants\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
valmap_type::const_iterator item = cmap.begin();
|
||||
for (; item!=cmap.end(); ++item)
|
||||
mu::console() << _T(" ") << item->first << _T(" = ") << item->second << _T("\n");
|
||||
}
|
||||
mu::valmap_type cmap = parser.GetConst();
|
||||
if (!cmap.size()) {
|
||||
mu::console() << _T("Expression does not contain constants\n");
|
||||
} else {
|
||||
valmap_type::const_iterator item = cmap.begin();
|
||||
for (; item != cmap.end(); ++item)
|
||||
mu::console() << _T(" ") << item->first << _T(" = ") << item->second << _T("\n");
|
||||
}
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
void ListExprVar(const mu::ParserBase &parser)
|
||||
{
|
||||
string_type sExpr = parser.GetExpr();
|
||||
if (sExpr.length()==0)
|
||||
{
|
||||
cout << _T("Expression string is empty\n");
|
||||
return;
|
||||
}
|
||||
void ListExprVar(const mu::ParserBase &parser) {
|
||||
string_type sExpr = parser.GetExpr();
|
||||
if (sExpr.length() == 0) {
|
||||
cout << _T("Expression string is empty\n");
|
||||
return;
|
||||
}
|
||||
|
||||
// Query the used variables (must be done after calc)
|
||||
mu::console() << _T("\nExpression variables:\n");
|
||||
mu::console() << _T("---------------------\n");
|
||||
mu::console() << _T("Expression: ") << parser.GetExpr() << _T("\n");
|
||||
// Query the used variables (must be done after calc)
|
||||
mu::console() << _T("\nExpression variables:\n");
|
||||
mu::console() << _T("---------------------\n");
|
||||
mu::console() << _T("Expression: ") << parser.GetExpr() << _T("\n");
|
||||
|
||||
varmap_type variables = parser.GetUsedVar();
|
||||
if (!variables.size())
|
||||
{
|
||||
mu::console() << _T("Expression does not contain variables\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
mu::console() << _T("Number: ") << (int)variables.size() << _T("\n");
|
||||
mu::varmap_type::const_iterator item = variables.begin();
|
||||
for (; item!=variables.end(); ++item)
|
||||
mu::console() << _T("Name: ") << item->first << _T(" Address: [0x") << item->second << _T("]\n");
|
||||
}
|
||||
varmap_type variables = parser.GetUsedVar();
|
||||
if (!variables.size()) {
|
||||
mu::console() << _T("Expression does not contain variables\n");
|
||||
} else {
|
||||
mu::console() << _T("Number: ") << (int)variables.size() << _T("\n");
|
||||
mu::varmap_type::const_iterator item = variables.begin();
|
||||
for (; item != variables.end(); ++item)
|
||||
mu::console() << _T("Name: ") << item->first << _T(" Address: [0x") << item->second
|
||||
<< _T("]\n");
|
||||
}
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
/** \brief Check for external keywords.
|
||||
*/
|
||||
int CheckKeywords(const mu::char_type *a_szLine, mu::Parser &a_Parser)
|
||||
{
|
||||
string_type sLine(a_szLine);
|
||||
int CheckKeywords(const mu::char_type *a_szLine, mu::Parser &a_Parser) {
|
||||
string_type sLine(a_szLine);
|
||||
|
||||
if ( sLine == _T("quit") )
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
else if ( sLine == _T("list var") )
|
||||
{
|
||||
ListVar(a_Parser);
|
||||
return 1;
|
||||
}
|
||||
else if ( sLine == _T("opt on") )
|
||||
{
|
||||
a_Parser.EnableOptimizer(true);
|
||||
mu::console() << _T("Optimizer enabled\n");
|
||||
return 1;
|
||||
}
|
||||
else if ( sLine == _T("opt off") )
|
||||
{
|
||||
a_Parser.EnableOptimizer(false);
|
||||
mu::console() << _T("Optimizer disabled\n");
|
||||
return 1;
|
||||
}
|
||||
else if ( sLine == _T("list const") )
|
||||
{
|
||||
ListConst(a_Parser);
|
||||
return 1;
|
||||
}
|
||||
else if ( sLine == _T("list exprvar") )
|
||||
{
|
||||
ListExprVar(a_Parser);
|
||||
return 1;
|
||||
}
|
||||
else if ( sLine == _T("locale de") )
|
||||
{
|
||||
mu::console() << _T("Setting german locale: ArgSep=';' DecSep=',' ThousandsSep='.'\n");
|
||||
a_Parser.SetArgSep(';');
|
||||
a_Parser.SetDecSep(',');
|
||||
a_Parser.SetThousandsSep('.');
|
||||
return 1;
|
||||
}
|
||||
else if ( sLine == _T("locale en") )
|
||||
{
|
||||
mu::console() << _T("Setting english locale: ArgSep=',' DecSep='.' ThousandsSep=''\n");
|
||||
a_Parser.SetArgSep(',');
|
||||
a_Parser.SetDecSep('.');
|
||||
a_Parser.SetThousandsSep();
|
||||
return 1;
|
||||
}
|
||||
else if ( sLine == _T("locale reset") )
|
||||
{
|
||||
mu::console() << _T("Resetting locale\n");
|
||||
a_Parser.ResetLocale();
|
||||
return 1;
|
||||
}
|
||||
else if ( sLine == _T("test bulk") )
|
||||
{
|
||||
mu::console() << _T("Testing bulk mode\n");
|
||||
CalcBulk();
|
||||
return 1;
|
||||
}
|
||||
if (sLine == _T("quit")) {
|
||||
return -1;
|
||||
} else if (sLine == _T("list var")) {
|
||||
ListVar(a_Parser);
|
||||
return 1;
|
||||
} else if (sLine == _T("opt on")) {
|
||||
a_Parser.EnableOptimizer(true);
|
||||
mu::console() << _T("Optimizer enabled\n");
|
||||
return 1;
|
||||
} else if (sLine == _T("opt off")) {
|
||||
a_Parser.EnableOptimizer(false);
|
||||
mu::console() << _T("Optimizer disabled\n");
|
||||
return 1;
|
||||
} else if (sLine == _T("list const")) {
|
||||
ListConst(a_Parser);
|
||||
return 1;
|
||||
} else if (sLine == _T("list exprvar")) {
|
||||
ListExprVar(a_Parser);
|
||||
return 1;
|
||||
} else if (sLine == _T("locale de")) {
|
||||
mu::console() << _T("Setting german locale: ArgSep=';' DecSep=',' ThousandsSep='.'\n");
|
||||
a_Parser.SetArgSep(';');
|
||||
a_Parser.SetDecSep(',');
|
||||
a_Parser.SetThousandsSep('.');
|
||||
return 1;
|
||||
} else if (sLine == _T("locale en")) {
|
||||
mu::console() << _T("Setting english locale: ArgSep=',' DecSep='.' ThousandsSep=''\n");
|
||||
a_Parser.SetArgSep(',');
|
||||
a_Parser.SetDecSep('.');
|
||||
a_Parser.SetThousandsSep();
|
||||
return 1;
|
||||
} else if (sLine == _T("locale reset")) {
|
||||
mu::console() << _T("Resetting locale\n");
|
||||
a_Parser.ResetLocale();
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
void CalcBulk()
|
||||
{
|
||||
const int nBulkSize = 200;
|
||||
value_type *x = new value_type[nBulkSize];
|
||||
value_type *y = new value_type[nBulkSize];
|
||||
value_type *result = new value_type[nBulkSize];
|
||||
void Calc() {
|
||||
mu::Parser parser;
|
||||
|
||||
try
|
||||
{
|
||||
for (int i=0; i<nBulkSize; ++i)
|
||||
{
|
||||
x[i] = i;
|
||||
y[i] = (value_type)i/10;
|
||||
}
|
||||
mu::Parser parser;
|
||||
parser.DefineVar(_T("x"), x);
|
||||
parser.DefineVar(_T("y"), y);
|
||||
parser.DefineFun(_T("fun1"), BulkFun1);
|
||||
parser.SetExpr(_T("fun1(0)+x+y"));
|
||||
parser.Eval(result, nBulkSize);
|
||||
|
||||
for (int i=0; i<nBulkSize; ++i)
|
||||
{
|
||||
mu::console() << _T("Eqn. ") << i << _T(": x=") << x[i] << _T("; y=") << y[i] << _T("; result=") << result[i] << _T("\n");
|
||||
}
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
delete [] x;
|
||||
delete [] y;
|
||||
delete [] result;
|
||||
throw;
|
||||
}
|
||||
|
||||
delete [] x;
|
||||
delete [] y;
|
||||
delete [] result;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
void Calc()
|
||||
{
|
||||
mu::Parser parser;
|
||||
|
||||
// Change locale settings if necessary
|
||||
// function argument separator: sum(2;3;4) vs. sum(2,3,4)
|
||||
// decimal separator: 3,14 vs. 3.14
|
||||
// thousands separator: 1000000 vs 1.000.000
|
||||
// Change locale settings if necessary
|
||||
// function argument separator: sum(2;3;4) vs. sum(2,3,4)
|
||||
// decimal separator: 3,14 vs. 3.14
|
||||
// thousands separator: 1000000 vs 1.000.000
|
||||
//#define USE_GERMAN_LOCALE
|
||||
#ifdef USE_GERMAN_LOCALE
|
||||
parser.SetArgSep(';');
|
||||
parser.SetDecSep(',');
|
||||
parser.SetThousandsSep('.');
|
||||
#ifdef USE_GERMAN_LOCALE
|
||||
parser.SetArgSep(';');
|
||||
parser.SetDecSep(',');
|
||||
parser.SetThousandsSep('.');
|
||||
#else
|
||||
// this is the default, so i it's commented:
|
||||
//parser.SetArgSep(',');
|
||||
//parser.SetDecSep('.');
|
||||
//parser.SetThousandsSep('');
|
||||
// this is the default, so i it's commented:
|
||||
// parser.SetArgSep(',');
|
||||
// parser.SetDecSep('.');
|
||||
// parser.SetThousandsSep('');
|
||||
#endif
|
||||
|
||||
// Add some variables
|
||||
value_type vVarVal[] = { 1, 2 }; // Values of the parser variables
|
||||
parser.DefineVar(_T("a"), &vVarVal[0]); // Assign Variable names and bind them to the C++ variables
|
||||
parser.DefineVar(_T("b"), &vVarVal[1]);
|
||||
parser.DefineVar(_T("ft"), &vVarVal[1]);
|
||||
parser.DefineStrConst(_T("sVar1"), _T("Sample string 1") );
|
||||
parser.DefineStrConst(_T("sVar2"), _T("Sample string 2") );
|
||||
parser.AddValIdent(IsHexValue);
|
||||
// Add some variables
|
||||
value_type vVarVal[] = {1, 2}; // Values of the parser variables
|
||||
parser.DefineVar(_T("a"),
|
||||
&vVarVal[0]); // Assign Variable names and bind them to the C++ variables
|
||||
parser.DefineVar(_T("b"), &vVarVal[1]);
|
||||
parser.DefineVar(_T("ft"), &vVarVal[1]);
|
||||
parser.DefineStrConst(_T("sVar1"), _T("Sample string 1"));
|
||||
parser.DefineStrConst(_T("sVar2"), _T("Sample string 2"));
|
||||
parser.AddValIdent(IsHexValue);
|
||||
|
||||
// Add user defined unary operators
|
||||
parser.DefinePostfixOprt(_T("M"), Mega);
|
||||
parser.DefinePostfixOprt(_T("m"), Milli);
|
||||
parser.DefineInfixOprt(_T("!"), Not);
|
||||
parser.DefineFun(_T("strfun0"), StrFun0);
|
||||
parser.DefineFun(_T("strfun2"), StrFun2);
|
||||
parser.DefineFun(_T("ping"), Ping);
|
||||
parser.DefineFun(_T("rnd"), Rnd); // Add an unoptimizeable function
|
||||
parser.DefineFun(_T("throw"), ThrowAnException);
|
||||
// Add user defined unary operators
|
||||
parser.DefinePostfixOprt(_T("M"), Mega);
|
||||
parser.DefinePostfixOprt(_T("m"), Milli);
|
||||
parser.DefineInfixOprt(_T("!"), Not);
|
||||
parser.DefineFun(_T("strfun0"), StrFun0);
|
||||
parser.DefineFun(_T("strfun2"), StrFun2);
|
||||
parser.DefineFun(_T("ping"), Ping);
|
||||
parser.DefineFun(_T("rnd"), Rnd); // Add an unoptimizeable function
|
||||
parser.DefineFun(_T("throw"), ThrowAnException);
|
||||
|
||||
|
||||
parser.DefineOprt(_T("add"), Add, 0);
|
||||
parser.DefineOprt(_T("mul"), Mul, 1);
|
||||
parser.DefineOprt(_T("add"), Add, 0);
|
||||
parser.DefineOprt(_T("mul"), Mul, 1);
|
||||
|
||||
// These are service and debug functions
|
||||
parser.DefineFun(_T("debug"), Debug);
|
||||
parser.DefineFun(_T("selftest"), SelfTest);
|
||||
parser.DefineFun(_T("help"), Help);
|
||||
// These are service and debug functions
|
||||
parser.DefineFun(_T("debug"), Debug);
|
||||
parser.DefineFun(_T("selftest"), SelfTest);
|
||||
parser.DefineFun(_T("help"), Help);
|
||||
|
||||
parser.DefinePostfixOprt(_T("{ft}"), Milli);
|
||||
parser.DefinePostfixOprt(_T("ft"), Milli);
|
||||
parser.DefinePostfixOprt(_T("{ft}"), Milli);
|
||||
parser.DefinePostfixOprt(_T("ft"), Milli);
|
||||
#ifdef _DEBUG
|
||||
// parser.EnableDebugDump(1, 0);
|
||||
#endif
|
||||
|
||||
// Define the variable factory
|
||||
parser.SetVarFactory(AddVariable, &parser);
|
||||
// Define the variable factory
|
||||
parser.SetVarFactory(AddVariable, &parser);
|
||||
|
||||
for(;;)
|
||||
{
|
||||
try
|
||||
{
|
||||
string_type sLine;
|
||||
std::getline(mu::console_in(), sLine);
|
||||
for (;;) {
|
||||
try {
|
||||
string_type sLine;
|
||||
std::getline(mu::console_in(), sLine);
|
||||
|
||||
switch (CheckKeywords(sLine.c_str(), parser))
|
||||
{
|
||||
case 0: break;
|
||||
case 1: continue;
|
||||
case -1: return;
|
||||
}
|
||||
switch (CheckKeywords(sLine.c_str(), parser)) {
|
||||
case 0:
|
||||
break;
|
||||
case 1:
|
||||
continue;
|
||||
case -1:
|
||||
return;
|
||||
}
|
||||
|
||||
if (!sLine.length())
|
||||
continue;
|
||||
if (!sLine.length()) continue;
|
||||
|
||||
parser.SetExpr(sLine);
|
||||
mu::console() << std::setprecision(12);
|
||||
parser.SetExpr(sLine);
|
||||
mu::console() << std::setprecision(12);
|
||||
|
||||
// There are multiple ways to retrieve the result...
|
||||
// 1.) If you know there is only a single return value or in case you only need the last
|
||||
// result of an expression consisting of comma separated subexpressions you can
|
||||
// simply use:
|
||||
mu::console() << _T("ans=") << parser.Eval() << _T("\n");
|
||||
// There are multiple ways to retrieve the result...
|
||||
// 1.) If you know there is only a single return value or in case you only need the last
|
||||
// result of an expression consisting of comma separated subexpressions you can
|
||||
// simply use:
|
||||
mu::console() << _T("ans=") << parser.Eval() << _T("\n");
|
||||
|
||||
// 2.) As an alternative you can also retrieve multiple return values using this API:
|
||||
int nNum = parser.GetNumResults();
|
||||
if (nNum>1)
|
||||
{
|
||||
mu::console() << _T("Multiple return values detected! Complete list:\n");
|
||||
// 2.) As an alternative you can also retrieve multiple return values using this API:
|
||||
int nNum = parser.GetNumResults();
|
||||
if (nNum > 1) {
|
||||
mu::console() << _T("Multiple return values detected! Complete list:\n");
|
||||
|
||||
// this is the hard way if you need to retrieve multiple subexpression
|
||||
// results
|
||||
value_type *v = parser.Eval(nNum);
|
||||
mu::console() << std::setprecision(12);
|
||||
for (int i=0; i<nNum; ++i)
|
||||
{
|
||||
mu::console() << v[i] << _T("\n");
|
||||
// this is the hard way if you need to retrieve multiple subexpression
|
||||
// results
|
||||
value_type *v = parser.Eval(nNum);
|
||||
mu::console() << std::setprecision(12);
|
||||
for (int i = 0; i < nNum; ++i) {
|
||||
mu::console() << v[i] << _T("\n");
|
||||
}
|
||||
}
|
||||
} catch (mu::Parser::exception_type &e) {
|
||||
mu::console() << _T("\nError:\n");
|
||||
mu::console() << _T("------\n");
|
||||
mu::console() << _T("Message: ") << e.GetMsg() << _T("\n");
|
||||
mu::console() << _T("Expression: \"") << e.GetExpr() << _T("\"\n");
|
||||
mu::console() << _T("Token: \"") << e.GetToken() << _T("\"\n");
|
||||
mu::console() << _T("Position: ") << (int)e.GetPos() << _T("\n");
|
||||
mu::console() << _T("Errc: ") << std::dec << e.GetCode() << _T("\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
catch(mu::Parser::exception_type &e)
|
||||
{
|
||||
mu::console() << _T("\nError:\n");
|
||||
mu::console() << _T("------\n");
|
||||
mu::console() << _T("Message: ") << e.GetMsg() << _T("\n");
|
||||
mu::console() << _T("Expression: \"") << e.GetExpr() << _T("\"\n");
|
||||
mu::console() << _T("Token: \"") << e.GetToken() << _T("\"\n");
|
||||
mu::console() << _T("Position: ") << (int)e.GetPos() << _T("\n");
|
||||
mu::console() << _T("Errc: ") << std::dec << e.GetCode() << _T("\n");
|
||||
}
|
||||
} // while running
|
||||
} // while running
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
int main(int, char**)
|
||||
{
|
||||
Splash();
|
||||
SelfTest();
|
||||
Help();
|
||||
int main(int, char **) {
|
||||
Splash();
|
||||
SelfTest();
|
||||
Help();
|
||||
|
||||
// CheckLocale();
|
||||
// CheckDiff();
|
||||
// CheckLocale();
|
||||
// CheckDiff();
|
||||
|
||||
mu::console() << _T("Enter an expression or a command:\n");
|
||||
mu::console() << _T("Enter an expression or a command:\n");
|
||||
|
||||
try
|
||||
{
|
||||
Calc();
|
||||
}
|
||||
catch(Parser::exception_type &e)
|
||||
{
|
||||
// Only erros raised during the initialization will end up here
|
||||
// formula related errors are treated in Calc()
|
||||
console() << _T("Initialization error: ") << e.GetMsg() << endl;
|
||||
console() << _T("aborting...") << endl;
|
||||
string_type sBuf;
|
||||
console_in() >> sBuf;
|
||||
}
|
||||
catch(std::exception & /*exc*/)
|
||||
{
|
||||
// there is no unicode compliant way to query exc.what()
|
||||
// so i'll leave it for this example.
|
||||
console() << _T("aborting...\n");
|
||||
}
|
||||
try {
|
||||
Calc();
|
||||
} catch (Parser::exception_type &e) {
|
||||
// Only erros raised during the initialization will end up here
|
||||
// formula related errors are treated in Calc()
|
||||
console() << _T("Initialization error: ") << e.GetMsg() << endl;
|
||||
console() << _T("aborting...") << endl;
|
||||
string_type sBuf;
|
||||
console_in() >> sBuf;
|
||||
} catch (std::exception & /*exc*/) {
|
||||
// there is no unicode compliant way to query exc.what()
|
||||
// so i'll leave it for this example.
|
||||
console() << _T("aborting...\n");
|
||||
}
|
||||
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -765,10 +765,6 @@ void ParserBase::ApplyFunc(ParserStack<token_type> &a_stOpt, ParserStack<token_t
|
||||
ApplyStrFunc(funTok, stArg);
|
||||
break;
|
||||
|
||||
case cmFUNC_BULK:
|
||||
m_vRPN.AddBulkFun(funTok.GetFuncAddr(), (int)stArg.size());
|
||||
break;
|
||||
|
||||
case cmOPRT_BIN:
|
||||
case cmOPRT_POSTFIX:
|
||||
case cmOPRT_INFIX:
|
||||
@@ -895,22 +891,8 @@ void ParserBase::ApplyRemainingOprt(ParserStack<token_type> &stOpt,
|
||||
associated operators. The Stack is filled beginning from index one the
|
||||
value at index zero is not used at all.
|
||||
*/
|
||||
value_type ParserBase::ParseCmdCode() const { return ParseCmdCodeBulk(0, 0); }
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
/** \brief Evaluate the RPN.
|
||||
\param nOffset The offset added to variable addresses (for bulk mode)
|
||||
\param nThreadID OpenMP Thread id of the calling thread
|
||||
*/
|
||||
value_type ParserBase::ParseCmdCodeBulk(int nOffset, int nThreadID) const {
|
||||
assert(nThreadID <= s_MaxNumOpenMPThreads);
|
||||
|
||||
// Note: The check for nOffset==0 and nThreadID here is not necessary but
|
||||
// brings a minor performance gain when not in bulk mode.
|
||||
value_type *Stack =
|
||||
((nOffset == 0) && (nThreadID == 0))
|
||||
? &m_vStackBuffer[0]
|
||||
: &m_vStackBuffer[nThreadID * (m_vStackBuffer.size() / s_MaxNumOpenMPThreads)];
|
||||
value_type ParserBase::ParseCmdCode() const {
|
||||
value_type *Stack = &m_vStackBuffer[0];
|
||||
value_type buf;
|
||||
int sidx(0);
|
||||
for (const SToken *pTok = m_vRPN.GetBase(); pTok->Cmd != cmEND; ++pTok) {
|
||||
@@ -980,7 +962,7 @@ value_type ParserBase::ParseCmdCodeBulk(int nOffset, int nThreadID) const {
|
||||
// for details see:
|
||||
// https://groups.google.com/forum/embed/?place=forum/muparser-dev&showsearch=true&showpopout=true&showtabs=false&parenturl=http://muparser.beltoforion.de/mup_forum.html&afterlogin&pli=1#!topic/muparser-dev/szgatgoHTws
|
||||
--sidx;
|
||||
Stack[sidx] = *(pTok->Oprt.ptr + nOffset) = Stack[sidx + 1];
|
||||
Stack[sidx] = *(pTok->Oprt.ptr) = Stack[sidx + 1];
|
||||
continue;
|
||||
// original code:
|
||||
//--sidx; Stack[sidx] = *pTok->Oprt.ptr = Stack[sidx+1]; continue;
|
||||
@@ -1007,29 +989,29 @@ value_type ParserBase::ParseCmdCodeBulk(int nOffset, int nThreadID) const {
|
||||
|
||||
// value and variable tokens
|
||||
case cmVAR:
|
||||
Stack[++sidx] = *(pTok->Val.ptr + nOffset);
|
||||
Stack[++sidx] = *(pTok->Val.ptr);
|
||||
continue;
|
||||
case cmVAL:
|
||||
Stack[++sidx] = pTok->Val.data2;
|
||||
continue;
|
||||
|
||||
case cmVARPOW2:
|
||||
buf = *(pTok->Val.ptr + nOffset);
|
||||
buf = *(pTok->Val.ptr);
|
||||
Stack[++sidx] = buf * buf;
|
||||
continue;
|
||||
|
||||
case cmVARPOW3:
|
||||
buf = *(pTok->Val.ptr + nOffset);
|
||||
buf = *(pTok->Val.ptr);
|
||||
Stack[++sidx] = buf * buf * buf;
|
||||
continue;
|
||||
|
||||
case cmVARPOW4:
|
||||
buf = *(pTok->Val.ptr + nOffset);
|
||||
buf = *(pTok->Val.ptr);
|
||||
Stack[++sidx] = buf * buf * buf * buf;
|
||||
continue;
|
||||
|
||||
case cmVARMUL:
|
||||
Stack[++sidx] = *(pTok->Val.ptr + nOffset) * pTok->Val.data + pTok->Val.data2;
|
||||
Stack[++sidx] = *(pTok->Val.ptr) * pTok->Val.data + pTok->Val.data2;
|
||||
continue;
|
||||
|
||||
// Next is treatment of numeric functions
|
||||
@@ -1135,80 +1117,6 @@ value_type ParserBase::ParseCmdCodeBulk(int nOffset, int nThreadID) const {
|
||||
continue;
|
||||
}
|
||||
|
||||
case cmFUNC_BULK: {
|
||||
int iArgCount = pTok->Fun.argc;
|
||||
|
||||
// switch according to argument count
|
||||
switch (iArgCount) {
|
||||
case 0:
|
||||
sidx += 1;
|
||||
Stack[sidx] = (*(bulkfun_type0)pTok->Fun.ptr)(nOffset, nThreadID);
|
||||
continue;
|
||||
case 1:
|
||||
Stack[sidx] =
|
||||
(*(bulkfun_type1)pTok->Fun.ptr)(nOffset, nThreadID, Stack[sidx]);
|
||||
continue;
|
||||
case 2:
|
||||
sidx -= 1;
|
||||
Stack[sidx] = (*(bulkfun_type2)pTok->Fun.ptr)(nOffset, nThreadID,
|
||||
Stack[sidx], Stack[sidx + 1]);
|
||||
continue;
|
||||
case 3:
|
||||
sidx -= 2;
|
||||
Stack[sidx] = (*(bulkfun_type3)pTok->Fun.ptr)(
|
||||
nOffset, nThreadID, Stack[sidx], Stack[sidx + 1], Stack[sidx + 2]);
|
||||
continue;
|
||||
case 4:
|
||||
sidx -= 3;
|
||||
Stack[sidx] = (*(bulkfun_type4)pTok->Fun.ptr)(
|
||||
nOffset, nThreadID, Stack[sidx], Stack[sidx + 1], Stack[sidx + 2],
|
||||
Stack[sidx + 3]);
|
||||
continue;
|
||||
case 5:
|
||||
sidx -= 4;
|
||||
Stack[sidx] = (*(bulkfun_type5)pTok->Fun.ptr)(
|
||||
nOffset, nThreadID, Stack[sidx], Stack[sidx + 1], Stack[sidx + 2],
|
||||
Stack[sidx + 3], Stack[sidx + 4]);
|
||||
continue;
|
||||
case 6:
|
||||
sidx -= 5;
|
||||
Stack[sidx] = (*(bulkfun_type6)pTok->Fun.ptr)(
|
||||
nOffset, nThreadID, Stack[sidx], Stack[sidx + 1], Stack[sidx + 2],
|
||||
Stack[sidx + 3], Stack[sidx + 4], Stack[sidx + 5]);
|
||||
continue;
|
||||
case 7:
|
||||
sidx -= 6;
|
||||
Stack[sidx] = (*(bulkfun_type7)pTok->Fun.ptr)(
|
||||
nOffset, nThreadID, Stack[sidx], Stack[sidx + 1], Stack[sidx + 2],
|
||||
Stack[sidx + 3], Stack[sidx + 4], Stack[sidx + 5], Stack[sidx + 6]);
|
||||
continue;
|
||||
case 8:
|
||||
sidx -= 7;
|
||||
Stack[sidx] = (*(bulkfun_type8)pTok->Fun.ptr)(
|
||||
nOffset, nThreadID, Stack[sidx], Stack[sidx + 1], Stack[sidx + 2],
|
||||
Stack[sidx + 3], Stack[sidx + 4], Stack[sidx + 5], Stack[sidx + 6],
|
||||
Stack[sidx + 7]);
|
||||
continue;
|
||||
case 9:
|
||||
sidx -= 8;
|
||||
Stack[sidx] = (*(bulkfun_type9)pTok->Fun.ptr)(
|
||||
nOffset, nThreadID, Stack[sidx], Stack[sidx + 1], Stack[sidx + 2],
|
||||
Stack[sidx + 3], Stack[sidx + 4], Stack[sidx + 5], Stack[sidx + 6],
|
||||
Stack[sidx + 7], Stack[sidx + 8]);
|
||||
continue;
|
||||
case 10:
|
||||
sidx -= 9;
|
||||
Stack[sidx] = (*(bulkfun_type10)pTok->Fun.ptr)(
|
||||
nOffset, nThreadID, Stack[sidx], Stack[sidx + 1], Stack[sidx + 2],
|
||||
Stack[sidx + 3], Stack[sidx + 4], Stack[sidx + 5], Stack[sidx + 6],
|
||||
Stack[sidx + 7], Stack[sidx + 8], Stack[sidx + 9]);
|
||||
continue;
|
||||
default:
|
||||
assert(0 && "muParser internal error");
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
default:
|
||||
assert(0 && "muParser internal error");
|
||||
return 0;
|
||||
@@ -1300,8 +1208,7 @@ void ParserBase::CreateRPN() const {
|
||||
|
||||
if (iArgCount > 1 &&
|
||||
(stOpt.size() == 0 ||
|
||||
(stOpt.top().GetCode() != cmFUNC && stOpt.top().GetCode() != cmFUNC_BULK &&
|
||||
stOpt.top().GetCode() != cmFUNC_STR)))
|
||||
(stOpt.top().GetCode() != cmFUNC && stOpt.top().GetCode() != cmFUNC_STR)))
|
||||
Error(ecUNEXPECTED_ARG, m_pTokenReader->GetPos());
|
||||
|
||||
// The opening bracket was popped from the stack now check if there
|
||||
@@ -1379,7 +1286,6 @@ void ParserBase::CreateRPN() const {
|
||||
|
||||
case cmOPRT_INFIX:
|
||||
case cmFUNC:
|
||||
case cmFUNC_BULK:
|
||||
case cmFUNC_STR:
|
||||
stOpt.push(opt);
|
||||
break;
|
||||
@@ -1624,9 +1530,6 @@ void ParserBase::StackDump(const ParserStack<token_type> &a_stVal,
|
||||
case cmFUNC:
|
||||
mu::console() << _T("FUNC \"") << stOprt.top().GetAsString() << _T("\"\n");
|
||||
break;
|
||||
case cmFUNC_BULK:
|
||||
mu::console() << _T("FUNC_BULK \"") << stOprt.top().GetAsString() << _T("\"\n");
|
||||
break;
|
||||
case cmOPRT_INFIX:
|
||||
mu::console() << _T("OPRT_INFIX \"") << stOprt.top().GetAsString()
|
||||
<< _T("\"\n");
|
||||
@@ -1712,23 +1615,4 @@ int ParserBase::GetNumResults() const { return m_nFinalResultIdx; }
|
||||
*/
|
||||
value_type ParserBase::Eval() const { return (this->*m_pParseFormula)(); }
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
void ParserBase::Eval(value_type *results, int nBulkSize) {
|
||||
/* <ibg 2014-09-24/> Commented because it is making a unit test impossible
|
||||
|
||||
// Parallelization does not make sense for fewer than 10000 computations
|
||||
// due to thread creation overhead. If the bulk size is below 2000
|
||||
// computation is refused.
|
||||
if (nBulkSize<2000)
|
||||
{
|
||||
throw ParserError(ecUNREASONABLE_NUMBER_OF_COMPUTATIONS);
|
||||
}
|
||||
*/
|
||||
CreateRPN();
|
||||
|
||||
int i = 0;
|
||||
for (i = 0; i < nBulkSize; ++i) {
|
||||
results[i] = ParseCmdCodeBulk(i, 0);
|
||||
}
|
||||
}
|
||||
} // namespace mu
|
||||
|
||||
@@ -380,24 +380,7 @@ void ParserByteCode::AddFun(generic_fun_type a_pFun, int a_iArgc) {
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
/** \brief Add a bulk function to bytecode.
|
||||
|
||||
\param a_iArgc Number of arguments, negative numbers indicate multiarg functions.
|
||||
\param a_pFun Pointer to function callback.
|
||||
*/
|
||||
void ParserByteCode::AddBulkFun(generic_fun_type a_pFun, int a_iArgc) {
|
||||
m_iStackPos = m_iStackPos - a_iArgc + 1;
|
||||
m_iMaxStackSize = std::max(m_iMaxStackSize, (size_t)m_iStackPos);
|
||||
|
||||
SToken tok;
|
||||
tok.Cmd = cmFUNC_BULK;
|
||||
tok.Fun.argc = a_iArgc;
|
||||
tok.Fun.ptr = a_pFun;
|
||||
m_vRPN.push_back(tok);
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
/** \brief Add Strung function entry to the parser bytecode.
|
||||
/** \brief Add String function entry to the parser bytecode.
|
||||
\throw nothrow
|
||||
|
||||
A string function entry consists of the stack position of the return value,
|
||||
|
||||
@@ -161,119 +161,6 @@ ParserCallback::ParserCallback(fun_type10 a_pFun, bool a_bAllowOpti)
|
||||
m_iType(tpDBL),
|
||||
m_bAllowOpti(a_bAllowOpti) {}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
ParserCallback::ParserCallback(bulkfun_type0 a_pFun, bool a_bAllowOpti)
|
||||
: m_pFun((void*)a_pFun),
|
||||
m_iArgc(0),
|
||||
m_iPri(-1),
|
||||
m_eOprtAsct(oaNONE),
|
||||
m_iCode(cmFUNC_BULK),
|
||||
m_iType(tpDBL),
|
||||
m_bAllowOpti(a_bAllowOpti) {}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
ParserCallback::ParserCallback(bulkfun_type1 a_pFun, bool a_bAllowOpti)
|
||||
: m_pFun((void*)a_pFun),
|
||||
m_iArgc(1),
|
||||
m_iPri(-1),
|
||||
m_eOprtAsct(oaNONE),
|
||||
m_iCode(cmFUNC_BULK),
|
||||
m_iType(tpDBL),
|
||||
m_bAllowOpti(a_bAllowOpti) {}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
/** \brief Constructor for constructing function callbacks taking two arguments.
|
||||
\throw nothrow
|
||||
*/
|
||||
ParserCallback::ParserCallback(bulkfun_type2 a_pFun, bool a_bAllowOpti)
|
||||
: m_pFun((void*)a_pFun),
|
||||
m_iArgc(2),
|
||||
m_iPri(-1),
|
||||
m_eOprtAsct(oaNONE),
|
||||
m_iCode(cmFUNC_BULK),
|
||||
m_iType(tpDBL),
|
||||
m_bAllowOpti(a_bAllowOpti) {}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
ParserCallback::ParserCallback(bulkfun_type3 a_pFun, bool a_bAllowOpti)
|
||||
: m_pFun((void*)a_pFun),
|
||||
m_iArgc(3),
|
||||
m_iPri(-1),
|
||||
m_eOprtAsct(oaNONE),
|
||||
m_iCode(cmFUNC_BULK),
|
||||
m_iType(tpDBL),
|
||||
m_bAllowOpti(a_bAllowOpti) {}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
ParserCallback::ParserCallback(bulkfun_type4 a_pFun, bool a_bAllowOpti)
|
||||
: m_pFun((void*)a_pFun),
|
||||
m_iArgc(4),
|
||||
m_iPri(-1),
|
||||
m_eOprtAsct(oaNONE),
|
||||
m_iCode(cmFUNC_BULK),
|
||||
m_iType(tpDBL),
|
||||
m_bAllowOpti(a_bAllowOpti) {}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
ParserCallback::ParserCallback(bulkfun_type5 a_pFun, bool a_bAllowOpti)
|
||||
: m_pFun((void*)a_pFun),
|
||||
m_iArgc(5),
|
||||
m_iPri(-1),
|
||||
m_eOprtAsct(oaNONE),
|
||||
m_iCode(cmFUNC_BULK),
|
||||
m_iType(tpDBL),
|
||||
m_bAllowOpti(a_bAllowOpti) {}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
ParserCallback::ParserCallback(bulkfun_type6 a_pFun, bool a_bAllowOpti)
|
||||
: m_pFun((void*)a_pFun),
|
||||
m_iArgc(6),
|
||||
m_iPri(-1),
|
||||
m_eOprtAsct(oaNONE),
|
||||
m_iCode(cmFUNC_BULK),
|
||||
m_iType(tpDBL),
|
||||
m_bAllowOpti(a_bAllowOpti) {}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
ParserCallback::ParserCallback(bulkfun_type7 a_pFun, bool a_bAllowOpti)
|
||||
: m_pFun((void*)a_pFun),
|
||||
m_iArgc(7),
|
||||
m_iPri(-1),
|
||||
m_eOprtAsct(oaNONE),
|
||||
m_iCode(cmFUNC_BULK),
|
||||
m_iType(tpDBL),
|
||||
m_bAllowOpti(a_bAllowOpti) {}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
ParserCallback::ParserCallback(bulkfun_type8 a_pFun, bool a_bAllowOpti)
|
||||
: m_pFun((void*)a_pFun),
|
||||
m_iArgc(8),
|
||||
m_iPri(-1),
|
||||
m_eOprtAsct(oaNONE),
|
||||
m_iCode(cmFUNC_BULK),
|
||||
m_iType(tpDBL),
|
||||
m_bAllowOpti(a_bAllowOpti) {}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
ParserCallback::ParserCallback(bulkfun_type9 a_pFun, bool a_bAllowOpti)
|
||||
: m_pFun((void*)a_pFun),
|
||||
m_iArgc(9),
|
||||
m_iPri(-1),
|
||||
m_eOprtAsct(oaNONE),
|
||||
m_iCode(cmFUNC_BULK),
|
||||
m_iType(tpDBL),
|
||||
m_bAllowOpti(a_bAllowOpti) {}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
ParserCallback::ParserCallback(bulkfun_type10 a_pFun, bool a_bAllowOpti)
|
||||
: m_pFun((void*)a_pFun),
|
||||
m_iArgc(10),
|
||||
m_iPri(-1),
|
||||
m_eOprtAsct(oaNONE),
|
||||
m_iCode(cmFUNC_BULK),
|
||||
m_iType(tpDBL),
|
||||
m_bAllowOpti(a_bAllowOpti) {}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
ParserCallback::ParserCallback(multfun_type a_pFun, bool a_bAllowOpti)
|
||||
: m_pFun((void*)a_pFun),
|
||||
|
||||
@@ -213,14 +213,6 @@ API_EXPORT(muFloat_t*) mupEvalMulti(muParserHandle_t a_hParser, int* nNum) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
API_EXPORT(void) mupEvalBulk(muParserHandle_t a_hParser, muFloat_t* a_res, int nSize) {
|
||||
MU_TRY
|
||||
muParser_t* p(AsParser(a_hParser));
|
||||
p->Eval(a_res, nSize);
|
||||
MU_CATCH
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
API_EXPORT(void) mupSetExpr(muParserHandle_t a_hParser, const muChar_t* a_szExpr) {
|
||||
MU_TRY
|
||||
@@ -388,105 +380,6 @@ mupDefineFun10(muParserHandle_t a_hParser, const muChar_t* a_szName, muFun10_t a
|
||||
MU_CATCH
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
API_EXPORT(void)
|
||||
mupDefineBulkFun0(muParserHandle_t a_hParser, const muChar_t* a_szName, muBulkFun0_t a_pFun) {
|
||||
MU_TRY
|
||||
muParser_t* const p(AsParser(a_hParser));
|
||||
p->DefineFun(a_szName, a_pFun, false);
|
||||
MU_CATCH
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
API_EXPORT(void)
|
||||
mupDefineBulkFun1(muParserHandle_t a_hParser, const muChar_t* a_szName, muBulkFun1_t a_pFun) {
|
||||
MU_TRY
|
||||
muParser_t* const p(AsParser(a_hParser));
|
||||
p->DefineFun(a_szName, a_pFun, false);
|
||||
MU_CATCH
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
API_EXPORT(void)
|
||||
mupDefineBulkFun2(muParserHandle_t a_hParser, const muChar_t* a_szName, muBulkFun2_t a_pFun) {
|
||||
MU_TRY
|
||||
muParser_t* const p(AsParser(a_hParser));
|
||||
p->DefineFun(a_szName, a_pFun, false);
|
||||
MU_CATCH
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
API_EXPORT(void)
|
||||
mupDefineBulkFun3(muParserHandle_t a_hParser, const muChar_t* a_szName, muBulkFun3_t a_pFun) {
|
||||
MU_TRY
|
||||
muParser_t* const p(AsParser(a_hParser));
|
||||
p->DefineFun(a_szName, a_pFun, false);
|
||||
MU_CATCH
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
API_EXPORT(void)
|
||||
mupDefineBulkFun4(muParserHandle_t a_hParser, const muChar_t* a_szName, muBulkFun4_t a_pFun) {
|
||||
MU_TRY
|
||||
muParser_t* const p(AsParser(a_hParser));
|
||||
p->DefineFun(a_szName, a_pFun, false);
|
||||
MU_CATCH
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
API_EXPORT(void)
|
||||
mupDefineBulkFun5(muParserHandle_t a_hParser, const muChar_t* a_szName, muBulkFun5_t a_pFun) {
|
||||
MU_TRY
|
||||
muParser_t* const p(AsParser(a_hParser));
|
||||
p->DefineFun(a_szName, a_pFun, false);
|
||||
MU_CATCH
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
API_EXPORT(void)
|
||||
mupDefineBulkFun6(muParserHandle_t a_hParser, const muChar_t* a_szName, muBulkFun6_t a_pFun) {
|
||||
MU_TRY
|
||||
muParser_t* const p(AsParser(a_hParser));
|
||||
p->DefineFun(a_szName, a_pFun, false);
|
||||
MU_CATCH
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
API_EXPORT(void)
|
||||
mupDefineBulkFun7(muParserHandle_t a_hParser, const muChar_t* a_szName, muBulkFun7_t a_pFun) {
|
||||
MU_TRY
|
||||
muParser_t* const p(AsParser(a_hParser));
|
||||
p->DefineFun(a_szName, a_pFun, false);
|
||||
MU_CATCH
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
API_EXPORT(void)
|
||||
mupDefineBulkFun8(muParserHandle_t a_hParser, const muChar_t* a_szName, muBulkFun8_t a_pFun) {
|
||||
MU_TRY
|
||||
muParser_t* const p(AsParser(a_hParser));
|
||||
p->DefineFun(a_szName, a_pFun, false);
|
||||
MU_CATCH
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
API_EXPORT(void)
|
||||
mupDefineBulkFun9(muParserHandle_t a_hParser, const muChar_t* a_szName, muBulkFun9_t a_pFun) {
|
||||
MU_TRY
|
||||
muParser_t* const p(AsParser(a_hParser));
|
||||
p->DefineFun(a_szName, a_pFun, false);
|
||||
MU_CATCH
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
API_EXPORT(void)
|
||||
mupDefineBulkFun10(muParserHandle_t a_hParser, const muChar_t* a_szName, muBulkFun10_t a_pFun) {
|
||||
MU_TRY
|
||||
muParser_t* const p(AsParser(a_hParser));
|
||||
p->DefineFun(a_szName, a_pFun, false);
|
||||
MU_CATCH
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
API_EXPORT(void)
|
||||
mupDefineStrFun1(muParserHandle_t a_hParser, const muChar_t* a_szName, muStrFun1_t a_pFun) {
|
||||
|
||||
@@ -57,7 +57,6 @@ ParserTester::ParserTester() : m_vTestFun() {
|
||||
AddTest(&ParserTester::TestBinOprt);
|
||||
AddTest(&ParserTester::TestException);
|
||||
AddTest(&ParserTester::TestStrArg);
|
||||
AddTest(&ParserTester::TestBulkMode);
|
||||
|
||||
ParserTester::c_iCount = 0;
|
||||
}
|
||||
@@ -142,39 +141,6 @@ int ParserTester::TestStrArg() {
|
||||
return iStat;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------------------------
|
||||
int ParserTester::TestBulkMode() {
|
||||
int iStat = 0;
|
||||
mu::console() << _T("testing bulkmode...");
|
||||
|
||||
#define EQN_TEST_BULK(EXPR, R1, R2, R3, R4, PASS) \
|
||||
{ \
|
||||
double res[] = {R1, R2, R3, R4}; \
|
||||
iStat += EqnTestBulk(_T(EXPR), res, (PASS)); \
|
||||
}
|
||||
|
||||
// Bulk Variables for the test:
|
||||
// a: 1,2,3,4
|
||||
// b: 2,2,2,2
|
||||
// c: 3,3,3,3
|
||||
// d: 5,4,3,2
|
||||
EQN_TEST_BULK("a", 1, 1, 1, 1, false)
|
||||
EQN_TEST_BULK("a", 1, 2, 3, 4, true)
|
||||
EQN_TEST_BULK("b=a", 1, 2, 3, 4, true)
|
||||
EQN_TEST_BULK("b=a, b*10", 10, 20, 30, 40, true)
|
||||
EQN_TEST_BULK("b=a, b*10, a", 1, 2, 3, 4, true)
|
||||
EQN_TEST_BULK("a+b", 3, 4, 5, 6, true)
|
||||
EQN_TEST_BULK("c*(a+b)", 9, 12, 15, 18, true)
|
||||
#undef EQN_TEST_BULK
|
||||
|
||||
if (iStat == 0)
|
||||
mu::console() << _T("passed") << endl;
|
||||
else
|
||||
mu::console() << _T("\n failed with ") << iStat << _T(" errors") << endl;
|
||||
|
||||
return iStat;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------------------------
|
||||
int ParserTester::TestBinOprt() {
|
||||
int iStat = 0;
|
||||
@@ -1388,56 +1354,6 @@ int ParserTester::EqnTestInt(const string_type &a_str, double a_fRes, bool a_fPa
|
||||
return iRet;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
/** \brief Test an expression in Bulk Mode. */
|
||||
int ParserTester::EqnTestBulk(const string_type &a_str, double a_fRes[4], bool a_fPass) {
|
||||
ParserTester::c_iCount++;
|
||||
|
||||
// Define Bulk Variables
|
||||
int nBulkSize = 4;
|
||||
value_type vVariableA[] = {1, 2, 3, 4}; // variable values
|
||||
value_type vVariableB[] = {2, 2, 2, 2}; // variable values
|
||||
value_type vVariableC[] = {3, 3, 3, 3}; // variable values
|
||||
value_type vResults[] = {0, 0, 0, 0}; // variable values
|
||||
int iRet(0);
|
||||
|
||||
try {
|
||||
Parser p;
|
||||
p.DefineConst(_T("const1"), 1);
|
||||
p.DefineConst(_T("const2"), 2);
|
||||
p.DefineVar(_T("a"), vVariableA);
|
||||
p.DefineVar(_T("b"), vVariableB);
|
||||
p.DefineVar(_T("c"), vVariableC);
|
||||
|
||||
p.SetExpr(a_str);
|
||||
p.Eval(vResults, nBulkSize);
|
||||
|
||||
bool bCloseEnough(true);
|
||||
for (int i = 0; i < nBulkSize; ++i) {
|
||||
bCloseEnough &= (fabs(a_fRes[i] - vResults[i]) <= fabs(a_fRes[i] * 0.00001));
|
||||
}
|
||||
|
||||
iRet = ((bCloseEnough && a_fPass) || (!bCloseEnough && !a_fPass)) ? 0 : 1;
|
||||
if (iRet == 1) {
|
||||
mu::console() << _T("\n fail: ") << a_str.c_str()
|
||||
<< _T(" (incorrect result; expected: {") << a_fRes[0] << _T(",")
|
||||
<< a_fRes[1] << _T(",") << a_fRes[2] << _T(",") << a_fRes[3] << _T("}")
|
||||
<< _T(" ;calculated: ") << vResults[0] << _T(",") << vResults[1]
|
||||
<< _T(",") << vResults[2] << _T(",") << vResults[3] << _T("}");
|
||||
}
|
||||
} catch (Parser::exception_type &e) {
|
||||
if (a_fPass) {
|
||||
mu::console() << _T("\n fail: ") << e.GetExpr() << _T(" : ") << e.GetMsg();
|
||||
iRet = 1;
|
||||
}
|
||||
} catch (...) {
|
||||
mu::console() << _T("\n fail: ") << a_str.c_str() << _T(" (unexpected exception)");
|
||||
iRet = 1; // exceptions other than ParserException are not allowed
|
||||
}
|
||||
|
||||
return iRet;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
/** \brief Internal error in test class Test is going to be aborted. */
|
||||
void ParserTester::Abort() const {
|
||||
|
||||
Reference in New Issue
Block a user