opensurgsim
Valid-inl.h
Go to the documentation of this file.
1 // This file is a part of the OpenSurgSim project.
2 // Copyright 2013, SimQuest Solutions Inc.
3 //
4 // Licensed under the Apache License, Version 2.0 (the "License");
5 // you may not use this file except in compliance with the License.
6 // You may obtain a copy of the License at
7 //
8 // http://www.apache.org/licenses/LICENSE-2.0
9 //
10 // Unless required by applicable law or agreed to in writing, software
11 // distributed under the License is distributed on an "AS IS" BASIS,
12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 // See the License for the specific language governing permissions and
14 // limitations under the License.
15 
18 
19 #ifndef SURGSIM_MATH_VALID_INL_H
20 #define SURGSIM_MATH_VALID_INL_H
21 
22 #include <boost/math/special_functions/fpclassify.hpp>
23 
24 
25 namespace SurgSim
26 {
27 namespace Math
28 {
29 
30 namespace internal
31 {
32 
33 template <typename T, class V>
35 {
36 public:
37  typedef typename T::Scalar Scalar;
38 
39  PredicateAlwaysTrueVisitor() : m_result(true)
40  {
41  }
42 
43  inline bool getResult() const
44  {
45  return m_result;
46  }
47 
48  inline void init(const Scalar& value, Eigen::Index i, Eigen::Index j)
49  {
50  if (! V::evaluate(value))
51  {
52  m_result = false;
53  }
54  }
55 
56  inline void operator()(const Scalar& value, Eigen::Index i, Eigen::Index j)
57  {
58  if (! V::evaluate(value))
59  {
60  m_result = false;
61  }
62  }
63 
64 private:
65  bool m_result;
66 };
67 
68 template <typename T>
69 class ValidVisitor : public PredicateAlwaysTrueVisitor<T, ValidVisitor<T>>
70 {
71 public:
72  typedef typename PredicateAlwaysTrueVisitor<T, ValidVisitor<T>>::Scalar Scalar;
73 
74  static bool evaluate(const Scalar& value)
75  {
76  // The extra parentheses protect from pain if isfinite() is also defined as a macro.
77  return (boost::math::isfinite)(value);
78  }
79 };
80 
81 template <typename T>
82 class NonSubnormalVisitor : public PredicateAlwaysTrueVisitor<T, NonSubnormalVisitor<T>>
83 {
84 public:
85  typedef typename PredicateAlwaysTrueVisitor<T, ValidVisitor<T>>::Scalar Scalar;
86 
87  static bool evaluate(const Scalar& value)
88  {
89  // The extra parentheses protect from pain if fpclassify() is also defined as a macro.
90  return ((boost::math::fpclassify)(value) != FP_SUBNORMAL);
91  }
92 };
93 
94 }; // namespace internal
95 
96 
97 inline bool isValid(float value)
98 {
99  // The extra parentheses protect from pain if isfinite() is also defined as a macro.
100  return (boost::math::isfinite)(value);
101 }
102 
103 inline bool isValid(double value)
104 {
105  // The extra parentheses protect from pain if isfinite() is also defined as a macro.
106  return (boost::math::isfinite)(value);
107 }
108 
109 template <typename T>
110 inline bool isValid(const Eigen::DenseBase<T>& value)
111 {
113  value.visit(visitor);
114  return visitor.getResult();
115 }
116 
117 template <typename T>
118 inline bool isValid(const Eigen::QuaternionBase<T>& value)
119 {
120  return isValid(value.coeffs());
121 }
122 
123 template <typename T>
124 inline bool isValid(const Eigen::AngleAxis<T>& value)
125 {
126  return isValid(value.angle()) && isValid(value.axis());
127 }
128 
129 template <typename T>
130 inline bool isValid(const Eigen::Rotation2D<T>& value)
131 {
132  return isValid(value.angle());
133 }
134 
135 template <typename T, int D, int M, int O>
136 inline bool isValid(const Eigen::Transform<T, D, M, O>& value)
137 {
138  return isValid(value.matrix());
139 }
140 
141 inline bool isSubnormal(float value)
142 {
143  // The extra parentheses protect from pain if fpclassify() is also defined as a macro.
144  return ((boost::math::fpclassify)(value) == FP_SUBNORMAL);
145 }
146 
147 inline bool isSubnormal(double value)
148 {
149  // The extra parentheses protect from pain if fpclassify() is also defined as a macro.
150  return ((boost::math::fpclassify)(value) == FP_SUBNORMAL);
151 }
152 
153 template <typename T>
154 inline bool isSubnormal(const Eigen::DenseBase<T>& value)
155 {
157  value.visit(visitor);
158  // The visitor checks whether *all* entries are "non-subnormal", i.e. false means some are subnormal.
159  // This is a consequence of deriving from PredicateAlwaysTrueVisitor.
160  return ! visitor.getResult();
161 }
162 
163 template <typename T>
164 inline bool isSubnormal(const Eigen::QuaternionBase<T>& value)
165 {
166  return isSubnormal(value.coeffs());
167 }
168 
169 template <typename T>
170 inline bool isSubnormal(const Eigen::AngleAxis<T>& value)
171 {
172  return isSubnormal(value.angle()) || isSubnormal(value.axis());
173 }
174 
175 template <typename T>
176 inline bool isSubnormal(const Eigen::Rotation2D<T>& value)
177 {
178  return isSubnormal(value.angle());
179 }
180 
181 template <typename T, int D, int M, int O>
182 inline bool isSubnormal(const Eigen::Transform<T, D, M, O>& value)
183 {
184  return isSubnormal(value.matrix());
185 }
186 
187 inline bool setSubnormalToZero(float* value)
188 {
189  // The extra parentheses protect from pain if fpclassify() is also defined as a macro.
190  if ((boost::math::fpclassify)(*value) != FP_SUBNORMAL)
191  {
192  return false;
193  }
194  else
195  {
196  *value = 0.0f;
197  return true;
198  }
199 }
200 
201 inline bool setSubnormalToZero(double* value)
202 {
203  // The extra parentheses protect from pain if fpclassify() is also defined as a macro.
204  if ((boost::math::fpclassify)(*value) != FP_SUBNORMAL)
205  {
206  return false;
207  }
208  else
209  {
210  *value = 0.0;
211  return true;
212  }
213 }
214 
215 template <typename T>
216 inline bool setSubnormalToZero(Eigen::DenseBase<T>* value)
217 {
218  if (! isSubnormal(*value)) // optimize for the common case where nothing is subnormal
219  {
220  return false;
221  }
222 
223  // TODO(bert): This is a simple implementation; it could be much more optimized by e.g. unrolling loops along
224  // the lines of the implementation of Eigen::DenseBase<T>::visit(). Unfortunately, we can't just *use* Eigen's
225  // visitors here, because the visitor API doesn't allow modifying the values.
226 
227  using Eigen::Index;
228  const Index numColumns = value->cols();
229  const Index numRows = value->rows();
230 
231  for (Index j = 0; j < numColumns; ++j)
232  {
233  for (Index i = 0; i < numRows; ++i)
234  {
235  // The extra parentheses protect from pain if fpclassify() is also defined as a macro.
236  if ((boost::math::fpclassify)(value->coeffRef(i, j)) == FP_SUBNORMAL)
237  {
238  value->coeffRef(i, j) = 0;
239  }
240  }
241  }
242  return true;
243 }
244 
245 template <typename T>
246 inline bool setSubnormalToZero(Eigen::QuaternionBase<T>* value)
247 {
248  return setSubnormalToZero(&(value->coeffs()));
249 }
250 
251 template <typename T>
252 inline bool setSubnormalToZero(Eigen::AngleAxis<T>* value)
253 {
254  bool angleChanged = setSubnormalToZero(&(value->angle()));
255  bool axisChanged = setSubnormalToZero(&(value->axis()));
256  return angleChanged || axisChanged; // careful about short-circuiting!
257 }
258 
259 template <typename T>
260 inline bool setSubnormalToZero(Eigen::Rotation2D<T>* value)
261 {
262  return setSubnormalToZero(&(value->angle()));
263 }
264 
265 template <typename T, int D, int M, int O>
266 inline bool setSubnormalToZero(Eigen::Transform<T, D, M, O>* value)
267 {
268  return setSubnormalToZero(&(value->matrix()));
269 }
270 
271 }; // namespace Math
272 }; // namespace SurgSim
273 
274 #endif // SURGSIM_MATH_VALID_INL_H
Wraps glewInit() to separate the glew opengl definitions from the osg opengl definitions only imgui n...
Definition: AddRandomSphereBehavior.cpp:36
bool setSubnormalToZero(float *value)
If the float value is subnormal, set it to zero.
Definition: Valid-inl.h:187
bool isSubnormal(float value)
Check if a float value is subnormal.
Definition: Valid-inl.h:141
bool isValid(float value)
Check if a float value is valid.
Definition: Valid-inl.h:97
Definition: Valid-inl.h:69