1 //
2 // Copyright 2016 Pixar
3 //
4 // Licensed under the Apache License, Version 2.0 (the "Apache License")
5 // with the following modification; you may not use this file except in
6 // compliance with the Apache License and the following modification to it:
7 // Section 6. Trademarks. is deleted and replaced with:
8 //
9 // 6. Trademarks. This License does not grant permission to use the trade
10 //    names, trademarks, service marks, or product names of the Licensor
11 //    and its affiliates, except as required to comply with Section 4(c) of
12 //    the License and to reproduce the content of the NOTICE file.
13 //
14 // You may obtain a copy of the Apache License at
15 //
16 //     http://www.apache.org/licenses/LICENSE-2.0
17 //
18 // Unless required by applicable law or agreed to in writing, software
19 // distributed under the Apache License with the above modification is
20 // distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
21 // KIND, either express or implied. See the Apache License for the specific
22 // language governing permissions and limitations under the Apache License.
23 //
24 #ifndef PXR_BASE_GF_MATH_H
25 #define PXR_BASE_GF_MATH_H
26 
27 /// \file gf/math.h
28 /// \ingroup group_gf_BasicMath
29 /// Assorted mathematical utility functions.
30 
31 #include "pxr/pxr.h"
32 #include "pxr/base/arch/math.h"
33 #include "pxr/base/gf/api.h"
34 #include "pxr/base/gf/traits.h"
35 
36 #include <type_traits>
37 
38 PXR_NAMESPACE_OPEN_SCOPE
39 
40 /// Returns true if \p a and \p b are with \p epsilon of each other.
41 /// \ingroup group_gf_BasicMath
GfIsClose(double a,double b,double epsilon)42 inline bool GfIsClose(double a, double b, double epsilon) {
43     return fabs(a-b) < epsilon;
44 }
45 
46 /// Converts an angle in radians to degrees.
47 /// \ingroup group_gf_BasicMath
GfRadiansToDegrees(double radians)48 inline double	GfRadiansToDegrees(double radians) {
49     return radians * (180.0 / M_PI);
50 }
51 
52 /// Converts an angle in degrees to radians.
53 /// \ingroup group_gf_BasicMath
GfDegreesToRadians(double degrees)54 inline double	GfDegreesToRadians(double degrees) {
55     return degrees * (M_PI / 180.0);
56 }
57 
58 /// Returns the inner product of \c x with itself: specifically, \c x*x.
59 /// Defined for \c int, \c float, \c double, and all \c GfVec types.
60 /// \ingroup group_gf_BasicMath
61 template <class T>
GfSqr(const T & x)62 inline double GfSqr(const T& x) {
63     return x * x;
64 }
65 
66 /// Return the signum of \p v (i.e. -1, 0, or 1).
67 ///
68 /// The type \c T must implement the < and > operators; the function returns
69 /// zero only if value neither positive, nor negative.
70 ///
71 /// \ingroup group_gf_BasicMath
72 template <typename T>
73 inline T
GfSgn(T v)74 GfSgn(T v) {
75     return (v < 0) ? -1 : ((v > 0) ? 1 : 0);
76 }
77 
78 /// Return sqrt(\p f).
79 /// \ingroup group_gf_BasicMath
GfSqrt(double f)80 inline double GfSqrt(double f) { return std::sqrt(f); }
81 /// Return sqrt(\p f).
82 /// \ingroup group_gf_BasicMath
GfSqrt(float f)83 inline float GfSqrt(float f) { return std::sqrt(f); }
84 
85 /// Return exp(\p f).
86 /// \ingroup group_gf_BasicMath
GfExp(double f)87 inline double GfExp(double f) { return std::exp(f); }
88 /// Return exp(\p f).
89 /// \ingroup group_gf_BasicMath
GfExp(float f)90 inline float GfExp(float f) { return std::exp(f); }
91 
92 /// Return log(\p f).
93 /// \ingroup group_gf_BasicMath
GfLog(double f)94 inline double GfLog(double f) { return std::log(f); }
95 /// Return log(\p f).
96 /// \ingroup group_gf_BasicMath
GfLog(float f)97 inline float GfLog(float f) { return std::log(f); }
98 
99 /// Return floor(\p f).
100 /// \ingroup group_gf_BasicMath
GfFloor(double f)101 inline double GfFloor(double f) { return std::floor(f); }
102 /// Return floor(\p f).
103 /// \ingroup group_gf_BasicMath
GfFloor(float f)104 inline float GfFloor(float f) { return std::floor(f); }
105 
106 /// Return ceil(\p f).
107 /// \ingroup group_gf_BasicMath
GfCeil(double f)108 inline double GfCeil(double f) { return std::ceil(f); }
109 /// Return ceil(\p f).
110 /// \ingroup group_gf_BasicMath
GfCeil(float f)111 inline float GfCeil(float f) { return std::ceil(f); }
112 
113 /// Return abs(\p f).
114 /// \ingroup group_gf_BasicMath
GfAbs(double f)115 inline double GfAbs(double f) { return std::fabs(f); }
116 /// Return abs(\p f).
117 /// \ingroup group_gf_BasicMath
GfAbs(float f)118 inline float GfAbs(float f) { return std::fabs(f); }
119 
120 /// Return round(\p f).
121 /// \ingroup group_gf_BasicMath
GfRound(double f)122 inline double GfRound(double f) { return std::rint(f); }
123 /// Return round(\p f).
124 /// \ingroup group_gf_BasicMath
GfRound(float f)125 inline float GfRound(float f) { return std::rint(f); }
126 
127 /// Return pow(\p f, \p p).
128 /// \ingroup group_gf_BasicMath
GfPow(double f,double p)129 inline double GfPow(double f, double p) { return std::pow(f, p); }
130 /// Return pow(\p f, \p p).
131 /// \ingroup group_gf_BasicMath
GfPow(float f,float p)132 inline float GfPow(float f, float p) { return std::pow(f, p); }
133 
134 /// Return sin(\p v).
135 /// \ingroup group_gf_BasicMath
GfSin(double v)136 inline double GfSin(double v) { return std::sin(v); }
137 /// Return sin(\p v).
138 /// \ingroup group_gf_BasicMath
GfSin(float v)139 inline float GfSin(float v) { return std::sin(v); }
140 /// Return cos(\p v).
141 /// \ingroup group_gf_BasicMath
GfCos(double v)142 inline double GfCos(double v) { return std::cos(v); }
143 /// Return cos(\p v).
144 /// \ingroup group_gf_BasicMath
GfCos(float v)145 inline float GfCos(float v) { return std::cos(v); }
146 /// Return sin(\p v) in \p s and cos(\p v) in \p c.
147 /// \ingroup group_gf_BasicMath
GfSinCos(double v,double * s,double * c)148 inline void GfSinCos(double v, double *s, double *c) { ArchSinCos(v, s, c); }
149 /// Return sin(\p v) in \p s and cos(\p v) in \p c.
150 /// \ingroup group_gf_BasicMath
GfSinCos(float v,float * s,float * c)151 inline void GfSinCos(float v, float *s, float *c) { ArchSinCosf(v, s, c); }
152 
153 /// Return the resulting of clamping \p value to lie between
154 /// \p min and \p max. This function is also defined for GfVecs.
155 /// \ingroup group_gf_BasicMath
GfClamp(double value,double min,double max)156 inline double GfClamp(double value, double min, double max) {
157     if (value < min) return min;
158     if (value > max) return max;
159     return value;
160 }
161 
162 /// \overload
163 /// \ingroup group_gf_BasicMath
GfClamp(float value,float min,float max)164 inline float GfClamp(float value, float min, float max) {
165     if (value < min) return min;
166     if (value > max) return max;
167     return value;
168 }
169 
170 /// The mod function with "correct" behaviour for negative numbers.
171 ///
172 /// If \p a = \c n \p b for some integer \p n, zero is returned.
173 /// Otherwise, for positive \p a, the value returned is \c fmod(a,b),
174 /// and for negative \p a, the value returned is \c fmod(a,b)+b.
175 ///
176 /// \ingroup group_gf_BasicMath
177 GF_API
178 double GfMod(double a, double b);
179 /// \overload
180 // \ingroup group_gf_BasicMath
181 GF_API
182 float GfMod(float a, float b);
183 
184 /// Linear interpolation function.
185 ///
186 /// For any type that supports multiplication by a scalar and binary addition, returns
187 /// \code
188 /// (1-alpha) * a + alpha * b
189 /// \endcode
190 ///
191 /// \ingroup group_gf_BasicMath
192 template <class T>
GfLerp(double alpha,const T & a,const T & b)193 inline T GfLerp( double alpha, const T& a, const T& b) {
194     return (1-alpha)* a + alpha * b;
195 }
196 
197 /// Returns the smallest of the given \c values.
198 /// \ingroup group_gf_BasicMath
199 template <class T>
GfMin(T a1,T a2)200 inline T GfMin(T a1, T a2) {
201     return (a1 < a2 ? a1 : a2);
202 }
203 template <class T>
GfMin(T a1,T a2,T a3)204 inline T GfMin(T a1, T a2, T a3) {
205     return GfMin(GfMin(a1, a2), a3);
206 }
207 template <class T>
GfMin(T a1,T a2,T a3,T a4)208 inline T GfMin(T a1, T a2, T a3, T a4) {
209     return GfMin(GfMin(a1, a2, a3), a4);
210 }
211 template <class T>
GfMin(T a1,T a2,T a3,T a4,T a5)212 inline T GfMin(T a1, T a2, T a3, T a4, T a5) {
213     return GfMin(GfMin(a1, a2, a3, a4), a5);
214 }
215 
216 /// Returns the largest of the given \c values.
217 /// \ingroup group_gf_BasicMath
218 template <class T>
GfMax(T a1,T a2)219 inline T GfMax(T a1, T a2) {
220     return (a1 < a2 ? a2 : a1);
221 }
222 template <class T>
GfMax(T a1,T a2,T a3)223 inline T GfMax(T a1, T a2, T a3) {
224     return GfMax(GfMax(a1, a2), a3);
225 }
226 template <class T>
GfMax(T a1,T a2,T a3,T a4)227 inline T GfMax(T a1, T a2, T a3, T a4) {
228     return GfMax(GfMax(a1, a2, a3), a4);
229 }
230 template <class T>
GfMax(T a1,T a2,T a3,T a4,T a5)231 inline T GfMax(T a1, T a2, T a3, T a4, T a5) {
232     return GfMax(GfMax(a1, a2, a3, a4), a5);
233 }
234 
235 /// Returns the dot (inner) product of two vectors.
236 /// For scalar types, this is just the regular product.
237 /// \ingroup group_gf_BasicMath
238 template <typename Left, typename Right,
239           std::enable_if_t<GfIsArithmetic<Left>::value &&
240                            GfIsArithmetic<Right>::value, int> = 0>
decltype(std::declval<Left> ()* std::declval<Right> ())241 inline decltype(std::declval<Left>() * std::declval<Right>())
242 GfDot(Left left, Right right) {
243     return left * right;
244 }
245 
246 /// Returns component-wise multiplication of vectors.
247 /// For scalar types, this is just the regular product.
248 /// \ingroup group_gf_BasicMath
249 template <typename Left, typename Right,
250           std::enable_if_t<GfIsArithmetic<Left>::value &&
251                            GfIsArithmetic<Right>::value, int> = 0>
decltype(std::declval<Left> ()* std::declval<Right> ())252 inline decltype(std::declval<Left>() * std::declval<Right>())
253 GfCompMult(Left left, Right right) {
254     return left * right;
255 }
256 
257 /// Returns component-wise quotient of vectors.
258 /// For scalar types, this is just the regular quotient.
259 /// \ingroup group_gf_BasicMath
260 template <typename Left, typename Right,
261           std::enable_if_t<GfIsArithmetic<Left>::value &&
262                            GfIsArithmetic<Right>::value, int> = 0>
263 inline decltype(std::declval<Left>() / std::declval<Right>())
GfCompDiv(Left left,Right right)264 GfCompDiv(Left left, Right right) {
265     return left / right;
266 }
267 
268 
269 PXR_NAMESPACE_CLOSE_SCOPE
270 
271 #endif // PXR_BASE_GF_MATH_H
272