1 // basic arithmetic objects
2 // Copyright (C) 2005, 2006, 2007, 2008 Tim Blechmann
3 //
4 // This program is free software; you can redistribute it and/or modify
5 // it under the terms of the GNU General Public License as published by
6 // the Free Software Foundation; either version 2 of the License, or
7 // (at your option) any later version.
8 //
9 // This program is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 // GNU General Public License for more details.
13 //
14 // You should have received a copy of the GNU General Public License
15 // along with this program; see the file COPYING. If not, write to
16 // the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17 // Boston, MA 02111-1307, USA.
18
19 #pragma once
20
21 #include <cmath>
22 #include <algorithm> // for std::min & std::max
23
24 #include <boost/math/special_functions/fpclassify.hpp>
25
26 #include "force_inline.hpp"
27
28 namespace nova {
identity(T arg)29 template <typename T> always_inline T identity(T arg) { return arg; }
30
plus(T lhs,T rhs)31 template <typename T> always_inline T plus(T lhs, T rhs) { return lhs + rhs; }
32
minus(T lhs,T rhs)33 template <typename T> always_inline T minus(T lhs, T rhs) { return lhs - rhs; }
34
inv_minus(F lhs,F rhs)35 template <typename F> always_inline F inv_minus(F lhs, F rhs) { return rhs - lhs; }
36
times(T lhs,T rhs)37 template <typename T> always_inline T times(T lhs, T rhs) { return lhs * rhs; }
38
over(T lhs,T rhs)39 template <typename T> always_inline T over(T lhs, T rhs) { return lhs / rhs; }
40
inv_over(F lhs,F rhs)41 template <typename F> always_inline F inv_over(F lhs, F rhs) { return rhs / lhs; }
42
fmod(F lhs,F rhs)43 template <typename F> always_inline F fmod(F lhs, F rhs) { return std::fmod(lhs, rhs); }
44
45
less(F lhs,F rhs)46 template <typename F> always_inline F less(F lhs, F rhs) { return F(lhs < rhs); }
47
less_equal(F lhs,F rhs)48 template <typename F> always_inline F less_equal(F lhs, F rhs) { return F(lhs <= rhs); }
49
equal(F lhs,F rhs)50 template <typename F> always_inline F equal(F lhs, F rhs) { return F(lhs == rhs); }
51
notequal(F lhs,F rhs)52 template <typename F> always_inline F notequal(F lhs, F rhs) { return F(lhs != rhs); }
53
greater(F lhs,F rhs)54 template <typename F> always_inline F greater(F lhs, F rhs) { return F(lhs > rhs); }
55
greater_equal(F lhs,F rhs)56 template <typename F> always_inline F greater_equal(F lhs, F rhs) { return F(lhs >= rhs); }
57
58 using std::max;
59 using std::min;
60
61
nova_max(F lhs,F rhs)62 template <typename F> always_inline F nova_max(F lhs, F rhs) { return max(lhs, rhs); }
63
nova_min(F lhs,F rhs)64 template <typename F> always_inline F nova_min(F lhs, F rhs) { return min(lhs, rhs); }
65
sign(F arg)66 template <typename F> always_inline F sign(F arg) {
67 if (arg > 0)
68 return F(1);
69 if (arg < 0)
70 return F(-1);
71 return F(0);
72 }
73
and_bool(F lhs,F rhs)74 template <typename F> always_inline F and_bool(F lhs, F rhs) { return F(bool(lhs) and bool(rhs)); }
75
and_bitwise(F lhs,F rhs)76 template <typename F> always_inline F and_bitwise(F lhs, F rhs) { return F(long(lhs) & long(rhs)); }
77
or_bool(F lhs,F rhs)78 template <typename F> always_inline F or_bool(F lhs, F rhs) { return F(bool(lhs) or bool(rhs)); }
79
or_bitwise(F lhs,F rhs)80 template <typename F> always_inline F or_bitwise(F lhs, F rhs) { return F(long(lhs) | long(rhs)); }
81
shift_left(F lhs,F rhs)82 template <typename F> always_inline F shift_left(F lhs, F rhs) { return F(long(lhs) << long(rhs)); }
83
shift_right(F lhs,F rhs)84 template <typename F> always_inline F shift_right(F lhs, F rhs) { return F(long(lhs) >> long(rhs)); }
85
inv_pow(F lhs,F rhs)86 template <typename F> always_inline F inv_pow(F lhs, F rhs) { return std::pow(rhs, lhs); }
87
square(F arg)88 template <typename F> always_inline F square(F arg) { return arg * arg; }
89
pow2(T const & arg)90 template <typename T> always_inline T pow2(T const& arg) { return square(arg); }
91
cube(T arg)92 template <typename T> always_inline T cube(T arg) { return arg * arg * arg; }
93
pow3(T const & arg)94 template <typename T> always_inline T pow3(T const& arg) { return cube(arg); }
95
96 using std::sqrt;
97
rsqrt(F arg)98 template <typename F> always_inline F rsqrt(F arg) { return F(1) / std::sqrt(arg); }
99
rcp(F arg)100 template <typename F> always_inline F rcp(F arg) { return F(1) / arg; }
101
102 using std::abs;
103
104
isnormal(F arg)105 template <typename F> always_inline F isnormal(F arg) {
106 #ifdef __INTEL_COMPILER /* intel compiler workaround */
107 return boost::math::isnormal(arg);
108 #else
109 return std::isnormal(arg);
110 #endif
111 }
112
113
clip(F1 t,F2 low,F3 hi)114 template <typename F1, typename F2, typename F3> always_inline F1 clip(F1 t, F2 low, F3 hi) {
115 if (t < low)
116 return low;
117 else if (t > hi)
118 return hi;
119 else
120 return t;
121 }
122
modulo(F lhs,F rhs)123 template <typename F> always_inline F modulo(F lhs, F rhs) {
124 F ret = fmod(lhs, rhs);
125 if (ret < 0)
126 ret += rhs;
127 return ret;
128 }
129
wrap_optimistic(I val,const I mod)130 template <typename I> always_inline I wrap_optimistic(I val, const I mod) {
131 if (unlikely(val >= mod))
132 do
133 val -= mod;
134 while (unlikely(val >= mod));
135 else
136 while (unlikely(val < I(0)))
137 val += mod;
138
139 return val;
140 }
141
142 template <typename I>
scale_linear(I in,I const & low_in,I const & high_in,I const & low_out,I const & high_out)143 always_inline I scale_linear(I in, I const& low_in, I const& high_in, I const& low_out, I const& high_out) {
144 return (in - low_in) / (high_in - low_in) * (high_out - low_out) + low_out;
145 }
146
147 template <typename I>
scale_linear_clipped(I in,I const & low_in,I const & high_in,I const & low_out,I const & high_out)148 always_inline I scale_linear_clipped(I in, I const& low_in, I const& high_in, I const& low_out, I const& high_out) {
149 return (in - low_in) / (high_in - low_in) * (high_out - low_out) + low_out;
150 }
151
152
153 } /* namespace nova */
154