/* * tokenutils.cc * * This file is part of NEST. * * Copyright (C) 2004 The NEST Initiative * * NEST is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 2 of the License, or * (at your option) any later version. * * NEST is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with NEST. If not, see <http://www.gnu.org/licenses/>. * */ #include "tokenutils.h" #include "integerdatum.h" #include "doubledatum.h" #include "namedatum.h" #include "booldatum.h" #include <string> #include "stringdatum.h" #include "symboldatum.h" #include "arraydatum.h" #include <cmath> // for sqrt() #include "sliexceptions.h" template<> long getValue<long>(const Token&t) { const IntegerDatum *id= dynamic_cast<const IntegerDatum *>(t.datum()); if (id == NULL) {// we have to create a Datum object to get the name... IntegerDatum const d; throw TypeMismatch(d.gettypename().toString(), t.datum()->gettypename().toString()); } return id->get(); } template<> void setValue<long>(const Token&t, long const &value) { IntegerDatum *id= dynamic_cast<IntegerDatum *>(t.datum()); if (id == NULL) {// we have to create a Datum object to get the name... IntegerDatum const d; throw TypeMismatch(d.gettypename().toString(), t.datum()->gettypename().toString()); } (*id) = value; } template<> Token newToken<long>(long const &value) { return Token( new IntegerDatum(value)); } template<> double getValue<double>(const Token&t) { DoubleDatum *id= dynamic_cast<DoubleDatum *>(t.datum()); if (id == NULL) {// we have to create a Datum object to get the name... DoubleDatum const d; throw TypeMismatch(d.gettypename().toString(), t.datum()->gettypename().toString()); } return id->get(); } template<> void setValue<double>(const Token&t, double const &value) { DoubleDatum *id= dynamic_cast<DoubleDatum *>(t.datum()); if (id == NULL) {// we have to create a Datum object to get the name... DoubleDatum const d; throw TypeMismatch(d.gettypename().toString(), t.datum()->gettypename().toString()); } (*id) = value; } template<> float getValue<float>(const Token&t) { DoubleDatum *id= dynamic_cast<DoubleDatum *>(t.datum()); if (id == NULL) {// we have to create a Datum object to get the name... DoubleDatum const d; throw TypeMismatch(d.gettypename().toString(), t.datum()->gettypename().toString()); } return (float)id->get(); } template<> void setValue<float>(const Token&t, float const &value) { DoubleDatum *id= dynamic_cast<DoubleDatum *>(t.datum()); if (id == NULL) {// we have to create a Datum object to get the name... DoubleDatum const d; throw TypeMismatch(d.gettypename().toString(), t.datum()->gettypename().toString()); } (*id) = (double)value; } template<> Token newToken<double>(double const &value) { return Token(new DoubleDatum(value)); } template<> bool getValue<bool>(const Token&t) { BoolDatum *bd = dynamic_cast<BoolDatum*>(t.datum()); if (bd == NULL) {// we have to create a Datum object to get the name... BoolDatum const d(false); throw TypeMismatch(d.gettypename().toString(), t.datum()->gettypename().toString()); } return static_cast<bool>(*bd); // we should have used i->true_name, bit we don't know the interpreter here. } template<> void setValue<bool>(const Token&t, bool const &value) { BoolDatum *bd= dynamic_cast<BoolDatum *>(t.datum()); if (bd == NULL) {// we have to create a Datum object to get the name... BoolDatum const d(false); throw TypeMismatch(d.gettypename().toString(), t.datum()->gettypename().toString()); } *bd = BoolDatum( value ); // we should have used i->true_name, bit we don't know the interpreter here. } template<> Token newToken<bool>(bool const &value) { return Token(new BoolDatum( value)); // we should have used i->true_name, bit we don't know the interpreter here. } // These will handle StringDatum, NameDatum, // LiteralDatum and SymbolDatum tokens: template<> std::string getValue<std::string>(const Token &t) { // If it is a StringDatum, it can be casted to a string: std::string *s = dynamic_cast<std::string*>(t.datum()); if (s != NULL) { return *s; } else { // If it is a NameDatum, LiteralDatum or SymbolDatum, // (or even a BoolDatum!) it can be casted to a Name: Name *n = dynamic_cast<Name*>(t.datum()); if (n != NULL) { return n->toString(); } else { // The given token can never yield a string! // we have to create Datum objects to get the expected names... StringDatum const d1; NameDatum const d2("dummy"); LiteralDatum const d3("dummy"); SymbolDatum const d4("dummy"); throw TypeMismatch(d1.gettypename().toString() + ", " + d2.gettypename().toString() + ", " + d3.gettypename().toString() + ", or " + d4.gettypename().toString(), t.datum()->gettypename().toString()); } } } template<> void setValue<std::string>(const Token &t, std::string const &value) { // If it is a StringDatum, it can be casted to a string: std::string *s = dynamic_cast<std::string*>(t.datum()); if (s != NULL) { *s = value; } else { // If it is a BoolDatum, it -could- be set from a string, but // this operation shall not be allowed! BoolDatum *b = dynamic_cast<BoolDatum*>(t.datum()); if (b != NULL) { // we have to create Datum objects to get the expected names... StringDatum const d1; NameDatum const d2("dummy"); LiteralDatum const d3("dummy"); SymbolDatum const d4("dummy"); throw TypeMismatch(d1.gettypename().toString() + ", " + d2.gettypename().toString() + ", " + d3.gettypename().toString() + ", or " + d4.gettypename().toString(), t.datum()->gettypename().toString()); } else { // If it is a NameDatum, LiteralDatum or SymbolDatum, // it can be casted to a Name: Name *n = dynamic_cast<Name*>(t.datum()); if (n != NULL) { *n = Name(value); } else { // The given token can never hold a string! // we have to create Datum objects to get the expected names... StringDatum const d1; NameDatum const d2("dummy"); LiteralDatum const d3("dummy"); SymbolDatum const d4("dummy"); throw TypeMismatch(d1.gettypename().toString() + ", " + d2.gettypename().toString() + ", " + d3.gettypename().toString() + ", or " + d4.gettypename().toString(), t.datum()->gettypename().toString()); } } } } // This will always yield StringDatum tokens: #ifndef HAVE_SPECIALIZATION_BUG template<> Token newToken<std::string>(std::string const &value) { return Token( new StringDatum(value)); } #endif // These will convert homogeneous double arrays to vectors: template<> std::vector<double> getValue<std::vector<double> >(const Token &t) { // try DoubleVectorDatum first DoubleVectorDatum* dvd = dynamic_cast<DoubleVectorDatum*>(t.datum()); if ( dvd ) return **dvd; // ok, try ArrayDatum ArrayDatum *ad= dynamic_cast<ArrayDatum *>(t.datum()); if ( ad ) { std::vector<double> data; ad->toVector(data); return data; } // out of options throw TypeMismatch(DoubleVectorDatum().gettypename().toString() + " or " + ArrayDatum().gettypename().toString(), t.datum()->gettypename().toString()); } template<> void setValue<std::vector<double> >(const Token&t, std::vector<double> const &value) { ArrayDatum *ad= dynamic_cast<ArrayDatum *>(t.datum()); if (ad == NULL) {// we have to create a Datum object to get the name... ArrayDatum const d; throw TypeMismatch(d.gettypename().toString(), t.datum()->gettypename().toString()); } // ArrayDatum is an AggregateDatum, which means, it is derived from // TokenArray. Hence, we can use ad just like a TokenArray: if (ad->size() != value.size()) {// arrays have incompatible size throw RangeCheck(value.size()); } for (size_t i=0; i<ad->size(); ++i) { setValue<double>((*ad)[i], value[i]); } } #ifndef HAVE_SPECIALIZATION_BUG template<> Token newToken<std::vector<double> >(std::vector<double> const &value) { return Token( new ArrayDatum(value)); } #endif // These will convert homogeneous int arrays to vectors: template<> std::vector<long> getValue<std::vector<long> >(const Token &t) { // try IntVectorDatum first IntVectorDatum* ivd = dynamic_cast<IntVectorDatum*>(t.datum()); if ( ivd ) return **ivd; // ok, try ArrayDatum ArrayDatum *ad= dynamic_cast<ArrayDatum *>(t.datum()); if ( ad ) { std::vector<long> data; ad->toVector(data); return data; } // out of options throw TypeMismatch(IntVectorDatum().gettypename().toString() + " or " + ArrayDatum().gettypename().toString(), t.datum()->gettypename().toString()); } template<> void setValue<std::vector<long> >(const Token&t, std::vector<long> const &value) { ArrayDatum *ad= dynamic_cast<ArrayDatum *>(t.datum()); if (ad == NULL) {// we have to create a Datum object to get the name... ArrayDatum const d; throw TypeMismatch(d.gettypename().toString(), t.datum()->gettypename().toString()); } // ArrayDatum is an AggregateDatum, which means, it is derived from // TokenArray. Hence, we can use ad just like a TokenArray: if (ad->size() != value.size()) {// arrays have incompatible size throw RangeCheck(value.size()); } for (size_t i=0; i<ad->size(); ++i) { setValue<long>((*ad)[i], value[i]); } } template<> Token newToken<std::vector<long> >(std::vector<long> const &value) { return Token( new ArrayDatum(value)); } // These will convert homogeneous double arrays to valarrays: template<> std::valarray<double> getValue<std::valarray<double> >(const Token &t) { // first get data to vector, then copy to valarray const std::vector<double> tmp = getValue<std::vector<double> >(t); std::valarray<double> data(tmp.size()); for (size_t i = 0; i < tmp.size(); ++i ) data[i] = tmp[i]; return data; } template<> void setValue<std::valarray<double> >(const Token&t, std::valarray<double> const &value) { ArrayDatum *ad= dynamic_cast<ArrayDatum *>(t.datum()); if (ad == NULL) {// we have to create a Datum object to get the name... ArrayDatum const d; throw TypeMismatch(d.gettypename().toString(), t.datum()->gettypename().toString()); } // ArrayDatum is an AggregateDatum, which means, it is derived from // TokenArray. Hence, we can use ad just like a TokenArray: if (ad->size() != value.size()) {// arrays have incompatible size throw RangeCheck(value.size()); } for (size_t i=0; i<ad->size(); ++i) { setValue<double>((*ad)[i], value[i]); } } #ifndef HAVE_SPECIALIZATION_BUG template<> Token newToken<std::valarray<double> >(std::valarray<double> const &value) { return Token( new ArrayDatum(value)); } #endif // These will convert homogeneous int arrays to valarrays: template<> std::valarray<long> getValue<std::valarray<long> >(const Token &t) { // first get data to vector, then copy to valarray const std::vector<long> tmp = getValue<std::vector<long> >(t); std::valarray<long> data(tmp.size()); for (size_t i = 0; i < tmp.size(); ++i ) data[i] = tmp[i]; return data; } template<> void setValue<std::valarray<long> >(const Token&t, std::valarray<long> const &value) { ArrayDatum *ad= dynamic_cast<ArrayDatum *>(t.datum()); if (ad == NULL) {// we have to create a Datum object to get the name... ArrayDatum const d; throw TypeMismatch(d.gettypename().toString(), t.datum()->gettypename().toString()); } // ArrayDatum is an AggregateDatum, which means, it is derived from // TokenArray. Hence, we can use ad just like a TokenArray: if (ad->size() != value.size()) {// arrays have incompatible size throw RangeCheck(value.size()); } for (size_t i=0; i<ad->size(); ++i) { setValue<long>((*ad)[i], value[i]); } } template<> Token newToken<std::valarray<long> >(std::valarray<long> const &value) { return Token( new ArrayDatum(value)); }