-
Notifications
You must be signed in to change notification settings - Fork 6
/
fp_to_chars.h
95 lines (89 loc) · 2.68 KB
/
fp_to_chars.h
1
2
3
4
5
6
7
8
9
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
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
// Copyright 2020 Junekey Jeon
//
// The contents of this file may be used under the terms of
// the Apache License v2.0 with LLVM Exceptions.
//
// (See accompanying file LICENSE-Apache or copy at
// https://llvm.org/foundation/relicensing/LICENSE.txt)
//
// Alternatively, the contents of this file may be used under the terms of
// the Boost Software License, Version 1.0.
// (See accompanying file LICENSE-Boost or copy at
// https://www.boost.org/LICENSE_1_0.txt)
//
// Unless required by applicable law or agreed to in writing, this software
// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied.
#ifndef JKJ_FP_TO_CHARS
#define JKJ_FP_TO_CHARS
#include "grisu_exact.h"
namespace jkj {
namespace fp_to_chars_detail {
char* float_to_chars(unsigned_fp_t<float> v, char* buffer);
char* double_to_chars(unsigned_fp_t<double> v, char* buffer);
}
// Returns the next-to-end position
template <class Float,
class RoundingMode = grisu_exact_rounding_modes::nearest_to_even,
class CorrectRoundingSearch = grisu_exact_correct_rounding::tie_to_even
>
char* fp_to_chars_n(Float x, char* buffer,
RoundingMode&& rounding_mode = {},
CorrectRoundingSearch&& crs = {})
{
auto br = get_bit_representation(x);
if (br.is_finite()) {
if (br.is_negative()) {
*buffer = '-';
++buffer;
}
if (br.is_nonzero()) {
if constexpr (sizeof(Float) == 4) {
return fp_to_chars_detail::float_to_chars(grisu_exact<false>(x,
std::forward<RoundingMode>(rounding_mode),
std::forward<CorrectRoundingSearch>(crs)), buffer);
}
else {
return fp_to_chars_detail::double_to_chars(grisu_exact<false>(x,
std::forward<RoundingMode>(rounding_mode),
std::forward<CorrectRoundingSearch>(crs)), buffer);
}
}
else {
std::memcpy(buffer, "0E0", 3);
return buffer + 3;
}
}
else {
if ((br.f << (grisu_exact_detail::common_info<Float>::exponent_bits + 1)) != 0)
{
std::memcpy(buffer, "NaN", 3);
return buffer + 3;
}
else {
if (br.is_negative()) {
*buffer = '-';
++buffer;
}
std::memcpy(buffer, "Infinity", 8);
return buffer + 8;
}
}
}
// Null-terminate and bypass the return value of fp_to_chars_n
template <class Float,
class RoundingMode = grisu_exact_rounding_modes::nearest_to_even,
class CorrectRoundingSearch = grisu_exact_correct_rounding::tie_to_even
>
char* fp_to_chars(Float x, char* buffer,
RoundingMode&& rounding_mode = {},
CorrectRoundingSearch&& crs = {})
{
auto ptr = fp_to_chars_n(x, buffer,
std::forward<RoundingMode>(rounding_mode),
std::forward<CorrectRoundingSearch>(crs));
*ptr = '\0';
return ptr;
}
}
#endif