| 1 | // -*- C++ -*- |
| 2 | //===----------------------------------------------------------------------===// |
| 3 | // |
| 4 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
| 5 | // See https://llvm.org/LICENSE.txt for license information. |
| 6 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
| 7 | // |
| 8 | //===----------------------------------------------------------------------===// |
| 9 | |
| 10 | // Copyright (c) Microsoft Corporation. |
| 11 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
| 12 | |
| 13 | // Copyright 2018 Ulf Adams |
| 14 | // Copyright (c) Microsoft Corporation. All rights reserved. |
| 15 | |
| 16 | // Boost Software License - Version 1.0 - August 17th, 2003 |
| 17 | |
| 18 | // Permission is hereby granted, free of charge, to any person or organization |
| 19 | // obtaining a copy of the software and accompanying documentation covered by |
| 20 | // this license (the "Software") to use, reproduce, display, distribute, |
| 21 | // execute, and transmit the Software, and to prepare derivative works of the |
| 22 | // Software, and to permit third-parties to whom the Software is furnished to |
| 23 | // do so, all subject to the following: |
| 24 | |
| 25 | // The copyright notices in the Software and this entire statement, including |
| 26 | // the above license grant, this restriction and the following disclaimer, |
| 27 | // must be included in all copies of the Software, in whole or in part, and |
| 28 | // all derivative works of the Software, unless such copies or derivative |
| 29 | // works are solely in the form of machine-executable object code generated by |
| 30 | // a source language processor. |
| 31 | |
| 32 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
| 33 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
| 34 | // FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT |
| 35 | // SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE |
| 36 | // FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, |
| 37 | // ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER |
| 38 | // DEALINGS IN THE SOFTWARE. |
| 39 | |
| 40 | #ifndef _LIBCPP_SRC_INCLUDE_RYU_RYU_H |
| 41 | #define _LIBCPP_SRC_INCLUDE_RYU_RYU_H |
| 42 | |
| 43 | // Avoid formatting to keep the changes with the original code minimal. |
| 44 | // clang-format off |
| 45 | |
| 46 | #include <__charconv/chars_format.h> |
| 47 | #include <__charconv/to_chars_result.h> |
| 48 | #include <__config> |
| 49 | #include <__system_error/errc.h> |
| 50 | #include <cstdint> |
| 51 | #include <cstring> |
| 52 | #include <type_traits> |
| 53 | |
| 54 | #include "include/ryu/f2s.h" |
| 55 | #include "include/ryu/d2s.h" |
| 56 | #include "include/ryu/d2fixed.h" |
| 57 | |
| 58 | #if defined(_MSC_VER) |
| 59 | #include <intrin.h> // for _umul128(), __shiftright128(), _BitScanForward{,64} |
| 60 | #endif // defined(_MSC_VER) |
| 61 | |
| 62 | #if defined(_WIN64) || defined(_M_AMD64) || defined(__x86_64__) || defined(__aarch64__) |
| 63 | #define _LIBCPP_64_BIT |
| 64 | #endif |
| 65 | |
| 66 | _LIBCPP_BEGIN_NAMESPACE_STD |
| 67 | |
| 68 | // https://github.com/ulfjack/ryu/tree/59661c3/ryu |
| 69 | |
| 70 | #if !defined(_MSC_VER) |
| 71 | _LIBCPP_HIDE_FROM_ABI inline unsigned char _BitScanForward64(unsigned long* __index, unsigned long long __mask) { |
| 72 | if (__mask == 0) { |
| 73 | return false; |
| 74 | } |
| 75 | *__index = __builtin_ctzll(__mask); |
| 76 | return true; |
| 77 | } |
| 78 | |
| 79 | _LIBCPP_HIDE_FROM_ABI inline unsigned char _BitScanForward(unsigned long* __index, unsigned int __mask) { |
| 80 | if (__mask == 0) { |
| 81 | return false; |
| 82 | } |
| 83 | *__index = __builtin_ctz(__mask); |
| 84 | return true; |
| 85 | } |
| 86 | #endif // !_MSC_VER |
| 87 | |
| 88 | template <class _Floating> |
| 89 | [[nodiscard]] to_chars_result _Floating_to_chars_ryu( |
| 90 | char* const _First, char* const _Last, const _Floating _Value, const chars_format _Fmt) noexcept { |
| 91 | if constexpr (_IsSame<_Floating, float>::value) { |
| 92 | return __f2s_buffered_n(_First, _Last, _Value, _Fmt); |
| 93 | } else { |
| 94 | return __d2s_buffered_n(_First, _Last, _Value, _Fmt); |
| 95 | } |
| 96 | } |
| 97 | |
| 98 | template <class _Floating> |
| 99 | [[nodiscard]] _LIBCPP_HIDE_FROM_ABI to_chars_result _Floating_to_chars_scientific_precision( |
| 100 | char* const _First, char* const _Last, const _Floating _Value, int _Precision) noexcept { |
| 101 | |
| 102 | // C11 7.21.6.1 "The fprintf function"/5: |
| 103 | // "A negative precision argument is taken as if the precision were omitted." |
| 104 | // /8: "e,E [...] if the precision is missing, it is taken as 6" |
| 105 | |
| 106 | if (_Precision < 0) { |
| 107 | _Precision = 6; |
| 108 | } else if (_Precision < 1'000'000'000) { // Match ' to fix compilation with GCC in C++11 mode |
| 109 | // _Precision is ok. |
| 110 | } else { |
| 111 | // Avoid integer overflow. |
| 112 | // (This defensive check is slightly nonconformant; it can be carefully improved in the future.) |
| 113 | return {.ptr: _Last, .ec: errc::value_too_large}; |
| 114 | } |
| 115 | |
| 116 | return __d2exp_buffered_n(_First, _Last, _Value, static_cast<uint32_t>(_Precision)); |
| 117 | } |
| 118 | |
| 119 | template <class _Floating> |
| 120 | [[nodiscard]] _LIBCPP_HIDE_FROM_ABI to_chars_result _Floating_to_chars_fixed_precision( |
| 121 | char* const _First, char* const _Last, const _Floating _Value, int _Precision) noexcept { |
| 122 | |
| 123 | // C11 7.21.6.1 "The fprintf function"/5: |
| 124 | // "A negative precision argument is taken as if the precision were omitted." |
| 125 | // /8: "f,F [...] If the precision is missing, it is taken as 6" |
| 126 | |
| 127 | if (_Precision < 0) { |
| 128 | _Precision = 6; |
| 129 | } else if (_Precision < 1'000'000'000) { // Match ' to fix compilation with GCC in C++11 mode |
| 130 | // _Precision is ok. |
| 131 | } else { |
| 132 | // Avoid integer overflow. |
| 133 | // (This defensive check is slightly nonconformant; it can be carefully improved in the future.) |
| 134 | return {.ptr: _Last, .ec: errc::value_too_large}; |
| 135 | } |
| 136 | |
| 137 | return __d2fixed_buffered_n(_First, _Last, _Value, static_cast<uint32_t>(_Precision)); |
| 138 | } |
| 139 | |
| 140 | #undef _LIBCPP_64_BIT |
| 141 | #undef _LIBCPP_INTRINSIC128 |
| 142 | |
| 143 | _LIBCPP_END_NAMESPACE_STD |
| 144 | |
| 145 | // clang-format on |
| 146 | |
| 147 | #endif // _LIBCPP_SRC_INCLUDE_RYU_RYU_H |
| 148 | |