Initial revision
[blender.git] / intern / moto / include / NM_Scalar.h
1 /**
2  * $Id$
3  * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
4  *
5  * This program is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU General Public License
7  * as published by the Free Software Foundation; either version 2
8  * of the License, or (at your option) any later version. The Blender
9  * Foundation also sells licenses for use in proprietary software under
10  * the Blender License.  See http://www.blender.org/BL/ for information
11  * about this.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, write to the Free Software Foundation,
20  * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
21  *
22  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
23  * All rights reserved.
24  *
25  * The Original Code is: all of this file.
26  *
27  * Contributor(s): none yet.
28  *
29  * ***** END GPL/BL DUAL LICENSE BLOCK *****
30  */
31
32 #include <math.h>
33
34 #include <iostream>
35
36 template <class T> 
37 class NM_Scalar {
38 public:    
39     NM_Scalar() {}
40     explicit NM_Scalar(T value, T error = 0.0) : 
41         m_value(value), m_error(error) {}
42
43     T getValue() const { return m_value; }
44     T getError() const { return m_error; }
45
46     operator T() const { return m_value; }
47
48     NM_Scalar operator-() const {
49         return NM_Scalar<T>(-m_value, m_error);
50     }
51
52     NM_Scalar& operator=(T value) {
53         m_value = value;
54         m_error = 0.0;
55         return *this;
56     }
57
58     NM_Scalar& operator+=(const NM_Scalar& x) {
59         m_value += x.m_value;
60         m_error = (fabs(m_value) * (m_error + 1.0) + 
61                    fabs(x.m_value) * (x.m_error + 1.0)) /
62             fabs(m_value + x.m_value);
63         return *this;
64     }
65
66     NM_Scalar& operator-=(const NM_Scalar& x) {
67         m_value -= x.m_value;
68         m_error = (fabs(m_value) * (m_error + 1.0) + 
69                    fabs(x.m_value) * (x.m_error + 1.0)) /
70             fabs(m_value - x.m_value);
71         return *this;
72     }
73
74     NM_Scalar& operator*=(const NM_Scalar& x) {
75         m_value *= x.m_value;
76         m_error += x.m_error + 1.0;
77         return *this;
78     }
79
80     NM_Scalar& operator/=(const NM_Scalar& x) {
81         m_value /= x.m_value;
82         m_error += x.m_error + 1.0;
83         return *this;
84     }
85
86 private:
87     T m_value;
88     T m_error;
89 };
90
91 template <class T>
92 inline NM_Scalar<T> operator+(const NM_Scalar<T>& x, const NM_Scalar<T>& y) {
93     return x.getValue() == 0.0 && y.getValue() == 0.0 ?
94         NM_Scalar<T>(0.0, 0.0) :
95         NM_Scalar<T>(x.getValue() + y.getValue(), 
96                      (fabs(x.getValue()) * (x.getError() + 1.0) + 
97                       fabs(y.getValue()) * (y.getError() + 1.0)) /
98                      fabs(x.getValue() + y.getValue()));
99 }
100
101 template <class T>
102 inline NM_Scalar<T> operator-(const NM_Scalar<T>& x, const NM_Scalar<T>& y) {
103     return x.getValue() == 0.0 && y.getValue() == 0.0 ?
104         NM_Scalar<T>(0.0, 0.0) :
105         NM_Scalar<T>(x.getValue() - y.getValue(), 
106                      (fabs(x.getValue()) * (x.getError() + 1.0) + 
107                       fabs(y.getValue()) * (y.getError() + 1.0)) /
108                      fabs(x.getValue() - y.getValue()));
109 }
110
111 template <class T>
112 inline NM_Scalar<T> operator*(const NM_Scalar<T>& x, const NM_Scalar<T>& y) {
113     return NM_Scalar<T>(x.getValue() * y.getValue(), 
114                         x.getError() + y.getError() + 1.0);
115 }
116
117 template <class T>
118 inline NM_Scalar<T> operator/(const NM_Scalar<T>& x, const NM_Scalar<T>& y) {
119     return NM_Scalar<T>(x.getValue() / y.getValue(), 
120                         x.getError() + y.getError() + 1.0);
121 }
122
123 template <class T>
124 inline std::ostream& operator<<(std::ostream& os, const NM_Scalar<T>& x) {
125     return os << x.getValue() << '[' << x.getError() << ']';
126 }
127
128 template <class T>
129 inline NM_Scalar<T> sqrt(const NM_Scalar<T>& x) {
130     return NM_Scalar<T>(sqrt(x.getValue()),
131                         0.5 * x.getError() + 1.0);
132 }
133
134 template <class T>
135 inline NM_Scalar<T> acos(const NM_Scalar<T>& x) {
136     return NM_Scalar<T>(acos(x.getValue()), x.getError() + 1.0);
137 }
138
139 template <class T>
140 inline NM_Scalar<T> cos(const NM_Scalar<T>& x) {
141     return NM_Scalar<T>(cos(x.getValue()), x.getError() + 1.0);
142 }
143
144 template <class T>
145 inline NM_Scalar<T> sin(const NM_Scalar<T>& x) {
146     return NM_Scalar<T>(sin(x.getValue()), x.getError() + 1.0);
147 }
148
149 template <class T>
150 inline NM_Scalar<T> fabs(const NM_Scalar<T>& x) {
151     return NM_Scalar<T>(fabs(x.getValue()), x.getError());
152 }
153
154 template <class T>
155 inline NM_Scalar<T> pow(const NM_Scalar<T>& x, const NM_Scalar<T>& y) {
156     return NM_Scalar<T>(pow(x.getValue(), y.getValue()), 
157                         fabs(y.getValue()) * x.getError() + 1.0);
158 }
159
160
161
162
163
164
165
166