kopia lustrzana https://github.com/fellesverkstedet/fabmodules
307 wiersze
7.4 KiB
C++
307 wiersze
7.4 KiB
C++
#include "node.hpp"
|
|
#include "switches.hpp"
|
|
|
|
#include "numeric_nodes.hpp"
|
|
#include "logic_nodes.hpp"
|
|
#include "translator_nodes.hpp"
|
|
#include "color_nodes.hpp"
|
|
|
|
using namespace std;
|
|
using boost::logic::indeterminate;
|
|
|
|
Node::Node(opcode operation)
|
|
: result_float(0), result_interval(0),
|
|
result_bool(indeterminate), result_color(0),
|
|
marked(false), operation(operation),
|
|
ref_count(0), weight(0),
|
|
clone_address(this)
|
|
{
|
|
// Nothing to do here.
|
|
}
|
|
|
|
Node::~Node()
|
|
{
|
|
// Nothing to do here
|
|
}
|
|
|
|
Node* Node::make(opcode operation)
|
|
{
|
|
switch (operation)
|
|
{
|
|
case OP_AND: return new LogicAnd();
|
|
case OP_OR: return new LogicOr();
|
|
case OP_NEQ: return new LogicNeq();
|
|
case OP_NOT: return new LogicNot();
|
|
case OP_LT: return new TransitionLt();
|
|
case OP_LEQ: return new TransitionLeq();
|
|
case OP_GT: return new TransitionGt();
|
|
case OP_GEQ: return new TransitionGeq();
|
|
case OP_ABS: return new NumericAbs();
|
|
case OP_COS: return new NumericCos();
|
|
case OP_SIN: return new NumericSin();
|
|
case OP_ACOS: return new NumericACos();
|
|
case OP_ASIN: return new NumericASin();
|
|
case OP_ATAN: return new NumericATan();
|
|
case OP_SQRT: return new NumericSqrt();
|
|
case OP_NEGATIVE: return new NumericNeg();
|
|
case OP_EXP: return new NumericExp();
|
|
case OP_SGN: return new NumericSgn();
|
|
case OP_PLUS: return new NumericPlus();
|
|
case OP_MINUS: return new NumericMinus();
|
|
case OP_MULT: return new NumericMult();
|
|
case OP_DIV: return new NumericDiv();
|
|
case OP_ATAN2: return new NumericATan2();
|
|
case OP_POW: return new NumericPow();
|
|
case OP_MIN: return new NumericMin();
|
|
case OP_MAX: return new NumericMax();
|
|
case NUM_CONST: return new NumericConst(0);
|
|
case VAR_X: return new VarX();
|
|
case VAR_Y: return new VarY();
|
|
case VAR_Z: return new VarZ();
|
|
case COLOR_AND: return new ColorAnd();
|
|
case COLOR_OR: return new ColorOr();
|
|
case COLOR_NOT: return new ColorNot();
|
|
case NUM2BOOL: return new NumToBool();
|
|
case BOOL2NUM: return new BoolToNum();
|
|
case NUM2COLOR: return new NumToColor();
|
|
case BOOL2COLOR: return new BoolToColor();
|
|
default:
|
|
cerr << "Unknown clone target " << operation << endl;
|
|
exit(1);
|
|
}
|
|
}
|
|
|
|
void Node::deactivate()
|
|
{
|
|
// If we clone this node, then we want to be pointing back here
|
|
// (not to a previous clone address).
|
|
clone_address = this;
|
|
}
|
|
|
|
void Node::activate()
|
|
{
|
|
// Nothing to do here
|
|
}
|
|
|
|
void Node::dot(ostream& o) const
|
|
{
|
|
o << "\"p" << this << "\" [shape = " << dot_shape(operation)
|
|
<< ", color = " << dot_color(operation) << ", fontsize = 24, label = \""
|
|
<< dot_label(operation) << "\"";
|
|
if (marked)
|
|
o << ", style=\"dotted\"";
|
|
o << "]\n";
|
|
}
|
|
|
|
ostream& operator<<(ostream& o, const Node& t)
|
|
{
|
|
t.print(o);
|
|
return o;
|
|
}
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
UnaryNode::UnaryNode(opcode operation)
|
|
: Node(operation), child(NULL)
|
|
{
|
|
// Nothing to do here.
|
|
}
|
|
|
|
Node* UnaryNode::clone()
|
|
{
|
|
clone_address = make(operation);
|
|
static_cast<UnaryNode*>(clone_address)->
|
|
set_child(child->get_clone_address());
|
|
return clone_address;
|
|
}
|
|
|
|
|
|
void UnaryNode::deactivate()
|
|
{
|
|
Node::deactivate();
|
|
child->sub_ref();
|
|
}
|
|
|
|
void UnaryNode::activate()
|
|
{
|
|
child->add_ref();
|
|
Node::activate();
|
|
}
|
|
|
|
bool UnaryNode::operator==(const Node& rhs)
|
|
{
|
|
if (operation != rhs.op() )
|
|
return false;
|
|
return *child == *static_cast<const UnaryNode&>(rhs).child;
|
|
}
|
|
|
|
void UnaryNode::print(ostream& o) const
|
|
{
|
|
o << operation;
|
|
if (child) {
|
|
o << '(';
|
|
child->print(o);
|
|
o << ')';
|
|
}
|
|
}
|
|
|
|
void UnaryNode::dot(ostream& o) const
|
|
{
|
|
Node::dot(o);
|
|
|
|
o << "p" << this << "->p" << child
|
|
<< " [color = " << dot_arrow(operation) << "]\n";
|
|
}
|
|
|
|
void UnaryNode::set_child(Node* child_)
|
|
{
|
|
child = child_;
|
|
child->add_ref();
|
|
marked = child->marked;
|
|
if (marked) {
|
|
// Evaluate for both floats and intervals to ensure that
|
|
// result_float and result_interval are both populated
|
|
eval(0,0,0);
|
|
eval(FabInterval(0),FabInterval(0),FabInterval(0));
|
|
} else {
|
|
weight = child->get_weight() + 1;
|
|
}
|
|
}
|
|
|
|
bool UnaryNode::null_children() const
|
|
{
|
|
return child == NULL;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
BinaryNode::BinaryNode(opcode operation)
|
|
: Node(operation), left(NULL), right(NULL)
|
|
{
|
|
// Nothing to do here.
|
|
}
|
|
|
|
Node* BinaryNode::clone()
|
|
{
|
|
clone_address = make(operation);
|
|
static_cast<BinaryNode*>(clone_address)->
|
|
set_children(left->get_clone_address(),
|
|
right->get_clone_address());
|
|
return clone_address;
|
|
}
|
|
|
|
void BinaryNode::deactivate()
|
|
{
|
|
Node::deactivate();
|
|
left->sub_ref();
|
|
right->sub_ref();
|
|
}
|
|
|
|
void BinaryNode::activate()
|
|
{
|
|
left->add_ref();
|
|
right->add_ref();
|
|
Node::activate();
|
|
}
|
|
|
|
bool BinaryNode::operator==(const Node& rhs)
|
|
{
|
|
if (operation != rhs.op() )
|
|
return false;
|
|
return *left == *static_cast<const BinaryNode&>(rhs).left &&
|
|
*right == *static_cast<const BinaryNode&>(rhs).right;
|
|
}
|
|
|
|
void BinaryNode::print(ostream& o) const
|
|
{
|
|
if (operation == OP_ATAN2 || operation == OP_POW ||
|
|
operation == OP_MAX || operation == OP_MIN)
|
|
o << operation;
|
|
if (left){
|
|
o << '(';
|
|
left->print(o);
|
|
}
|
|
|
|
if (operation == OP_ATAN2 || operation == OP_POW ||
|
|
operation == OP_MAX || operation == OP_MIN) {
|
|
if (left && right)
|
|
o << ", ";
|
|
}
|
|
else
|
|
o << operation;
|
|
|
|
if (right) {
|
|
right->print(o);
|
|
o << ')';
|
|
}
|
|
}
|
|
|
|
void BinaryNode::dot(ostream& o) const
|
|
{
|
|
Node::dot(o);
|
|
|
|
o << "p" << this << "->p" << left
|
|
<< " [color = " << dot_arrow(operation) << "]\n";
|
|
o << "p" << this << "->p" << right
|
|
<< " [color = " << dot_arrow(operation) << "]\n";
|
|
}
|
|
|
|
void BinaryNode::set_children(Node* left_, Node* right_)
|
|
{
|
|
left = left_;
|
|
left->add_ref();
|
|
right = right_;
|
|
right->add_ref();
|
|
marked = left->marked && right->marked;
|
|
if (marked) {
|
|
// Evaluate for both floats and intervals to ensure that
|
|
// result_float and result_interval are both populated
|
|
eval(0,0,0);
|
|
eval(FabInterval(0),FabInterval(0),FabInterval(0));
|
|
} else {
|
|
weight = max(left->get_weight() + 1, right->get_weight() + 1);
|
|
}
|
|
|
|
}
|
|
|
|
bool BinaryNode::null_children() const
|
|
{
|
|
return left == NULL || right == NULL;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
NonaryNode::NonaryNode(opcode operation)
|
|
: Node(operation)
|
|
{
|
|
// Nothing to do here.
|
|
}
|
|
|
|
Node* NonaryNode::clone()
|
|
{
|
|
clone_address = make(operation);
|
|
return clone_address;
|
|
}
|
|
|
|
void NonaryNode::deactivate() {
|
|
Node::deactivate();
|
|
}
|
|
|
|
void NonaryNode::activate()
|
|
{
|
|
Node::activate();
|
|
}
|
|
|
|
bool NonaryNode::operator==(const Node& rhs)
|
|
{
|
|
return operation == rhs.op();
|
|
}
|
|
|
|
void NonaryNode::print(ostream& o) const
|
|
{
|
|
o << operation;
|
|
}
|
|
|
|
bool NonaryNode::null_children() const
|
|
{
|
|
return false;
|
|
} |