Line data Source code
1 : /**
2 : * Copyright (C) 2020 Samsung Electronics Co., Ltd. All Rights Reserved.
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 : * http://www.apache.org/licenses/LICENSE-2.0
8 : * Unless required by applicable law or agreed to in writing, software
9 : * distributed under the License is distributed on an "AS IS" BASIS,
10 : * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11 : * See the License for the specific language governing permissions and
12 : * limitations under the License.
13 : *
14 : * @file util_func.h
15 : * @date 08 April 2020
16 : * @brief This is collection of math functions.
17 : * @see https://github.com/nnstreamer/nntrainer
18 : * @author Jijoong Moon <jijoong.moon@samsung.com>
19 : * @bug No known bugs except for NYI items
20 : *
21 : */
22 :
23 : #ifndef __UTIL_FUNC_H__
24 : #define __UTIL_FUNC_H__
25 :
26 : #ifdef __cplusplus
27 :
28 : #include <cstring>
29 : #include <regex>
30 : #include <sstream>
31 :
32 : #include <nntrainer_error.h>
33 : #include <random>
34 : #include <variant>
35 :
36 : // /**
37 : // * @brief get the seed
38 : // * @return seed
39 : // */
40 : // unsigned int getSeed() { return 0; }
41 :
42 : namespace nntrainer {
43 : using ReadSource = std::variant<std::ifstream *, const char *>;
44 :
45 : #define NN_RETURN_STATUS() \
46 : do { \
47 : if (status != ML_ERROR_NONE) { \
48 : return status; \
49 : } \
50 : } while (0)
51 :
52 : /**
53 : * @brief convert integer based status to throw
54 : *
55 : * @param status status to throw
56 : */
57 351 : inline void throw_status(int status) {
58 351 : switch (status) {
59 : case ML_ERROR_NONE:
60 : break;
61 1 : case ML_ERROR_INVALID_PARAMETER:
62 1 : throw std::invalid_argument("invalid argument from c style throw");
63 1 : case ML_ERROR_OUT_OF_MEMORY:
64 1 : throw std::bad_alloc();
65 1 : case ML_ERROR_TIMED_OUT:
66 1 : throw std::runtime_error("Timed out from c style throw");
67 1 : case ML_ERROR_PERMISSION_DENIED:
68 1 : throw std::runtime_error("permission denied from c style throw");
69 4 : case ML_ERROR_UNKNOWN:
70 : default:
71 4 : throw std::runtime_error("unknown error from c style throw");
72 : }
73 343 : }
74 :
75 6047 : static auto rng = [] {
76 : std::mt19937 rng;
77 : // rng.seed(getSeed());
78 : rng.seed(0);
79 6047 : return rng;
80 : }();
81 :
82 : /**
83 : * @brief sqrt function for float type
84 : * @param[in] x float
85 : */
86 0 : template <typename T = float> T sqrtFloat(T x) {
87 2296 : return static_cast<T>(sqrt((float)x));
88 : }
89 :
90 : /**
91 : * @brief sqrt function for dobuld type
92 : *
93 : * @param x value to take sqrt
94 : * @return double return value
95 : */
96 : double sqrtDouble(double x);
97 :
98 : /**
99 : * @brief abs function for float type
100 : * @param[in] x float
101 : */
102 : template <typename T = float> T absFloat(T x) {
103 : return static_cast<T>(abs((float)x));
104 : }
105 :
106 : /**
107 : * @brief log function for float type
108 : * @param[in] x float
109 : */
110 120170 : template <typename T = float> T logFloat(T x) {
111 120170 : return static_cast<T>(log(x + 1.0e-20));
112 : }
113 :
114 : /**
115 : * @brief exp function for float type
116 : * @param[in] x float
117 : */
118 28449870 : template <typename T = float> T exp_util(T x) { return static_cast<T>(exp(x)); }
119 :
120 : uint32_t ceilDiv(uint32_t a, uint32_t b);
121 :
122 : uint32_t align(uint32_t a, uint32_t b);
123 :
124 : #ifdef _WIN32
125 : #ifdef _Float16
126 : template <> _Float16 exp_util<_Float16>(_Float16 x) {
127 : return static_cast<_Float16>(std::exp(static_cast<float>(x)));
128 : }
129 : #endif
130 : #endif
131 :
132 : /**
133 : * @brief Check if float is not nan and not inf
134 : * @param[in] value float
135 : * @note We can switch to use std::isfinite once it will start support half
136 : floats
137 : */
138 : template <typename T> bool isFloatValid(const T value) {
139 14 : return !((value != value) ||
140 28 : (value == std::numeric_limits<float>::infinity()) ||
141 : (value == -std::numeric_limits<float>::infinity()));
142 : }
143 :
144 : /**
145 : * @brief Check Existance of File
146 : * @param[in] file path of the file to be checked
147 : * @returns true if file exists, else false
148 : */
149 : bool isFileExist(std::string file);
150 :
151 : constexpr const char *default_error_msg =
152 : "[util::checkeFile] file operation failed";
153 :
154 : /**
155 : * @brief same as file.read except it checks if fail to read the file
156 : *
157 : * @param file file to read
158 : * @param array char * array
159 : * @param size size of the array
160 : * @param error_msg error msg to print when operation fail
161 : * @throw std::runtime_error if file.fail() is true after read.
162 : */
163 : void checkedRead(std::ifstream &file, char *array, std::streamsize size,
164 : const char *error_msg = default_error_msg,
165 : size_t start_offset = 0, bool read_from_offset = false);
166 :
167 : /**
168 : * @brief same as file.read except it checks if fail to read the file
169 : *
170 : * @param ReadSource Source to read
171 : * @param array char * array
172 : * @param size size of the array
173 : * @param error_msg error msg to print when operation fail
174 : * @throw std::runtime_error if file.fail() is true after read.
175 : */
176 : void checkedRead(ReadSource src, char *array, std::streamsize size,
177 : const char *error_msg, size_t start_offset,
178 : bool read_from_offset);
179 :
180 : /**
181 : * @brief same as file.write except it checks if fail to write the file
182 : *
183 : * @param file file to write
184 : * @param array char * array
185 : * @param size size of the array
186 : * @param error_msg error msg to print when operation fail
187 : * @throw std::runtime_error if file.fail() is true after write.
188 : */
189 : void checkedWrite(std::ostream &file, const char *array, std::streamsize size,
190 : const char *error_msg = default_error_msg);
191 : /**
192 : * @brief read string from a binary file
193 : *
194 : * @param file file to input
195 : * @return std::string result string
196 : */
197 : std::string readString(std::ifstream &file,
198 : const char *error_msg = default_error_msg);
199 :
200 : /**
201 : * @brief write string to a binary file
202 : *
203 : * @param file file to write
204 : * @param str target string to write
205 : */
206 : void writeString(std::ofstream &file, const std::string &str,
207 : const char *error_msg = default_error_msg);
208 :
209 : /**
210 : * @brief check if string ends with @a suffix
211 : *
212 : * @param target string to cehck
213 : * @param suffix check if string ends with @a suffix
214 : * @retval true @a target ends with @a suffix
215 : * @retval false @a target does not ends with @a suffix
216 : */
217 : bool endswith(const std::string &target, const std::string &suffix);
218 :
219 : /**
220 : * @brief print instance info. as <Type at (address)>
221 : * @param[in] std::ostream &out, T&& t
222 : * @param[in] t pointer to the instance
223 : */
224 : template <typename T,
225 : typename std::enable_if_t<std::is_pointer<T>::value, T> * = nullptr>
226 11 : void printInstance(std::ostream &out, const T &t) {
227 22 : out << '<' << typeid(*t).name() << " at " << t << '>' << std::endl;
228 11 : }
229 :
230 : /**
231 : * @brief make "key=value" from key and value
232 : *
233 : * @tparam T type of a value
234 : * @param key key
235 : * @param value value
236 : * @return std::string with "key=value"
237 : */
238 : template <typename T>
239 83 : static std::string withKey(const std::string &key, const T &value) {
240 83 : std::stringstream ss;
241 83 : ss << key << "=" << value;
242 83 : return ss.str();
243 83 : }
244 :
245 : /**
246 : * @brief make "key=value1,value2,...valueN" from key and multiple values
247 : *
248 : * @tparam T type of a value
249 : * @param key key
250 : * @param value list of values
251 : * @return std::string with "key=value1,value2,...valueN"
252 : */
253 : template <typename T>
254 8 : static std::string withKey(const std::string &key,
255 : std::initializer_list<T> value) {
256 8 : if (std::empty(value)) {
257 0 : throw std::invalid_argument("empty data cannot be converted");
258 : }
259 8 : std::stringstream ss;
260 8 : ss << key << "=";
261 : auto iter = value.begin();
262 16 : for (; iter != value.end() - 1; ++iter) {
263 8 : ss << *iter << ',';
264 : }
265 8 : ss << *iter;
266 8 : return ss.str();
267 8 : }
268 :
269 : /**
270 : * @brief creat a stream, and if !stream.good() throw appropriate error code
271 : * depending on @c errno
272 : *
273 : * @tparam T return type
274 : * @param path path
275 : * @param mode mode to open path
276 : * @return T created stream
277 : */
278 : template <typename T>
279 2090 : T checkedOpenStream(const std::string &path, std::ios_base::openmode mode) {
280 2090 : T model_file(path, mode);
281 2090 : if (!model_file.good()) {
282 : const size_t error_buflen = 100;
283 : char error_buf[error_buflen];
284 0 : std::stringstream ss;
285 : ss << "[parseutil] requested file not opened, file path: " << path
286 0 : << " reason: " << SAFE_STRERROR(errno, error_buf, error_buflen);
287 0 : if (errno == EPERM || errno == EACCES) {
288 0 : throw nntrainer::exception::permission_denied(ss.str().c_str());
289 : } else {
290 0 : throw std::invalid_argument(ss.str().c_str());
291 : }
292 0 : }
293 :
294 2090 : return model_file;
295 0 : }
296 :
297 : /**
298 : * @brief parse string and return key & value
299 : * @param[in] input_str input string to split with '='
300 : * @param[out] key key
301 : * @param[out] value value
302 : * @retval #ML_ERROR_NONE Successful.
303 : * @retval #ML_ERROR_INVALID_PARAMETER invalid parameter.
304 : */
305 : int getKeyValue(const std::string &input_str, std::string &key,
306 : std::string &value);
307 :
308 : /**
309 : * @brief parse string and stored to int
310 : * @param[in] n_str number of data
311 : * @param[in] str string to parse
312 : * @param[in] value int value to stored
313 : * @retval #ML_ERROR_NONE Successful.
314 : * @retval #ML_ERROR_INVALID_PARAMETER invalid parameter.
315 : */
316 : int getValues(int n_str, std::string str, int *value);
317 :
318 : /**
319 : * @brief split string into vector with delimiter regex
320 : * @param[in] str string
321 : * @param[in] reg regular expression to use as delimiter
322 : * @retval output string vector
323 : */
324 : std::vector<std::string> split(const std::string &s, const std::regex ®);
325 :
326 : /**
327 : * @brief Cast insensitive string comparison
328 : *
329 : * @param a first string to compare
330 : * @param b second string to compare
331 : * @retval true if string is case-insensitive equal
332 : * @retval false if string is case-insensitive not equal
333 : */
334 : bool istrequal(const std::string &a, const std::string &b);
335 :
336 : /**
337 : * @brief Perform INT_LOGICAL_AND operation on enum class value
338 : *
339 : * @param e1 enum value
340 : * @param e2 enum value
341 : *
342 : * @return enum value after performing logical AND operation
343 : */
344 : template <typename T, typename C = int>
345 : bool enum_class_logical_and(T e1, T e2) {
346 : C i1 = static_cast<int>(e1);
347 : C i2 = static_cast<int>(e2);
348 :
349 10552 : return (i1 & i2) != 0;
350 : }
351 :
352 : /**
353 : * @brief Perform INT_OR operation on enum class value
354 : *
355 : * @param e1 enum value
356 : * @param e2 enum value
357 : *
358 : * @return enum value after performing OR operation
359 : */
360 : template <typename T, typename C = int> T enum_class_or(T e1, T e2) {
361 : C i1 = static_cast<int>(e1);
362 : C i2 = static_cast<int>(e2);
363 :
364 65725 : return static_cast<T>(i1 | i2);
365 : }
366 :
367 : /**
368 : * @brief Find value in tuple by key (internal impl)
369 : *
370 : * @tparam Tuple Tuple type to search
371 : * @tparam ls... Tuple index sequence
372 : * @param t Tuple to search
373 : * @param key Key to find
374 : *
375 : * @return Found value or empty string
376 : */
377 : template <typename Tuple, std::size_t... ls>
378 0 : std::string find_in_tuple(const Tuple &t, std::index_sequence<ls...>,
379 : const std::string &key) {
380 0 : std::string result = "";
381 :
382 0 : (..., ([&] {
383 0 : auto &&elem = std::get<ls>(t);
384 0 : if (strcmp(getPropKey(elem), key.c_str()) == 0) {
385 0 : result = elem.empty() ? "empty" : to_string(elem);
386 : }
387 0 : }()));
388 :
389 0 : return result;
390 : }
391 :
392 : /**
393 : * @brief Find value in tuple by key (user-friendly wrapper)
394 : *
395 : * @tparam Args Tuple element types
396 : * @param t Tuple to search
397 : * @param key Key to find
398 : *
399 : * @return Found value or empty string
400 : */
401 : template <typename... Args>
402 : std::string find_in_tuple(const std::tuple<Args...> &t,
403 : const std::string &key) {
404 0 : return find_in_tuple(t, std::index_sequence_for<Args...>{}, key);
405 : }
406 :
407 : /**
408 : * @brief Convert a relative path into an absolute path.
409 : *
410 : * @param name relative path
411 : * @param resolved variable to store the result value.
412 : *
413 : * @return absolute path
414 : */
415 : char *getRealpath(const char *name, char *resolved);
416 :
417 : /**
418 : * @brief Get local time in tm struct format
419 : *
420 : * @param tp variable to store the result values
421 : *
422 : * @return tm struct
423 : */
424 : tm *getLocaltime(tm *tp);
425 :
426 : /**
427 : * @brief Create and return std::regex with the received string
428 : * @param str String in regular expression form
429 : * @return std::regex
430 : */
431 : std::regex getRegex(const std::string &str);
432 :
433 : /**
434 : * @brief Convert a floating-point number into its fixed-point component (the
435 : * mantissa) and its exponent component.
436 : *
437 : * @param[in] input floating point to convert
438 : * @param[out] fixedpoint fixed-point
439 : * @param[out] exponent exponent
440 : */
441 : void floatToFixedPointAndExponent(float input, int &fixedpoint, int &exponent);
442 :
443 : /**
444 : * @brief Convert a fixed-point number and an exponent into a floating-point
445 : * number.
446 : *
447 : * @param[in] fixedpoint fixed-point
448 : * @param[in] exponent exponent
449 : * @return floating point result
450 : */
451 : float fixedPointAndExponentToFloat(int fixedpoint, int exponent);
452 :
453 : } /* namespace nntrainer */
454 :
455 : #endif /* __cplusplus */
456 : #endif /* __UTIL_FUNC_H__ */
|