//////////////////////////////////////////////////////////////////////////////// /// DISCLAIMER /// /// Copyright 2016 by EMC Corporation, All Rights Reserved /// /// 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. /// /// Copyright holder is EMC Corporation /// /// @author Andrey Abramov /// @author Vasiliy Nabatchikov //////////////////////////////////////////////////////////////////////////////// #ifndef IRESEARCH_NUMERIC_UTILS_H #define IRESEARCH_NUMERIC_UTILS_H #include "utils/string.hpp" NS_LOCAL // MSVC < v14.0 (Visual Studio >2015) does not support explicit initializer for arrays: error C2536 // GCC < v4.9 does not initialize the union array member with the specified value (initializes with {0,0}) // CLANG (at least 4.0.1) does not support constexpr reinterpret cast // for versions @see https://github.com/thp/psmoveapi/blob/master/external/glm/glm/simd/platform.h #if defined(__APPLE__) \ || (defined(__clang__) && (__clang_major__ > 4)) \ || (defined(_MSC_VER) && (_MSC_VER >= 1900)) \ || (defined(__GNUC__) && (__GNUC__ >= 5)) \ || (defined(__GNUC__) && (__GNUC__ == 4) && (__GNUC_MINOR__ >= 9)) union big_endian_check { char raw[2]{ '\0', '\xff' }; uint16_t num; // big endian: num < 0x100 CONSTEXPR operator bool() const { return num < 0x100; } }; #endif template struct equal_size_type; template<> struct equal_size_type { typedef int32_t type; }; template<> struct equal_size_type { typedef int64_t type; }; template<> struct equal_size_type { typedef uint32_t type; }; template<> struct equal_size_type { typedef uint64_t type; }; NS_END NS_ROOT NS_BEGIN(numeric_utils) #if defined(__APPLE__) \ || (defined(__clang__) && (__clang_major__ > 4)) \ || (defined(_MSC_VER) && (_MSC_VER >= 1900)) \ || (defined(__GNUC__) && (__GNUC__ >= 5)) \ || (defined(__GNUC__) && (__GNUC__ == 4) && (__GNUC_MINOR__ >= 9)) inline CONSTEXPR bool is_big_endian() { return big_endian_check(); } #else inline CONSTEXPR bool is_big_endian() { return *(uint16_t*)"\0\xff" < 0x100; } #endif IRESEARCH_API const bytes_ref& mini64(); IRESEARCH_API const bytes_ref& maxi64(); IRESEARCH_API uint64_t decode64(const byte_type* out); IRESEARCH_API size_t encode64(uint64_t value, byte_type* out, size_t shift = 0); IRESEARCH_API uint64_t hton64(uint64_t value); IRESEARCH_API uint64_t ntoh64(uint64_t value); IRESEARCH_API const bytes_ref& minu64(); IRESEARCH_API const bytes_ref& maxu64(); IRESEARCH_API const bytes_ref& mini32(); IRESEARCH_API const bytes_ref& maxi32(); IRESEARCH_API uint32_t decode32(const byte_type* out); IRESEARCH_API size_t encode32(uint32_t value, byte_type* out, size_t shift = 0); IRESEARCH_API uint32_t hton32(uint32_t value); IRESEARCH_API uint32_t ntoh32(uint32_t value); IRESEARCH_API const bytes_ref& minu32(); IRESEARCH_API const bytes_ref& maxu32(); IRESEARCH_API size_t encodef32(uint32_t value, byte_type* out, size_t shift = 0); IRESEARCH_API uint32_t decodef32(const byte_type* out); IRESEARCH_API int32_t ftoi32(float_t value); IRESEARCH_API float_t i32tof(int32_t value); IRESEARCH_API const bytes_ref& minf32(); IRESEARCH_API const bytes_ref& maxf32(); IRESEARCH_API const bytes_ref& finf32(); IRESEARCH_API const bytes_ref& nfinf32(); IRESEARCH_API size_t encoded64(uint64_t value, byte_type* out, size_t shift = 0); IRESEARCH_API uint64_t decoded64(const byte_type* out); IRESEARCH_API int64_t dtoi64(double_t value); IRESEARCH_API double_t i64tod(int64_t value); IRESEARCH_API const bytes_ref& mind64(); IRESEARCH_API const bytes_ref& maxd64(); IRESEARCH_API const bytes_ref& dinf64(); IRESEARCH_API const bytes_ref& ndinf64(); template struct numeric_traits; template<> struct numeric_traits { typedef int32_t integral_t; static const bytes_ref& (min)() { return mini32(); } static const bytes_ref& (max)() { return maxi32(); } inline static integral_t integral(integral_t value) { return value; } CONSTEXPR static size_t size() { return sizeof(integral_t)+1; } static size_t encode(integral_t value, byte_type* out, size_t offset = 0) { return encode32(value, out, offset); } static integral_t decode(const byte_type* in) { return decode32(in); } }; // numeric_traits template<> struct numeric_traits { typedef uint32_t integral_t; static integral_t decode(const byte_type* in) { return decode32(in); } static size_t encode(integral_t value, byte_type* out, size_t offset = 0) { return encode32(value, out, offset); } static integral_t hton(integral_t value) { return hton32(value); } static integral_t ntoh(integral_t value) { return ntoh32(value); } inline static integral_t integral(integral_t value) { return value; } static const bytes_ref& (min)() { return minu32(); } static const bytes_ref& (max)() { return maxu32(); } static bytes_ref raw_ref(integral_t const& value) { return bytes_ref( reinterpret_cast(&value), sizeof(value) ); } CONSTEXPR static size_t size() { return sizeof(integral_t) + 1; } }; template<> struct numeric_traits { typedef int64_t integral_t; static const bytes_ref& (min)() { return mini64(); } static const bytes_ref& (max)() { return maxi64(); } inline static integral_t integral(integral_t value) { return value; } CONSTEXPR static size_t size() { return sizeof(integral_t)+1; } static size_t encode(integral_t value, byte_type* out, size_t offset = 0) { return encode64(value, out, offset); } static integral_t decode(const byte_type* in) { return decode64(in); } }; // numeric_traits template<> struct numeric_traits { typedef uint64_t integral_t; static integral_t decode(const byte_type* in) { return decode64(in); } static size_t encode(integral_t value, byte_type* out, size_t offset = 0) { return encode64(value, out, offset); } static integral_t hton(integral_t value) { return hton64(value); } static integral_t ntoh(integral_t value) { return ntoh64(value); } inline static integral_t integral(integral_t value) { return value; } static const bytes_ref& (max)() { return maxu64(); } static const bytes_ref& (min)() { return minu64(); } static bytes_ref raw_ref(integral_t const& value) { return bytes_ref( reinterpret_cast(&value), sizeof(value) ); } CONSTEXPR static size_t size() { return sizeof(integral_t) + 1; } }; // MacOS 'unsigned long' is a different type from any of the above // MSVC 'unsigned long' is a different type from any of the above #if defined (__APPLE__) || defined(_MSC_VER) template<> struct numeric_traits : public numeric_traits::type> { }; #endif template<> struct numeric_traits { typedef int32_t integral_t; static const bytes_ref& ninf() { return nfinf32(); } static const bytes_ref& (min)() { return minf32(); } static const bytes_ref& (max)() { return maxf32(); } static const bytes_ref& inf() { return finf32(); } static float_t floating(integral_t value) { return i32tof(value); } static integral_t integral(float_t value) { return ftoi32(value); } CONSTEXPR static size_t size() { return sizeof(integral_t)+1; } static size_t encode(integral_t value, byte_type* out, size_t offset = 0) { return encodef32(value, out, offset); } static float_t decode(const byte_type* in) { return floating(decodef32(in)); } }; // numeric_traits template<> struct numeric_traits { typedef int64_t integral_t; static const bytes_ref& ninf() { return ndinf64(); } static const bytes_ref& (min)() { return mind64(); } static const bytes_ref& (max)() { return maxd64(); } static const bytes_ref& inf() { return dinf64(); } static double_t floating(integral_t value) { return i64tod(value); } static integral_t integral(double_t value) { return dtoi64(value); } CONSTEXPR static size_t size() { return sizeof(integral_t)+1; } static size_t encode(integral_t value, byte_type* out, size_t offset = 0) { return encoded64(value, out, offset); } static double_t decode(const byte_type* in) { return floating(decoded64(in)); } }; // numeric_traits template<> struct numeric_traits { }; // numeric_traits NS_END // numeric_utils NS_END // ROOT #endif // IRESEARCH_NUMERIC_UTILS_H