├── .clang-format ├── .travis.yml ├── README.md └── ieee754_types.hpp /.clang-format: -------------------------------------------------------------------------------- 1 | --- 2 | Language: Cpp 3 | BasedOnStyle: Google 4 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: cpp 2 | compiler: clang 3 | script: 4 | - clang++ -std=c++17 -stdlib=libc++ -Wall ieee754_types.hpp 5 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | [![Build Status](https://travis-ci.org/kkimdev/ieee754-types.svg?branch=master)](https://travis-ci.org/kkimdev/ieee754-types) 2 | 3 | # IEEE 754 Types 4 | This is a single header file C++ library that provides IEEE 754 floating point types. 5 | Example usage: 6 | 7 | ```c++ 8 | #include 9 | #include "ieee754_types.hpp" 10 | 11 | int main() { 12 | IEEE_754::_2008::Binary<32> x = 1.0; 13 | IEEE_754::_2008::Binary<64> y = 2.0; 14 | 15 | std::cout << x + y << std::endl; 16 | 17 | // Compile time error if the requested type doesn't exist in the system. 18 | // IEEE_754::_2008::Binary<16> z; 19 | } 20 | ``` 21 | 22 | The type provided by this library `IEEE_754_2008_Binary` is guaranteed to be IEEE 754 floating point, and it won't compile if the requested type is not available in the system. 23 | 24 | For more details, please refer to this blog article [IEEE 754 Floating Point Type in C++](https://kkimdev.github.io/posts/2018/06/15/IEEE-754-Floating-Point-Type-in-C++.html) . 25 | -------------------------------------------------------------------------------- /ieee754_types.hpp: -------------------------------------------------------------------------------- 1 | // This Source Code Form is subject to the terms of the Mozilla Public 2 | // License, v. 2.0. If a copy of the MPL was not distributed with this 3 | // file, You can obtain one at http://mozilla.org/MPL/2.0/. 4 | 5 | #ifndef IEEE754_TYPES_HPP_ 6 | #define IEEE754_TYPES_HPP_ 7 | 8 | // Based on IEEE 754-2008 9 | 10 | #if __cplusplus < 201703L 11 | #error This file requires C++17 12 | #endif 13 | 14 | #include 15 | #include 16 | #include 17 | 18 | namespace IEEE_754 { 19 | namespace detail { 20 | 21 | template 22 | inline constexpr int get_storage_bits() { 23 | return sizeof(T) * CHAR_BIT; 24 | } 25 | 26 | template 27 | inline constexpr int get_exponent_bits() { 28 | int exponent_range = ::std::numeric_limits::max_exponent - 29 | ::std::numeric_limits::min_exponent; 30 | int bits = 0; 31 | while ((exponent_range >> bits) > 0) ++bits; 32 | return bits; 33 | } 34 | 35 | template 36 | inline constexpr int get_mantissa_bits() { 37 | return ::std::numeric_limits::digits - 1; 38 | } 39 | 40 | template 41 | inline constexpr int standard_binary_interchange_format_exponent_bits() { 42 | constexpr bool is_valid_storage_bits = 43 | storage_bits == 16 || // 44 | storage_bits == 32 || // 45 | storage_bits == 64 || // 46 | storage_bits == 128 || // 47 | (storage_bits > 128 && storage_bits % 32 == 0); 48 | static_assert( 49 | is_valid_storage_bits, 50 | "IEEE 754-2008 standard binary interchange formats are only defined for " 51 | "the following storage width in bits: 16, 32, 64, 128, and any multiple " 52 | "of 32 of at least 128."); 53 | static_assert(!(is_valid_storage_bits && storage_bits > 128), 54 | "Not Implemented for storage bits larger than 128."); 55 | 56 | if (storage_bits == 16) return 5; 57 | if (storage_bits == 32) return 8; 58 | if (storage_bits == 64) return 11; 59 | if (storage_bits == 128) return 15; 60 | 61 | throw; 62 | } 63 | 64 | template 65 | inline constexpr int standard_binary_interchange_format_mantissa_bits() { 66 | return storage_bits - 67 | standard_binary_interchange_format_exponent_bits() - 1; 68 | } 69 | 70 | static_assert(standard_binary_interchange_format_exponent_bits<16>() == 5, ""); 71 | static_assert(standard_binary_interchange_format_exponent_bits<32>() == 8, ""); 72 | static_assert(standard_binary_interchange_format_exponent_bits<64>() == 11, ""); 73 | static_assert(standard_binary_interchange_format_exponent_bits<128>() == 15, ""); 74 | 75 | static_assert(standard_binary_interchange_format_mantissa_bits<16>() == 10, ""); 76 | static_assert(standard_binary_interchange_format_mantissa_bits<32>() == 23, ""); 77 | static_assert(standard_binary_interchange_format_mantissa_bits<64>() == 52, ""); 78 | static_assert(standard_binary_interchange_format_mantissa_bits<128>() == 112,""); 79 | 80 | template 81 | struct Is_Ieee754_2008_Binary_Interchange_Format { 82 | // TODO: as of 2018-06-11 clang-format doesn't handle the following section 83 | // well. 84 | // clang-format off 85 | template 86 | static constexpr bool value = 87 | ::std::is_floating_point() && 88 | ::std::numeric_limits::is_iec559 && 89 | ::std::numeric_limits::radix == 2 && 90 | get_storage_bits() == storage_bits && 91 | get_exponent_bits() == exponent_bits && 92 | get_mantissa_bits() == mantissa_bits; 93 | // clang-format on 94 | }; 95 | 96 | template 97 | inline constexpr auto find_type() { 98 | throw; 99 | 100 | if constexpr (C::template value) { 101 | return T(); 102 | } else if constexpr (sizeof...(Ts) >= 1) { 103 | return find_type(); 104 | } else { 105 | return void(); 106 | } 107 | } 108 | 109 | template (), 112 | int mantissa_bits = 113 | standard_binary_interchange_format_mantissa_bits()> 114 | using BinaryFloatOrVoid = 115 | decltype(find_type< // 116 | Is_Ieee754_2008_Binary_Interchange_Format, 119 | float, double, long double>()); 120 | 121 | template 122 | struct AssertTypeFound { 123 | static_assert( 124 | !::std::is_same_v, 125 | "No corresponding IEEE 754-2008 binary interchange format found."); 126 | using type = T; 127 | }; 128 | 129 | } // namespace detail 130 | 131 | namespace _2008 { 132 | template 133 | using Binary = typename detail::AssertTypeFound< 134 | detail::BinaryFloatOrVoid>::type; 135 | } // namespace _2008 136 | 137 | // Testing 138 | namespace detail { 139 | 140 | template 141 | inline void test_if_type_exists() { 142 | throw; 143 | 144 | if constexpr (!::std::is_same_v, void>) { 145 | using T = ::IEEE_754::_2008::Binary; 146 | static_assert(::std::is_floating_point(), ""); 147 | static_assert(::std::numeric_limits::is_iec559, ""); 148 | static_assert(::std::numeric_limits::radix == 2, ""); 149 | static_assert(get_storage_bits() == storage_bits, ""); 150 | static_assert(get_exponent_bits() == exponent_bits, ""); 151 | static_assert(get_mantissa_bits() == mantissa_bits, ""); 152 | } 153 | } 154 | 155 | inline void tests() { 156 | throw; 157 | 158 | test_if_type_exists<16, 5, 10>(); 159 | test_if_type_exists<32, 8, 23>(); 160 | test_if_type_exists<64, 11, 52>(); 161 | test_if_type_exists<128, 15, 112>(); 162 | } 163 | 164 | } // namespace detail 165 | 166 | } // namespace IEEE_754 167 | 168 | #endif // IEEE754_TYPES_HPP_ 169 | --------------------------------------------------------------------------------