summaryrefslogtreecommitdiff
path: root/src/value.cc
diff options
context:
space:
mode:
authorMarius Kintel <marius@kintel.net>2012-03-27 22:05:00 (GMT)
committerMarius Kintel <marius@kintel.net>2012-03-27 22:05:58 (GMT)
commit327310f190bbd81c7b71b568d5bf72bb900cc9db (patch)
tree9399bb490ecafe9f0c7fd209c680311d829eb631 /src/value.cc
parent4394c7a030ce7a08c95bd1af2e8c38ffcf972439 (diff)
Rewrote the Value class to be based on boost::variant - this should reduce memory footprint and improve performance
Diffstat (limited to 'src/value.cc')
-rw-r--r--src/value.cc1000
1 files changed, 544 insertions, 456 deletions
diff --git a/src/value.cc b/src/value.cc
index 93c4d5e..13b395d 100644
--- a/src/value.cc
+++ b/src/value.cc
@@ -25,507 +25,595 @@
*/
#include "value.h"
-#include "mathc99.h"
#include <assert.h>
#include <sstream>
-#include <QDir>
#include <boost/foreach.hpp>
-#include "printutils.h"
+#include <boost/variant/apply_visitor.hpp>
+#include <boost/variant/static_visitor.hpp>
+#include <boost/format.hpp>
-Value::Value()
+#include <QtCore/QDir>
+
+std::ostream &operator<<(std::ostream &stream, const Filename &filename)
{
- reset_undef();
+ stream << QuotedString(QDir::current().relativeFilePath(QString::fromStdString(filename)).toStdString());
+ return stream;
}
-Value::~Value()
+// FIXME: This could probably be done more elegantly using boost::regex
+std::ostream &operator<<(std::ostream &stream, const QuotedString &s)
{
- for (size_t i = 0; i < this->vec.size(); i++) delete this->vec[i];
- this->vec.clear();
+ stream << '"';
+ BOOST_FOREACH(char c, s) {
+ switch (c) {
+ case '\t':
+ stream << "\\t";
+ break;
+ case '\n':
+ stream << "\\n";
+ break;
+ case '"':
+ case '\\':
+ stream << '\\';
+ stream << c;
+ break;
+ default:
+ stream << c;
+ }
+ }
+ stream << '"';
+ return stream;
}
-Value::Value(bool v)
+Value Value::undefined;
+
+Value::Value() : value(boost::blank())
{
- reset_undef();
- this->type = BOOL;
- this->b = v;
+ // std::cout << "creating undef\n";
}
-Value::Value(double v)
+Value::Value(bool v) : value(v)
{
- reset_undef();
- this->type = NUMBER;
- this->num = v;
+ // std::cout << "creating bool\n";
}
-Value::Value(const std::string &t)
+Value::Value(int v) : value(double(v))
{
- reset_undef();
- this->type = STRING;
- this->text = t;
+ // std::cout << "creating int\n";
}
-Value::Value(const Value &v)
+Value::Value(double v) : value(v)
{
- *this = v;
+ // std::cout << "creating double " << v << "\n";
}
-Value& Value::operator = (const Value &v)
+Value::Value(const std::string &v) : value(v)
{
- reset_undef();
- this->type = v.type;
- this->b = v.b;
- this->num = v.num;
- for (size_t i = 0; i < v.vec.size(); i++) {
- this->vec.push_back(new Value(*v.vec[i]));
- }
- this->range_begin = v.range_begin;
- this->range_step = v.range_step;
- this->range_end = v.range_end;
- this->text = v.text;
- return *this;
+ // std::cout << "creating string\n";
}
-Value Value::operator ! () const
-{
- if (this->type == BOOL) {
- return Value(!this->b);
- }
- return Value();
-}
-
-Value Value::operator && (const Value &v) const
-{
- if (this->type == BOOL && v.type == BOOL) {
- return Value(this->b && v.b);
- }
- return Value();
-}
-
-Value Value::operator || (const Value &v) const
-{
- if (this->type == BOOL && v.type == BOOL) {
- return Value(this->b || v.b);
- }
- return Value();
-}
-
-Value Value::operator + (const Value &v) const
-{
- if (this->type == VECTOR && v.type == VECTOR) {
- Value r;
- r.type = VECTOR;
- for (size_t i = 0; i < this->vec.size() && i < v.vec.size(); i++)
- r.vec.push_back(new Value(*this->vec[i] + *v.vec[i]));
- return r;
- }
- if (this->type == NUMBER && v.type == NUMBER) {
- return Value(this->num + v.num);
- }
- return Value();
-}
-
-Value Value::operator - (const Value &v) const
-{
- if (this->type == VECTOR && v.type == VECTOR) {
- Value r;
- r.type = VECTOR;
- for (size_t i = 0; i < this->vec.size() && i < v.vec.size(); i++)
- r.vec.push_back(new Value(*this->vec[i] - *v.vec[i]));
- return r;
- }
- if (this->type == NUMBER && v.type == NUMBER) {
- return Value(this->num - v.num);
- }
- return Value();
-}
-
-Value Value::operator * (const Value &v) const
-{
- if (this->type == VECTOR && v.type == NUMBER) {
- Value r;
- r.type = VECTOR;
- for (size_t i = 0; i < this->vec.size(); i++)
- r.vec.push_back(new Value(*this->vec[i] * v));
- return r;
- }
- if (this->type == NUMBER && v.type == VECTOR) {
- Value r;
- r.type = VECTOR;
- for (size_t i = 0; i < v.vec.size(); i++)
- r.vec.push_back(new Value(*this * *v.vec[i]));
- return r;
- }
- if (this->type == NUMBER && v.type == NUMBER) {
- return Value(this->num * v.num);
- }
- if (this->type == VECTOR && v.type == VECTOR && this->vec.size() == v.vec.size() ) {
- if ( this->vec[0]->type == NUMBER && v.vec[0]->type == NUMBER ) {
- // Vector dot product.
- double r=0.0;
- for (size_t i=0; i <this->vec.size(); i++) {
- if ( this->vec[i]->type != NUMBER || v.vec[i]->type != NUMBER ) return Value();
- r = r + (this->vec[i]->num * v.vec[i]->num);
- }
- return Value(r);
- } else if ( this->vec[0]->type == VECTOR && v.vec[0]->type == NUMBER ) {
- // Matrix * Vector
- Value r;
- r.type = VECTOR;
- for ( size_t i=0; i < this->vec.size(); i++) {
- double r_e=0.0;
- if ( this->vec[i]->vec.size() != v.vec.size() ) return Value();
- for ( size_t j=0; j < this->vec[i]->vec.size(); j++) {
- if ( this->vec[i]->vec[j]->type != NUMBER || v.vec[i]->type != NUMBER ) return Value();
- r_e = r_e + (this->vec[i]->vec[j]->num * v.vec[j]->num);
- }
- r.vec.push_back(new Value(r_e));
- }
- return r;
- } else if (this->vec[0]->type == NUMBER && v.vec[0]->type == VECTOR ) {
- // Vector * Matrix
- Value r;
- r.type = VECTOR;
- for ( size_t i=0; i < v.vec[0]->vec.size(); i++) {
- double r_e=0.0;
- for ( size_t j=0; j < v.vec.size(); j++) {
- if ( v.vec[j]->vec.size() != v.vec[0]->vec.size() ) return Value();
- if ( this->vec[j]->type != NUMBER || v.vec[j]->vec[i]->type != NUMBER ) return Value();
- r_e = r_e + (this->vec[j]->num * v.vec[j]->vec[i]->num);
- }
- r.vec.push_back(new Value(r_e));
- }
- return r;
- }
- }
- if (this->type == VECTOR && v.type == VECTOR && this->vec[0]->type == VECTOR && v.vec[0]->type == VECTOR && this->vec[0]->vec.size() == v.vec.size() ) {
- // Matrix * Matrix
- Value rrow;
- rrow.type = VECTOR;
- for ( size_t i=0; i < this->vec.size(); i++ ) {
- Value * rcol=new Value();
- rcol->type = VECTOR;
- for ( size_t j=0; j < this->vec.size(); j++ ) {
- double r_e=0.0;
- for ( size_t k=0; k < v.vec.size(); k++ ) {
- r_e = r_e + (this->vec[i]->vec[k]->num * v.vec[k]->vec[j]->num);
- }
- // PRINTB(" r_e = %s",r_e);
- rcol->vec.push_back(new Value(r_e));
- }
- rrow.vec.push_back(rcol);
- }
- return rrow;
- }
- return Value();
-}
-
-Value Value::operator / (const Value &v) const
-{
- if (this->type == VECTOR && v.type == NUMBER) {
- Value r;
- r.type = VECTOR;
- for (size_t i = 0; i < this->vec.size(); i++)
- r.vec.push_back(new Value(*this->vec[i] / v));
- return r;
- }
- if (this->type == NUMBER && v.type == VECTOR) {
- Value r;
- r.type = VECTOR;
- for (size_t i = 0; i < v.vec.size(); i++)
- r.vec.push_back(new Value(v / *v.vec[i]));
- return r;
- }
- if (this->type == NUMBER && v.type == NUMBER) {
- return Value(this->num / v.num);
- }
- return Value();
-}
-
-Value Value::operator % (const Value &v) const
-{
- if (this->type == NUMBER && v.type == NUMBER) {
- return Value(fmod(this->num, v.num));
- }
- return Value();
-}
-
-Value Value::operator < (const Value &v) const
-{
- if (this->type == NUMBER && v.type == NUMBER) {
- return Value(this->num < v.num);
- }
- else if (this->type == STRING && v.type == STRING) {
- return Value(this->text < v.text);
- }
- return Value();
-}
-
-Value Value::operator <= (const Value &v) const
-{
- if (this->type == NUMBER && v.type == NUMBER) {
- return Value(this->num <= v.num);
- }
- else if (this->type == STRING && v.type == STRING) {
- return Value(this->text <= v.text);
- }
- return Value();
-}
-
-Value Value::operator == (const Value &v) const
-{
- if (this->type == BOOL && v.type == BOOL) {
- return Value(this->b == v.b);
- }
- if (this->type == NUMBER && v.type == NUMBER) {
- return Value(this->num == v.num);
- }
- if (this->type == RANGE && v.type == RANGE) {
- return Value(this->range_begin == v.range_begin && this->range_step == v.range_step && this->range_end == v.range_end);
- }
- if (this->type == VECTOR && v.type == VECTOR) {
- if (this->vec.size() != v.vec.size())
- return Value(false);
- for (size_t i=0; i<this->vec.size(); i++)
- if (!(*this->vec[i] == *v.vec[i]).b)
- return Value(false);
- return Value(true);
- }
- if (this->type == STRING && v.type == STRING) {
- return Value(this->text == v.text);
- }
- return Value(false);
-}
-
-Value Value::operator != (const Value &v) const
-{
- Value eq = *this == v;
- return Value(!eq.b);
-}
-
-Value Value::operator >= (const Value &v) const
-{
- if (this->type == NUMBER && v.type == NUMBER) {
- return Value(this->num >= v.num);
- }
- else if (this->type == STRING && v.type == STRING) {
- return Value(this->text >= v.text);
- }
- return Value();
-}
-
-Value Value::operator > (const Value &v) const
-{
- if (this->type == NUMBER && v.type == NUMBER) {
- return Value(this->num > v.num);
- }
- else if (this->type == STRING && v.type == STRING) {
- return Value(this->text > v.text);
- }
- return Value();
-}
-
-Value Value::inv() const
-{
- if (this->type == VECTOR) {
- Value r;
- r.type = VECTOR;
- for (size_t i = 0; i < this->vec.size(); i++)
- r.vec.push_back(new Value(this->vec[i]->inv()));
- return r;
- }
- if (this->type == NUMBER)
- return Value(-this->num);
- return Value();
-}
-
-bool Value::getnum(double &v) const
-{
- if (this->type != NUMBER)
- return false;
- v = this->num;
- return true;
-}
-
-bool Value::getv2(double &x, double &y) const
-{
- if (this->type != VECTOR || this->vec.size() != 2)
- return false;
- if (this->vec[0]->type != NUMBER)
- return false;
- if (this->vec[1]->type != NUMBER)
- return false;
- x = this->vec[0]->num;
- y = this->vec[1]->num;
- return true;
-}
-
-bool Value::getv3(double &x, double &y, double &z, double defaultval) const
-{
- if (this->type == VECTOR && this->vec.size() == 2) {
- if (getv2(x, y)) {
- z = defaultval;
- return true;
- }
- return false;
- }
- if (this->type != VECTOR || this->vec.size() != 3)
- return false;
- if (this->vec[0]->type != NUMBER)
- return false;
- if (this->vec[1]->type != NUMBER)
- return false;
- if (this->vec[2]->type != NUMBER)
- return false;
- x = this->vec[0]->num;
- y = this->vec[1]->num;
- z = this->vec[2]->num;
- return true;
-}
-
-void Value::reset_undef()
-{
- this->type = UNDEFINED;
- this->b = false;
- this->num = 0;
- for (size_t i = 0; i < this->vec.size(); i++) delete this->vec[i];
- this->vec.clear();
- this->range_begin = 0;
- this->range_step = 0;
- this->range_end = 0;
- this->text = "";
+Value::Value(const char *v) : value(std::string(v))
+{
+ // std::cout << "creating string from char *\n";
}
-std::string Value::toString() const
+Value::Value(char v) : value(std::string(1, v))
+{
+ // std::cout << "creating string from char\n";
+}
+
+Value::Value(const VectorType &v) : value(v)
+{
+ // std::cout << "creating vector\n";
+}
+
+Value::Value(const RangeType &v) : value(v)
+{
+ // std::cout << "creating range\n";
+}
+
+Value::Value(double begin, double step, double end) : value(RangeType(begin, step, end))
+{
+ // std::cout << "creating range from numbers\n";
+}
+
+Value::ValueType Value::type() const
+{
+ return static_cast<ValueType>(this->value.which());
+}
+
+bool Value::isUndefined() const
{
- std::stringstream stream;
- stream.precision(16);
-
- switch (this->type) {
- case STRING:
- stream << this->text;
- break;
- case VECTOR:
- stream << '[';
- for (size_t i = 0; i < this->vec.size(); i++) {
- if (i > 0) stream << ", ";
- stream << *(this->vec[i]);
- }
- stream << ']';
- break;
- case RANGE:
- stream << '['
- << this->range_begin
- << " : "
- << this->range_step
- << " : "
- << this->range_end
- << ']';
- break;
- case NUMBER:
+ return this->type() == UNDEFINED;
+}
+
+bool Value::toBool() const
+{
+ switch (this->type()) {
+ case BOOL:
+ return boost::get<bool>(this->value);
+ break;
+ case NUMBER:
+ return boost::get<double>(this->value)!= 0;
+ break;
+ case STRING:
+ return boost::get<std::string>(this->value).size() > 0;
+ break;
+ case VECTOR:
+ return boost::get<VectorType >(this->value).size() > 0;
+ break;
+ case RANGE:
+ return true;
+ break;
+ default:
+ return false;
+ break;
+ }
+}
+
+double Value::toDouble() const
+{
+ double d = 0;
+ getDouble(d);
+ return d;
+}
+
+bool Value::getDouble(double &v) const
+{
+ const double *d = boost::get<double>(&this->value);
+ if (d) {
+ v = *d;
+ return true;
+ }
+ return false;
+}
+
+class tostring_visitor : public boost::static_visitor<std::string>
+{
+public:
+ template <typename T> std::string operator()(const T &op1) const {
+ // std::cout << "[generic tostring_visitor]\n";
+ return boost::lexical_cast<std::string>(op1);
+ }
+
+ std::string operator()(const double &op1) const {
#ifdef OPENSCAD_TESTING
- // Quick and dirty hack to work around floating point rounding differences
- // across platforms for testing purposes.
- {
- if (this->num != this->num) { // Fix for avoiding nan vs. -nan across platforms
- stream << "nan";
- break;
- }
- std::stringstream tmp;
- tmp.precision(12);
- tmp.setf(std::ios_base::fixed);
- tmp << this->num;
- std::string tmpstr = tmp.str();
- size_t endpos = tmpstr.find_last_not_of('0');
- if (endpos >= 0 && tmpstr[endpos] == '.') endpos--;
- tmpstr = tmpstr.substr(0, endpos+1);
- size_t dotpos = tmpstr.find('.');
- if (dotpos != std::string::npos) {
- if (tmpstr.size() - dotpos > 12) tmpstr.erase(dotpos + 12);
- }
- stream << tmpstr;
- }
+ // Quick and dirty hack to work around floating point rounding differences
+ // across platforms for testing purposes.
+ if (op1 != op1) { // Fix for avoiding nan vs. -nan across platforms
+ return "nan";
+ }
+ std::stringstream tmp;
+ tmp.precision(12);
+ tmp.setf(std::ios_base::fixed);
+ tmp << op1;
+ std::string tmpstr = tmp.str();
+ size_t endpos = tmpstr.find_last_not_of('0');
+ if (endpos >= 0 && tmpstr[endpos] == '.') endpos--;
+ tmpstr = tmpstr.substr(0, endpos+1);
+ size_t dotpos = tmpstr.find('.');
+ if (dotpos != std::string::npos) {
+ if (tmpstr.size() - dotpos > 12) tmpstr.erase(dotpos + 12);
+ }
+ return tmpstr;
#else
- stream << this->num;
+ return boost::lexical_cast<std::string>(op1);
#endif
- break;
- case BOOL:
- stream << (this->b ? "true" : "false");
- break;
- default:
- stream << "undef";
- }
+ }
+
+ std::string operator()(const boost::blank &v) const {
+ return "undef";
+ }
+
+ std::string operator()(const bool &v) const {
+ return v ? "true" : "false";
+ }
+
+ std::string operator()(const Value::VectorType &v) const {
+ std::stringstream stream;
+ stream << '[';
+ for (size_t i = 0; i < v.size(); i++) {
+ if (i > 0) stream << ", ";
+ stream << v[i];
+ }
+ stream << ']';
+ return stream.str();
+ }
+
+ std::string operator()(const Value::RangeType &v) const {
+ return (boost::format("[%1% : %2% : %3%]") % v.begin % v.step % v.end).str();
+ }
+};
- return stream.str();
+std::string Value::toString() const
+{
+ return boost::apply_visitor(tostring_visitor(), this->value);
}
-bool Value::toBool() const
+const Value::VectorType &Value::toVector() const
{
- switch (this->type) {
- case STRING:
- return this->text.size() > 0;
- break;
- case VECTOR:
- return this->vec.size() > 0;
- break;
- case RANGE:
- return true;
- break;
- case NUMBER:
- return this->num != 0;
- break;
- case BOOL:
- return this->b;
- break;
- default:
- return false;
- break;
- }
+ static VectorType empty;
+
+ const VectorType *v = boost::get<VectorType>(&this->value);
+ if (v) return *v;
+ else return empty;
}
-/*!
- Append a value to this vector.
- This must be of type VECTOR.
-*/
-void Value::append(Value *val)
+bool Value::getVec2(double &x, double &y) const
+{
+ if (this->type() != VECTOR) return false;
+
+ const VectorType &v = toVector();
+
+ if (v.size() != 2) return false;
+ return (v[0].getDouble(x) && v[1].getDouble(y));
+}
+
+bool Value::getVec3(double &x, double &y, double &z, double defaultval) const
{
- assert(this->type == VECTOR);
- this->vec.push_back(val);
+ if (this->type() != VECTOR) return false;
+
+ const VectorType &v = toVector();
+
+ if (v.size() == 2) {
+ getVec2(x, y);
+ z = defaultval;
+ return true;
+ }
+ else {
+ if (v.size() != 3) return false;
+ }
+
+ return (v[0].getDouble(x) && v[1].getDouble(y) && v[2].getDouble(z));
}
-std::ostream &operator<<(std::ostream &stream, const Value &value)
+Value::RangeType Value::toRange() const
{
- if (value.type == Value::STRING) stream << QuotedString(value.toString());
- else stream << value.toString();
- return stream;
+ const RangeType *val = boost::get<RangeType>(&this->value);
+ if (val) {
+ return *val;
+ }
+ else return RangeType(0,0,0);
}
-std::ostream &operator<<(std::ostream &stream, const Filename &filename)
+Value &Value::operator=(const Value &v)
{
- stream << QuotedString(QDir::current().relativeFilePath(QString::fromStdString(filename)).toStdString());
- return stream;
+ if (this != &v) {
+ this->value = v.value;
+ }
+ return *this;
}
-// FIXME: This could probably be done more elegantly using boost::regex
-std::ostream &operator<<(std::ostream &stream, const QuotedString &s)
+Value Value::operator!() const
+{
+ return Value(!this->toBool());
+}
+
+class equals_visitor : public boost::static_visitor<bool>
{
- stream << '"';
- BOOST_FOREACH(char c, s) {
- switch (c) {
- case '\t':
- stream << "\\t";
- break;
- case '\n':
- stream << "\\n";
- break;
- case '"':
- case '\\':
- stream << '\\';
- stream << c;
- break;
- default:
- stream << c;
- }
- }
- stream << '"';
- return stream;
+public:
+ template <typename T, typename U> bool operator()(const T &op1, const U &op2) const {
+ return false;
+ }
+
+ template <typename T> bool operator()(const T &op1, const T &op2) const {
+ return op1 == op2;
+ }
+};
+
+bool Value::operator==(const Value &v) const
+{
+ return boost::apply_visitor(equals_visitor(), this->value, v.value);
+}
+
+bool Value::operator!=(const Value &v) const
+{
+ return !(*this == v);
+}
+
+bool Value::operator&&(const Value &v) const
+{
+ return this->toBool() && v.toBool();
+}
+
+bool Value::operator||(const Value &v) const
+{
+ return this->toBool() || v.toBool();
+}
+
+class less_visitor : public boost::static_visitor<bool>
+{
+public:
+ template <typename T, typename U> bool operator()(const T &op1, const U &op2) const {
+ return false;
+ }
+
+ bool operator()(const double &op1, const double &op2) const {
+ return op1 < op2;
+ }
+
+ bool operator()(const std::string &op1, const std::string &op2) const {
+ return op1 < op2;
+ }
+};
+
+class greater_visitor : public boost::static_visitor<bool>
+{
+public:
+ template <typename T, typename U> bool operator()(const T &op1, const U &op2) const {
+ return false;
+ }
+
+ bool operator()(const double &op1, const double &op2) const {
+ return op1 > op2;
+ }
+
+ bool operator()(const std::string &op1, const std::string &op2) const {
+ return op1 > op2;
+ }
+};
+
+bool Value::operator<(const Value &v) const
+{
+ return boost::apply_visitor(less_visitor(), this->value, v.value);
+}
+
+bool Value::operator>=(const Value &v) const
+{
+ return !(*this < v);
+}
+
+bool Value::operator>(const Value &v) const
+{
+ return boost::apply_visitor(greater_visitor(), this->value, v.value);
+}
+
+bool Value::operator<=(const Value &v) const
+{
+ return !(*this > v);
+}
+
+class plus_visitor : public boost::static_visitor<Value>
+{
+public:
+ template <typename T, typename U> Value operator()(const T &op1, const U &op2) const {
+ return Value::undefined;
+ }
+
+ Value operator()(const double &op1, const double &op2) const {
+ return Value(op1 + op2);
+ }
+
+ Value operator()(const Value::VectorType &op1, const Value::VectorType &op2) const {
+ Value::VectorType sum;
+ for (size_t i = 0; i < op1.size() && i < op2.size(); i++) {
+ sum.push_back(op1[i] + op2[i]);
+ }
+ return Value(sum);
+ }
+};
+
+Value Value::operator+(const Value &v) const
+{
+ return boost::apply_visitor(plus_visitor(), this->value, v.value);
+}
+
+class minus_visitor : public boost::static_visitor<Value>
+{
+public:
+ template <typename T, typename U> Value operator()(const T &op1, const U &op2) const {
+ return Value::undefined;
+ }
+
+ Value operator()(const double &op1, const double &op2) const {
+ return Value(op1 - op2);
+ }
+
+ Value operator()(const Value::VectorType &op1, const Value::VectorType &op2) const {
+ Value::VectorType sum;
+ for (size_t i = 0; i < op1.size() && i < op2.size(); i++) {
+ sum.push_back(op1[i] - op2[i]);
+ }
+ return Value(sum);
+ }
+};
+
+Value Value::operator-(const Value &v) const
+{
+ return boost::apply_visitor(minus_visitor(), this->value, v.value);
+}
+
+Value Value::operator*(const Value &v) const
+{
+ if (this->type() == NUMBER && v.type() == NUMBER) {
+ return Value(this->toDouble() * v.toDouble());
+ }
+ else if (this->type() == VECTOR && v.type() == NUMBER) {
+ const VectorType &vec = this->toVector();
+ VectorType tmpv;
+ Value result(tmpv);
+ VectorType &dstv = boost::get<VectorType>(result.value);
+ BOOST_FOREACH(const Value &vecval, vec) {
+ dstv.push_back(vecval * v);
+ }
+ return result;
+ }
+ else if (this->type() == NUMBER && v.type() == VECTOR) {
+ const VectorType &vec = v.toVector();
+ VectorType tmpv;
+ Value result(tmpv);
+ VectorType &dstv = boost::get<VectorType>(result.value);
+ BOOST_FOREACH(const Value &vecval, vec) {
+ dstv.push_back(*this * vecval);
+ }
+ return result;
+ }
+ else if (this->type() == VECTOR && v.type() == VECTOR &&
+ this->toVector().size() == v.toVector().size()) {
+ const VectorType &vec1 = this->toVector();
+ const VectorType &vec2 = v.toVector();
+ if (vec1[0].type() == NUMBER && vec2[0].type() == NUMBER) {
+ // Vector dot product.
+ double r = 0.0;
+ for (size_t i=0;i<vec1.size();i++) {
+ if (vec1[i].type() != NUMBER || vec2[i].type() != NUMBER) {
+ return Value::undefined;
+ }
+ r += (vec1[i].toDouble() * vec2[i].toDouble());
+ }
+ return Value(r);
+ // } else if ( this->vec[0]->type() == VECTOR && v.vec[0]->type() == NUMBER ) {
+ // // Matrix * Vector
+ // Value r;
+ // r.type() = VECTOR;
+ // for ( size_t i=0; i < this->vec.size(); i++) {
+ // double r_e=0.0;
+ // if ( this->vec[i]->vec.size() != v.vec.size() ) return Value();
+ // for ( size_t j=0; j < this->vec[i]->vec.size(); j++) {
+ // if ( this->vec[i]->vec[j]->type() != NUMBER || v.vec[i]->type() != NUMBER ) return Value();
+ // r_e = r_e + (this->vec[i]->vec[j]->num * v.vec[j]->num);
+ // }
+ // r.vec.push_back(new Value(r_e));
+ // }
+ // return r;
+ // } else if (this->vec[0]->type() == NUMBER && v.vec[0]->type() == VECTOR ) {
+ // // Vector * Matrix
+ // Value r;
+ // r.type() = VECTOR;
+ // for ( size_t i=0; i < v.vec[0]->vec.size(); i++) {
+ // double r_e=0.0;
+ // for ( size_t j=0; j < v.vec.size(); j++) {
+ // if ( v.vec[j]->vec.size() != v.vec[0]->vec.size() ) return Value();
+ // if ( this->vec[j]->type() != NUMBER || v.vec[j]->vec[i]->type() != NUMBER ) return Value();
+ // r_e = r_e + (this->vec[j]->num * v.vec[j]->vec[i]->num);
+ // }
+ // r.vec.push_back(new Value(r_e));
+ // }
+ // return r;
+ // }
+ }
+ // if (this->type() == VECTOR && v.type() == VECTOR && this->vec[0]->type() == VECTOR && v.vec[0]->type() == VECTOR && this->vec[0]->vec.size() == v.vec.size() ) {
+ // // Matrix * Matrix
+ // Value rrow;
+ // rrow.type() = VECTOR;
+ // for ( size_t i=0; i < this->vec.size(); i++ ) {
+ // Value * rcol=new Value();
+ // rcol->type() = VECTOR;
+ // for ( size_t j=0; j < this->vec.size(); j++ ) {
+ // double r_e=0.0;
+ // for ( size_t k=0; k < v.vec.size(); k++ ) {
+ // r_e = r_e + (this->vec[i]->vec[k]->num * v.vec[k]->vec[j]->num);
+ // }
+ // rcol->vec.push_back(new Value(r_e));
+ // }
+ // rrow.vec.push_back(rcol);
+ // }
+ // return rrow;
+ }
+ return Value::undefined;
+}
+
+Value Value::operator/(const Value &v) const
+{
+ if (this->type() == NUMBER && v.type() == NUMBER) {
+ return Value(this->toDouble() / v.toDouble());
+ }
+ else if (this->type() == VECTOR && v.type() == NUMBER) {
+ const VectorType &vec = this->toVector();
+ VectorType tmpv;
+ Value result(tmpv);
+ VectorType &dstv = boost::get<VectorType>(result.value);
+ BOOST_FOREACH(const Value &vecval, vec) {
+ dstv.push_back(vecval / v);
+ }
+ return result;
+ }
+ else if (this->type() == NUMBER && v.type() == VECTOR) {
+ const VectorType &vec = v.toVector();
+ VectorType tmpv;
+ Value result(tmpv);
+ VectorType &dstv = boost::get<VectorType>(result.value);
+ BOOST_FOREACH(const Value &vecval, vec) {
+ dstv.push_back(*this / vecval);
+ }
+ return result;
+ }
+ return Value::undefined;
+}
+
+Value Value::operator%(const Value &v) const
+{
+ if (this->type() == NUMBER && v.type() == NUMBER) {
+ return Value(fmod(boost::get<double>(this->value), boost::get<double>(v.value)));
+ }
+ return Value::undefined;
+}
+
+Value Value::operator-() const
+{
+ if (this->type() == NUMBER) {
+ return Value(-this->toDouble());
+ }
+ else if (this->type() == VECTOR) {
+ const VectorType &vec = this->toVector();
+ VectorType tmpv;
+ Value result(tmpv);
+ VectorType &dstv = boost::get<VectorType>(result.value);
+ BOOST_FOREACH(const Value &vecval, vec) {
+ dstv.push_back(-vecval);
+ }
+ return result;
+ }
+ return Value::undefined;
+}
+
+/*!
+ Append a value to this vector.
+ This must be of valtype VECTOR.
+*/
+/*
+ void Value::append(Value *val)
+ {
+ assert(this->type() == VECTOR);
+ this->vec.push_back(val);
+ }
+*/
+
+class bracket_visitor : public boost::static_visitor<Value>
+{
+public:
+ Value operator()(const std::string &str, const double &idx) const {
+ int i = int(idx);
+ Value v;
+ if (i >= 0 && i < str.size()) {
+ v = Value(str[int(idx)]);
+ // std::cout << "bracket_visitor: " << v << "\n";
+ }
+ return v;
+ }
+
+ Value operator()(const Value::VectorType &vec, const double &idx) const {
+ int i = int(idx);
+ if (i >= 0 && i < vec.size()) return vec[int(idx)];
+ return Value::undefined;
+ }
+
+ Value operator()(const Value::RangeType &range, const double &idx) const {
+ switch(int(idx)) {
+ case 0: return Value(range.begin);
+ case 1: return Value(range.step);
+ case 2: return Value(range.end);
+ }
+ return Value::undefined;
+ }
+
+ template <typename T, typename U> Value operator()(const T &op1, const U &op2) const {
+ // std::cout << "generic bracket_visitor\n";
+ return Value::undefined;
+ }
+};
+
+Value Value::operator[](const Value &v)
+{
+ return boost::apply_visitor(bracket_visitor(), this->value, v.value);
}
contact: Jan Huwald // Impressum