CARVIEW |
Select Language
HTTP/2 302
date: Mon, 21 Jul 2025 19:50:44 GMT
content-type: text/html; charset=utf-8
content-length: 0
vary: X-PJAX, X-PJAX-Container, Turbo-Visit, Turbo-Frame, X-Requested-With,Accept-Encoding, Accept, X-Requested-With
location: https://objects.githubusercontent.com/github-production-release-asset-2e65be/305438763/0ddcdd65-9ee9-4c82-b3bd-a82fcdcd934e?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=releaseassetproduction%2F20250721%2Fus-east-1%2Fs3%2Faws4_request&X-Amz-Date=20250721T195044Z&X-Amz-Expires=1800&X-Amz-Signature=c78169a111f3fd364402e58f19ca66db2094626f9615798a6537defa6455be48&X-Amz-SignedHeaders=host&response-content-disposition=attachment%3B%20filename%3Dfast_float.h&response-content-type=application%2Foctet-stream
cache-control: no-cache
strict-transport-security: max-age=31536000; includeSubdomains; preload
x-frame-options: deny
x-content-type-options: nosniff
x-xss-protection: 0
referrer-policy: no-referrer-when-downgrade
content-security-policy: default-src 'none'; base-uri 'self'; child-src github.githubassets.com github.com/assets-cdn/worker/ github.com/assets/ gist.github.com/assets-cdn/worker/; connect-src 'self' uploads.github.com www.githubstatus.com collector.github.com raw.githubusercontent.com api.github.com github-cloud.s3.amazonaws.com github-production-repository-file-5c1aeb.s3.amazonaws.com github-production-upload-manifest-file-7fdce7.s3.amazonaws.com github-production-user-asset-6210df.s3.amazonaws.com *.rel.tunnels.api.visualstudio.com wss://*.rel.tunnels.api.visualstudio.com objects-origin.githubusercontent.com copilot-proxy.githubusercontent.com proxy.individual.githubcopilot.com proxy.business.githubcopilot.com proxy.enterprise.githubcopilot.com *.actions.githubusercontent.com wss://*.actions.githubusercontent.com productionresultssa0.blob.core.windows.net/ productionresultssa1.blob.core.windows.net/ productionresultssa2.blob.core.windows.net/ productionresultssa3.blob.core.windows.net/ productionresultssa4.blob.core.windows.net/ productionresultssa5.blob.core.windows.net/ productionresultssa6.blob.core.windows.net/ productionresultssa7.blob.core.windows.net/ productionresultssa8.blob.core.windows.net/ productionresultssa9.blob.core.windows.net/ productionresultssa10.blob.core.windows.net/ productionresultssa11.blob.core.windows.net/ productionresultssa12.blob.core.windows.net/ productionresultssa13.blob.core.windows.net/ productionresultssa14.blob.core.windows.net/ productionresultssa15.blob.core.windows.net/ productionresultssa16.blob.core.windows.net/ productionresultssa17.blob.core.windows.net/ productionresultssa18.blob.core.windows.net/ productionresultssa19.blob.core.windows.net/ github-production-repository-image-32fea6.s3.amazonaws.com github-production-release-asset-2e65be.s3.amazonaws.com insights.github.com wss://alive.github.com api.githubcopilot.com api.individual.githubcopilot.com api.business.githubcopilot.com api.enterprise.githubcopilot.com; font-src github.githubassets.com; form-action 'self' github.com gist.github.com copilot-workspace.githubnext.com objects-origin.githubusercontent.com; frame-ancestors 'none'; frame-src viewscreen.githubusercontent.com notebooks.githubusercontent.com; img-src 'self' data: blob: github.githubassets.com media.githubusercontent.com camo.githubusercontent.com identicons.github.com avatars.githubusercontent.com private-avatars.githubusercontent.com github-cloud.s3.amazonaws.com objects.githubusercontent.com release-assets.githubusercontent.com secured-user-images.githubusercontent.com/ user-images.githubusercontent.com/ private-user-images.githubusercontent.com opengraph.githubassets.com copilotprodattachments.blob.core.windows.net/github-production-copilot-attachments/ github-production-user-asset-6210df.s3.amazonaws.com customer-stories-feed.github.com spotlights-feed.github.com objects-origin.githubusercontent.com *.githubusercontent.com; manifest-src 'self'; media-src github.com user-images.githubusercontent.com/ secured-user-images.githubusercontent.com/ private-user-images.githubusercontent.com github-production-user-asset-6210df.s3.amazonaws.com gist.github.com; script-src github.githubassets.com; style-src 'unsafe-inline' github.githubassets.com; upgrade-insecure-requests; worker-src github.githubassets.com github.com/assets-cdn/worker/ github.com/assets/ gist.github.com/assets-cdn/worker/
server: github.com
x-github-request-id: 95F8:2031FD:82A8:B3BC:687E9A14
HTTP/2 200
content-type: application/octet-stream
last-modified: Tue, 11 Mar 2025 13:52:40 GMT
etag: "0x8DD60A3FD6CDB54"
server: Windows-Azure-Blob/1.0 Microsoft-HTTPAPI/2.0
x-ms-request-id: 3d210675-301e-0053-3669-e0c261000000
x-ms-version: 2025-05-05
x-ms-creation-time: Tue, 11 Mar 2025 13:52:40 GMT
x-ms-blob-content-md5: K+sHo58/w5DUyl+JW9/EFA==
x-ms-lease-status: unlocked
x-ms-lease-state: available
x-ms-blob-type: BlockBlob
content-disposition: attachment; filename=fast_float.h
x-ms-server-encrypted: true
via: 1.1 varnish, 1.1 varnish
fastly-restarts: 1
accept-ranges: bytes
age: 0
date: Mon, 21 Jul 2025 19:50:46 GMT
x-served-by: cache-iad-kcgs7200027-IAD, cache-bom4730-BOM
x-cache: HIT, MISS
x-cache-hits: 1, 0
x-timer: S1753127445.961520,VS0,VE215
content-length: 154514
// fast_float by Daniel Lemire
// fast_float by João Paulo Magalhaes
//
//
// with contributions from Eugene Golushkov
// with contributions from Maksim Kita
// with contributions from Marcin Wojdyr
// with contributions from Neal Richardson
// with contributions from Tim Paine
// with contributions from Fabio Pellacini
// with contributions from Lénárd Szolnoki
// with contributions from Jan Pharago
// with contributions from Maya Warrier
// with contributions from Taha Khokhar
// with contributions from Anders Dalvander
//
//
// Licensed under the Apache License, Version 2.0, or the
// MIT License or the Boost License. This file may not be copied,
// modified, or distributed except according to those terms.
//
// MIT License Notice
//
// MIT License
//
// Copyright (c) 2021 The fast_float authors
//
// Permission is hereby granted, free of charge, to any
// person obtaining a copy of this software and associated
// documentation files (the "Software"), to deal in the
// Software without restriction, including without
// limitation the rights to use, copy, modify, merge,
// publish, distribute, sublicense, and/or sell copies of
// the Software, and to permit persons to whom the Software
// is furnished to do so, subject to the following
// conditions:
//
// The above copyright notice and this permission notice
// shall be included in all copies or substantial portions
// of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
// ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
// PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
// SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
// IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
//
// Apache License (Version 2.0) Notice
//
// Copyright 2021 The fast_float authors
// 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
//
// https://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
//
// BOOST License Notice
//
// Boost Software License - Version 1.0 - August 17th, 2003
//
// Permission is hereby granted, free of charge, to any person or organization
// obtaining a copy of the software and accompanying documentation covered by
// this license (the "Software") to use, reproduce, display, distribute,
// execute, and transmit the Software, and to prepare derivative works of the
// Software, and to permit third-parties to whom the Software is furnished to
// do so, all subject to the following:
//
// The copyright notices in the Software and this entire statement, including
// the above license grant, this restriction and the following disclaimer,
// must be included in all copies of the Software, in whole or in part, and
// all derivative works of the Software, unless such copies or derivative
// works are solely in the form of machine-executable object code generated by
// a source language processor.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
//
#ifndef FASTFLOAT_CONSTEXPR_FEATURE_DETECT_H
#define FASTFLOAT_CONSTEXPR_FEATURE_DETECT_H
#ifdef __has_include
#if __has_include()
#include
#endif
#endif
// Testing for https://wg21.link/N3652, adopted in C++14
#if defined(__cpp_constexpr) && __cpp_constexpr >= 201304
#define FASTFLOAT_CONSTEXPR14 constexpr
#else
#define FASTFLOAT_CONSTEXPR14
#endif
#if defined(__cpp_lib_bit_cast) && __cpp_lib_bit_cast >= 201806L
#define FASTFLOAT_HAS_BIT_CAST 1
#else
#define FASTFLOAT_HAS_BIT_CAST 0
#endif
#if defined(__cpp_lib_is_constant_evaluated) && \
__cpp_lib_is_constant_evaluated >= 201811L
#define FASTFLOAT_HAS_IS_CONSTANT_EVALUATED 1
#else
#define FASTFLOAT_HAS_IS_CONSTANT_EVALUATED 0
#endif
#if defined(__cpp_if_constexpr) && __cpp_if_constexpr >= 201606L
#define FASTFLOAT_IF_CONSTEXPR17(x) if constexpr (x)
#else
#define FASTFLOAT_IF_CONSTEXPR17(x) if (x)
#endif
// Testing for relevant C++20 constexpr library features
#if FASTFLOAT_HAS_IS_CONSTANT_EVALUATED && FASTFLOAT_HAS_BIT_CAST && \
defined(__cpp_lib_constexpr_algorithms) && \
__cpp_lib_constexpr_algorithms >= 201806L /*For std::copy and std::fill*/
#define FASTFLOAT_CONSTEXPR20 constexpr
#define FASTFLOAT_IS_CONSTEXPR 1
#else
#define FASTFLOAT_CONSTEXPR20
#define FASTFLOAT_IS_CONSTEXPR 0
#endif
#if __cplusplus >= 201703L || (defined(_MSVC_LANG) && _MSVC_LANG >= 201703L)
#define FASTFLOAT_DETAIL_MUST_DEFINE_CONSTEXPR_VARIABLE 0
#else
#define FASTFLOAT_DETAIL_MUST_DEFINE_CONSTEXPR_VARIABLE 1
#endif
#endif // FASTFLOAT_CONSTEXPR_FEATURE_DETECT_H
#ifndef FASTFLOAT_FLOAT_COMMON_H
#define FASTFLOAT_FLOAT_COMMON_H
#include
#include
#include
#include
#include
#include
#include
#ifdef __has_include
#if __has_include() && (__cplusplus > 202002L || (defined(_MSVC_LANG) && (_MSVC_LANG > 202002L)))
#include
#endif
#endif
#define FASTFLOAT_VERSION_MAJOR 8
#define FASTFLOAT_VERSION_MINOR 0
#define FASTFLOAT_VERSION_PATCH 2
#define FASTFLOAT_STRINGIZE_IMPL(x) #x
#define FASTFLOAT_STRINGIZE(x) FASTFLOAT_STRINGIZE_IMPL(x)
#define FASTFLOAT_VERSION_STR \
FASTFLOAT_STRINGIZE(FASTFLOAT_VERSION_MAJOR) \
"." FASTFLOAT_STRINGIZE(FASTFLOAT_VERSION_MINOR) "." FASTFLOAT_STRINGIZE( \
FASTFLOAT_VERSION_PATCH)
#define FASTFLOAT_VERSION \
(FASTFLOAT_VERSION_MAJOR * 10000 + FASTFLOAT_VERSION_MINOR * 100 + \
FASTFLOAT_VERSION_PATCH)
namespace fast_float {
enum class chars_format : uint64_t;
namespace detail {
constexpr chars_format basic_json_fmt = chars_format(1 << 5);
constexpr chars_format basic_fortran_fmt = chars_format(1 << 6);
} // namespace detail
enum class chars_format : uint64_t {
scientific = 1 << 0,
fixed = 1 << 2,
hex = 1 << 3,
no_infnan = 1 << 4,
// RFC 8259: https://datatracker.ietf.org/doc/html/rfc8259#section-6
json = uint64_t(detail::basic_json_fmt) | fixed | scientific | no_infnan,
// Extension of RFC 8259 where, e.g., "inf" and "nan" are allowed.
json_or_infnan = uint64_t(detail::basic_json_fmt) | fixed | scientific,
fortran = uint64_t(detail::basic_fortran_fmt) | fixed | scientific,
general = fixed | scientific,
allow_leading_plus = 1 << 7,
skip_white_space = 1 << 8,
};
template struct from_chars_result_t {
UC const *ptr;
std::errc ec;
};
using from_chars_result = from_chars_result_t;
template struct parse_options_t {
constexpr explicit parse_options_t(chars_format fmt = chars_format::general,
UC dot = UC('.'), int b = 10)
: format(fmt), decimal_point(dot), base(b) {}
/** Which number formats are accepted */
chars_format format;
/** The character used as decimal point */
UC decimal_point;
/** The base used for integers */
int base;
};
using parse_options = parse_options_t;
} // namespace fast_float
#if FASTFLOAT_HAS_BIT_CAST
#include
#endif
#if (defined(__x86_64) || defined(__x86_64__) || defined(_M_X64) || \
defined(__amd64) || defined(__aarch64__) || defined(_M_ARM64) || \
defined(__MINGW64__) || defined(__s390x__) || \
(defined(__ppc64__) || defined(__PPC64__) || defined(__ppc64le__) || \
defined(__PPC64LE__)) || \
defined(__loongarch64))
#define FASTFLOAT_64BIT 1
#elif (defined(__i386) || defined(__i386__) || defined(_M_IX86) || \
defined(__arm__) || defined(_M_ARM) || defined(__ppc__) || \
defined(__MINGW32__) || defined(__EMSCRIPTEN__))
#define FASTFLOAT_32BIT 1
#else
// Need to check incrementally, since SIZE_MAX is a size_t, avoid overflow.
// We can never tell the register width, but the SIZE_MAX is a good
// approximation. UINTPTR_MAX and INTPTR_MAX are optional, so avoid them for max
// portability.
#if SIZE_MAX == 0xffff
#error Unknown platform (16-bit, unsupported)
#elif SIZE_MAX == 0xffffffff
#define FASTFLOAT_32BIT 1
#elif SIZE_MAX == 0xffffffffffffffff
#define FASTFLOAT_64BIT 1
#else
#error Unknown platform (not 32-bit, not 64-bit?)
#endif
#endif
#if ((defined(_WIN32) || defined(_WIN64)) && !defined(__clang__)) || \
(defined(_M_ARM64) && !defined(__MINGW32__))
#include
#endif
#if defined(_MSC_VER) && !defined(__clang__)
#define FASTFLOAT_VISUAL_STUDIO 1
#endif
#if defined __BYTE_ORDER__ && defined __ORDER_BIG_ENDIAN__
#define FASTFLOAT_IS_BIG_ENDIAN (__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__)
#elif defined _WIN32
#define FASTFLOAT_IS_BIG_ENDIAN 0
#else
#if defined(__APPLE__) || defined(__FreeBSD__)
#include
#elif defined(sun) || defined(__sun)
#include
#elif defined(__MVS__)
#include
#else
#ifdef __has_include
#if __has_include()
#include
#endif //__has_include()
#endif //__has_include
#endif
#
#ifndef __BYTE_ORDER__
// safe choice
#define FASTFLOAT_IS_BIG_ENDIAN 0
#endif
#
#ifndef __ORDER_LITTLE_ENDIAN__
// safe choice
#define FASTFLOAT_IS_BIG_ENDIAN 0
#endif
#
#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
#define FASTFLOAT_IS_BIG_ENDIAN 0
#else
#define FASTFLOAT_IS_BIG_ENDIAN 1
#endif
#endif
#if defined(__SSE2__) || (defined(FASTFLOAT_VISUAL_STUDIO) && \
(defined(_M_AMD64) || defined(_M_X64) || \
(defined(_M_IX86_FP) && _M_IX86_FP == 2)))
#define FASTFLOAT_SSE2 1
#endif
#if defined(__aarch64__) || defined(_M_ARM64)
#define FASTFLOAT_NEON 1
#endif
#if defined(FASTFLOAT_SSE2) || defined(FASTFLOAT_NEON)
#define FASTFLOAT_HAS_SIMD 1
#endif
#if defined(__GNUC__)
// disable -Wcast-align=strict (GCC only)
#define FASTFLOAT_SIMD_DISABLE_WARNINGS \
_Pragma("GCC diagnostic push") \
_Pragma("GCC diagnostic ignored \"-Wcast-align\"")
#else
#define FASTFLOAT_SIMD_DISABLE_WARNINGS
#endif
#if defined(__GNUC__)
#define FASTFLOAT_SIMD_RESTORE_WARNINGS _Pragma("GCC diagnostic pop")
#else
#define FASTFLOAT_SIMD_RESTORE_WARNINGS
#endif
#ifdef FASTFLOAT_VISUAL_STUDIO
#define fastfloat_really_inline __forceinline
#else
#define fastfloat_really_inline inline __attribute__((always_inline))
#endif
#ifndef FASTFLOAT_ASSERT
#define FASTFLOAT_ASSERT(x) \
{ ((void)(x)); }
#endif
#ifndef FASTFLOAT_DEBUG_ASSERT
#define FASTFLOAT_DEBUG_ASSERT(x) \
{ ((void)(x)); }
#endif
// rust style `try!()` macro, or `?` operator
#define FASTFLOAT_TRY(x) \
{ \
if (!(x)) \
return false; \
}
#define FASTFLOAT_ENABLE_IF(...) \
typename std::enable_if<(__VA_ARGS__), int>::type
namespace fast_float {
fastfloat_really_inline constexpr bool cpp20_and_in_constexpr() {
#if FASTFLOAT_HAS_IS_CONSTANT_EVALUATED
return std::is_constant_evaluated();
#else
return false;
#endif
}
template
struct is_supported_float_type
: std::integral_constant<
bool, std::is_same::value || std::is_same::value
#ifdef __STDCPP_FLOAT64_T__
|| std::is_same::value
#endif
#ifdef __STDCPP_FLOAT32_T__
|| std::is_same::value
#endif
#ifdef __STDCPP_FLOAT16_T__
|| std::is_same::value
#endif
#ifdef __STDCPP_BFLOAT16_T__
|| std::is_same::value
#endif
> {
};
template
using equiv_uint_t = typename std::conditional<
sizeof(T) == 1, uint8_t,
typename std::conditional<
sizeof(T) == 2, uint16_t,
typename std::conditional::type>::type>::type;
template struct is_supported_integer_type : std::is_integral {};
template
struct is_supported_char_type
: std::integral_constant::value ||
std::is_same::value ||
std::is_same::value ||
std::is_same::value
#ifdef __cpp_char8_t
|| std::is_same::value
#endif
> {
};
// Compares two ASCII strings in a case insensitive manner.
template
inline FASTFLOAT_CONSTEXPR14 bool
fastfloat_strncasecmp(UC const *actual_mixedcase, UC const *expected_lowercase,
size_t length) {
for (size_t i = 0; i < length; ++i) {
UC const actual = actual_mixedcase[i];
if ((actual < 256 ? actual | 32 : actual) != expected_lowercase[i]) {
return false;
}
}
return true;
}
#ifndef FLT_EVAL_METHOD
#error "FLT_EVAL_METHOD should be defined, please include cfloat."
#endif
// a pointer and a length to a contiguous block of memory
template struct span {
T const *ptr;
size_t length;
constexpr span(T const *_ptr, size_t _length) : ptr(_ptr), length(_length) {}
constexpr span() : ptr(nullptr), length(0) {}
constexpr size_t len() const noexcept { return length; }
FASTFLOAT_CONSTEXPR14 const T &operator[](size_t index) const noexcept {
FASTFLOAT_DEBUG_ASSERT(index < length);
return ptr[index];
}
};
struct value128 {
uint64_t low;
uint64_t high;
constexpr value128(uint64_t _low, uint64_t _high) : low(_low), high(_high) {}
constexpr value128() : low(0), high(0) {}
};
/* Helper C++14 constexpr generic implementation of leading_zeroes */
fastfloat_really_inline FASTFLOAT_CONSTEXPR14 int
leading_zeroes_generic(uint64_t input_num, int last_bit = 0) {
if (input_num & uint64_t(0xffffffff00000000)) {
input_num >>= 32;
last_bit |= 32;
}
if (input_num & uint64_t(0xffff0000)) {
input_num >>= 16;
last_bit |= 16;
}
if (input_num & uint64_t(0xff00)) {
input_num >>= 8;
last_bit |= 8;
}
if (input_num & uint64_t(0xf0)) {
input_num >>= 4;
last_bit |= 4;
}
if (input_num & uint64_t(0xc)) {
input_num >>= 2;
last_bit |= 2;
}
if (input_num & uint64_t(0x2)) { /* input_num >>= 1; */
last_bit |= 1;
}
return 63 - last_bit;
}
/* result might be undefined when input_num is zero */
fastfloat_really_inline FASTFLOAT_CONSTEXPR20 int
leading_zeroes(uint64_t input_num) {
assert(input_num > 0);
if (cpp20_and_in_constexpr()) {
return leading_zeroes_generic(input_num);
}
#ifdef FASTFLOAT_VISUAL_STUDIO
#if defined(_M_X64) || defined(_M_ARM64)
unsigned long leading_zero = 0;
// Search the mask data from most significant bit (MSB)
// to least significant bit (LSB) for a set bit (1).
_BitScanReverse64(&leading_zero, input_num);
return (int)(63 - leading_zero);
#else
return leading_zeroes_generic(input_num);
#endif
#else
return __builtin_clzll(input_num);
#endif
}
// slow emulation routine for 32-bit
fastfloat_really_inline constexpr uint64_t emulu(uint32_t x, uint32_t y) {
return x * (uint64_t)y;
}
fastfloat_really_inline FASTFLOAT_CONSTEXPR14 uint64_t
umul128_generic(uint64_t ab, uint64_t cd, uint64_t *hi) {
uint64_t ad = emulu((uint32_t)(ab >> 32), (uint32_t)cd);
uint64_t bd = emulu((uint32_t)ab, (uint32_t)cd);
uint64_t adbc = ad + emulu((uint32_t)ab, (uint32_t)(cd >> 32));
uint64_t adbc_carry = (uint64_t)(adbc < ad);
uint64_t lo = bd + (adbc << 32);
*hi = emulu((uint32_t)(ab >> 32), (uint32_t)(cd >> 32)) + (adbc >> 32) +
(adbc_carry << 32) + (uint64_t)(lo < bd);
return lo;
}
#ifdef FASTFLOAT_32BIT
// slow emulation routine for 32-bit
#if !defined(__MINGW64__)
fastfloat_really_inline FASTFLOAT_CONSTEXPR14 uint64_t _umul128(uint64_t ab,
uint64_t cd,
uint64_t *hi) {
return umul128_generic(ab, cd, hi);
}
#endif // !__MINGW64__
#endif // FASTFLOAT_32BIT
// compute 64-bit a*b
fastfloat_really_inline FASTFLOAT_CONSTEXPR20 value128
full_multiplication(uint64_t a, uint64_t b) {
if (cpp20_and_in_constexpr()) {
value128 answer;
answer.low = umul128_generic(a, b, &answer.high);
return answer;
}
value128 answer;
#if defined(_M_ARM64) && !defined(__MINGW32__)
// ARM64 has native support for 64-bit multiplications, no need to emulate
// But MinGW on ARM64 doesn't have native support for 64-bit multiplications
answer.high = __umulh(a, b);
answer.low = a * b;
#elif defined(FASTFLOAT_32BIT) || \
(defined(_WIN64) && !defined(__clang__) && !defined(_M_ARM64))
answer.low = _umul128(a, b, &answer.high); // _umul128 not available on ARM64
#elif defined(FASTFLOAT_64BIT) && defined(__SIZEOF_INT128__)
__uint128_t r = ((__uint128_t)a) * b;
answer.low = uint64_t(r);
answer.high = uint64_t(r >> 64);
#else
answer.low = umul128_generic(a, b, &answer.high);
#endif
return answer;
}
struct adjusted_mantissa {
uint64_t mantissa{0};
int32_t power2{0}; // a negative value indicates an invalid result
adjusted_mantissa() = default;
constexpr bool operator==(adjusted_mantissa const &o) const {
return mantissa == o.mantissa && power2 == o.power2;
}
constexpr bool operator!=(adjusted_mantissa const &o) const {
return mantissa != o.mantissa || power2 != o.power2;
}
};
// Bias so we can get the real exponent with an invalid adjusted_mantissa.
constexpr static int32_t invalid_am_bias = -0x8000;
// used for binary_format_lookup_tables::max_mantissa
constexpr uint64_t constant_55555 = 5 * 5 * 5 * 5 * 5;
template struct binary_format_lookup_tables;
template struct binary_format : binary_format_lookup_tables {
using equiv_uint = equiv_uint_t;
static constexpr int mantissa_explicit_bits();
static constexpr int minimum_exponent();
static constexpr int infinite_power();
static constexpr int sign_index();
static constexpr int
min_exponent_fast_path(); // used when fegetround() == FE_TONEAREST
static constexpr int max_exponent_fast_path();
static constexpr int max_exponent_round_to_even();
static constexpr int min_exponent_round_to_even();
static constexpr uint64_t max_mantissa_fast_path(int64_t power);
static constexpr uint64_t
max_mantissa_fast_path(); // used when fegetround() == FE_TONEAREST
static constexpr int largest_power_of_ten();
static constexpr int smallest_power_of_ten();
static constexpr T exact_power_of_ten(int64_t power);
static constexpr size_t max_digits();
static constexpr equiv_uint exponent_mask();
static constexpr equiv_uint mantissa_mask();
static constexpr equiv_uint hidden_bit_mask();
};
template struct binary_format_lookup_tables {
static constexpr double powers_of_ten[] = {
1e0, 1e1, 1e2, 1e3, 1e4, 1e5, 1e6, 1e7, 1e8, 1e9, 1e10, 1e11,
1e12, 1e13, 1e14, 1e15, 1e16, 1e17, 1e18, 1e19, 1e20, 1e21, 1e22};
// Largest integer value v so that (5**index * v) <= 1<<53.
// 0x20000000000000 == 1 << 53
static constexpr uint64_t max_mantissa[] = {
0x20000000000000,
0x20000000000000 / 5,
0x20000000000000 / (5 * 5),
0x20000000000000 / (5 * 5 * 5),
0x20000000000000 / (5 * 5 * 5 * 5),
0x20000000000000 / (constant_55555),
0x20000000000000 / (constant_55555 * 5),
0x20000000000000 / (constant_55555 * 5 * 5),
0x20000000000000 / (constant_55555 * 5 * 5 * 5),
0x20000000000000 / (constant_55555 * 5 * 5 * 5 * 5),
0x20000000000000 / (constant_55555 * constant_55555),
0x20000000000000 / (constant_55555 * constant_55555 * 5),
0x20000000000000 / (constant_55555 * constant_55555 * 5 * 5),
0x20000000000000 / (constant_55555 * constant_55555 * 5 * 5 * 5),
0x20000000000000 / (constant_55555 * constant_55555 * constant_55555),
0x20000000000000 / (constant_55555 * constant_55555 * constant_55555 * 5),
0x20000000000000 /
(constant_55555 * constant_55555 * constant_55555 * 5 * 5),
0x20000000000000 /
(constant_55555 * constant_55555 * constant_55555 * 5 * 5 * 5),
0x20000000000000 /
(constant_55555 * constant_55555 * constant_55555 * 5 * 5 * 5 * 5),
0x20000000000000 /
(constant_55555 * constant_55555 * constant_55555 * constant_55555),
0x20000000000000 / (constant_55555 * constant_55555 * constant_55555 *
constant_55555 * 5),
0x20000000000000 / (constant_55555 * constant_55555 * constant_55555 *
constant_55555 * 5 * 5),
0x20000000000000 / (constant_55555 * constant_55555 * constant_55555 *
constant_55555 * 5 * 5 * 5),
0x20000000000000 / (constant_55555 * constant_55555 * constant_55555 *
constant_55555 * 5 * 5 * 5 * 5)};
};
#if FASTFLOAT_DETAIL_MUST_DEFINE_CONSTEXPR_VARIABLE
template
constexpr double binary_format_lookup_tables::powers_of_ten[];
template
constexpr uint64_t binary_format_lookup_tables::max_mantissa[];
#endif
template struct binary_format_lookup_tables {
static constexpr float powers_of_ten[] = {1e0f, 1e1f, 1e2f, 1e3f, 1e4f, 1e5f,
1e6f, 1e7f, 1e8f, 1e9f, 1e10f};
// Largest integer value v so that (5**index * v) <= 1<<24.
// 0x1000000 == 1<<24
static constexpr uint64_t max_mantissa[] = {
0x1000000,
0x1000000 / 5,
0x1000000 / (5 * 5),
0x1000000 / (5 * 5 * 5),
0x1000000 / (5 * 5 * 5 * 5),
0x1000000 / (constant_55555),
0x1000000 / (constant_55555 * 5),
0x1000000 / (constant_55555 * 5 * 5),
0x1000000 / (constant_55555 * 5 * 5 * 5),
0x1000000 / (constant_55555 * 5 * 5 * 5 * 5),
0x1000000 / (constant_55555 * constant_55555),
0x1000000 / (constant_55555 * constant_55555 * 5)};
};
#if FASTFLOAT_DETAIL_MUST_DEFINE_CONSTEXPR_VARIABLE
template
constexpr float binary_format_lookup_tables::powers_of_ten[];
template
constexpr uint64_t binary_format_lookup_tables::max_mantissa[];
#endif
template <>
inline constexpr int binary_format::min_exponent_fast_path() {
#if (FLT_EVAL_METHOD != 1) && (FLT_EVAL_METHOD != 0)
return 0;
#else
return -22;
#endif
}
template <>
inline constexpr int binary_format::min_exponent_fast_path() {
#if (FLT_EVAL_METHOD != 1) && (FLT_EVAL_METHOD != 0)
return 0;
#else
return -10;
#endif
}
template <>
inline constexpr int binary_format::mantissa_explicit_bits() {
return 52;
}
template <>
inline constexpr int binary_format::mantissa_explicit_bits() {
return 23;
}
template <>
inline constexpr int binary_format::max_exponent_round_to_even() {
return 23;
}
template <>
inline constexpr int binary_format::max_exponent_round_to_even() {
return 10;
}
template <>
inline constexpr int binary_format::min_exponent_round_to_even() {
return -4;
}
template <>
inline constexpr int binary_format::min_exponent_round_to_even() {
return -17;
}
template <> inline constexpr int binary_format::minimum_exponent() {
return -1023;
}
template <> inline constexpr int binary_format::minimum_exponent() {
return -127;
}
template <> inline constexpr int binary_format::infinite_power() {
return 0x7FF;
}
template <> inline constexpr int binary_format::infinite_power() {
return 0xFF;
}
template <> inline constexpr int binary_format::sign_index() {
return 63;
}
template <> inline constexpr int binary_format::sign_index() {
return 31;
}
template <>
inline constexpr int binary_format::max_exponent_fast_path() {
return 22;
}
template <>
inline constexpr int binary_format::max_exponent_fast_path() {
return 10;
}
template <>
inline constexpr uint64_t binary_format::max_mantissa_fast_path() {
return uint64_t(2) << mantissa_explicit_bits();
}
template <>
inline constexpr uint64_t binary_format::max_mantissa_fast_path() {
return uint64_t(2) << mantissa_explicit_bits();
}
// credit: Jakub Jelínek
#ifdef __STDCPP_FLOAT16_T__
template struct binary_format_lookup_tables {
static constexpr std::float16_t powers_of_ten[] = {1e0f16, 1e1f16, 1e2f16,
1e3f16, 1e4f16};
// Largest integer value v so that (5**index * v) <= 1<<11.
// 0x800 == 1<<11
static constexpr uint64_t max_mantissa[] = {0x800,
0x800 / 5,
0x800 / (5 * 5),
0x800 / (5 * 5 * 5),
0x800 / (5 * 5 * 5 * 5),
0x800 / (constant_55555)};
};
#if FASTFLOAT_DETAIL_MUST_DEFINE_CONSTEXPR_VARIABLE
template
constexpr std::float16_t
binary_format_lookup_tables::powers_of_ten[];
template
constexpr uint64_t
binary_format_lookup_tables::max_mantissa[];
#endif
template <>
inline constexpr std::float16_t
binary_format::exact_power_of_ten(int64_t power) {
// Work around clang bug https://godbolt.org/z/zedh7rrhc
return (void)powers_of_ten[0], powers_of_ten[power];
}
template <>
inline constexpr binary_format::equiv_uint
binary_format::exponent_mask() {
return 0x7C00;
}
template <>
inline constexpr binary_format::equiv_uint
binary_format::mantissa_mask() {
return 0x03FF;
}
template <>
inline constexpr binary_format::equiv_uint
binary_format::hidden_bit_mask() {
return 0x0400;
}
template <>
inline constexpr int binary_format::max_exponent_fast_path() {
return 4;
}
template <>
inline constexpr int binary_format::mantissa_explicit_bits() {
return 10;
}
template <>
inline constexpr uint64_t
binary_format::max_mantissa_fast_path() {
return uint64_t(2) << mantissa_explicit_bits();
}
template <>
inline constexpr uint64_t
binary_format::max_mantissa_fast_path(int64_t power) {
// caller is responsible to ensure that
// power >= 0 && power <= 4
//
// Work around clang bug https://godbolt.org/z/zedh7rrhc
return (void)max_mantissa[0], max_mantissa[power];
}
template <>
inline constexpr int binary_format::min_exponent_fast_path() {
return 0;
}
template <>
inline constexpr int
binary_format::max_exponent_round_to_even() {
return 5;
}
template <>
inline constexpr int
binary_format::min_exponent_round_to_even() {
return -22;
}
template <>
inline constexpr int binary_format::minimum_exponent() {
return -15;
}
template <>
inline constexpr int binary_format::infinite_power() {
return 0x1F;
}
template <> inline constexpr int binary_format::sign_index() {
return 15;
}
template <>
inline constexpr int binary_format::largest_power_of_ten() {
return 4;
}
template <>
inline constexpr int binary_format::smallest_power_of_ten() {
return -27;
}
template <>
inline constexpr size_t binary_format::max_digits() {
return 22;
}
#endif // __STDCPP_FLOAT16_T__
// credit: Jakub Jelínek
#ifdef __STDCPP_BFLOAT16_T__
template struct binary_format_lookup_tables {
static constexpr std::bfloat16_t powers_of_ten[] = {1e0bf16, 1e1bf16, 1e2bf16,
1e3bf16};
// Largest integer value v so that (5**index * v) <= 1<<8.
// 0x100 == 1<<8
static constexpr uint64_t max_mantissa[] = {0x100, 0x100 / 5, 0x100 / (5 * 5),
0x100 / (5 * 5 * 5),
0x100 / (5 * 5 * 5 * 5)};
};
#if FASTFLOAT_DETAIL_MUST_DEFINE_CONSTEXPR_VARIABLE
template
constexpr std::bfloat16_t
binary_format_lookup_tables::powers_of_ten[];
template
constexpr uint64_t
binary_format_lookup_tables::max_mantissa[];
#endif
template <>
inline constexpr std::bfloat16_t
binary_format::exact_power_of_ten(int64_t power) {
// Work around clang bug https://godbolt.org/z/zedh7rrhc
return (void)powers_of_ten[0], powers_of_ten[power];
}
template <>
inline constexpr int binary_format::max_exponent_fast_path() {
return 3;
}
template <>
inline constexpr binary_format::equiv_uint
binary_format::exponent_mask() {
return 0x7F80;
}
template <>
inline constexpr binary_format::equiv_uint
binary_format::mantissa_mask() {
return 0x007F;
}
template <>
inline constexpr binary_format::equiv_uint
binary_format::hidden_bit_mask() {
return 0x0080;
}
template <>
inline constexpr int binary_format::mantissa_explicit_bits() {
return 7;
}
template <>
inline constexpr uint64_t
binary_format::max_mantissa_fast_path() {
return uint64_t(2) << mantissa_explicit_bits();
}
template <>
inline constexpr uint64_t
binary_format::max_mantissa_fast_path(int64_t power) {
// caller is responsible to ensure that
// power >= 0 && power <= 3
//
// Work around clang bug https://godbolt.org/z/zedh7rrhc
return (void)max_mantissa[0], max_mantissa[power];
}
template <>
inline constexpr int binary_format::min_exponent_fast_path() {
return 0;
}
template <>
inline constexpr int
binary_format::max_exponent_round_to_even() {
return 3;
}
template <>
inline constexpr int
binary_format::min_exponent_round_to_even() {
return -24;
}
template <>
inline constexpr int binary_format::minimum_exponent() {
return -127;
}
template <>
inline constexpr int binary_format::infinite_power() {
return 0xFF;
}
template <> inline constexpr int binary_format::sign_index() {
return 15;
}
template <>
inline constexpr int binary_format::largest_power_of_ten() {
return 38;
}
template <>
inline constexpr int binary_format::smallest_power_of_ten() {
return -60;
}
template <>
inline constexpr size_t binary_format::max_digits() {
return 98;
}
#endif // __STDCPP_BFLOAT16_T__
template <>
inline constexpr uint64_t
binary_format::max_mantissa_fast_path(int64_t power) {
// caller is responsible to ensure that
// power >= 0 && power <= 22
//
// Work around clang bug https://godbolt.org/z/zedh7rrhc
return (void)max_mantissa[0], max_mantissa[power];
}
template <>
inline constexpr uint64_t
binary_format::max_mantissa_fast_path(int64_t power) {
// caller is responsible to ensure that
// power >= 0 && power <= 10
//
// Work around clang bug https://godbolt.org/z/zedh7rrhc
return (void)max_mantissa[0], max_mantissa[power];
}
template <>
inline constexpr double
binary_format::exact_power_of_ten(int64_t power) {
// Work around clang bug https://godbolt.org/z/zedh7rrhc
return (void)powers_of_ten[0], powers_of_ten[power];
}
template <>
inline constexpr float binary_format::exact_power_of_ten(int64_t power) {
// Work around clang bug https://godbolt.org/z/zedh7rrhc
return (void)powers_of_ten[0], powers_of_ten[power];
}
template <> inline constexpr int binary_format::largest_power_of_ten() {
return 308;
}
template <> inline constexpr int binary_format::largest_power_of_ten() {
return 38;
}
template <>
inline constexpr int binary_format::smallest_power_of_ten() {
return -342;
}
template <> inline constexpr int binary_format::smallest_power_of_ten() {
return -64;
}
template <> inline constexpr size_t binary_format::max_digits() {
return 769;
}
template <> inline constexpr size_t binary_format::max_digits() {
return 114;
}
template <>
inline constexpr binary_format::equiv_uint
binary_format::exponent_mask() {
return 0x7F800000;
}
template <>
inline constexpr binary_format::equiv_uint
binary_format::exponent_mask() {
return 0x7FF0000000000000;
}
template <>
inline constexpr binary_format::equiv_uint
binary_format::mantissa_mask() {
return 0x007FFFFF;
}
template <>
inline constexpr binary_format::equiv_uint
binary_format::mantissa_mask() {
return 0x000FFFFFFFFFFFFF;
}
template <>
inline constexpr binary_format::equiv_uint
binary_format::hidden_bit_mask() {
return 0x00800000;
}
template <>
inline constexpr binary_format::equiv_uint
binary_format::hidden_bit_mask() {
return 0x0010000000000000;
}
template
fastfloat_really_inline FASTFLOAT_CONSTEXPR20 void
to_float(bool negative, adjusted_mantissa am, T &value) {
using equiv_uint = equiv_uint_t;
equiv_uint word = equiv_uint(am.mantissa);
word = equiv_uint(word | equiv_uint(am.power2)
<< binary_format::mantissa_explicit_bits());
word =
equiv_uint(word | equiv_uint(negative) << binary_format::sign_index());
#if FASTFLOAT_HAS_BIT_CAST
value = std::bit_cast(word);
#else
::memcpy(&value, &word, sizeof(T));
#endif
}
template struct space_lut {
static constexpr bool value[] = {
0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
};
#if FASTFLOAT_DETAIL_MUST_DEFINE_CONSTEXPR_VARIABLE
template constexpr bool space_lut::value[];
#endif
template constexpr bool is_space(UC c) {
return c < 256 && space_lut<>::value[uint8_t(c)];
}
template static constexpr uint64_t int_cmp_zeros() {
static_assert((sizeof(UC) == 1) || (sizeof(UC) == 2) || (sizeof(UC) == 4),
"Unsupported character size");
return (sizeof(UC) == 1) ? 0x3030303030303030
: (sizeof(UC) == 2)
? (uint64_t(UC('0')) << 48 | uint64_t(UC('0')) << 32 |
uint64_t(UC('0')) << 16 | UC('0'))
: (uint64_t(UC('0')) << 32 | UC('0'));
}
template static constexpr int int_cmp_len() {
return sizeof(uint64_t) / sizeof(UC);
}
template constexpr UC const *str_const_nan();
template <> constexpr char const *str_const_nan() { return "nan"; }
template <> constexpr wchar_t const *str_const_nan() { return L"nan"; }
template <> constexpr char16_t const *str_const_nan() {
return u"nan";
}
template <> constexpr char32_t const *str_const_nan() {
return U"nan";
}
#ifdef __cpp_char8_t
template <> constexpr char8_t const *str_const_nan() {
return u8"nan";
}
#endif
template constexpr UC const *str_const_inf();
template <> constexpr char const *str_const_inf() { return "infinity"; }
template <> constexpr wchar_t const *str_const_inf() {
return L"infinity";
}
template <> constexpr char16_t const *str_const_inf() {
return u"infinity";
}
template <> constexpr char32_t const *str_const_inf() {
return U"infinity";
}
#ifdef __cpp_char8_t
template <> constexpr char8_t const *str_const_inf() {
return u8"infinity";
}
#endif
template struct int_luts {
static constexpr uint8_t chdigit[] = {
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 255, 255,
255, 255, 255, 255, 255, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19,
20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34,
35, 255, 255, 255, 255, 255, 255, 10, 11, 12, 13, 14, 15, 16, 17,
18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32,
33, 34, 35, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255};
static constexpr size_t maxdigits_u64[] = {
64, 41, 32, 28, 25, 23, 22, 21, 20, 19, 18, 18, 17, 17, 16, 16, 16, 16,
15, 15, 15, 15, 14, 14, 14, 14, 14, 14, 14, 13, 13, 13, 13, 13, 13};
static constexpr uint64_t min_safe_u64[] = {
9223372036854775808ull, 12157665459056928801ull, 4611686018427387904,
7450580596923828125, 4738381338321616896, 3909821048582988049,
9223372036854775808ull, 12157665459056928801ull, 10000000000000000000ull,
5559917313492231481, 2218611106740436992, 8650415919381337933,
2177953337809371136, 6568408355712890625, 1152921504606846976,
2862423051509815793, 6746640616477458432, 15181127029874798299ull,
1638400000000000000, 3243919932521508681, 6221821273427820544,
11592836324538749809ull, 876488338465357824, 1490116119384765625,
2481152873203736576, 4052555153018976267, 6502111422497947648,
10260628712958602189ull, 15943230000000000000ull, 787662783788549761,
1152921504606846976, 1667889514952984961, 2386420683693101056,
3379220508056640625, 4738381338321616896};
};
#if FASTFLOAT_DETAIL_MUST_DEFINE_CONSTEXPR_VARIABLE
template constexpr uint8_t int_luts::chdigit[];
template constexpr size_t int_luts::maxdigits_u64[];
template constexpr uint64_t int_luts::min_safe_u64[];
#endif
template
fastfloat_really_inline constexpr uint8_t ch_to_digit(UC c) {
return int_luts<>::chdigit[static_cast(c)];
}
fastfloat_really_inline constexpr size_t max_digits_u64(int base) {
return int_luts<>::maxdigits_u64[base - 2];
}
// If a u64 is exactly max_digits_u64() in length, this is
// the value below which it has definitely overflowed.
fastfloat_really_inline constexpr uint64_t min_safe_u64(int base) {
return int_luts<>::min_safe_u64[base - 2];
}
static_assert(std::is_same, uint64_t>::value,
"equiv_uint should be uint64_t for double");
static_assert(std::numeric_limits::is_iec559,
"double must fulfill the requirements of IEC 559 (IEEE 754)");
static_assert(std::is_same, uint32_t>::value,
"equiv_uint should be uint32_t for float");
static_assert(std::numeric_limits::is_iec559,
"float must fulfill the requirements of IEC 559 (IEEE 754)");
#ifdef __STDCPP_FLOAT64_T__
static_assert(std::is_same, uint64_t>::value,
"equiv_uint should be uint64_t for std::float64_t");
static_assert(
std::numeric_limits::is_iec559,
"std::float64_t must fulfill the requirements of IEC 559 (IEEE 754)");
#endif // __STDCPP_FLOAT64_T__
#ifdef __STDCPP_FLOAT32_T__
static_assert(std::is_same, uint32_t>::value,
"equiv_uint should be uint32_t for std::float32_t");
static_assert(
std::numeric_limits::is_iec559,
"std::float32_t must fulfill the requirements of IEC 559 (IEEE 754)");
#endif // __STDCPP_FLOAT32_T__
#ifdef __STDCPP_FLOAT16_T__
static_assert(
std::is_same::equiv_uint, uint16_t>::value,
"equiv_uint should be uint16_t for std::float16_t");
static_assert(
std::numeric_limits::is_iec559,
"std::float16_t must fulfill the requirements of IEC 559 (IEEE 754)");
#endif // __STDCPP_FLOAT16_T__
#ifdef __STDCPP_BFLOAT16_T__
static_assert(
std::is_same::equiv_uint, uint16_t>::value,
"equiv_uint should be uint16_t for std::bfloat16_t");
static_assert(
std::numeric_limits::is_iec559,
"std::bfloat16_t must fulfill the requirements of IEC 559 (IEEE 754)");
#endif // __STDCPP_BFLOAT16_T__
constexpr chars_format operator~(chars_format rhs) noexcept {
using int_type = std::underlying_type::type;
return static_cast(~static_cast(rhs));
}
constexpr chars_format operator&(chars_format lhs, chars_format rhs) noexcept {
using int_type = std::underlying_type::type;
return static_cast(static_cast(lhs) &
static_cast(rhs));
}
constexpr chars_format operator|(chars_format lhs, chars_format rhs) noexcept {
using int_type = std::underlying_type::type;
return static_cast(static_cast(lhs) |
static_cast(rhs));
}
constexpr chars_format operator^(chars_format lhs, chars_format rhs) noexcept {
using int_type = std::underlying_type::type;
return static_cast(static_cast(lhs) ^
static_cast(rhs));
}
fastfloat_really_inline FASTFLOAT_CONSTEXPR14 chars_format &
operator&=(chars_format &lhs, chars_format rhs) noexcept {
return lhs = (lhs & rhs);
}
fastfloat_really_inline FASTFLOAT_CONSTEXPR14 chars_format &
operator|=(chars_format &lhs, chars_format rhs) noexcept {
return lhs = (lhs | rhs);
}
fastfloat_really_inline FASTFLOAT_CONSTEXPR14 chars_format &
operator^=(chars_format &lhs, chars_format rhs) noexcept {
return lhs = (lhs ^ rhs);
}
namespace detail {
// adjust for deprecated feature macros
constexpr chars_format adjust_for_feature_macros(chars_format fmt) {
return fmt
#ifdef FASTFLOAT_ALLOWS_LEADING_PLUS
| chars_format::allow_leading_plus
#endif
#ifdef FASTFLOAT_SKIP_WHITE_SPACE
| chars_format::skip_white_space
#endif
;
}
} // namespace detail
} // namespace fast_float
#endif
#ifndef FASTFLOAT_FAST_FLOAT_H
#define FASTFLOAT_FAST_FLOAT_H
namespace fast_float {
/**
* This function parses the character sequence [first,last) for a number. It
* parses floating-point numbers expecting a locale-indepent format equivalent
* to what is used by std::strtod in the default ("C") locale. The resulting
* floating-point value is the closest floating-point values (using either float
* or double), using the "round to even" convention for values that would
* otherwise fall right in-between two values. That is, we provide exact parsing
* according to the IEEE standard.
*
* Given a successful parse, the pointer (`ptr`) in the returned value is set to
* point right after the parsed number, and the `value` referenced is set to the
* parsed value. In case of error, the returned `ec` contains a representative
* error, otherwise the default (`std::errc()`) value is stored.
*
* The implementation does not throw and does not allocate memory (e.g., with
* `new` or `malloc`).
*
* Like the C++17 standard, the `fast_float::from_chars` functions take an
* optional last argument of the type `fast_float::chars_format`. It is a bitset
* value: we check whether `fmt & fast_float::chars_format::fixed` and `fmt &
* fast_float::chars_format::scientific` are set to determine whether we allow
* the fixed point and scientific notation respectively. The default is
* `fast_float::chars_format::general` which allows both `fixed` and
* `scientific`.
*/
template ::value)>
FASTFLOAT_CONSTEXPR20 from_chars_result_t
from_chars(UC const *first, UC const *last, T &value,
chars_format fmt = chars_format::general) noexcept;
/**
* Like from_chars, but accepts an `options` argument to govern number parsing.
* Both for floating-point types and integer types.
*/
template
FASTFLOAT_CONSTEXPR20 from_chars_result_t
from_chars_advanced(UC const *first, UC const *last, T &value,
parse_options_t options) noexcept;
/**
* from_chars for integer types.
*/
template ::value)>
FASTFLOAT_CONSTEXPR20 from_chars_result_t
from_chars(UC const *first, UC const *last, T &value, int base = 10) noexcept;
} // namespace fast_float
#endif // FASTFLOAT_FAST_FLOAT_H
#ifndef FASTFLOAT_ASCII_NUMBER_H
#define FASTFLOAT_ASCII_NUMBER_H
#include
#include
#include
#include
#include
#include
#ifdef FASTFLOAT_SSE2
#include
#endif
#ifdef FASTFLOAT_NEON
#include
#endif
namespace fast_float {
template fastfloat_really_inline constexpr bool has_simd_opt() {
#ifdef FASTFLOAT_HAS_SIMD
return std::is_same::value;
#else
return false;
#endif
}
// Next function can be micro-optimized, but compilers are entirely
// able to optimize it well.
template
fastfloat_really_inline constexpr bool is_integer(UC c) noexcept {
return !(c > UC('9') || c < UC('0'));
}
fastfloat_really_inline constexpr uint64_t byteswap(uint64_t val) {
return (val & 0xFF00000000000000) >> 56 | (val & 0x00FF000000000000) >> 40 |
(val & 0x0000FF0000000000) >> 24 | (val & 0x000000FF00000000) >> 8 |
(val & 0x00000000FF000000) << 8 | (val & 0x0000000000FF0000) << 24 |
(val & 0x000000000000FF00) << 40 | (val & 0x00000000000000FF) << 56;
}
// Read 8 UC into a u64. Truncates UC if not char.
template
fastfloat_really_inline FASTFLOAT_CONSTEXPR20 uint64_t
read8_to_u64(UC const *chars) {
if (cpp20_and_in_constexpr() || !std::is_same::value) {
uint64_t val = 0;
for (int i = 0; i < 8; ++i) {
val |= uint64_t(uint8_t(*chars)) << (i * 8);
++chars;
}
return val;
}
uint64_t val;
::memcpy(&val, chars, sizeof(uint64_t));
#if FASTFLOAT_IS_BIG_ENDIAN == 1
// Need to read as-if the number was in little-endian order.
val = byteswap(val);
#endif
return val;
}
#ifdef FASTFLOAT_SSE2
fastfloat_really_inline uint64_t simd_read8_to_u64(__m128i const data) {
FASTFLOAT_SIMD_DISABLE_WARNINGS
__m128i const packed = _mm_packus_epi16(data, data);
#ifdef FASTFLOAT_64BIT
return uint64_t(_mm_cvtsi128_si64(packed));
#else
uint64_t value;
// Visual Studio + older versions of GCC don't support _mm_storeu_si64
_mm_storel_epi64(reinterpret_cast<__m128i *>(&value), packed);
return value;
#endif
FASTFLOAT_SIMD_RESTORE_WARNINGS
}
fastfloat_really_inline uint64_t simd_read8_to_u64(char16_t const *chars) {
FASTFLOAT_SIMD_DISABLE_WARNINGS
return simd_read8_to_u64(
_mm_loadu_si128(reinterpret_cast<__m128i const *>(chars)));
FASTFLOAT_SIMD_RESTORE_WARNINGS
}
#elif defined(FASTFLOAT_NEON)
fastfloat_really_inline uint64_t simd_read8_to_u64(uint16x8_t const data) {
FASTFLOAT_SIMD_DISABLE_WARNINGS
uint8x8_t utf8_packed = vmovn_u16(data);
return vget_lane_u64(vreinterpret_u64_u8(utf8_packed), 0);
FASTFLOAT_SIMD_RESTORE_WARNINGS
}
fastfloat_really_inline uint64_t simd_read8_to_u64(char16_t const *chars) {
FASTFLOAT_SIMD_DISABLE_WARNINGS
return simd_read8_to_u64(
vld1q_u16(reinterpret_cast(chars)));
FASTFLOAT_SIMD_RESTORE_WARNINGS
}
#endif // FASTFLOAT_SSE2
// MSVC SFINAE is broken pre-VS2017
#if defined(_MSC_VER) && _MSC_VER <= 1900
template
#else
template ()) = 0>
#endif
// dummy for compile
uint64_t simd_read8_to_u64(UC const *) {
return 0;
}
// credit @aqrit
fastfloat_really_inline FASTFLOAT_CONSTEXPR14 uint32_t
parse_eight_digits_unrolled(uint64_t val) {
uint64_t const mask = 0x000000FF000000FF;
uint64_t const mul1 = 0x000F424000000064; // 100 + (1000000ULL << 32)
uint64_t const mul2 = 0x0000271000000001; // 1 + (10000ULL << 32)
val -= 0x3030303030303030;
val = (val * 10) + (val >> 8); // val = (val * 2561) >> 8;
val = (((val & mask) * mul1) + (((val >> 16) & mask) * mul2)) >> 32;
return uint32_t(val);
}
// Call this if chars are definitely 8 digits.
template
fastfloat_really_inline FASTFLOAT_CONSTEXPR20 uint32_t
parse_eight_digits_unrolled(UC const *chars) noexcept {
if (cpp20_and_in_constexpr() || !has_simd_opt()) {
return parse_eight_digits_unrolled(read8_to_u64(chars)); // truncation okay
}
return parse_eight_digits_unrolled(simd_read8_to_u64(chars));
}
// credit @aqrit
fastfloat_really_inline constexpr bool
is_made_of_eight_digits_fast(uint64_t val) noexcept {
return !((((val + 0x4646464646464646) | (val - 0x3030303030303030)) &
0x8080808080808080));
}
#ifdef FASTFLOAT_HAS_SIMD
// Call this if chars might not be 8 digits.
// Using this style (instead of is_made_of_eight_digits_fast() then
// parse_eight_digits_unrolled()) ensures we don't load SIMD registers twice.
fastfloat_really_inline FASTFLOAT_CONSTEXPR20 bool
simd_parse_if_eight_digits_unrolled(char16_t const *chars,
uint64_t &i) noexcept {
if (cpp20_and_in_constexpr()) {
return false;
}
#ifdef FASTFLOAT_SSE2
FASTFLOAT_SIMD_DISABLE_WARNINGS
__m128i const data =
_mm_loadu_si128(reinterpret_cast<__m128i const *>(chars));
// (x - '0') <= 9
// https://0x80.pl/articles/simd-parsing-int-sequences.html
__m128i const t0 = _mm_add_epi16(data, _mm_set1_epi16(32720));
__m128i const t1 = _mm_cmpgt_epi16(t0, _mm_set1_epi16(-32759));
if (_mm_movemask_epi8(t1) == 0) {
i = i * 100000000 + parse_eight_digits_unrolled(simd_read8_to_u64(data));
return true;
} else
return false;
FASTFLOAT_SIMD_RESTORE_WARNINGS
#elif defined(FASTFLOAT_NEON)
FASTFLOAT_SIMD_DISABLE_WARNINGS
uint16x8_t const data = vld1q_u16(reinterpret_cast(chars));
// (x - '0') <= 9
// https://0x80.pl/articles/simd-parsing-int-sequences.html
uint16x8_t const t0 = vsubq_u16(data, vmovq_n_u16('0'));
uint16x8_t const mask = vcltq_u16(t0, vmovq_n_u16('9' - '0' + 1));
if (vminvq_u16(mask) == 0xFFFF) {
i = i * 100000000 + parse_eight_digits_unrolled(simd_read8_to_u64(data));
return true;
} else
return false;
FASTFLOAT_SIMD_RESTORE_WARNINGS
#else
(void)chars;
(void)i;
return false;
#endif // FASTFLOAT_SSE2
}
#endif // FASTFLOAT_HAS_SIMD
// MSVC SFINAE is broken pre-VS2017
#if defined(_MSC_VER) && _MSC_VER <= 1900
template
#else
template ()) = 0>
#endif
// dummy for compile
bool simd_parse_if_eight_digits_unrolled(UC const *, uint64_t &) {
return 0;
}
template ::value) = 0>
fastfloat_really_inline FASTFLOAT_CONSTEXPR20 void
loop_parse_if_eight_digits(UC const *&p, UC const *const pend, uint64_t &i) {
if (!has_simd_opt()) {
return;
}
while ((std::distance(p, pend) >= 8) &&
simd_parse_if_eight_digits_unrolled(
p, i)) { // in rare cases, this will overflow, but that's ok
p += 8;
}
}
fastfloat_really_inline FASTFLOAT_CONSTEXPR20 void
loop_parse_if_eight_digits(char const *&p, char const *const pend,
uint64_t &i) {
// optimizes better than parse_if_eight_digits_unrolled() for UC = char.
while ((std::distance(p, pend) >= 8) &&
is_made_of_eight_digits_fast(read8_to_u64(p))) {
i = i * 100000000 +
parse_eight_digits_unrolled(read8_to_u64(
p)); // in rare cases, this will overflow, but that's ok
p += 8;
}
}
enum class parse_error {
no_error,
// [JSON-only] The minus sign must be followed by an integer.
missing_integer_after_sign,
// A sign must be followed by an integer or dot.
missing_integer_or_dot_after_sign,
// [JSON-only] The integer part must not have leading zeros.
leading_zeros_in_integer_part,
// [JSON-only] The integer part must have at least one digit.
no_digits_in_integer_part,
// [JSON-only] If there is a decimal point, there must be digits in the
// fractional part.
no_digits_in_fractional_part,
// The mantissa must have at least one digit.
no_digits_in_mantissa,
// Scientific notation requires an exponential part.
missing_exponential_part,
};
template struct parsed_number_string_t {
int64_t exponent{0};
uint64_t mantissa{0};
UC const *lastmatch{nullptr};
bool negative{false};
bool valid{false};
bool too_many_digits{false};
// contains the range of the significant digits
span integer{}; // non-nullable
span fraction{}; // nullable
parse_error error{parse_error::no_error};
};
using byte_span = span;
using parsed_number_string = parsed_number_string_t;
template
fastfloat_really_inline FASTFLOAT_CONSTEXPR20 parsed_number_string_t
report_parse_error(UC const *p, parse_error error) {
parsed_number_string_t answer;
answer.valid = false;
answer.lastmatch = p;
answer.error = error;
return answer;
}
// Assuming that you use no more than 19 digits, this will
// parse an ASCII string.
template