/* * LogicalDataType.hh * @brief is a complement of ParamData.hh, contain mathematics function between ParamData element * @see paramData.hh * Created on: Dec 21, 2012 * Author: f.casimir */ #ifndef LOGICALDATATYPE_HH_ #define LOGICALDATATYPE_HH_ #define MU_0 1.25664e-06 #define RE 6.3712e+06 #include #include #include "ParamData.hh" inline AMDA::Parameters::LogicalData castToLogicalData(int a) { if (isNAN(a)) { return AMDA::Parameters::LogicalData::NaN; } return (a >= 1) ? AMDA::Parameters::LogicalData::True : AMDA::Parameters::LogicalData::False; } inline AMDA::Parameters::LogicalData castToLogicalData(AMDA::Parameters::LogicalData a) { return a; } /** * @brief Operator And (&&) between LogicalData */ template inline AMDA::Parameters::LogicalData And(Type1 a, Type2 b) { AMDA::Parameters::LogicalData aa = castToLogicalData(a); AMDA::Parameters::LogicalData bb = castToLogicalData(b); AMDA::Parameters::LogicalData res = AMDA::Parameters::LogicalData::NaN; if (aa != AMDA::Parameters::LogicalData::NaN && bb != AMDA::Parameters::LogicalData::NaN) { res = ((aa == AMDA::Parameters::LogicalData::True) && (bb == AMDA::Parameters::LogicalData::True)) ? AMDA::Parameters::LogicalData::True : AMDA::Parameters::LogicalData::False; } return res; } /** * @brief Operator Or (||) between LogicalData */ template inline AMDA::Parameters::LogicalData Or(Type1 a, Type2 b) { AMDA::Parameters::LogicalData aa = castToLogicalData(a); AMDA::Parameters::LogicalData bb = castToLogicalData(b); AMDA::Parameters::LogicalData res = AMDA::Parameters::LogicalData::NaN; if (aa != AMDA::Parameters::LogicalData::NaN && bb != AMDA::Parameters::LogicalData::NaN) { res = ((aa == AMDA::Parameters::LogicalData::True) || (bb == AMDA::Parameters::LogicalData::True)) ? AMDA::Parameters::LogicalData::True : AMDA::Parameters::LogicalData::False; } return res; } /** * @brief Operator greater_than (>) between LogicalData */ template AMDA::Parameters::LogicalData greater_than(Type1 a, Type2 b) { AMDA::Parameters::LogicalData res = AMDA::Parameters::LogicalData::True; if (std::isfinite(a) && std::isfinite(b)) { res = (a > b) ? AMDA::Parameters::LogicalData::True : AMDA::Parameters::LogicalData::False; } else { res = AMDA::Parameters::LogicalData::NaN; } return res; } /** * @brief Operator greater_than (>) between table of LogicalData */ template std::vector greater_than(std::vector a, std::vector b) { std::vector r; if (a.size() != b.size()) { BOOST_THROW_EXCEPTION( AMDA::AMDA_exception() << AMDA::errno_code(AMDA_OPER_NOT_ALLOWED) << AMDA::ex_msg("Logical comparison between two vector of different size")); } for (unsigned int i = 0; i < a.size(); ++i) { r.push_back(greater_than(a[i], b[i])); } return r; } /** * @brief Operator lower_than (<) between table of LogicalData */ template AMDA::Parameters::LogicalData lower_than(Type1 a, Type2 b) { AMDA::Parameters::LogicalData res = AMDA::Parameters::LogicalData::True; if (std::isfinite(a) && std::isfinite(b)) { res = (a < b) ? AMDA::Parameters::LogicalData::True : AMDA::Parameters::LogicalData::False; } else { res = AMDA::Parameters::LogicalData::NaN; } return res; } /** * @brief Operator lower_than (<) between table of LogicalData */ template std::vector lower_than(std::vector a, std::vector b) { std::vector r; if (a.size() != b.size()) { BOOST_THROW_EXCEPTION( AMDA::AMDA_exception() << AMDA::errno_code(AMDA_OPER_NOT_ALLOWED) << AMDA::ex_msg("Logical comparison between two vector of different size")); } for (unsigned int i = 0; i < a.size(); ++i) { r.push_back(lower_than(a[i], b[i])); } return r; } /** * @brief Operator * between two scalars, one is LogicalData */ template Type operator*(Type a, AMDA::Parameters::LogicalData b) { Type r; r << NotANumber(); if (isNAN(a) || isNAN(b)) { return r; } r = a * (Type) b; return r; } template Type operator*(AMDA::Parameters::LogicalData a, Type b) { return b * a; } /** * @brief Operator / between two scalars, one is LogicalData */ template Type operator/(Type a, AMDA::Parameters::LogicalData b) { Type r; r << NotANumber(); if (isNAN(a) || isNAN(b) || (b == AMDA::Parameters::LogicalData::False)) { return r; } r = a / (Type) b; return r; } template Type operator/(AMDA::Parameters::LogicalData a, Type b) { Type r; r << NotANumber(); if (isNAN(a) || isNAN(b) || (b == 0)) { return r; } r = (Type) a / b; return r; } /** * @brief Operator + between two scalars, one is LogicalData */ template Type operator+(Type a, AMDA::Parameters::LogicalData b) { Type r; r << NotANumber(); if (isNAN(a) || isNAN(b)) { return r; } r = a + (Type) b; return r; } template Type operator+(AMDA::Parameters::LogicalData a, Type b) { return b + a; } /** * @brief Operator - between two scalars, one is LogicalData */ template Type operator-(Type a, AMDA::Parameters::LogicalData b) { Type r; r << NotANumber(); if (isNAN(a) || isNAN(b)) { return r; } r = a - (Type) b; return r; } template Type operator-(AMDA::Parameters::LogicalData a, Type b) { Type r; r << NotANumber(); if (isNAN(a) || isNAN(b)) { return r; } r = (Type) a - b; return r; } /** * @brief Operator addition between two vector * @details * r[0] = a[0] + b[0] * r[1] = a[1] + b[1] * r[2] = a[2] + b[2] * @return r */ template std::vector operator+(std::vector a, std::vector b) { std::vector r; if (a.size() != b.size()) { BOOST_THROW_EXCEPTION(AMDA::AMDA_exception() << AMDA::errno_code(AMDA_OPER_NOT_ALLOWED) << AMDA::ex_msg("Add two vector of different size")); } for (unsigned int i = 0; i < a.size(); ++i) { r.push_back((Type1) (a[i] + b[i])); } return r; } /** * @brief Operator subtraction between two vector * @details * r[0] = a[0] - b[0] * r[1] = a[1] - b[1] * r[2] = a[2] - b[2] * @return r */ template std::vector operator-(std::vector a, std::vector b) { std::vector r; if (a.size() != b.size()) { BOOST_THROW_EXCEPTION(AMDA::AMDA_exception() << AMDA::errno_code(AMDA_OPER_NOT_ALLOWED) << AMDA::ex_msg("Subtract two vector of different size")); } for (unsigned int i = 0; i < a.size(); ++i) { r.push_back(a[i] - b[i]); } return r; } /** * @brief Operator dot product between two vector * @details * r = a[0]*b[0] + a[1]*b[1] + a[2]+b[2] * @return the scalar r */ template Type1 operator*(std::vector a, std::vector b) { Type1 r = 0; if (a.size() != b.size()) { BOOST_THROW_EXCEPTION(AMDA::AMDA_exception() << AMDA::errno_code(AMDA_OPER_NOT_ALLOWED) << AMDA::ex_msg("Multiply two vector of different size")); } for (unsigned int i = 0; i < a.size(); ++i) { r += a[i] * b[i]; } return r; } /** * @brief Function dot between two vectors can be used for dot product */ template Type1 dot(std::vector a, std::vector b) { return a*b; } template Type magnitude(std::vector a) { Type mag = 0; for (unsigned int i = 0; i < a.size(); ++i) mag += a[i] * a[i]; return std::sqrt(mag); } template Type1 angle(std::vector a, std::vector b) { if (magnitude(a) == 0 || magnitude(b) == 0) { BOOST_THROW_EXCEPTION(AMDA::AMDA_exception() << AMDA::errno_code(AMDA_OPER_NOT_ALLOWED) << AMDA::ex_msg("One of the two vectors is NULL")); } Type1 res; if (dot(a, b) / magnitude(a) / magnitude(b) > 0.99999) { res = 0; } else { res = std::acos(dot(a, b) / magnitude(a) / magnitude(b)); } return res; } /** * @brief alfvenVelocity : args magnetic field magnitude and density * @details * * V= mag / std::sqrt(MU_0 * density) */ template Type1 alfvenVelocity(Type1 density, Type2 mag) { Type1 val; if (density <= 0) { val << NotANumber(); } else { val = mag / std::sqrt(MU_0 * density); } return val; } /** * @brief FAIRFIELD 1970 model of neutral sheet position * @details * z_sm-std::sqrt(pow(11.0, 2.0) - pow(11.0, 2.0) / pow(15.0, 2.0) * pow(y_sm, 2.0)) * std::sin(x_ss); * where y_sm and z_sm are the solar magnetospheric coordinates of the spacecraft and x_ss is geomagnetic latitude of the sun (tilt angle) template Type1 fairfield70(Type1 y_sm, Type2 z_sm,Type3 x_ss) { Type1 val = z_sm-std::sqrt(pow(11.0, 2.0) - pow(11.0, 2.0) / pow(15.0, 2.0) * pow(y_sm, 2.0)) * std::sin(x_ss); return val; } * */ /** * @brief FAIRFIELD 1970 model of neutral sheet position * @param xyz_sm SM coordinates of the sat * @param x_ss tilt Angle * @return delata Z */ template Type1 fairfield70(std::vector xyz_sm, Type2 x_ss) { Type1 val = xyz_sm[2]-std::sqrt(pow(11.0, 2.0) - pow(11.0, 2.0) / pow(15.0, 2.0) * pow(xyz_sm[1], 2.0)) * std::sin(x_ss); return val; } /** * @brief FAIRFIELD 1980 model of neutral sheet position * @param xyz_sm SM coordinates of the sat * @param x_ss tilt Angle * @return delata Z */ template Type1 fairfield80(std::vector xyz_sm, Type2 x_ss) { Type1 val = xyz_sm[2]-10.5*std::sqrt(1-pow(xyz_sm[1], 2.0)/pow(17.0,2.0))* std::sin(x_ss); return val; } /** * @brief Perrault and Akasofu 1978 geomagnetic storms * @details * u(t) = E_mag(t)*B_mag(t)/4pi(7RE sin²(theta_p(t)/2))² * where u(t) is total energy dissipation * E_mag(t) The magnitude of the solar-wind electric field * theta_p is a measure of the angle between the geomagnetic field vector and the IMF vector at the front of the * B_mag(t) The magnitude of the IMF magnetosphere in the equatorial plane. theta_p = pi/2 -theta where theta * denotes the latitudinal angle of the IMF vector measured from the solar equatorial plane. */ template Type1 perreault78(Type1 E_mag, Type2 B_mag,Type3 theta_p) { Type1 val = E_mag*B_mag/(4*std::atan(1)*4)*std::pow((7*RE*std::pow(sin(theta_p/2),2)),2); return val; } /** * @brief NEWELL et al 2007 solar wind-magnetosphere coupling function * @details d_phi/d_t = mu^4/3*Bt^2/3*sin(theta/2)^8/3 * where mu is rate IMF field lines approach the magnetopause * B_mag interplanetary field magnitude, * theta IMF clock angle arctan(By/Bz) */ template Type1 newell2007(Type1 mu, Type2 B_mag,Type3 theta) { Type1 val = std::pow(mu , 4./3.)*std::pow(B_mag , 2./3.)*pow(std::sin(theta/2),8./3.); return val; } /** * @brief Lopez 1990 model of magnetic latitude of the neutral sheet * @details *MLAT = -(0.14*Kp+0.69)*std::pow(phi, 1.0/3.0)*(0.065*R-0.16)*DTA; * where Kp is the 3-hour magnetic index, phi the magnetic local time in degrees (phi = 0° at midnight) * R is the radial distance in RE and DTA is the dipole tilt angle */ template Type1 lopez90(Type1 Kp, Type2 phi,Type3 R, Type4 DTA) { Type1 val = -(0.14*Kp+0.69)*std::pow(phi, 1.0/3.0)*(0.065*R-0.16)*DTA; return val; } /** * @brief Operator cross product between two vector * @details * r[0] = a[1]*b[2] - a[2]*b[1] * r[1] = a[2]*b[0] - a[0]*b[2] * r[2] = a[0]*b[1] - a[1]*b[0] * @return r */ template std::vector operator ^(std::vector a, std::vector b) { std::vector r; if (a.size() != b.size() || b.size() != 3) { BOOST_THROW_EXCEPTION(AMDA::AMDA_exception() << AMDA::errno_code(AMDA_OPER_NOT_ALLOWED) << AMDA::ex_msg("Vector product on two vector of different size")); } r.push_back(a[1] * b[2] - a[2] * b[1]); r.push_back(a[2] * b[0] - a[0] * b[2]); r.push_back(a[0] * b[1] - a[1] * b[0]); return r; } /** * @brief Function cross between two vectors can be used for cross product */ template std::vector cross(std::vector a, std::vector b) { return a^b; } /** * @brief div each coordinate one to one * @details * r[0] = a[0] / b[0] * r[1] = a[1] / b[1] * r[2] = a[2] / b[2] */ template std::vector div(std::vector a, std::vector b) { std::vector r; if (a.size() != b.size()) { BOOST_THROW_EXCEPTION(AMDA::AMDA_exception() << AMDA::errno_code(AMDA_OPER_NOT_ALLOWED) << AMDA::ex_msg("Vector div on two vector of different size")); } for (unsigned int i = 0; i < a.size(); ++i) { r.push_back(a[i] / b[i]); } return r; } // //Idea but more complex: template //auto operator ^(std::vector a, std::vector b) -> std::vector { // std::vector r; // Idea but more complex: template // double operator ^(Type1 a, Type2 b) { // return pow(a, b); // } // class Integer { // public: // Integer(int i) : _i(i) {}; // int _i; // }; // // inline double operator ^(double a, Integer b) { // return pow(a, b._i); // } // // // class Double { // public: // Double(double i) : _i(i) {}; // double _i; // }; // inline double operator ^(double a, Double b) { // return pow(a, b._i); // } // vector with scalar operation /** * @brief Operator division between a vector and a scalar * @details all member of vector are divided by the scalar */ template std::vector operator/(std::vector a, Type2 b) { std::vector r; for (typename std::vector::iterator it = a.begin(); it != a.end(); ++it) { r.push_back((Type1) (*it / b)); } return r; } /** * @brief Operator division between a scalar and a vector * @details apply the division on each vector component */ template std::vector operator/(Type1 a, std::vector b) { std::vector r; for (typename std::vector::iterator it = b.begin(); it != b.end(); ++it) { r.push_back((Type2) (a / *it)); } return r; } /** * @brief Operator addition between a vector and a scalar * @details all member of vector are added with the scalar */ template std::vector operator+(std::vector a, Type2 b) { std::vector r; for (typename std::vector::iterator it = a.begin(); it != a.end(); ++it) { r.push_back((Type1) (*it + b)); } return r; } /** * @brief Operator addition between a scalar and a vector * @details all member of vector are added with the scalar */ template std::vector operator+(Type1 a, std::vector b) { std::vector r; for (typename std::vector::iterator it = b.begin(); it != b.end(); ++it) { r.push_back((Type2) (a + *it)); } return r; } /** * @brief Operator subtraction between a vector and a scalar * @details scalar is substracted to all vector components */ template std::vector operator-(std::vector a, Type2 b) { std::vector r; for (typename std::vector::iterator it = a.begin(); it != a.end(); ++it) { r.push_back((Type1) (*it - b)); } return r; } /** * @brief Operator subtraction between a scalar and a vector * @details all member of vector are subtracted with the scalar */ template std::vector operator-(Type1 a, std::vector b) { std::vector r; for (typename std::vector::iterator it = b.begin(); it != b.end(); ++it) { r.push_back((Type2) (a - *it)); } return r; } /** * @brief Operator product between a vector and a scalar * @details product applied in all member of vector */ template std::vector operator*(std::vector a, Type2 b) { std::vector r; for (typename std::vector::iterator it = a.begin(); it != a.end(); ++it) { r.push_back((Type1) ((*it) * b)); } return r; } /** * @brief Operator product between a scalar and a vector * @details all member of vector are added by the scalar */ template std::vector operator*(Type1 a, std::vector b) { std::vector r; for (typename std::vector::iterator it = b.begin(); it != b.end(); ++it) { r.push_back((Type2) (a * (*it))); } return r; } /** * @return false if val is NaN or inf or -inf */ template inline bool isFinite(Type val) { return std::isfinite(val); } inline bool isFinite(AMDA::Parameters::LogicalData val) { return !isNAN(val); } /** * @return false if elem of val is NaN or inf or -inf */ template inline bool isFinite(std::vector val) { bool ret = false; auto it = val.begin(); while (it != val.end() && !ret) { ret &= std::isfinite(*it); ++it; } return ret; } /** * @return false if elem of val is NaN or inf or -inf */ template inline bool isFinite(const AMDA::Parameters::Tab2DData& val) { bool ret = false; for (int i = 0; i < val.getDim1Size(); ++i) for (int j = 0; j < val.getDim2Size(); ++j) ret &= std::isfinite(val[i][j]); return ret; } /** * @return the average of std::list */ template inline Type average(std::list tab, int /*dim1*/, int /*dim2*/) { Type mean; if (tab.empty()) { mean << NotANumber(); } else { mean << ElemNull(); auto it = tab.begin(); if (it != tab.end()) { unsigned int nbNan = 0; Type sum; sum << NotANumber(); for (; it != tab.end(); ++it) { if (isFinite(*it) && !isNAN(*it)) { if (isNAN(sum)) sum = *it; else sum = sum + *it; } else { ++nbNan; } } if ((tab.size() - nbNan == 0) || isNAN(sum)) { mean << NotANumber(); } else { mean = sum / (int) (tab.size() - nbNan); } } else { mean << NotANumber(); } } return mean; } inline AMDA::Parameters::LogicalData average(std::list /*tab*/, int /*dim1*/, int /*dim2*/) { AMDA::Parameters::LogicalData mean; mean << NotANumber(); return mean; } template inline AMDA::Parameters::Tab2DData average(std::list > tab, int dim1, int dim2) { AMDA::Parameters::Tab2DData mean(dim1, dim2); AMDA::Parameters::Tab2DData nbNan(dim1, dim2); AMDA::Parameters::Tab2DData sum(dim1, dim2); if (tab.empty()) { mean << NotANumber(); return mean; } for (int index1 = 0; index1 < dim1; ++index1) { for (int index2 = 0; index2 < dim2; ++index2) { nbNan[index1][index2] = 0; } } sum << NotANumber(); for (auto it = tab.begin(); it != tab.end(); ++it) { for (int index1 = 0; index1 < dim1; ++index1) { for (int index2 = 0; index2 < dim2; ++index2) { Type val = (*it)[index1][index2]; if (std::isfinite(val) && !isNAN(val)) { if (isNAN(sum[index1][index2])) sum[index1][index2] = val; else sum[index1][index2] += val; } else { ++(nbNan[index1][index2]); } } } } for (int index1 = 0; index1 < dim1; ++index1) { for (int index2 = 0; index2 < dim2; ++index2) { if (tab.size() - nbNan[index1][index2] == 0) { mean[index1][index2] << NotANumber(); } else { mean[index1][index2] = sum[index1][index2] / (int) (tab.size() - nbNan[index1][index2]); } } } return mean; } inline AMDA::Parameters::Tab2DData average(std::list> /*tab*/, int dim1, int dim2) { AMDA::Parameters::Tab2DData mean(dim1, dim2); mean << NotANumber(); return mean; } /** * @return the average of std::list */ template inline std::vector average(std::list > tab, int dim1, int /*dim2*/) { std::vector mean; mean.resize(dim1); std::vectornbNan; nbNan.resize(dim1); std::vector sum; sum.resize(dim1); if (tab.empty()) { mean << NotANumber(); return mean; } for (unsigned int index = 0; index < tab.begin()->size(); ++index) { nbNan[index] = 0; } sum << NotANumber(); for (auto it = tab.begin(); it != tab.end(); ++it) { for (unsigned int index = 0; index < it->size(); ++index) { Type val = it->at(index); if (std::isfinite(val) && !isNAN(val)) { if (isNAN(sum[index])) sum[index] = val; else sum[index] += val; } else { ++(nbNan[index]); } } } for (unsigned int index = 0; index < tab.begin()->size(); ++index) { if (tab.size() - nbNan[index] == 0) { mean[index] << NotANumber(); } else { mean[index] = sum[index] / (int) (tab.size() - nbNan[index]); } } return mean; } inline std::vector average(std::list> /*tab*/, int dim1, int /*dim2*/) { std::vector mean; mean.resize(dim1); mean << NotANumber(); return mean; } /** * */ template inline Type interpolation(const Type& leftVal, const Type& rightVal, double coef, int /*dim1*/, int /*dim2*/) { Type val; val << NotANumber(); if (isNAN(leftVal) || isNAN(rightVal) || coef < 0. || coef > 1.) return val; val = leftVal + (rightVal - leftVal) * coef; return val; } inline AMDA::Parameters::LogicalData interpolation(const AMDA::Parameters::LogicalData& leftVal, const AMDA::Parameters::LogicalData& rightVal, double /*coef*/, int /*dim1*/, int /*dim2*/) { AMDA::Parameters::LogicalData val; if (leftVal == rightVal) { val = leftVal; } else { val << NotANumber(); } return val; } /** * */ template inline AMDA::Parameters::Tab2DData interpolation(const AMDA::Parameters::Tab2DData& leftVal, const AMDA::Parameters::Tab2DData& rightVal, double coef, int dim1, int dim2) { AMDA::Parameters::Tab2DData val(dim1, dim2); val << NotANumber(); for (int index1 = 0; index1 < dim1; ++index1) { for (int index2 = 0; index2 < dim2; ++index2) { Type leftValComp = leftVal[index1][index2]; Type rightValComp = rightVal[index1][index2]; val[index1][index2] = interpolation(leftValComp, rightValComp, coef, 1, 1); } } return val; } template inline std::vector interpolation(const std::vector& leftVal, const std::vector& rightVal, double coef, int dim1, int /*dim2*/) { std::vector val; val.resize(dim1); val << NotANumber(); for (int index = 0; index < dim1; ++index) { Type leftValComp = leftVal[index]; Type rightValComp = rightVal[index]; val[index] = interpolation(leftValComp, rightValComp, coef, 1, 1); } return val; } /** * @brief Operator + between Tab2D and scalar */ template AMDA::Parameters::Tab2DData operator+(const AMDA::Parameters::Tab2DData& a, Type2 b) { AMDA::Parameters::Tab2DData r(a); if (isNAN(b)) { r << NotANumber(); return r; } for (int i = 0; i < r.getDim1Size(); ++i) for (int j = 0; j < r.getDim2Size(); ++j) { if (!isNAN(r[i][j])) r[i][j] += b; } return r; } template AMDA::Parameters::Tab2DData operator+(Type1 a, const AMDA::Parameters::Tab2DData& b) { return (b + a); } /** * @brief Operator - between Tab2D and scalar */ template AMDA::Parameters::Tab2DData operator-(const AMDA::Parameters::Tab2DData& a, Type2 b) { return (a + (-b)); } template AMDA::Parameters::Tab2DData operator-(Type1 a, const AMDA::Parameters::Tab2DData& b) { AMDA::Parameters::Tab2DData r(b); if (isNAN(a)) { r << NotANumber(); return r; } for (int i = 0; i < r.getDim1Size(); ++i) for (int j = 0; j < r.getDim2Size(); ++j) { if (!isNAN(r[i][j])) r[i][j] = a - r[i][j]; } return r; } /** * @brief Operator * between Tab2D and scalar */ template AMDA::Parameters::Tab2DData operator*(const AMDA::Parameters::Tab2DData& a, Type2 b) { AMDA::Parameters::Tab2DData r(a); if (isNAN(b)) { r << NotANumber(); return r; } for (int i = 0; i < r.getDim1Size(); ++i) for (int j = 0; j < r.getDim2Size(); ++j) { if (!isNAN(r[i][j])) r[i][j] *= b; } return r; } template AMDA::Parameters::Tab2DData operator*(Type1 a, const AMDA::Parameters::Tab2DData& b) { return (b * a); } /** * @brief Operator / between Tab2D and scalar */ template AMDA::Parameters::Tab2DData operator/(const AMDA::Parameters::Tab2DData& a, Type2 b) { if (b == 0) { AMDA::Parameters::Tab2DData r(a); r << NotANumber(); return r; } return (a * (1. / b)); } template AMDA::Parameters::Tab2DData operator/(Type1 a, const AMDA::Parameters::Tab2DData& b) { AMDA::Parameters::Tab2DData r(b); if (isNAN(a)) { r << NotANumber(); return r; } for (int i = 0; i < r.getDim1Size(); ++i) for (int j = 0; j < r.getDim2Size(); ++j) { if (isNAN(r[i][j]) || (r[i][j] == 0)) r[i][j] << NotANumber(); else r[i][j] = a / r[i][j]; } return r; } /* * @brief Function add between a Tab2D and a vector */ template AMDA::Parameters::Tab2DData add(const AMDA::Parameters::Tab2DData& a, std::vector b, int mode) { AMDA::Parameters::Tab2DData r(a); switch (mode) { case 1: if (r.getDim1Size() != b.size()) { BOOST_THROW_EXCEPTION( AMDA::AMDA_exception() << AMDA::errno_code(AMDA_OPER_NOT_ALLOWED) << AMDA::ex_msg("Operation not allowed due to incompatibility in data dimensions")); } for (int i = 0; i < r.getDim1Size(); ++i) for (int j = 0; j < r.getDim2Size(); ++j) { if (isNAN(r[i][j]) || isNAN(b[i])) r[i][j] << NotANumber(); else r[i][j] += b[i]; } break; case 2: if (r.getDim2Size() != b.size()) { BOOST_THROW_EXCEPTION( AMDA::AMDA_exception() << AMDA::errno_code(AMDA_OPER_NOT_ALLOWED) << AMDA::ex_msg("Operation not allowed due to incompatibility in data dimensions")); } for (int i = 0; i < r.getDim1Size(); ++i) for (int j = 0; j < r.getDim2Size(); ++j) { if (isNAN(r[i][j]) || isNAN(b[j])) r[i][j] << NotANumber(); else r[i][j] += b[j]; } break; default: BOOST_THROW_EXCEPTION( AMDA::AMDA_exception() << AMDA::errno_code(AMDA_OPER_NOT_ALLOWED) << AMDA::ex_msg("Operation not allowed due a not implemented mode")); } return r; } template AMDA::Parameters::Tab2DData add(std::vector a, const AMDA::Parameters::Tab2DData& b, int mode) { return add(b, a, mode); } /** * @brief Operator + between Tab2D and vector */ template AMDA::Parameters::Tab2DData operator+(const AMDA::Parameters::Tab2DData& a, std::vector b) { return add(a, b, 1); } template AMDA::Parameters::Tab2DData operator+(std::vector a, const AMDA::Parameters::Tab2DData& b) { return add(a, b, 1); } /** * @brief Function sub between Tab2D and vector */ template AMDA::Parameters::Tab2DData sub(const AMDA::Parameters::Tab2DData& a, std::vector b, int mode) { return add(a, (-1) * b, mode); } template AMDA::Parameters::Tab2DData sub(std::vector a, const AMDA::Parameters::Tab2DData& b, int mode) { AMDA::Parameters::Tab2DData r(b); switch (mode) { case 1: if (r.getDim1Size() != a.size()) { BOOST_THROW_EXCEPTION( AMDA::AMDA_exception() << AMDA::errno_code(AMDA_OPER_NOT_ALLOWED) << AMDA::ex_msg("Operation not allowed due to incompatibility in data dimensions")); } for (int i = 0; i < r.getDim1Size(); ++i) for (int j = 0; j < r.getDim2Size(); ++j) { if (isNAN(r[i][j]) || isNAN(a[i])) r[i][j] << NotANumber(); else r[i][j] = a[i] - r[i][j]; } break; case 2: if (r.getDim2Size() != a.size()) { BOOST_THROW_EXCEPTION( AMDA::AMDA_exception() << AMDA::errno_code(AMDA_OPER_NOT_ALLOWED) << AMDA::ex_msg("Operation not allowed due to incompatibility in data dimensions")); } for (int i = 0; i < r.getDim1Size(); ++i) for (int j = 0; j < r.getDim2Size(); ++j) { if (isNAN(r[i][j]) || isNAN(a[j])) r[i][j] << NotANumber(); else r[i][j] = a[j] - r[i][j]; } break; default: BOOST_THROW_EXCEPTION( AMDA::AMDA_exception() << AMDA::errno_code(AMDA_OPER_NOT_ALLOWED) << AMDA::ex_msg("Operation not allowed due a not implemented mode")); } return r; } /** * @brief Operator - between Tab2D and vector */ template AMDA::Parameters::Tab2DData operator-(const AMDA::Parameters::Tab2DData& a, std::vector b) { return sub(a, b, 1); } template AMDA::Parameters::Tab2DData operator-(std::vector a, const AMDA::Parameters::Tab2DData& b) { return sub(a, b, 1); } /** * @brief Function mult between Tab2D and vector */ template AMDA::Parameters::Tab2DData mult(const AMDA::Parameters::Tab2DData& a, std::vector b, int mode) { AMDA::Parameters::Tab2DData r(a); switch (mode) { case 1: if (r.getDim1Size() != b.size()) { BOOST_THROW_EXCEPTION( AMDA::AMDA_exception() << AMDA::errno_code(AMDA_OPER_NOT_ALLOWED) << AMDA::ex_msg("Operation not allowed due to incompatibility in data dimensions")); } for (int i = 0; i < r.getDim1Size(); ++i) for (int j = 0; j < r.getDim2Size(); ++j) { if (isNAN(r[i][j]) || isNAN(b[i])) r[i][j] << NotANumber(); else r[i][j] *= b[i]; } break; case 2: if (r.getDim2Size() != b.size()) { BOOST_THROW_EXCEPTION( AMDA::AMDA_exception() << AMDA::errno_code(AMDA_OPER_NOT_ALLOWED) << AMDA::ex_msg("Operation not allowed due to incompatibility in data dimensions")); } for (int i = 0; i < r.getDim1Size(); ++i) for (int j = 0; j < r.getDim2Size(); ++j) { if (isNAN(r[i][j]) || isNAN(b[j])) r[i][j] << NotANumber(); else r[i][j] *= b[j]; } break; default: BOOST_THROW_EXCEPTION( AMDA::AMDA_exception() << AMDA::errno_code(AMDA_OPER_NOT_ALLOWED) << AMDA::ex_msg("Operation not allowed due a not implemented mode")); } return r; } template AMDA::Parameters::Tab2DData mult(std::vector a, const AMDA::Parameters::Tab2DData& b, int mode) { return mult(b, a, mode); } /** * @brief Operator * between Tab2D and vector */ template AMDA::Parameters::Tab2DData operator*(const AMDA::Parameters::Tab2DData& a, std::vector b) { return mult(a, b, 1); } template AMDA::Parameters::Tab2DData operator*(std::vector a, const AMDA::Parameters::Tab2DData& b) { return mult(b, a, 1); } /** * @brief Function div between Tab2D and vector */ template AMDA::Parameters::Tab2DData div(const AMDA::Parameters::Tab2DData& a, std::vector b, int mode) { AMDA::Parameters::Tab2DData r(a); switch (mode) { case 1: if (r.getDim1Size() != b.size()) { BOOST_THROW_EXCEPTION( AMDA::AMDA_exception() << AMDA::errno_code(AMDA_OPER_NOT_ALLOWED) << AMDA::ex_msg("Operation not allowed due to incompatibility in data dimensions")); } for (int i = 0; i < r.getDim1Size(); ++i) for (int j = 0; j < r.getDim2Size(); ++j) { if (isNAN(r[i][j]) || isNAN(b[i]) || (b[i] == 0)) r[i][j] << NotANumber(); else r[i][j] = r[i][j] / b[i]; } break; case 2: if (r.getDim2Size() != b.size()) { BOOST_THROW_EXCEPTION( AMDA::AMDA_exception() << AMDA::errno_code(AMDA_OPER_NOT_ALLOWED) << AMDA::ex_msg("Operation not allowed due to incompatibility in data dimensions")); } for (int i = 0; i < r.getDim1Size(); ++i) for (int j = 0; j < r.getDim2Size(); ++j) { if (isNAN(r[i][j]) || isNAN(b[j]) || (b[j] == 0)) r[i][j] << NotANumber(); else r[i][j] = r[i][j] / b[j]; } break; default: BOOST_THROW_EXCEPTION( AMDA::AMDA_exception() << AMDA::errno_code(AMDA_OPER_NOT_ALLOWED) << AMDA::ex_msg("Operation not allowed due a not implemented mode")); } return r; } template AMDA::Parameters::Tab2DData div(std::vector a, const AMDA::Parameters::Tab2DData& b, int mode) { AMDA::Parameters::Tab2DData r(b); switch (mode) { case 1: if (r.getDim1Size() != a.size()) { BOOST_THROW_EXCEPTION( AMDA::AMDA_exception() << AMDA::errno_code(AMDA_OPER_NOT_ALLOWED) << AMDA::ex_msg("Operation not allowed due to incompatibility in data dimensions")); } for (int i = 0; i < r.getDim1Size(); ++i) for (int j = 0; j < r.getDim2Size(); ++j) { if (isNAN(r[i][j]) || isNAN(a[i]) || (r[i][j] == 0)) r[i][j] << NotANumber(); else r[i][j] = a[i] / r[i][j]; } break; case 2: if (r.getDim2Size() != a.size()) { BOOST_THROW_EXCEPTION( AMDA::AMDA_exception() << AMDA::errno_code(AMDA_OPER_NOT_ALLOWED) << AMDA::ex_msg("Operation not allowed due to incompatibility in data dimensions")); } for (int i = 0; i < r.getDim1Size(); ++i) for (int j = 0; j < r.getDim2Size(); ++j) { if (isNAN(r[i][j]) || isNAN(a[j]) || (r[i][j] == 0)) r[i][j] << NotANumber(); else r[i][j] = a[j] / r[i][j]; } break; default: BOOST_THROW_EXCEPTION( AMDA::AMDA_exception() << AMDA::errno_code(AMDA_OPER_NOT_ALLOWED) << AMDA::ex_msg("Operation not allowed due a not implemented mode")); } return r; } /** * @brief Operator / between Tab2D and vector */ template AMDA::Parameters::Tab2DData operator/(const AMDA::Parameters::Tab2DData& a, std::vector b) { return div(a, b, 1); } template AMDA::Parameters::Tab2DData operator/(std::vector a, const AMDA::Parameters::Tab2DData& b) { return div(b, a, 1); } /** * @brief Operator + between two Tab2D */ template AMDA::Parameters::Tab2DData operator+(const AMDA::Parameters::Tab2DData& a, const AMDA::Parameters::Tab2DData& b) { if ((a.getDim1Size() != b.getDim1Size()) || (a.getDim2Size() != b.getDim2Size())) { BOOST_THROW_EXCEPTION( AMDA::AMDA_exception() << AMDA::errno_code(AMDA_OPER_NOT_ALLOWED) << AMDA::ex_msg("Operation not allowed due to incompatibility in data dimensions")); } AMDA::Parameters::Tab2DData r(a); for (int i = 0; i < r.getDim1Size(); ++i) for (int j = 0; j < r.getDim2Size(); ++j) { if (isNAN(a[i][j]) || isNAN(b[i][j])) r[i][j] << NotANumber(); else r[i][j] = a[i][j] + b[i][j]; } return r; } /** * @brief Operator - between two Tab2D */ template AMDA::Parameters::Tab2DData operator-(const AMDA::Parameters::Tab2DData& a, const AMDA::Parameters::Tab2DData& b) { if ((a.getDim1Size() != b.getDim1Size()) || (a.getDim2Size() != b.getDim2Size())) { BOOST_THROW_EXCEPTION( AMDA::AMDA_exception() << AMDA::errno_code(AMDA_OPER_NOT_ALLOWED) << AMDA::ex_msg("Operation not allowed due to incompatibility in data dimensions")); } AMDA::Parameters::Tab2DData r(a); for (int i = 0; i < r.getDim1Size(); ++i) for (int j = 0; j < r.getDim2Size(); ++j) { if (isNAN(a[i][j]) || isNAN(b[i][j])) r[i][j] << NotANumber(); else r[i][j] = a[i][j] - b[i][j]; } return r; } /** * @brief Operator * between two Tab2D */ template AMDA::Parameters::Tab2DData operator*(const AMDA::Parameters::Tab2DData& a, const AMDA::Parameters::Tab2DData& b) { if ((a.getDim1Size() != b.getDim1Size()) || (a.getDim2Size() != b.getDim2Size())) { BOOST_THROW_EXCEPTION( AMDA::AMDA_exception() << AMDA::errno_code(AMDA_OPER_NOT_ALLOWED) << AMDA::ex_msg("Operation not allowed due to incompatibility in data dimensions")); } AMDA::Parameters::Tab2DData r(a); for (int i = 0; i < r.getDim1Size(); ++i) for (int j = 0; j < r.getDim2Size(); ++j) { if (isNAN(a[i][j]) || isNAN(b[i][j])) r[i][j] << NotANumber(); else r[i][j] = a[i][j] * b[i][j]; } return r; } /** * @brief Operator + between two Tab2D */ template AMDA::Parameters::Tab2DData operator/(const AMDA::Parameters::Tab2DData& a, const AMDA::Parameters::Tab2DData& b) { if ((a.getDim1Size() != b.getDim1Size()) || (a.getDim2Size() != b.getDim2Size())) { BOOST_THROW_EXCEPTION( AMDA::AMDA_exception() << AMDA::errno_code(AMDA_OPER_NOT_ALLOWED) << AMDA::ex_msg("Operation not allowed due to incompatibility in data dimensions")); } AMDA::Parameters::Tab2DData r(a); for (int i = 0; i < r.getDim1Size(); ++i) for (int j = 0; j < r.getDim2Size(); ++j) { if (isNAN(a[i][j]) || isNAN(b[i][j]) || (b[i][j] == 0)) r[i][j] << NotANumber(); else r[i][j] = a[i][j] / b[i][j]; } return r; } /** * @brief Function total on all components of a vector => result is a scalar */ template Type total(const std::vector& a) { Type sum; sum << NotANumber(); for (int j = 0; j < a.size(); ++j) { if (isFinite(a[j])) { if (isNAN(sum)) sum = a[j]; else sum += a[j]; } } return sum; } /** * @brief Function total on all components of a Tab2D => result is a scalar */ template Type total(const AMDA::Parameters::Tab2DData& a) { Type sum; sum << NotANumber(); for (int i = 0; i < a.getDim1Size(); ++i) for (int j = 0; j < a.getDim2Size(); ++j) { if (isFinite(a[i][j])) { if (isNAN(sum)) sum = a[i][j]; else sum += a[i][j]; } } return sum; } /** * @brief Function total on lines or columns of a Tab2D => result is a vector * mode = 1 => sum on lines * mode = 2 => sum on columns */ template std::vector total(const AMDA::Parameters::Tab2DData& a, int mode) { std::vector sum; switch (mode) { case 1: for (int j = 0; j < a.getDim2Size(); ++j) { Type elem; elem << NotANumber(); for (int i = 0; i < a.getDim1Size(); ++i) { if (isFinite(a[i][j])) { if (isNAN(elem)) elem = a[i][j]; else elem += a[i][j]; } } sum.push_back(elem); } break; case 2: for (int i = 0; i < a.getDim1Size(); ++i) { Type elem; elem << NotANumber(); for (int j = 0; j < a.getDim2Size(); ++j) { if (isFinite(a[i][j])) { if (isNAN(elem)) elem = a[i][j]; else elem += a[i][j]; } } sum.push_back(elem); } break; default: BOOST_THROW_EXCEPTION( AMDA::AMDA_exception() << AMDA::errno_code(AMDA_OPER_NOT_ALLOWED) << AMDA::ex_msg("Operation not allowed due a not implemented mode")); } return sum; } template std::vector operator+(AMDA::Parameters::TabRow a, AMDA::Parameters::TabRow b) { std::vector av(a); std::vector bv(b); return av + bv; } template std::vector operator+(std::vector a, AMDA::Parameters::TabRow b) { std::vector bv(b); return a + bv; } template std::vector operator+(AMDA::Parameters::TabRow a, std::vector b) { std::vector av(a); return av + b; } template std::vector operator*(AMDA::Parameters::TabRow a, AMDA::Parameters::TabRow b) { std::vector av(a); std::vector bv(b); return av*bv; } template std::vector operator*(std::vector a, AMDA::Parameters::TabRow b) { std::vector bv(b); return a*bv; } template std::vector operator*(AMDA::Parameters::TabRow a, std::vector b) { std::vector av(a); return av*b; } template std::vector operator-(AMDA::Parameters::TabRow a, AMDA::Parameters::TabRow b) { std::vector av(a); std::vector bv(b); return av - bv; } template std::vector operator-(std::vector a, AMDA::Parameters::TabRow b) { std::vector bv(b); return a - bv; } template std::vector operator-(AMDA::Parameters::TabRow a, std::vector b) { std::vector av(a); return av - b; } template std::vector operator/(AMDA::Parameters::TabRow a, AMDA::Parameters::TabRow b) { std::vector av(a); std::vector bv(b); return av / bv; } template std::vector operator/(std::vector a, AMDA::Parameters::TabRow b) { std::vector bv(b); return a / bv; } template std::vector operator/(AMDA::Parameters::TabRow a, std::vector b) { std::vector av(a); return av / b; } #endif /* LOGICALDATATYPE_HH_ */