mirror of
https://gitlab.com/c3d/db48x.git
synced 2024-09-29 05:36:58 +02:00
functions: Optimize abs and neg
Optimize `abs` and `neg` functions which can be simplified in almost all cases without invoking the complex "function" mechanism. Signed-off-by: Christophe de Dinechin <christophe@dinechin.org>
This commit is contained in:
parent
f7a7790294
commit
d580089be9
1 changed files with 128 additions and 44 deletions
172
src/functions.cc
172
src/functions.cc
|
@ -235,7 +235,7 @@ object::result function::evaluate(algebraic_fn op, bool mat)
|
|||
{
|
||||
top = list_p(top)->map(op);
|
||||
}
|
||||
else if (is_algebraic(topty))
|
||||
else if (is_algebraic(topty) || (topty == ID_array && mat))
|
||||
{
|
||||
algebraic_g x = algebraic_p(top);
|
||||
x = op(x);
|
||||
|
@ -253,6 +253,87 @@ object::result function::evaluate(algebraic_fn op, bool mat)
|
|||
}
|
||||
|
||||
|
||||
FUNCTION_BODY(neg)
|
||||
// ----------------------------------------------------------------------------
|
||||
// Implementation of 'neg'
|
||||
// ----------------------------------------------------------------------------
|
||||
// Special case where we don't need to promote argument to decimal
|
||||
{
|
||||
if (!x)
|
||||
return nullptr;
|
||||
|
||||
id xt = x->type();
|
||||
switch(xt)
|
||||
{
|
||||
case ID_expression:
|
||||
case ID_local:
|
||||
case ID_symbol:
|
||||
case ID_pi:
|
||||
case ID_ImaginaryUnit:
|
||||
return symbolic(ID_neg, x);
|
||||
|
||||
case ID_integer:
|
||||
case ID_bignum:
|
||||
case ID_fraction:
|
||||
case ID_big_fraction:
|
||||
case ID_decimal:
|
||||
{
|
||||
// We can keep the object, just changing the type
|
||||
id negty = id(xt + 1);
|
||||
algebraic_p clone = algebraic_p(rt.clone(x));
|
||||
byte *tp = (byte *) clone;
|
||||
*tp = negty;
|
||||
return clone;
|
||||
}
|
||||
|
||||
case ID_neg_integer:
|
||||
case ID_neg_bignum:
|
||||
case ID_neg_fraction:
|
||||
case ID_neg_big_fraction:
|
||||
case ID_neg_decimal:
|
||||
{
|
||||
// We can keep the object, just changing the type
|
||||
id negty = id(xt - 1);
|
||||
algebraic_p clone = algebraic_p(rt.clone(x));
|
||||
byte *tp = (byte *) clone;
|
||||
*tp = negty;
|
||||
return clone;
|
||||
}
|
||||
|
||||
case ID_rectangular:
|
||||
return rectangular::make(-rectangular_p(+x)->re(),
|
||||
-rectangular_p(+x)->im());
|
||||
case ID_polar:
|
||||
return polar::make(-polar_p(+x)->mod(),
|
||||
polar_p(+x)->arg(object::ID_PiRadians),
|
||||
object::ID_PiRadians);
|
||||
|
||||
case ID_unit:
|
||||
return unit::simple(neg::run(unit_p(+x)->value()),
|
||||
unit_p(+x)->uexpr());
|
||||
case ID_tag:
|
||||
{
|
||||
algebraic_g tagged = tag_p(+x)->tagged_object()->as_algebraic();
|
||||
return evaluate(tagged);
|
||||
}
|
||||
|
||||
case ID_array:
|
||||
case ID_list:
|
||||
return list_p(+x)->map(neg::evaluate);
|
||||
|
||||
case ID_hwfloat:
|
||||
return hwfloat::neg((hwfloat::hwfp_r) x);
|
||||
case ID_hwdouble:
|
||||
return hwdouble::neg((hwdouble::hwfp_r) x);
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
rt.type_error();
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
||||
FUNCTION_BODY(abs)
|
||||
// ----------------------------------------------------------------------------
|
||||
|
@ -264,13 +345,27 @@ FUNCTION_BODY(abs)
|
|||
return nullptr;
|
||||
|
||||
id xt = x->type();
|
||||
if (should_be_symbolic(xt))
|
||||
switch(xt)
|
||||
{
|
||||
case ID_expression:
|
||||
case ID_local:
|
||||
case ID_symbol:
|
||||
case ID_pi:
|
||||
case ID_ImaginaryUnit:
|
||||
return symbolic(ID_abs, x);
|
||||
|
||||
if (xt == ID_neg_integer ||
|
||||
xt == ID_neg_bignum ||
|
||||
xt == ID_neg_fraction ||
|
||||
xt == ID_neg_big_fraction)
|
||||
case ID_integer:
|
||||
case ID_bignum:
|
||||
case ID_fraction:
|
||||
case ID_big_fraction:
|
||||
case ID_decimal:
|
||||
return x;
|
||||
|
||||
case ID_neg_integer:
|
||||
case ID_neg_bignum:
|
||||
case ID_neg_fraction:
|
||||
case ID_neg_big_fraction:
|
||||
case ID_neg_decimal:
|
||||
{
|
||||
// We can keep the object, just changing the type
|
||||
id absty = id(xt - 1);
|
||||
|
@ -279,26 +374,36 @@ FUNCTION_BODY(abs)
|
|||
*tp = absty;
|
||||
return clone;
|
||||
}
|
||||
else if (is_integer(xt) || is_bignum(xt) || is_fraction(xt))
|
||||
|
||||
case ID_rectangular:
|
||||
case ID_polar:
|
||||
return complex_p(+x)->mod();
|
||||
|
||||
case ID_unit:
|
||||
return unit::simple(abs::run(unit_p(+x)->value()),
|
||||
unit_p(+x)->uexpr());
|
||||
case ID_tag:
|
||||
{
|
||||
// No-op
|
||||
return x;
|
||||
}
|
||||
else if (is_complex(xt))
|
||||
{
|
||||
return complex_p(algebraic_p(x))->mod();
|
||||
}
|
||||
else if (xt == ID_array)
|
||||
{
|
||||
return array_p(algebraic_p(x))->norm();
|
||||
algebraic_g tagged = tag_p(+x)->tagged_object()->as_algebraic();
|
||||
return evaluate(tagged);
|
||||
}
|
||||
|
||||
// Fall-back to floating-point abs
|
||||
static const ops_t optable = { decimal::abs,
|
||||
hwfloat_fn(hwfloat::abs),
|
||||
hwdouble_fn(hwdouble::abs),
|
||||
nullptr };
|
||||
return function::evaluate(x, ID_abs, optable);
|
||||
case ID_array:
|
||||
return array_p(+x)->norm();
|
||||
case ID_list:
|
||||
return list_p(+x)->map(abs::evaluate);
|
||||
|
||||
case ID_hwfloat:
|
||||
return hwfloat::abs((hwfloat::hwfp_r) x);
|
||||
case ID_hwdouble:
|
||||
return hwdouble::abs((hwdouble::hwfp_r) x);
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
rt.type_error();
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
||||
|
@ -544,27 +649,6 @@ INSERT_BODY(inv)
|
|||
}
|
||||
|
||||
|
||||
FUNCTION_BODY(neg)
|
||||
// ----------------------------------------------------------------------------
|
||||
// Negate is implemented as 0-x
|
||||
// ----------------------------------------------------------------------------
|
||||
{
|
||||
if (!x)
|
||||
return nullptr;
|
||||
if (unit_p uobj = x->as<unit>())
|
||||
{
|
||||
algebraic_g v = uobj->value();
|
||||
algebraic_g u = uobj->uexpr();
|
||||
v = neg::run(v);
|
||||
return unit::simple(v, u);
|
||||
}
|
||||
if (x->is_symbolic())
|
||||
return symbolic(ID_neg, x);
|
||||
algebraic_g zero = rt.make<integer>(ID_integer, 0);
|
||||
return zero - x;
|
||||
}
|
||||
|
||||
|
||||
FUNCTION_BODY(sq)
|
||||
// ----------------------------------------------------------------------------
|
||||
// Square is implemented using a multiplication
|
||||
|
|
Loading…
Reference in a new issue