/** * $Id: NM_Scalar.h 26841 2010-02-12 13:34:04Z campbellbarton $ * ***** BEGIN GPL LICENSE BLOCK ***** * * This program 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. * * This program 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 this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. * All rights reserved. * * The Original Code is: all of this file. * * Contributor(s): none yet. * * ***** END GPL LICENSE BLOCK ***** */ #include #include template class NM_Scalar { public: NM_Scalar() {} explicit NM_Scalar(T value, T error = 0.0) : m_value(value), m_error(error) {} T getValue() const { return m_value; } T getError() const { return m_error; } operator T() const { return m_value; } NM_Scalar operator-() const { return NM_Scalar(-m_value, m_error); } NM_Scalar& operator=(T value) { m_value = value; m_error = 0.0; return *this; } NM_Scalar& operator+=(const NM_Scalar& x) { m_value += x.m_value; m_error = (fabs(m_value) * (m_error + 1.0) + fabs(x.m_value) * (x.m_error + 1.0)) / fabs(m_value + x.m_value); return *this; } NM_Scalar& operator-=(const NM_Scalar& x) { m_value -= x.m_value; m_error = (fabs(m_value) * (m_error + 1.0) + fabs(x.m_value) * (x.m_error + 1.0)) / fabs(m_value - x.m_value); return *this; } NM_Scalar& operator*=(const NM_Scalar& x) { m_value *= x.m_value; m_error += x.m_error + 1.0; return *this; } NM_Scalar& operator/=(const NM_Scalar& x) { m_value /= x.m_value; m_error += x.m_error + 1.0; return *this; } private: T m_value; T m_error; }; template inline NM_Scalar operator+(const NM_Scalar& x, const NM_Scalar& y) { return x.getValue() == 0.0 && y.getValue() == 0.0 ? NM_Scalar(0.0, 0.0) : NM_Scalar(x.getValue() + y.getValue(), (fabs(x.getValue()) * (x.getError() + 1.0) + fabs(y.getValue()) * (y.getError() + 1.0)) / fabs(x.getValue() + y.getValue())); } template inline NM_Scalar operator-(const NM_Scalar& x, const NM_Scalar& y) { return x.getValue() == 0.0 && y.getValue() == 0.0 ? NM_Scalar(0.0, 0.0) : NM_Scalar(x.getValue() - y.getValue(), (fabs(x.getValue()) * (x.getError() + 1.0) + fabs(y.getValue()) * (y.getError() + 1.0)) / fabs(x.getValue() - y.getValue())); } template inline NM_Scalar operator*(const NM_Scalar& x, const NM_Scalar& y) { return NM_Scalar(x.getValue() * y.getValue(), x.getError() + y.getError() + 1.0); } template inline NM_Scalar operator/(const NM_Scalar& x, const NM_Scalar& y) { return NM_Scalar(x.getValue() / y.getValue(), x.getError() + y.getError() + 1.0); } template inline std::ostream& operator<<(std::ostream& os, const NM_Scalar& x) { return os << x.getValue() << '[' << x.getError() << ']'; } template inline NM_Scalar sqrt(const NM_Scalar& x) { return NM_Scalar(sqrt(x.getValue()), 0.5 * x.getError() + 1.0); } template inline NM_Scalar acos(const NM_Scalar& x) { return NM_Scalar(acos(x.getValue()), x.getError() + 1.0); } template inline NM_Scalar cos(const NM_Scalar& x) { return NM_Scalar(cos(x.getValue()), x.getError() + 1.0); } template inline NM_Scalar sin(const NM_Scalar& x) { return NM_Scalar(sin(x.getValue()), x.getError() + 1.0); } template inline NM_Scalar fabs(const NM_Scalar& x) { return NM_Scalar(fabs(x.getValue()), x.getError()); } template inline NM_Scalar pow(const NM_Scalar& x, const NM_Scalar& y) { return NM_Scalar(pow(x.getValue(), y.getValue()), fabs(y.getValue()) * x.getError() + 1.0); }