Blender  V2.59
NM_Scalar.h
Go to the documentation of this file.
00001 /*
00002  * $Id: NM_Scalar.h 35158 2011-02-25 11:49:19Z jesterking $
00003  * ***** BEGIN GPL LICENSE BLOCK *****
00004  *
00005  * This program is free software; you can redistribute it and/or
00006  * modify it under the terms of the GNU General Public License
00007  * as published by the Free Software Foundation; either version 2
00008  * of the License, or (at your option) any later version.
00009  *
00010  * This program is distributed in the hope that it will be useful,
00011  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00012  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00013  * GNU General Public License for more details.
00014  *
00015  * You should have received a copy of the GNU General Public License
00016  * along with this program; if not, write to the Free Software Foundation,
00017  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
00018  *
00019  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
00020  * All rights reserved.
00021  *
00022  * The Original Code is: all of this file.
00023  *
00024  * Contributor(s): none yet.
00025  *
00026  * ***** END GPL LICENSE BLOCK *****
00027  */
00028 
00034 #include <math.h>
00035 #include <iostream>
00036 
00037 template <class T> 
00038 class NM_Scalar {
00039 public:    
00040     NM_Scalar() {}
00041     explicit NM_Scalar(T value, T error = 0.0) : 
00042         m_value(value), m_error(error) {}
00043 
00044     T getValue() const { return m_value; }
00045     T getError() const { return m_error; }
00046 
00047     operator T() const { return m_value; }
00048 
00049     NM_Scalar operator-() const {
00050         return NM_Scalar<T>(-m_value, m_error);
00051     }
00052 
00053     NM_Scalar& operator=(T value) {
00054         m_value = value;
00055         m_error = 0.0;
00056         return *this;
00057     }
00058 
00059     NM_Scalar& operator+=(const NM_Scalar& x) {
00060         m_value += x.m_value;
00061         m_error = (fabs(m_value) * (m_error + 1.0) + 
00062                    fabs(x.m_value) * (x.m_error + 1.0)) /
00063             fabs(m_value + x.m_value);
00064         return *this;
00065     }
00066 
00067     NM_Scalar& operator-=(const NM_Scalar& x) {
00068         m_value -= x.m_value;
00069         m_error = (fabs(m_value) * (m_error + 1.0) + 
00070                    fabs(x.m_value) * (x.m_error + 1.0)) /
00071             fabs(m_value - x.m_value);
00072         return *this;
00073     }
00074 
00075     NM_Scalar& operator*=(const NM_Scalar& x) {
00076         m_value *= x.m_value;
00077         m_error += x.m_error + 1.0;
00078         return *this;
00079     }
00080 
00081     NM_Scalar& operator/=(const NM_Scalar& x) {
00082         m_value /= x.m_value;
00083         m_error += x.m_error + 1.0;
00084         return *this;
00085     }
00086 
00087 private:
00088     T m_value;
00089     T m_error;
00090 };
00091 
00092 template <class T>
00093 inline NM_Scalar<T> operator+(const NM_Scalar<T>& x, const NM_Scalar<T>& y) {
00094     return x.getValue() == 0.0 && y.getValue() == 0.0 ?
00095         NM_Scalar<T>(0.0, 0.0) :
00096         NM_Scalar<T>(x.getValue() + y.getValue(), 
00097                      (fabs(x.getValue()) * (x.getError() + 1.0) + 
00098                       fabs(y.getValue()) * (y.getError() + 1.0)) /
00099                      fabs(x.getValue() + y.getValue()));
00100 }
00101 
00102 template <class T>
00103 inline NM_Scalar<T> operator-(const NM_Scalar<T>& x, const NM_Scalar<T>& y) {
00104     return x.getValue() == 0.0 && y.getValue() == 0.0 ?
00105         NM_Scalar<T>(0.0, 0.0) :
00106         NM_Scalar<T>(x.getValue() - y.getValue(), 
00107                      (fabs(x.getValue()) * (x.getError() + 1.0) + 
00108                       fabs(y.getValue()) * (y.getError() + 1.0)) /
00109                      fabs(x.getValue() - y.getValue()));
00110 }
00111 
00112 template <class T>
00113 inline NM_Scalar<T> operator*(const NM_Scalar<T>& x, const NM_Scalar<T>& y) {
00114     return NM_Scalar<T>(x.getValue() * y.getValue(), 
00115                         x.getError() + y.getError() + 1.0);
00116 }
00117 
00118 template <class T>
00119 inline NM_Scalar<T> operator/(const NM_Scalar<T>& x, const NM_Scalar<T>& y) {
00120     return NM_Scalar<T>(x.getValue() / y.getValue(), 
00121                         x.getError() + y.getError() + 1.0);
00122 }
00123 
00124 template <class T>
00125 inline std::ostream& operator<<(std::ostream& os, const NM_Scalar<T>& x) {
00126     return os << x.getValue() << '[' << x.getError() << ']';
00127 }
00128 
00129 template <class T>
00130 inline NM_Scalar<T> sqrt(const NM_Scalar<T>& x) {
00131     return NM_Scalar<T>(sqrt(x.getValue()),
00132                         0.5 * x.getError() + 1.0);
00133 }
00134 
00135 template <class T>
00136 inline NM_Scalar<T> acos(const NM_Scalar<T>& x) {
00137     return NM_Scalar<T>(acos(x.getValue()), x.getError() + 1.0);
00138 }
00139 
00140 template <class T>
00141 inline NM_Scalar<T> cos(const NM_Scalar<T>& x) {
00142     return NM_Scalar<T>(cos(x.getValue()), x.getError() + 1.0);
00143 }
00144 
00145 template <class T>
00146 inline NM_Scalar<T> sin(const NM_Scalar<T>& x) {
00147     return NM_Scalar<T>(sin(x.getValue()), x.getError() + 1.0);
00148 }
00149 
00150 template <class T>
00151 inline NM_Scalar<T> fabs(const NM_Scalar<T>& x) {
00152     return NM_Scalar<T>(fabs(x.getValue()), x.getError());
00153 }
00154 
00155 template <class T>
00156 inline NM_Scalar<T> pow(const NM_Scalar<T>& x, const NM_Scalar<T>& y) {
00157     return NM_Scalar<T>(pow(x.getValue(), y.getValue()), 
00158                         fabs(y.getValue()) * x.getError() + 1.0);
00159 }
00160