kopia lustrzana https://github.com/fellesverkstedet/fabmodules
559 wiersze
13 KiB
C++
559 wiersze
13 KiB
C++
#include "numeric_nodes.hpp"
|
|
#include "switches.hpp"
|
|
|
|
using namespace std;
|
|
|
|
using boost::logic::indeterminate;
|
|
using namespace boost::numeric::interval_lib;
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
NumericAbs::NumericAbs()
|
|
: UnaryNode(OP_ABS)
|
|
{
|
|
// Nothing to do here.
|
|
}
|
|
|
|
void NumericAbs::eval(const float X, const float Y, const float Z)
|
|
{
|
|
result_float = abs(child->result_float);
|
|
}
|
|
|
|
void NumericAbs::eval(const FabInterval& X,
|
|
const FabInterval& Y,
|
|
const FabInterval& Z)
|
|
{
|
|
result_interval = abs(child->result_interval);
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
NumericCos::NumericCos()
|
|
: UnaryNode(OP_COS)
|
|
{
|
|
// Nothing to do here.
|
|
}
|
|
|
|
void NumericCos::eval(const float X, const float Y, const float Z)
|
|
{
|
|
result_float = cos(child->result_float);
|
|
}
|
|
|
|
void NumericCos::eval(const FabInterval& X,
|
|
const FabInterval& Y,
|
|
const FabInterval& Z)
|
|
{
|
|
result_interval = cos(child->result_interval);
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
NumericSin::NumericSin()
|
|
: UnaryNode(OP_SIN)
|
|
{
|
|
// Nothing to do here.
|
|
}
|
|
|
|
void NumericSin::eval(const float X, const float Y, const float Z)
|
|
{
|
|
result_float = sin(child->result_float);
|
|
}
|
|
|
|
void NumericSin::eval(const FabInterval& X,
|
|
const FabInterval& Y,
|
|
const FabInterval& Z)
|
|
{
|
|
result_interval = sin(child->result_interval);
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
NumericACos::NumericACos()
|
|
: UnaryNode(OP_ACOS)
|
|
{
|
|
// Nothing to do here.
|
|
}
|
|
|
|
void NumericACos::eval(const float X, const float Y, const float Z)
|
|
{
|
|
result_float = acos(child->result_float);
|
|
}
|
|
|
|
void NumericACos::eval(const FabInterval& X,
|
|
const FabInterval& Y,
|
|
const FabInterval& Z)
|
|
{
|
|
result_interval = acos(child->result_interval);
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
NumericASin::NumericASin()
|
|
: UnaryNode(OP_ASIN)
|
|
{
|
|
// Nothing to do here.
|
|
}
|
|
|
|
void NumericASin::eval(const float X, const float Y, const float Z)
|
|
{
|
|
result_float = asin(child->result_float);
|
|
}
|
|
|
|
void NumericASin::eval(const FabInterval& X,
|
|
const FabInterval& Y,
|
|
const FabInterval& Z)
|
|
{
|
|
result_interval = asin(child->result_interval);
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
NumericATan::NumericATan()
|
|
: UnaryNode(OP_ATAN)
|
|
{
|
|
// Nothing to do here.
|
|
}
|
|
|
|
void NumericATan::eval(const float X, const float Y, const float Z)
|
|
{
|
|
result_float = atan(child->result_float);
|
|
}
|
|
|
|
void NumericATan::eval(const FabInterval& X,
|
|
const FabInterval& Y,
|
|
const FabInterval& Z)
|
|
{
|
|
result_interval = atan(child->result_interval);
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
NumericSqrt::NumericSqrt()
|
|
: UnaryNode(OP_SQRT)
|
|
{
|
|
// Nothing to do here.
|
|
}
|
|
|
|
void NumericSqrt::eval(const float X, const float Y, const float Z)
|
|
{
|
|
result_float = sqrt(child->result_float);
|
|
}
|
|
|
|
void NumericSqrt::eval(const FabInterval& X,
|
|
const FabInterval& Y,
|
|
const FabInterval& Z)
|
|
{
|
|
result_interval = sqrt(child->result_interval);
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
NumericNeg::NumericNeg()
|
|
: UnaryNode(OP_NEGATIVE)
|
|
{
|
|
// Nothing to do here.
|
|
}
|
|
|
|
void NumericNeg::eval(const float X, const float Y, const float Z)
|
|
{
|
|
result_float = -child->result_float;
|
|
}
|
|
|
|
void NumericNeg::eval(const FabInterval& X,
|
|
const FabInterval& Y,
|
|
const FabInterval& Z)
|
|
{
|
|
result_interval = -child->result_interval;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
NumericExp::NumericExp()
|
|
: UnaryNode(OP_EXP)
|
|
{
|
|
// Nothing to do here.
|
|
}
|
|
|
|
void NumericExp::eval(const float X, const float Y, const float Z)
|
|
{
|
|
result_float = exp(child->result_float);
|
|
}
|
|
|
|
void NumericExp::eval(const FabInterval& X,
|
|
const FabInterval& Y,
|
|
const FabInterval& Z)
|
|
{
|
|
result_interval = exp(child->result_interval);
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
NumericSgn::NumericSgn()
|
|
: UnaryNode(OP_SGN)
|
|
{
|
|
// Nothing to do here.
|
|
}
|
|
|
|
void NumericSgn::eval(const float X, const float Y, const float Z)
|
|
{
|
|
if (child->result_float > 0)
|
|
result_float = 1;
|
|
else if (child->result_float < 0)
|
|
result_float = -1;
|
|
else
|
|
result_float = 0;
|
|
}
|
|
|
|
void NumericSgn::eval(const FabInterval& X,
|
|
const FabInterval& Y,
|
|
const FabInterval& Z)
|
|
{
|
|
result_interval = sgn(child->result_interval);
|
|
}
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
NumericPlus::NumericPlus()
|
|
: BinaryNode(OP_PLUS)
|
|
{
|
|
// Nothing to do here.
|
|
}
|
|
|
|
void NumericPlus::eval(const float X, const float Y, const float Z)
|
|
{
|
|
result_float = left->result_float + right->result_float;
|
|
}
|
|
|
|
void NumericPlus::eval(const FabInterval& X,
|
|
const FabInterval& Y,
|
|
const FabInterval& Z)
|
|
{
|
|
result_interval = left->result_interval + right->result_interval;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
NumericMinus::NumericMinus()
|
|
: BinaryNode(OP_MINUS)
|
|
{
|
|
// Nothing to do here.
|
|
}
|
|
|
|
void NumericMinus::eval(const float X, const float Y, const float Z)
|
|
{
|
|
result_float = left->result_float - right->result_float;
|
|
}
|
|
|
|
void NumericMinus::eval(const FabInterval& X,
|
|
const FabInterval& Y,
|
|
const FabInterval& Z)
|
|
{
|
|
result_interval = left->result_interval - right->result_interval;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
NumericMult::NumericMult()
|
|
: BinaryNode(OP_MULT)
|
|
{
|
|
// Nothing to do here.
|
|
}
|
|
|
|
void NumericMult::eval(const float X, const float Y, const float Z)
|
|
{
|
|
result_float = left->result_float * right->result_float;
|
|
}
|
|
|
|
void NumericMult::eval(const FabInterval& X,
|
|
const FabInterval& Y,
|
|
const FabInterval& Z)
|
|
{
|
|
result_interval = left->result_interval * right->result_interval;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
NumericDiv::NumericDiv()
|
|
: BinaryNode(OP_DIV)
|
|
{
|
|
// Nothing to do here.
|
|
}
|
|
|
|
void NumericDiv::eval(const float X, const float Y, const float Z)
|
|
{
|
|
result_float = left->result_float / right->result_float;
|
|
}
|
|
|
|
void NumericDiv::eval(const FabInterval& X,
|
|
const FabInterval& Y,
|
|
const FabInterval& Z)
|
|
{
|
|
result_interval = left->result_interval / right->result_interval;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
NumericATan2::NumericATan2()
|
|
: BinaryNode(OP_ATAN2)
|
|
{
|
|
// Nothing to do here.
|
|
}
|
|
|
|
void NumericATan2::eval(const float X, const float Y, const float Z)
|
|
{
|
|
result_float = atan2(left->result_float, right->result_float);
|
|
}
|
|
|
|
void NumericATan2::eval(const FabInterval& X,
|
|
const FabInterval& Y,
|
|
const FabInterval& Z)
|
|
{
|
|
result_interval = atan2(left->result_interval, right->result_interval);
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
NumericPow::NumericPow()
|
|
: BinaryNode(OP_POW)
|
|
{
|
|
// Nothing to do here.
|
|
}
|
|
|
|
void NumericPow::eval(const float X, const float Y, const float Z)
|
|
{
|
|
result_float = pow(left->result_float, right->result_float);
|
|
}
|
|
|
|
void NumericPow::eval(const FabInterval& X,
|
|
const FabInterval& Y,
|
|
const FabInterval& Z)
|
|
{
|
|
result_interval = pow(left->result_interval, right->result_interval.lower());
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
NumericMin::NumericMin()
|
|
: BinaryNode(OP_MIN), left_cached(false), right_cached(false)
|
|
{
|
|
// Nothing to do here.
|
|
}
|
|
|
|
void NumericMin::eval(const float X, const float Y, const float Z)
|
|
{
|
|
result_float = min(left->result_float, right->result_float);
|
|
}
|
|
|
|
void NumericMin::eval(const FabInterval& X,
|
|
const FabInterval& Y,
|
|
const FabInterval& Z)
|
|
{
|
|
result_interval = min(left->result_interval, right->result_interval);
|
|
|
|
#if MINMAX_PRUNE
|
|
if (right->result_interval < left->result_interval) {
|
|
if (!left_cached) {
|
|
left_cached = true;
|
|
left->sub_ref();
|
|
}
|
|
|
|
// In case this node gets deactivated out, save a float result
|
|
left->result_float = left->result_interval.lower();
|
|
|
|
} else if (left_cached) {
|
|
left_cached = false;
|
|
left->add_ref();
|
|
}
|
|
|
|
if (left->result_interval < right->result_interval) {
|
|
if (!right_cached) {
|
|
right->sub_ref();
|
|
right_cached = true;
|
|
}
|
|
|
|
// In case this node gets deactivated, save a float result
|
|
right->result_float = right->result_interval.lower();
|
|
|
|
} else if (right_cached) {
|
|
right_cached = false;
|
|
right->add_ref();
|
|
}
|
|
#endif
|
|
|
|
}
|
|
|
|
void NumericMin::deactivate()
|
|
{
|
|
Node::deactivate();
|
|
if (!left_cached)
|
|
left->sub_ref();
|
|
if (!right_cached)
|
|
right->sub_ref();
|
|
}
|
|
|
|
void NumericMin::activate()
|
|
{
|
|
if (!left_cached)
|
|
left->add_ref();
|
|
if (!right_cached)
|
|
right->add_ref();
|
|
Node::activate();
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
NumericMax::NumericMax()
|
|
: BinaryNode(OP_MAX), left_cached(false), right_cached(false)
|
|
{
|
|
// Nothing to do here.
|
|
}
|
|
|
|
void NumericMax::eval(const float X, const float Y, const float Z)
|
|
{
|
|
result_float = max(left->result_float, right->result_float);
|
|
}
|
|
|
|
void NumericMax::eval(const FabInterval& X,
|
|
const FabInterval& Y,
|
|
const FabInterval& Z)
|
|
{
|
|
result_interval = max(left->result_interval, right->result_interval);
|
|
|
|
#if MINMAX_PRUNE
|
|
if (right->result_interval > left->result_interval) {
|
|
if (!left_cached) {
|
|
left->sub_ref();
|
|
left_cached = true;
|
|
}
|
|
|
|
// In case this node gets deactivated out, save a float result
|
|
left->result_float = left->result_interval.lower();
|
|
|
|
} else if (left_cached) {
|
|
left->add_ref();
|
|
left_cached = false;
|
|
}
|
|
|
|
if (left->result_interval > right->result_interval) {
|
|
if (!right_cached) {
|
|
right->sub_ref();
|
|
right_cached = true;
|
|
}
|
|
|
|
// In case this node gets deactivated, save a float result
|
|
right->result_float = right->result_interval.lower();
|
|
|
|
} else if (right_cached) {
|
|
right->add_ref();
|
|
right_cached = false;
|
|
}
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
void NumericMax::activate()
|
|
{
|
|
if (!left_cached)
|
|
left->add_ref();
|
|
if (!right_cached)
|
|
right->add_ref();
|
|
Node::activate();
|
|
}
|
|
|
|
void NumericMax::deactivate()
|
|
{
|
|
Node::deactivate();
|
|
if (!left_cached)
|
|
left->sub_ref();
|
|
if (!right_cached)
|
|
right->sub_ref();
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
VarX::VarX()
|
|
: NonaryNode(VAR_X)
|
|
{
|
|
// Nothing to do here.
|
|
}
|
|
|
|
void VarX::eval(const float X, const float Y, const float Z)
|
|
{
|
|
result_float = X;
|
|
}
|
|
|
|
void VarX::eval(const FabInterval& X,
|
|
const FabInterval& Y,
|
|
const FabInterval& Z)
|
|
{
|
|
result_interval = X;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
VarY::VarY()
|
|
: NonaryNode(VAR_Y)
|
|
{
|
|
// Nothing to do here.
|
|
}
|
|
|
|
void VarY::eval(const float X, const float Y, const float Z)
|
|
{
|
|
result_float = Y;
|
|
}
|
|
|
|
void VarY::eval(const FabInterval& X,
|
|
const FabInterval& Y,
|
|
const FabInterval& Z)
|
|
{
|
|
result_interval = Y;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
VarZ::VarZ()
|
|
: NonaryNode(VAR_Z)
|
|
{
|
|
// Nothing to do here.
|
|
}
|
|
|
|
void VarZ::eval(const float X, const float Y, const float Z)
|
|
{
|
|
result_float = Z;
|
|
}
|
|
|
|
void VarZ::eval(const FabInterval& X,
|
|
const FabInterval& Y,
|
|
const FabInterval& Z)
|
|
{
|
|
result_interval = Z;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
NumericConst::NumericConst(float value)
|
|
: NonaryNode(NUM_CONST)
|
|
{
|
|
marked = true;
|
|
|
|
result_float = value;
|
|
result_interval = value;
|
|
}
|
|
|
|
bool NumericConst::operator==(const Node& rhs)
|
|
{
|
|
if (operation != rhs.op())
|
|
return false;
|
|
return result_float == rhs.result_float;
|
|
}
|
|
|
|
void NumericConst::print(ostream& o) const
|
|
{
|
|
o << result_float;
|
|
}
|
|
|
|
void NumericConst::dot(ostream& o) const
|
|
{
|
|
o << "\"p" << this << "\" [shape = " << dot_shape(operation)
|
|
<< ", color = " << dot_color(operation) << ", fontsize = 24, label = \""
|
|
<< result_float << "\", style=\"dotted\"]\n";
|
|
} |