OmniSciDB  d2f719934e
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
misc.h
Go to the documentation of this file.
1 /*
2  * Copyright 2019 OmniSci, Inc.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #ifndef SHARED_MISC_H
18 #define SHARED_MISC_H
19 
20 #include <array>
21 #include <cstdint>
22 #include <cstring>
23 #include <deque>
24 #include <iterator>
25 #include <list>
26 #include <map>
27 #include <set>
28 #include <string_view>
29 #include <unordered_set>
30 #include <vector>
31 
32 namespace {
33 
34 template <typename T>
35 constexpr T power(T const a, T const n) {
36  return n ? a * power(a, n - 1) : static_cast<T>(1);
37 }
38 
39 template <typename T, size_t... Indices>
40 constexpr std::array<T, sizeof...(Indices)> powersOfImpl(
41  T const a,
42  std::index_sequence<Indices...>) {
43  return {power(a, static_cast<T>(Indices))...};
44 }
45 
46 template <size_t... Indices>
47 constexpr std::array<double, sizeof...(Indices)> inversePowersOfImpl(
48  double const a,
49  std::index_sequence<Indices...>) {
50  return {(1.0 / power(a, static_cast<double>(Indices)))...};
51 }
52 
53 } // namespace
54 
55 namespace shared {
56 
57 template <typename K, typename V>
58 V& get_from_map(std::map<K, V>& map, const K& key) {
59  auto find_it = map.find(key);
60  CHECK(find_it != map.end());
61  return find_it->second;
62 }
63 
64 template <typename K, typename V>
65 const V& get_from_map(const std::map<K, V>& map, const K& key) {
66  auto find_it = map.find(key);
67  CHECK(find_it != map.end());
68  return find_it->second;
69 }
70 
71 // source is destructively appended to the back of destination.
72 // Return number of elements appended.
73 template <typename T>
74 size_t append_move(std::vector<T>& destination, std::vector<T>&& source) {
75  if (source.empty()) {
76  return 0;
77  } else if (destination.empty()) {
78  destination = std::move(source);
79  return destination.size();
80  } else {
81  size_t const source_size = source.size();
82  destination.reserve(destination.size() + source_size);
83  std::move(std::begin(source), std::end(source), std::back_inserter(destination));
84  return source_size;
85  }
86 }
87 
88 template <typename... Ts, typename T>
89 bool dynamic_castable_to_any(T const* ptr) {
90  return (... || dynamic_cast<Ts const*>(ptr));
91 }
92 
93 // Helper to print out contents of simple containers (e.g. vector, list, deque)
94 // including nested containers, e.g. 2d vectors, list of vectors, etc.
95 // Base value_type must be a std::is_scalar_v type, though you can add custom
96 // objects below with a new `else if constexpr` block.
97 // Example: VLOG(1) << "container=" << shared::printContainer(container);
98 template <typename CONTAINER>
100  CONTAINER& container;
101 };
102 
103 template <typename CONTAINER>
105  return {container};
106 }
107 
108 template <typename CONTAINER>
109 struct is_std_container : std::false_type {};
110 template <typename T, typename A>
111 struct is_std_container<std::deque<T, A> > : std::true_type {};
112 template <typename T, typename A>
113 struct is_std_container<std::list<T, A> > : std::true_type {};
114 template <typename T, typename A>
115 struct is_std_container<std::set<T, A> > : std::true_type {};
116 template <typename T, typename A>
117 struct is_std_container<std::unordered_set<T, A> > : std::true_type {};
118 template <typename T, typename A>
119 struct is_std_container<std::vector<T, A> > : std::true_type {};
120 
121 template <typename OSTREAM, typename CONTAINER>
122 OSTREAM& operator<<(OSTREAM& os, PrintContainer<CONTAINER> pc) {
123  if (pc.container.empty()) {
124  return os << "()";
125  } else {
127  os << '(';
128  for (auto& container : pc.container) {
129  os << printContainer(container);
130  }
131  } else {
132  for (auto itr = pc.container.begin(); itr != pc.container.end(); ++itr) {
133  if constexpr (std::is_pointer_v<typename CONTAINER::value_type>) { // NOLINT
134  os << (itr == pc.container.begin() ? '(' : ' ') << (void const*)*itr;
135  } else {
136  os << (itr == pc.container.begin() ? '(' : ' ') << *itr;
137  }
138  }
139  }
140  return os << ')';
141  }
142 }
143 
144 // Same as strftime(buf, max, "%F", tm) but guarantees that the year is
145 // zero-padded to a minimum length of 4. Return the number of characters
146 // written, not including null byte. If max is not large enough, return 0.
147 size_t formatDate(char* buf, size_t const max, int64_t const unixtime);
148 
149 // Same as strftime(buf, max, "%F %T", tm) but guarantees that the year is
150 // zero-padded to a minimum length of 4. Return the number of characters
151 // written, not including null byte. If max is not large enough, return 0.
152 // Requirement: 0 <= dimension <= 9.
153 size_t formatDateTime(char* buf,
154  size_t const max,
155  int64_t const timestamp,
156  int const dimension);
157 
158 // Write unixtime in seconds since epoch as "HH:MM:SS" format.
159 size_t formatHMS(char* buf, size_t const max, int64_t const unixtime);
160 
161 // Result of division where quot is floored and rem is unsigned.
162 struct DivUMod {
163  int64_t quot;
164  int64_t rem;
165 };
166 
167 // Requirement: 0 < den
168 inline DivUMod divUMod(int64_t num, int64_t den) {
169  DivUMod div{num / den, num % den};
170  if (div.rem < 0) {
171  --div.quot;
172  div.rem += den;
173  }
174  return div;
175 }
176 
177 // Requirement: 0 < den.
178 inline uint64_t unsignedMod(int64_t num, int64_t den) {
179  int64_t mod = num % den;
180  if (mod < 0) {
181  mod += den;
182  }
183  return mod;
184 }
185 
186 template <typename T, typename U>
187 inline bool contains(const T& container, const U& element) {
188  if (std::find(container.begin(), container.end(), element) == container.end()) {
189  return false;
190  } else {
191  return true;
192  }
193 }
194 
195 // Calculate polynomial c0 + c1*x + c2*x^2 + ... + cn*x^n using Horner's method.
196 template <typename... COEFFICIENTS>
197 constexpr double horner(double const x, double const c0, COEFFICIENTS... c) {
198  if constexpr (sizeof...(COEFFICIENTS) == 0) { // NOLINT
199  return c0;
200  } else {
201  return horner(x, c...) * x + c0;
202  }
203  return {}; // quiet nvcc warning https://stackoverflow.com/a/64561686/2700898
204 }
205 
206 // OK for -0.15 <= x <= 0.15
207 inline double fastAtanh(double const x) {
208  // Mathematica: CoefficientList[Normal@Series[ArcTanh[x],{x,0,16}],x] // InputForm
209  return x * horner(x * x, 1, 1 / 3., 1 / 5., 1 / 7., 1 / 9., 1 / 11., 1 / 13., 1 / 15.);
210 }
211 
212 // OK for -1 <= x <= 1
213 inline double fastCos(double const x) {
214  // Mathematica: CoefficientList[Normal@Series[Cos[x],{x,0,16}],x] // InputForm
215  // clang-format off
216  return horner(x * x, 1, -1/2., 1/24., -1/720., 1/40320., -1/3628800.,
217  1/479001600., -1/87178291200., 1/20922789888000.);
218  // clang-format on
219 }
220 
221 // OK for -1 <= x <= 1
222 inline double fastCosh(double const x) {
223  // Mathematica: CoefficientList[Normal@Series[Cosh[x],{x,0,16}],x] // InputForm
224  // clang-format off
225  return horner(x * x, 1, 1/2., 1/24., 1/720., 1/40320., 1/3628800.,
226  1/479001600., 1/87178291200., 1/20922789888000.);
227  // clang-format on
228 }
229 
230 // OK for -1 <= x <= 1
231 inline double fastSin(double const x) {
232  // Mathematica: CoefficientList[Normal@Series[Sin[x],{x,0,16}],x] // InputForm
233  // clang-format off
234  return x * horner(x * x, 1, -1/6., 1/120., -1/5040., 1/362880.,
235  -1/39916800., 1/6227020800., -1/1307674368000.);
236  // clang-format on
237 }
238 
239 // OK for -1 <= x <= 1
240 inline double fastSinh(double const x) {
241  // Mathematica: CoefficientList[Normal@Series[Sinh[x],{x,0,16}],x] // InputForm
242  // clang-format off
243  return x * horner(x * x, 1, 1/6., 1/120., 1/5040., 1/362880.,
244  1/39916800., 1/6227020800., 1/1307674368000.);
245  // clang-format on
246 }
247 
248 // Return constexpr std::array<T, N> of {1, a, a^2, a^3, ..., a^(N-1)}.
249 template <typename T, size_t N>
250 constexpr std::array<T, N> powersOf(T const a) {
251  return powersOfImpl<T>(a, std::make_index_sequence<N>{});
252 }
253 
254 // Return constexpr std::array<double, N> of {1, 1/a, 1/a^2, 1/a^3, ..., 1/a^(N-1)}.
255 template <size_t N>
256 constexpr std::array<double, N> inversePowersOf(double const a) {
257  return inversePowersOfImpl(a, std::make_index_sequence<N>{});
258 }
259 
260 // Return pow(10,x). Single-lookup for x < 20.
261 inline double power10(unsigned const x) {
262  constexpr unsigned N = 20;
263  constexpr auto pow10 = powersOf<double, N>(10.0);
264  return x < N ? pow10[x] : (pow10[N - 1] * 10) * power10(x - N);
265 }
266 
267 // Return 1/pow(10,x). Single-lookup for x < 20.
268 inline double power10inv(unsigned const x) {
269  constexpr unsigned N = 20;
270  constexpr auto pow10inv = inversePowersOf<N>(10.0);
271  return x < N ? pow10inv[x] : (pow10inv[N - 1] / 10) * power10inv(x - N);
272 }
273 
274 // May be constexpr in C++20.
275 template <typename TO, typename FROM>
276 inline TO reinterpret_bits(FROM const from) {
277  TO to{0};
278  memcpy(&to, &from, sizeof(TO) < sizeof(FROM) ? sizeof(TO) : sizeof(FROM));
279  return to;
280 }
281 
282 template <typename... STR>
283 constexpr std::array<std::string_view, sizeof...(STR)> string_view_array(STR&&... str) {
284  return {std::forward<STR>(str)...};
285 }
286 
287 template <typename OUTPUT, typename INPUT, typename FUNC>
288 OUTPUT transform(INPUT const& input, FUNC const& func) {
289  OUTPUT output;
290  output.reserve(input.size());
291  for (auto const& x : input) {
292  output.push_back(func(x));
293  }
294  return output;
295 }
296 
297 } // namespace shared
298 
299 #endif // SHARED_MISC_H
bool contains(const T &container, const U &element)
Definition: misc.h:187
double power10(unsigned const x)
Definition: misc.h:261
double fastCosh(double const x)
Definition: misc.h:222
TO reinterpret_bits(FROM const from)
Definition: misc.h:276
int64_t quot
Definition: misc.h:163
constexpr std::array< double, N > inversePowersOf(double const a)
Definition: misc.h:256
double fastCos(double const x)
Definition: misc.h:213
EXTENSION_NOINLINE double power(const double x, const double y)
#define TO
size_t formatDateTime(char *buf, size_t const max, int64_t const timestamp, int const dimension)
Definition: misc.cpp:43
constexpr std::array< T, sizeof...(Indices)> powersOfImpl(T const a, std::index_sequence< Indices...>)
Definition: misc.h:40
size_t formatHMS(char *buf, size_t const max, int64_t const unixtime)
Definition: misc.cpp:80
constexpr double a
Definition: Utm.h:33
size_t append_move(std::vector< T > &destination, std::vector< T > &&source)
Definition: misc.h:74
constexpr std::array< double, sizeof...(Indices)> inversePowersOfImpl(double const a, std::index_sequence< Indices...>)
Definition: misc.h:47
#define FROM
OUTPUT transform(INPUT const &input, FUNC const &func)
Definition: misc.h:288
double power10inv(unsigned const x)
Definition: misc.h:268
constexpr std::array< std::string_view, sizeof...(STR)> string_view_array(STR &&...str)
Definition: misc.h:283
CONTAINER & container
Definition: misc.h:100
char * to
size_t formatDate(char *buf, size_t const max, int64_t const unixtime)
Definition: misc.cpp:25
uint64_t unsignedMod(int64_t num, int64_t den)
Definition: misc.h:178
V & get_from_map(std::map< K, V > &map, const K &key)
Definition: misc.h:58
constexpr double horner(double const x, double const c0, COEFFICIENTS...c)
Definition: misc.h:197
constexpr unsigned N
Definition: Utm.h:111
#define CHECK(condition)
Definition: Logger.h:211
double fastSinh(double const x)
Definition: misc.h:240
int64_t rem
Definition: misc.h:164
bool dynamic_castable_to_any(T const *ptr)
Definition: misc.h:89
PrintContainer< CONTAINER > printContainer(CONTAINER &container)
Definition: misc.h:104
constexpr double n
Definition: Utm.h:39
constexpr std::array< T, N > powersOf(T const a)
Definition: misc.h:250
double fastAtanh(double const x)
Definition: misc.h:207
double fastSin(double const x)
Definition: misc.h:231
DivUMod divUMod(int64_t num, int64_t den)
Definition: misc.h:168