/******************************************************************************* * Copyright 2016-2018 Intel Corporation * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. *******************************************************************************/ #ifndef UTILS_HPP #define UTILS_HPP #include #include #include #include namespace mkldnn { namespace impl { #define UNUSED(x) ((void)x) #define MAYBE_UNUSED(x) UNUSED(x) #define CHECK(f) do { \ status_t status = f; \ if (status != status::success) \ return status; \ } while (0) #ifdef _WIN32 #define __PRETTY_FUNCTION__ __FUNCSIG__ #endif namespace utils { /* a bunch of std:: analogues to be compliant with any msvs version * * Rationale: msvs c++ (and even some c) headers contain special pragma that * injects msvs-version check into object files in order to abi-mismatches * during the static linking. This makes sense if e.g. std:: objects are passed * through between application and library, which is not the case for mkl-dnn * (since there is no any c++-rt dependent stuff, ideally...). */ /* SFINAE helper -- analogue to std::enable_if */ template struct enable_if {}; template struct enable_if { typedef T type; }; /* analogue std::conditional */ template struct conditional {}; template struct conditional { typedef T type; }; template struct conditional { typedef F type; }; template struct conditional3 {}; template struct conditional3 { typedef T type; }; template struct conditional3 { typedef FT type; }; template struct conditional3 { typedef FF type; }; template struct conditional_v {}; template struct conditional_v { static constexpr U value = t; }; template struct conditional_v { static constexpr U value = f; }; template struct remove_reference { typedef T type; }; template struct remove_reference { typedef T type; }; template struct remove_reference { typedef T type; }; template inline T&& forward(typename utils::remove_reference::type &t) { return static_cast(t); } template inline T&& forward(typename utils::remove_reference::type &&t) { return static_cast(t); } template inline typename remove_reference::type zero() { auto zero = typename remove_reference::type(); return zero; } template inline bool everyone_is(T val, P item) { return val == item; } template inline bool everyone_is(T val, P item, Args... item_others) { return val == item && everyone_is(val, item_others...); } template inline bool one_of(T val, P item) { return val == item; } template inline bool one_of(T val, P item, Args... item_others) { return val == item || one_of(val, item_others...); } template inline bool any_null(Args... ptrs) { return one_of(nullptr, ptrs...); } inline bool implication(bool cause, bool effect) { return !cause || effect; } template inline void array_copy(T *dst, const T *src, size_t size) { for (size_t i = 0; i < size; ++i) dst[i] = src[i]; } template inline bool array_cmp(const T *a1, const T *a2, size_t size) { for (size_t i = 0; i < size; ++i) if (a1[i] != a2[i]) return false; return true; } template inline void array_set(T *arr, const U& val, size_t size) { for (size_t i = 0; i < size; ++i) arr[i] = static_cast(val); } namespace product_impl { template struct int2type{}; template constexpr int product_impl(const T *arr, int2type<0>) { return arr[0]; } template inline T product_impl(const T *arr, int2type) { return arr[0]*product_impl(arr+1, int2type()); } } template inline T array_product(const T *arr) { return product_impl::product_impl(arr, product_impl::int2type()); } template inline R array_product(const T *arr, size_t size) { R prod = 1; for (size_t i = 0; i < size; ++i) prod *= arr[i]; return prod; } template inline typename remove_reference::type div_up(const T a, const U b) { assert(b); return (a + b - 1) / b; } template inline typename remove_reference::type rnd_up(const T a, const U b) { return div_up(a, b) * b; } template inline typename remove_reference::type rnd_dn(const T a, const U b) { return (a / b) * b; } template inline U this_block_size(const T offset, const U max, const V block_size) { assert(offset < max); // TODO (Roma): can't use nstl::max() due to circular dependency... we // need to fix this const T block_boundary = offset + block_size; if (block_boundary > max) return max - offset; else return block_size; } template inline T nd_iterator_init(T start) { return start; } template inline T nd_iterator_init(T start, U &x, const W &X, Args &&... tuple) { start = nd_iterator_init(start, utils::forward(tuple)...); x = start % X; return start / X; } inline bool nd_iterator_step() { return true; } template inline bool nd_iterator_step(U &x, const W &X, Args &&... tuple) { if (nd_iterator_step(utils::forward(tuple)...) ) { x = (x + 1) % X; return x == 0; } return false; } template inline bool nd_iterator_jump(U &cur, const U end, W &x, const Y &X) { U max_jump = end - cur; U dim_jump = X - x; if (dim_jump <= max_jump) { x = 0; cur += dim_jump; return true; } else { cur += max_jump; x += max_jump; return false; } } template inline bool nd_iterator_jump(U &cur, const U end, W &x, const Y &X, Args &&... tuple) { if (nd_iterator_jump(cur, end, utils::forward(tuple)...)) { x = (x + 1) % X; return x == 0; } return false; } template struct array_offset_calculator { template array_offset_calculator(Telem *base, Targs... Fargs) : _dims{ Fargs... } { _base_ptr = base; } template inline Telem &operator()(Targs... Fargs) { return *(_base_ptr + _offset(1, Fargs...)); } private: template inline size_t _offset(size_t const dimension, size_t element) { return element; } template inline size_t _offset(size_t const dimension, size_t theta, size_t element) { return element + (_dims[dimension] * theta); } template inline size_t _offset(size_t const dimension, size_t theta, size_t element, Targs... Fargs) { size_t t_prime = element + (_dims[dimension] * theta); return _offset(dimension + 1, t_prime, Fargs...); } Telem *_base_ptr; const int _dims[Tdims]; }; } void *malloc(size_t size, int alignment); void free(void *p); struct c_compatible { enum { default_alignment = 64 }; static void *operator new(size_t sz) { return malloc(sz, default_alignment); } static void *operator new(size_t sz, void *p) { UNUSED(sz); return p; } static void *operator new[](size_t sz) { return malloc(sz, default_alignment); } static void operator delete(void *p) { free(p); } static void operator delete[](void *p) { free(p); } }; inline void yield_thread() { } int mkldnn_getenv(char *value, const char *name, int len); bool mkldnn_jit_dump(); FILE *mkldnn_fopen(const char *filename, const char *mode); unsigned int get_cache_size(int level, bool per_core); } } #endif // vim: et ts=4 sw=4 cindent cino^=l0,\:0,N-s