//--------------------------------------------------------------------------- IValue& IValue::operator=(const IValue &ref) { if (this==&ref) return *this; switch(ref.GetType()) { case 'i': case 'f': case 'c': return *this = cmplx_type(ref.GetFloat(), ref.GetImag()); case 's': return *this = ref.GetString(); case 'm': return *this = ref.GetArray(); case 'b': return *this = ref.GetBool(); case 'v': throw ParserError(_T("Assignment from void type is not possible")); default: throw ParserError(_T("Internal error: unexpected data type identifier in IValue& operator=(const IValue &ref)")); } }
//----------------------------------------------------------- void OprtSub::Eval(ptr_val_type &ret, const ptr_val_type *a_pArg, int num) { assert(num==2); if (a_pArg[0]->GetType()=='m' && a_pArg[1]->GetType()=='m') { const matrix_type &a1 = a_pArg[0]->GetArray(), &a2 = a_pArg[1]->GetArray(); if (a1.GetRows()!=a2.GetRows()) throw ParserError(ErrorContext(ecARRAY_SIZE_MISMATCH, -1, GetIdent(), 'm', 'm', 2)); matrix_type rv(a1.GetRows()); for (int i=0; i<a1.GetRows(); ++i) { if (!a1.At(i).IsNonComplexScalar()) throw ParserError( ErrorContext(ecTYPE_CONFLICT_FUN, -1, GetIdent(), a1.At(i).GetType(), 'f', 1)); if (!a2.At(i).IsNonComplexScalar()) throw ParserError( ErrorContext(ecTYPE_CONFLICT_FUN, -1, GetIdent(), a2.At(i).GetType(), 'f', 1)); rv.At(i) = cmplx_type(a1.At(i).GetFloat() - a2.At(i).GetFloat(), a1.At(i).GetImag() - a2.At(i).GetImag()); } *ret = rv; } else { if (!a_pArg[0]->IsNonComplexScalar()) throw ParserError( ErrorContext(ecTYPE_CONFLICT_FUN, -1, GetIdent(), a_pArg[0]->GetType(), 'f', 1)); if (!a_pArg[1]->IsNonComplexScalar()) throw ParserError( ErrorContext(ecTYPE_CONFLICT_FUN, -1, GetIdent(), a_pArg[1]->GetType(), 'f', 2)); *ret = a_pArg[0]->GetFloat() - a_pArg[1]->GetFloat(); } }
//----------------------------------------------------------------------------------------------- void OprtPowCmplx::Eval(ptr_val_type& ret, const ptr_val_type *arg, int argc) { assert(argc==2); // Problem: -2^3 will introduce small imaginary parts due to computational errors. // -1^0.5 will introduce small real parts due to computational errors. // // Fix: If roots of negative values are calculated (exponents are non integer) or complex numbers // are involved the complex version of pow is used. The float version is used otherwise. if (arg[0]->IsComplex() || arg[1]->IsComplex() || (arg[0]->GetFloat()<0 && !arg[1]->IsInteger()) ) { cmplx_type res = std::pow(arg[0]->GetComplex(), arg[1]->GetComplex()); // remove obviousely bogus real/imaginary parts from the result if (std::abs(res.imag()) < std::numeric_limits<mup::float_type>::epsilon()) res = res.real(); else if (std::abs(res.real()) < std::numeric_limits<mup::float_type>::epsilon()) res = cmplx_type(0, res.imag()); *ret = res; } else *ret = std::pow(arg[0]->GetFloat(), arg[1]->GetFloat()); }
//----------------------------------------------------------------------- void FunCmplxConj::Eval(ptr_val_type &ret, const ptr_val_type *a_pArg, int) { *ret = cmplx_type(a_pArg[0]->GetFloat(), -a_pArg[0]->GetImag()); }