summaryrefslogtreecommitdiffstats
path: root/src/common/ryu_common.h
blob: ad850acf62f29180d482a8b519ae6553dfef415e (plain)
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
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
/*---------------------------------------------------------------------------
 *
 * Common routines for Ryu floating-point output.
 *
 * Portions Copyright (c) 2018-2023, PostgreSQL Global Development Group
 *
 * IDENTIFICATION
 *	  src/common/ryu_common.h
 *
 * This is a modification of code taken from github.com/ulfjack/ryu under the
 * terms of the Boost license (not the Apache license). The original copyright
 * notice follows:
 *
 * Copyright 2018 Ulf Adams
 *
 * The contents of this file may be used under the terms of the Apache
 * License, Version 2.0.
 *
 *     (See accompanying file LICENSE-Apache or copy at
 *      http://www.apache.org/licenses/LICENSE-2.0)
 *
 * 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 RYU_COMMON_H
#define RYU_COMMON_H

/*
 * Upstream Ryu's output is always the shortest possible. But we adjust that
 * slightly to improve portability: we avoid outputting the exact midpoint
 * value between two representable floats, since that relies on the reader
 * getting the round-to-even rule correct, which seems to be the common
 * failure mode.
 *
 * Defining this to 1 would restore the upstream behavior.
 */
#define STRICTLY_SHORTEST 0

#if SIZEOF_SIZE_T < 8
#define RYU_32_BIT_PLATFORM
#endif

/*  Returns e == 0 ? 1 : ceil(log_2(5^e)). */
static inline uint32
pow5bits(const int32 e)
{
	/*
	 * This approximation works up to the point that the multiplication
	 * overflows at e = 3529.
	 *
	 * If the multiplication were done in 64 bits, it would fail at 5^4004
	 * which is just greater than 2^9297.
	 */
	Assert(e >= 0);
	Assert(e <= 3528);
	return ((((uint32) e) * 1217359) >> 19) + 1;
}

/*  Returns floor(log_10(2^e)). */
static inline int32
log10Pow2(const int32 e)
{
	/*
	 * The first value this approximation fails for is 2^1651 which is just
	 * greater than 10^297.
	 */
	Assert(e >= 0);
	Assert(e <= 1650);
	return (int32) ((((uint32) e) * 78913) >> 18);
}

/*  Returns floor(log_10(5^e)). */
static inline int32
log10Pow5(const int32 e)
{
	/*
	 * The first value this approximation fails for is 5^2621 which is just
	 * greater than 10^1832.
	 */
	Assert(e >= 0);
	Assert(e <= 2620);
	return (int32) ((((uint32) e) * 732923) >> 20);
}

static inline int
copy_special_str(char *const result, const bool sign, const bool exponent, const bool mantissa)
{
	if (mantissa)
	{
		memcpy(result, "NaN", 3);
		return 3;
	}
	if (sign)
	{
		result[0] = '-';
	}
	if (exponent)
	{
		memcpy(result + sign, "Infinity", 8);
		return sign + 8;
	}
	result[sign] = '0';
	return sign + 1;
}

static inline uint32
float_to_bits(const float f)
{
	uint32		bits = 0;

	memcpy(&bits, &f, sizeof(float));
	return bits;
}

static inline uint64
double_to_bits(const double d)
{
	uint64		bits = 0;

	memcpy(&bits, &d, sizeof(double));
	return bits;
}

#endif							/* RYU_COMMON_H */