| 1 | /******************************************************************************* | 
|---|
| 2 | * Copyright 2016-2018 Intel Corporation | 
|---|
| 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 NSTL_HPP | 
|---|
| 18 | #define NSTL_HPP | 
|---|
| 19 |  | 
|---|
| 20 | #include <stdint.h> | 
|---|
| 21 | #include <limits.h> | 
|---|
| 22 | #include <float.h> | 
|---|
| 23 |  | 
|---|
| 24 | #include <vector> | 
|---|
| 25 | #include <map> | 
|---|
| 26 |  | 
|---|
| 27 | #include "z_magic.hpp" | 
|---|
| 28 |  | 
|---|
| 29 | namespace mkldnn { | 
|---|
| 30 | namespace impl { | 
|---|
| 31 |  | 
|---|
| 32 | void *malloc(size_t size, int alignment); | 
|---|
| 33 | void free(void *p); | 
|---|
| 34 |  | 
|---|
| 35 | struct c_compatible { | 
|---|
| 36 | enum { default_alignment = 64 }; | 
|---|
| 37 | static void *operator new(size_t sz) { | 
|---|
| 38 | return malloc(sz, default_alignment); | 
|---|
| 39 | } | 
|---|
| 40 | static void *operator new(size_t sz, void *p) { UNUSED(sz); return p; } | 
|---|
| 41 | static void *operator new[](size_t sz) { | 
|---|
| 42 | return malloc(sz, default_alignment); | 
|---|
| 43 | } | 
|---|
| 44 | static void operator delete(void *p) { free(p); } | 
|---|
| 45 | static void operator delete[](void *p) { free(p); } | 
|---|
| 46 | }; | 
|---|
| 47 |  | 
|---|
| 48 | namespace nstl { | 
|---|
| 49 |  | 
|---|
| 50 | template<typename T> | 
|---|
| 51 | inline const T abs(const T& a) { | 
|---|
| 52 | return a >= 0 ? a : -a; | 
|---|
| 53 | } | 
|---|
| 54 |  | 
|---|
| 55 | template<typename T> | 
|---|
| 56 | inline const T& max(const T& a, const T& b) { | 
|---|
| 57 | return a > b ? a : b; | 
|---|
| 58 | } | 
|---|
| 59 |  | 
|---|
| 60 | template<typename T> | 
|---|
| 61 | inline const T& min(const T& a, const T& b) { | 
|---|
| 62 | return a < b ? a : b; | 
|---|
| 63 | } | 
|---|
| 64 |  | 
|---|
| 65 | template<typename T> void swap(T& t1, T& t2) { | 
|---|
| 66 | T tmp(t1); | 
|---|
| 67 | t1 = t2; | 
|---|
| 68 | t2 = tmp; | 
|---|
| 69 | } | 
|---|
| 70 |  | 
|---|
| 71 | // Rationale: MKL-DNN needs numeric limits implementation that does not | 
|---|
| 72 | // generate dependencies on C++ run-time libraries. | 
|---|
| 73 |  | 
|---|
| 74 | template<typename T> struct numeric_limits; | 
|---|
| 75 |  | 
|---|
| 76 | template<> struct numeric_limits<float> { | 
|---|
| 77 | static constexpr float lowest() { return -FLT_MAX; } | 
|---|
| 78 | static constexpr float max() { return FLT_MAX; } | 
|---|
| 79 | }; | 
|---|
| 80 |  | 
|---|
| 81 | template<> struct numeric_limits<int32_t> { | 
|---|
| 82 | static constexpr int lowest() { return INT32_MIN; } | 
|---|
| 83 | static constexpr int max() { return INT32_MAX; } | 
|---|
| 84 | }; | 
|---|
| 85 |  | 
|---|
| 86 | template<> struct numeric_limits<int16_t> { | 
|---|
| 87 | static constexpr int16_t lowest() { return INT16_MIN; } | 
|---|
| 88 | static constexpr int16_t max() { return INT16_MAX; } | 
|---|
| 89 | }; | 
|---|
| 90 |  | 
|---|
| 91 | template<> struct numeric_limits<int8_t> { | 
|---|
| 92 | static constexpr int8_t lowest() { return INT8_MIN; } | 
|---|
| 93 | static constexpr int8_t max() { return INT8_MAX; } | 
|---|
| 94 | }; | 
|---|
| 95 |  | 
|---|
| 96 | template<> struct numeric_limits<uint8_t> { | 
|---|
| 97 | static constexpr uint8_t lowest() { return 0; } | 
|---|
| 98 | static constexpr uint8_t max() { return UINT8_MAX; } | 
|---|
| 99 | }; | 
|---|
| 100 |  | 
|---|
| 101 | template<typename T> struct is_integral | 
|---|
| 102 | { static constexpr bool value = false; }; | 
|---|
| 103 | template<> struct is_integral<int32_t> { static constexpr bool value = true; }; | 
|---|
| 104 | template<> struct is_integral<int16_t> { static constexpr bool value = true; }; | 
|---|
| 105 | template<> struct is_integral<int8_t> { static constexpr bool value = true; }; | 
|---|
| 106 | template<> struct is_integral<uint8_t> { static constexpr bool value = true; }; | 
|---|
| 107 |  | 
|---|
| 108 | template <typename T, typename U> struct is_same | 
|---|
| 109 | { static constexpr bool value = false; }; | 
|---|
| 110 | template <typename T> struct is_same<T, T> | 
|---|
| 111 | { static constexpr bool value = true; }; | 
|---|
| 112 |  | 
|---|
| 113 | // Rationale: MKL-DNN needs container implementations that do not generate | 
|---|
| 114 | // dependencies on C++ run-time libraries. | 
|---|
| 115 | // | 
|---|
| 116 | // Implementation philosophy: caller is responsible to check if the operation | 
|---|
| 117 | // is valid. The only functions that have to return status are those that | 
|---|
| 118 | // depend on memory allocation or similar operations. | 
|---|
| 119 | // | 
|---|
| 120 | // This means that e.g. an operator [] does not have to check for boundaries. | 
|---|
| 121 | // The caller should have checked the boundaries. If it did not we crash and | 
|---|
| 122 | // burn: this is a bug in MKL-DNN and throwing an exception would not have been | 
|---|
| 123 | // recoverable. | 
|---|
| 124 | // | 
|---|
| 125 | // On the other hand, insert() or resize() or a similar operation needs to | 
|---|
| 126 | // return a status because the outcome depends on factors external to the | 
|---|
| 127 | // caller. The situation is probably also not recoverable also, but MKL-DNN | 
|---|
| 128 | // needs to be nice and report "out of memory" to the users. | 
|---|
| 129 |  | 
|---|
| 130 | enum nstl_status_t { | 
|---|
| 131 | success = 0, | 
|---|
| 132 | out_of_memory | 
|---|
| 133 | }; | 
|---|
| 134 |  | 
|---|
| 135 | template <typename T> class vector: public c_compatible { | 
|---|
| 136 | private: | 
|---|
| 137 | std::vector<T> _impl; | 
|---|
| 138 | public: | 
|---|
| 139 | typedef typename std::vector<T>::iterator iterator; | 
|---|
| 140 | typedef typename std::vector<T>::const_iterator const_iterator; | 
|---|
| 141 | typedef typename std::vector<T>::size_type size_type; | 
|---|
| 142 | vector() {} | 
|---|
| 143 | vector(size_type n): _impl(n) {} | 
|---|
| 144 | vector(size_type n, const T &value): _impl(n, value) {} | 
|---|
| 145 | template <typename input_iterator> | 
|---|
| 146 | vector(input_iterator first, input_iterator last): _impl(first, last) {} | 
|---|
| 147 | ~vector() {} | 
|---|
| 148 | size_type size() const { return _impl.size(); } | 
|---|
| 149 | T& operator[] (size_type i) { return _impl[i]; } | 
|---|
| 150 | const T& operator[] (size_type i) const { return _impl[i]; } | 
|---|
| 151 | iterator begin() { return _impl.begin(); } | 
|---|
| 152 | const_iterator begin() const { return _impl.begin(); } | 
|---|
| 153 | iterator end() { return _impl.end(); } | 
|---|
| 154 | const_iterator end() const { return _impl.end(); } | 
|---|
| 155 | template <typename input_iterator> | 
|---|
| 156 | nstl_status_t insert(iterator pos, input_iterator begin, input_iterator end) | 
|---|
| 157 | { | 
|---|
| 158 | _impl.insert(pos, begin, end); | 
|---|
| 159 | return success; | 
|---|
| 160 | } | 
|---|
| 161 | void clear() { _impl.clear(); } | 
|---|
| 162 | void push_back(const T& t) { _impl.push_back(t); } | 
|---|
| 163 | void resize(size_type count) { _impl.resize(count); } | 
|---|
| 164 | void reserve(size_type count) { _impl.reserve(count); } | 
|---|
| 165 | }; | 
|---|
| 166 |  | 
|---|
| 167 | template <typename Key, typename T> class map: public c_compatible { | 
|---|
| 168 | private: | 
|---|
| 169 | std::map<Key, T> _impl; | 
|---|
| 170 | public: | 
|---|
| 171 | typedef typename std::map<Key, T>::iterator iterator; | 
|---|
| 172 | typedef typename std::map<Key, T>::const_iterator const_iterator; | 
|---|
| 173 | typedef typename std::map<Key, T>::size_type size_type; | 
|---|
| 174 | map() {} | 
|---|
| 175 | ~map() {} | 
|---|
| 176 | size_type size() const { return _impl.size(); } | 
|---|
| 177 | T& operator[](const Key &k) { return _impl[k]; } | 
|---|
| 178 | const T& operator[](const Key &k) const { return _impl[k]; } | 
|---|
| 179 | iterator begin() { return _impl.begin(); } | 
|---|
| 180 | const_iterator begin() const { return _impl.begin(); } | 
|---|
| 181 | iterator end() { return _impl.end(); } | 
|---|
| 182 | const_iterator end() const { return _impl.end(); } | 
|---|
| 183 | template <typename input_iterator> | 
|---|
| 184 | void clear() { _impl.clear(); } | 
|---|
| 185 | }; | 
|---|
| 186 |  | 
|---|
| 187 | } | 
|---|
| 188 | } | 
|---|
| 189 | } | 
|---|
| 190 |  | 
|---|
| 191 | #endif | 
|---|
| 192 |  | 
|---|
| 193 | // vim: et ts=4 sw=4 cindent cino^=l0,\:0,N-s | 
|---|
| 194 |  | 
|---|