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