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
11namespace taichi {
12
13using std::abs;
14using std::acos;
15using std::asin;
16using std::atan;
17using std::cos;
18using std::floor;
19using std::max;
20using std::min;
21using std::sin;
22using std::tan;
23
24const real pi{acosf(-1.0_f)};
25const real eps = 1e-6_f;
26
27template <int I, typename T>
28constexpr 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
36TI_FORCE_INLINE float32 fract(float32 a) noexcept {
37 return a - (int)floor(a);
38}
39
40TI_FORCE_INLINE float64 fract(float64 a) noexcept {
41 return a - (int)floor(a);
42}
43
44template <typename T>
45TI_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
53template <typename T>
54TI_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
62template <typename T>
63TI_FORCE_INLINE T clamp(const T &a) noexcept {
64 return clamp01(a);
65}
66
67template <typename T, typename V>
68TI_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
72template <typename T>
73TI_FORCE_INLINE T sqr(const T &a) noexcept {
74 return pow<2>(a);
75}
76
77TI_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
85TI_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
93TI_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
102TI_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); }
107TI_FORCE_INLINE float32 rand() noexcept {
108 return rand_int() * (1.0_f / 4294967296.0f);
109}
110
111template <typename T>
112TI_FORCE_INLINE T rand() noexcept;
113
114template <>
115TI_FORCE_INLINE float rand<float>() noexcept {
116 return rand_int() * (1.0_f / 4294967296.0f);
117}
118
119template <>
120TI_FORCE_INLINE double rand<double>() noexcept {
121 return rand_int() * (1.0 / 4294967296.0);
122}
123
124template <>
125TI_FORCE_INLINE int rand<int>() noexcept {
126 return rand_int();
127}
128
129inline 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
138template <typename T>
139TI_FORCE_INLINE T hypot2(const T &x, const T &y) noexcept {
140 return x * x + y * y;
141}
142
143TI_FORCE_INLINE float32 pow(const float32 &a, const float32 &b) noexcept {
144 return ::pow(a, b);
145}
146
147TI_FORCE_INLINE float64 pow(const float64 &a, const float64 &b) noexcept {
148 return ::pow(a, b);
149}
150
151template <typename T>
152TI_FORCE_INLINE bool is_normal(T m) noexcept {
153 return std::isfinite(m);
154}
155
156template <typename T>
157TI_FORCE_INLINE bool abnormal(T m) noexcept {
158 return !is_normal(m);
159}
160
161inline 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