1 | /******************************************************************************* |
2 | Copyright (c) The Taichi Authors (2016- ). All Rights Reserved. |
3 | The use of this software is governed by the LICENSE file. |
4 | *******************************************************************************/ |
5 | |
6 | #pragma once |
7 | |
8 | #include <cmath> |
9 | #include "taichi/common/core.h" |
10 | |
11 | namespace taichi { |
12 | |
13 | using std::abs; |
14 | using std::acos; |
15 | using std::asin; |
16 | using std::atan; |
17 | using std::cos; |
18 | using std::floor; |
19 | using std::max; |
20 | using std::min; |
21 | using std::sin; |
22 | using std::tan; |
23 | |
24 | const real pi{acosf(-1.0_f)}; |
25 | const real eps = 1e-6_f; |
26 | |
27 | template <int I, typename T> |
28 | constexpr TI_FORCE_INLINE T pow(T a) noexcept { |
29 | T ret(1); |
30 | for (int i = 0; i < I; i++) { |
31 | ret *= a; |
32 | } |
33 | return ret; |
34 | }; |
35 | |
36 | TI_FORCE_INLINE float32 fract(float32 a) noexcept { |
37 | return a - (int)floor(a); |
38 | } |
39 | |
40 | TI_FORCE_INLINE float64 fract(float64 a) noexcept { |
41 | return a - (int)floor(a); |
42 | } |
43 | |
44 | template <typename T> |
45 | TI_FORCE_INLINE T clamp(const T &a, const T &min, const T &max) noexcept { |
46 | if (a < min) |
47 | return min; |
48 | if (a > max) |
49 | return max; |
50 | return a; |
51 | } |
52 | |
53 | template <typename T> |
54 | TI_FORCE_INLINE T clamp01(const T &a) noexcept { |
55 | if (a < T(0)) |
56 | return T(0); |
57 | if (a > T(1)) |
58 | return T(1); |
59 | return a; |
60 | } |
61 | |
62 | template <typename T> |
63 | TI_FORCE_INLINE T clamp(const T &a) noexcept { |
64 | return clamp01(a); |
65 | } |
66 | |
67 | template <typename T, typename V> |
68 | TI_FORCE_INLINE V lerp(T a, V x_0, V x_1) noexcept { |
69 | return V((T(1) - a) * x_0 + a * x_1); |
70 | } |
71 | |
72 | template <typename T> |
73 | TI_FORCE_INLINE T sqr(const T &a) noexcept { |
74 | return pow<2>(a); |
75 | } |
76 | |
77 | TI_FORCE_INLINE int sgn(float a) noexcept { |
78 | if (a < -eps) |
79 | return -1; |
80 | else if (a > eps) |
81 | return 1; |
82 | return 0; |
83 | } |
84 | |
85 | TI_FORCE_INLINE int sgn(double a) noexcept { |
86 | if (a < -eps) |
87 | return -1; |
88 | else if (a > eps) |
89 | return 1; |
90 | return 0; |
91 | } |
92 | |
93 | TI_FORCE_INLINE uint32 rand_int() noexcept { |
94 | static unsigned int x = 123456789, y = 362436069, z = 521288629, w = 88675123; |
95 | unsigned int t = x ^ (x << 11); |
96 | x = y; |
97 | y = z; |
98 | z = w; |
99 | return (w = (w ^ (w >> 19)) ^ (t ^ (t >> 8))); |
100 | } |
101 | |
102 | TI_FORCE_INLINE uint64 rand_int64() noexcept { |
103 | return ((uint64)rand_int() << 32) + rand_int(); |
104 | } |
105 | |
106 | // inline float frand() { return (float)rand() / (RAND_MAX + 1); } |
107 | TI_FORCE_INLINE float32 rand() noexcept { |
108 | return rand_int() * (1.0_f / 4294967296.0f); |
109 | } |
110 | |
111 | template <typename T> |
112 | TI_FORCE_INLINE T rand() noexcept; |
113 | |
114 | template <> |
115 | TI_FORCE_INLINE float rand<float>() noexcept { |
116 | return rand_int() * (1.0_f / 4294967296.0f); |
117 | } |
118 | |
119 | template <> |
120 | TI_FORCE_INLINE double rand<double>() noexcept { |
121 | return rand_int() * (1.0 / 4294967296.0); |
122 | } |
123 | |
124 | template <> |
125 | TI_FORCE_INLINE int rand<int>() noexcept { |
126 | return rand_int(); |
127 | } |
128 | |
129 | inline int is_prime(int a) noexcept { |
130 | assert(a >= 2); |
131 | for (int i = 2; i * i <= a; i++) { |
132 | if (a % i == 0) |
133 | return false; |
134 | } |
135 | return true; |
136 | } |
137 | |
138 | template <typename T> |
139 | TI_FORCE_INLINE T hypot2(const T &x, const T &y) noexcept { |
140 | return x * x + y * y; |
141 | } |
142 | |
143 | TI_FORCE_INLINE float32 pow(const float32 &a, const float32 &b) noexcept { |
144 | return ::pow(a, b); |
145 | } |
146 | |
147 | TI_FORCE_INLINE float64 pow(const float64 &a, const float64 &b) noexcept { |
148 | return ::pow(a, b); |
149 | } |
150 | |
151 | template <typename T> |
152 | TI_FORCE_INLINE bool is_normal(T m) noexcept { |
153 | return std::isfinite(m); |
154 | } |
155 | |
156 | template <typename T> |
157 | TI_FORCE_INLINE bool abnormal(T m) noexcept { |
158 | return !is_normal(m); |
159 | } |
160 | |
161 | inline int64 get_largest_pot(int64 a) noexcept { |
162 | TI_ASSERT_INFO(a > 0, |
163 | "a should be positive, instead of " + std::to_string(a)); |
164 | |
165 | /* This code was copied from https://stackoverflow.com/a/20207950 and edited |
166 | It uses loop unrolling, which all (modern) compilers will do. */ |
167 | for (int64 i = 1; i < 64; i *= 2) { |
168 | a |= (a >> i); |
169 | } |
170 | return a - (a >> 1); |
171 | } |
172 | |
173 | } // namespace taichi |
174 | |