/******************************************************************************* * 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 NSTL_HPP #define NSTL_HPP #include #include #include #include #include #include "z_magic.hpp" namespace mkldnn { namespace impl { 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); } }; namespace nstl { template inline const T abs(const T& a) { return a >= 0 ? a : -a; } template inline const T& max(const T& a, const T& b) { return a > b ? a : b; } template inline const T& min(const T& a, const T& b) { return a < b ? a : b; } template void swap(T& t1, T& t2) { T tmp(t1); t1 = t2; t2 = tmp; } // Rationale: MKL-DNN needs numeric limits implementation that does not // generate dependencies on C++ run-time libraries. template struct numeric_limits; template<> struct numeric_limits { static constexpr float lowest() { return -FLT_MAX; } static constexpr float max() { return FLT_MAX; } }; template<> struct numeric_limits { static constexpr int lowest() { return INT32_MIN; } static constexpr int max() { return INT32_MAX; } }; template<> struct numeric_limits { static constexpr int16_t lowest() { return INT16_MIN; } static constexpr int16_t max() { return INT16_MAX; } }; template<> struct numeric_limits { static constexpr int8_t lowest() { return INT8_MIN; } static constexpr int8_t max() { return INT8_MAX; } }; template<> struct numeric_limits { static constexpr uint8_t lowest() { return 0; } static constexpr uint8_t max() { return UINT8_MAX; } }; template struct is_integral { static constexpr bool value = false; }; template<> struct is_integral { static constexpr bool value = true; }; template<> struct is_integral { static constexpr bool value = true; }; template<> struct is_integral { static constexpr bool value = true; }; template<> struct is_integral { static constexpr bool value = true; }; template struct is_same { static constexpr bool value = false; }; template struct is_same { static constexpr bool value = true; }; // Rationale: MKL-DNN needs container implementations that do not generate // dependencies on C++ run-time libraries. // // Implementation philosophy: caller is responsible to check if the operation // is valid. The only functions that have to return status are those that // depend on memory allocation or similar operations. // // This means that e.g. an operator [] does not have to check for boundaries. // The caller should have checked the boundaries. If it did not we crash and // burn: this is a bug in MKL-DNN and throwing an exception would not have been // recoverable. // // On the other hand, insert() or resize() or a similar operation needs to // return a status because the outcome depends on factors external to the // caller. The situation is probably also not recoverable also, but MKL-DNN // needs to be nice and report "out of memory" to the users. enum nstl_status_t { success = 0, out_of_memory }; template class vector: public c_compatible { private: std::vector _impl; public: typedef typename std::vector::iterator iterator; typedef typename std::vector::const_iterator const_iterator; typedef typename std::vector::size_type size_type; vector() {} vector(size_type n): _impl(n) {} vector(size_type n, const T &value): _impl(n, value) {} template vector(input_iterator first, input_iterator last): _impl(first, last) {} ~vector() {} size_type size() const { return _impl.size(); } T& operator[] (size_type i) { return _impl[i]; } const T& operator[] (size_type i) const { return _impl[i]; } iterator begin() { return _impl.begin(); } const_iterator begin() const { return _impl.begin(); } iterator end() { return _impl.end(); } const_iterator end() const { return _impl.end(); } template nstl_status_t insert(iterator pos, input_iterator begin, input_iterator end) { _impl.insert(pos, begin, end); return success; } void clear() { _impl.clear(); } void push_back(const T& t) { _impl.push_back(t); } void resize(size_type count) { _impl.resize(count); } void reserve(size_type count) { _impl.reserve(count); } }; template class map: public c_compatible { private: std::map _impl; public: typedef typename std::map::iterator iterator; typedef typename std::map::const_iterator const_iterator; typedef typename std::map::size_type size_type; map() {} ~map() {} size_type size() const { return _impl.size(); } T& operator[](const Key &k) { return _impl[k]; } const T& operator[](const Key &k) const { return _impl[k]; } iterator begin() { return _impl.begin(); } const_iterator begin() const { return _impl.begin(); } iterator end() { return _impl.end(); } const_iterator end() const { return _impl.end(); } template void clear() { _impl.clear(); } }; } } } #endif // vim: et ts=4 sw=4 cindent cino^=l0,\:0,N-s