Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 1 addition & 12 deletions parser/mpFuncNonCmplx.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
</pre>
*/
#include "mpFuncNonCmplx.h"
#include "mpFuncRound.h"

//--- Standard includes ----------------------------------------------------
#include <cmath>
Expand All @@ -48,16 +49,6 @@

MUP_NAMESPACE_START

//------------------------------------------------------------------------------
//
// Auxiliary Functions
//
//------------------------------------------------------------------------------
double round(long_double_type number, int_type precision) {
int_type decimals = std::pow(10, precision);
return (std::round(number * decimals)) / decimals;
}

//------------------------------------------------------------------------------
//
//
Expand Down Expand Up @@ -111,7 +102,6 @@ double round(long_double_type number, int_type precision) {
MUP_UNARY_FUNC(FunExp, "exp", std::exp, "exp(x) - e to the power of x")
// number functions
MUP_UNARY_FUNC(FunAbs, "abs", std::fabs, "abs(x) - absolute value of x")
MUP_UNARY_FUNC(FunRound, "round", std::round, "round(x) - round the value of x to its nearest integer")
#undef MUP_UNARY_FUNC

#define MUP_BINARY_FUNC(CLASS, IDENT, FUNC, DESC) \
Expand All @@ -138,7 +128,6 @@ double round(long_double_type number, int_type precision) {
MUP_BINARY_FUNC(FunHypot, "hypot", std::hypot, "hypot(x, y) - compute the length of the vector x,y")
MUP_BINARY_FUNC(FunAtan2, "atan2", std::atan2, "arcus tangens with quadrant fix")
MUP_BINARY_FUNC(FunFmod, "fmod", std::fmod, "fmod(x, y) - floating point remainder of x / y")
MUP_BINARY_FUNC(FunRoundDecimal, "round_decimal", round, "round_decimal(x, y) - round the x number considering y precision")
MUP_BINARY_FUNC(FunRemainder, "remainder", std::remainder, "remainder(x, y) - IEEE remainder of x / y")
#undef MUP_BINARY_FUNC

Expand Down
2 changes: 0 additions & 2 deletions parser/mpFuncNonCmplx.h
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,6 @@ MUP_NAMESPACE_START
MUP_UNARY_FUNC_DEF(FunExp)
// number functions
MUP_UNARY_FUNC_DEF(FunAbs)
MUP_UNARY_FUNC_DEF(FunRound)
#undef MUP_UNARY_FUNC_DEF

#define MUP_BINARY_FUNC_DEF(CLASS) \
Expand All @@ -98,7 +97,6 @@ MUP_NAMESPACE_START
MUP_BINARY_FUNC_DEF(FunHypot)
MUP_BINARY_FUNC_DEF(FunAtan2)
MUP_BINARY_FUNC_DEF(FunFmod)
MUP_BINARY_FUNC_DEF(FunRoundDecimal)
MUP_BINARY_FUNC_DEF(FunRemainder)
#undef MUP_BINARY_FUNC_DEF

Expand Down
94 changes: 94 additions & 0 deletions parser/mpFuncRound.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
#include "mpFuncRound.h"

#include <cmath>

#include "mpError.h"
#include "mpValue.h"

MUP_NAMESPACE_START

namespace
{
void eval_round(ICallback &callback,
ptr_val_type &ret,
const ptr_val_type *args,
int argc,
bool has_precision)
{
int required_argc = has_precision ? 2 : 1;
if (argc < required_argc) {
throw ParserError(ErrorContext(ecTOO_FEW_PARAMS,
callback.GetExprPos(),
callback.GetIdent()));
} else if (argc > required_argc + 1) {
throw ParserError(ErrorContext(ecTOO_MANY_PARAMS,
callback.GetExprPos(),
callback.GetIdent()));
}

int_type scale = 1;
if (has_precision) {
int_type precision = args[1]->GetFloat();
scale = std::pow(10, precision);
}

float_type value = args[0]->GetFloat() * scale;
if (argc == required_argc) {
*ret = std::round(value) / scale;
return;
}

string_type direction = args[required_argc]->GetString();
if (direction == _T("up")) {
*ret = std::ceil(value) / scale;
} else if (direction == _T("down")) {
*ret = std::floor(value) / scale;
} else {
ErrorContext err(ecINVALID_PARAMETER,
callback.GetExprPos(),
callback.GetIdent());
err.Arg = required_argc + 1;
throw ParserError(err);
}
}
}

FunRound::FunRound()
:ICallback(cmFUNC, _T("round"), -1)
{}

void FunRound::Eval(ptr_val_type &ret, const ptr_val_type *a_pArg, int a_iArgc)
{
eval_round(*this, ret, a_pArg, a_iArgc, false);
}

const char_type* FunRound::GetDesc() const
{
return _T("round(x[, direction]) - round x normally, up or down");
}

IToken* FunRound::Clone() const
{
return new FunRound(*this);
}

FunRoundDecimal::FunRoundDecimal()
:ICallback(cmFUNC, _T("round_decimal"), -1)
{}

void FunRoundDecimal::Eval(ptr_val_type &ret, const ptr_val_type *a_pArg, int a_iArgc)
{
eval_round(*this, ret, a_pArg, a_iArgc, true);
}

const char_type* FunRoundDecimal::GetDesc() const
{
return _T("round_decimal(x, precision[, direction]) - round x at the given precision");
}

IToken* FunRoundDecimal::Clone() const
{
return new FunRoundDecimal(*this);
}

MUP_NAMESPACE_END
28 changes: 28 additions & 0 deletions parser/mpFuncRound.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
#ifndef MUP_FUNC_ROUND_H
#define MUP_FUNC_ROUND_H

#include "mpICallback.h"

MUP_NAMESPACE_START

class FunRound : public ICallback
{
public:
FunRound();
virtual void Eval(ptr_val_type &ret, const ptr_val_type *a_pArg, int a_iArgc) override;
virtual const char_type* GetDesc() const override;
virtual IToken* Clone() const override;
};

class FunRoundDecimal : public ICallback
{
public:
FunRoundDecimal();
virtual void Eval(ptr_val_type &ret, const ptr_val_type *a_pArg, int a_iArgc) override;
virtual const char_type* GetDesc() const override;
virtual IToken* Clone() const override;
};

MUP_NAMESPACE_END

#endif
1 change: 1 addition & 0 deletions parser/mpPackageNonCmplx.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@

#include "mpParserBase.h"
#include "mpFuncNonCmplx.h"
#include "mpFuncRound.h"
#include "mpOprtNonCmplx.h"
#include "mpOprtBinCommon.h"

Expand Down
8 changes: 8 additions & 0 deletions tests.sh
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,10 @@ test_eval "10.5 / 5.25" "2"
test_eval "abs(-5)" "5"
test_eval "log10(10)" "1"
test_eval "round(4.4)" "4"
test_eval 'round(10.1, "up")' "11"
test_eval 'round(10.9, "down")' "10"
test_eval 'round(-10.9, "up")' "-10"
test_eval 'round(-10.1, "down")' "-11"
test_eval "(3^3)^2" "729"
test_eval "3^(3^(2))" "19683"
test_eval "10!" "3628800"
Expand All @@ -75,6 +79,10 @@ test_eval "max(1, 2) + min(3, 4) + sum(5, 6)" "16"
test_eval "avg(9, 9.8, 10)" "9.6"
test_eval "pow(2, 3)" "8"
test_eval "round_decimal(4.559, 2)" "4.56"
test_eval 'round_decimal(10.11, 1, "up")' "10.2"
test_eval 'round_decimal(10.19, 1, "down")' "10.1"
test_eval 'round_decimal(-10.19, 1, "up")' "-10.1"
test_eval 'round_decimal(-10.11, 1, "down")' "-10.2"

# Conditional tests
test_eval "4 > 2 ? \"bigger\" : \"smaller\"" "\"bigger\""
Expand Down