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