Skip to content

Commit 3957642

Browse files
authored
Merge pull request #38 from lemire/dlemire/issue37
Adding support for big endian systems
2 parents db539b2 + 1b5e3f3 commit 3957642

File tree

4 files changed

+226
-1
lines changed

4 files changed

+226
-1
lines changed

.travis.yml

Lines changed: 174 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,174 @@
1+
language: cpp
2+
3+
dist: bionic
4+
5+
arch:
6+
- amd64
7+
- ppc64le
8+
- s390x
9+
10+
cache:
11+
directories:
12+
- $HOME/.dep_cache
13+
14+
env:
15+
global:
16+
- fastfloat_DEPENDENCY_CACHE_DIR=$HOME/.dep_cache
17+
18+
matrix:
19+
include:
20+
- os: linux
21+
addons:
22+
apt:
23+
sources:
24+
- ubuntu-toolchain-r-test
25+
packages:
26+
- g++-8
27+
env:
28+
- COMPILER="CC=gcc-8 && CXX=g++-8"
29+
compiler: gcc-8
30+
31+
- os: linux
32+
addons:
33+
apt:
34+
sources:
35+
- ubuntu-toolchain-r-test
36+
packages:
37+
- g++-9
38+
env:
39+
- COMPILER="CC=gcc-9 && CXX=g++-9"
40+
compiler: gcc-9
41+
42+
- os: linux
43+
addons:
44+
apt:
45+
sources:
46+
- ubuntu-toolchain-r-test
47+
packages:
48+
- g++-10
49+
env:
50+
- COMPILER="CC=gcc-10 && CXX=g++-10"
51+
compiler: gcc-10
52+
53+
- os: linux
54+
addons:
55+
apt:
56+
sources:
57+
- ubuntu-toolchain-r-test
58+
packages:
59+
- g++-10
60+
env:
61+
- COMPILER="CC=gcc-10 && CXX=g++-10"
62+
- SANITIZE="on"
63+
compiler: gcc-10-sanitize
64+
65+
- os: linux
66+
addons:
67+
apt:
68+
sources:
69+
- ubuntu-toolchain-r-test
70+
packages:
71+
- g++-10
72+
env:
73+
- COMPILER="CC=gcc-10 && CXX=g++-10"
74+
- STATIC="on"
75+
compiler: gcc-10-static
76+
77+
- os: linux
78+
addons:
79+
apt:
80+
sources:
81+
- llvm-toolchain-bionic-6.0
82+
packages:
83+
- clang-6.0
84+
env:
85+
- COMPILER="CC=clang-6.0 && CXX=clang++-6.0"
86+
compiler: clang-6
87+
88+
- os: linux
89+
addons:
90+
apt:
91+
sources:
92+
- llvm-toolchain-bionic-7
93+
packages:
94+
- clang-7
95+
env:
96+
- COMPILER="CC=clang-7 && CXX=clang++-7"
97+
compiler: clang-7
98+
99+
- os: linux
100+
addons:
101+
apt:
102+
sources:
103+
- llvm-toolchain-bionic-8
104+
packages:
105+
- clang-8
106+
env:
107+
- COMPILER="CC=clang-8 && CXX=clang++-8"
108+
compiler: clang-8
109+
110+
- os: linux
111+
addons:
112+
apt:
113+
sources:
114+
- llvm-toolchain-bionic-9
115+
packages:
116+
- clang-9
117+
env:
118+
- COMPILER="CC=clang-9 && CXX=clang++-9"
119+
compiler: clang-9
120+
121+
- os: linux
122+
addons:
123+
apt:
124+
packages:
125+
- clang-10
126+
sources:
127+
- ubuntu-toolchain-r-test
128+
- sourceline: 'deb http://apt.llvm.org/bionic/ llvm-toolchain-bionic-10 main'
129+
key_url: 'https://apt.llvm.org/llvm-snapshot.gpg.key'
130+
env:
131+
- COMPILER="CC=clang-10 && CXX=clang++-10"
132+
compiler: clang-10
133+
134+
- os: linux
135+
addons:
136+
apt:
137+
packages:
138+
- clang-10
139+
sources:
140+
- ubuntu-toolchain-r-test
141+
- sourceline: 'deb http://apt.llvm.org/bionic/ llvm-toolchain-bionic-10 main'
142+
key_url: 'https://apt.llvm.org/llvm-snapshot.gpg.key'
143+
env:
144+
- COMPILER="CC=clang-10 && CXX=clang++-10"
145+
- STATIC="on"
146+
compiler: clang-10-static
147+
148+
- os: linux
149+
addons:
150+
apt:
151+
packages:
152+
- clang-10
153+
sources:
154+
- ubuntu-toolchain-r-test
155+
- sourceline: 'deb http://apt.llvm.org/bionic/ llvm-toolchain-bionic-10 main'
156+
key_url: 'https://apt.llvm.org/llvm-snapshot.gpg.key'
157+
env:
158+
- COMPILER="CC=clang-10 && CXX=clang++-10"
159+
- SANITIZE="on"
160+
compiler: clang-10-sanitize
161+
162+
before_install:
163+
- eval "${COMPILER}"
164+
165+
install:
166+
- sudo apt-get -qq update
167+
168+
script:
169+
- mkdir build
170+
- cd build
171+
- cmake -DFASTFLOAT_TEST=ON ..
172+
- make
173+
- ctest --output-on-failure -R basictest
174+

include/fast_float/ascii_number.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,8 @@ parsed_number_string parse_number_string(const char *p, const char *pend, chars_
7878
if ((p != pend) && (*p == '.')) {
7979
++p;
8080
const char *first_after_period = p;
81+
#if FASTFLOAT_IS_BIG_ENDIAN == 0
82+
// Fast approach only tested under little endian systems
8183
if ((p + 8 <= pend) && is_made_of_eight_digits_fast(p)) {
8284
i = i * 100000000 + parse_eight_digits_unrolled(p); // in rare cases, this will overflow, but that's ok
8385
p += 8;
@@ -86,6 +88,7 @@ parsed_number_string parse_number_string(const char *p, const char *pend, chars_
8688
p += 8;
8789
}
8890
}
91+
#endif
8992
while ((p != pend) && is_integer(*p)) {
9093
uint8_t digit = uint8_t(*p - '0');
9194
++p;
@@ -196,6 +199,7 @@ fastfloat_really_inline decimal parse_decimal(const char *p, const char *pend) n
196199
++p;
197200
}
198201
}
202+
#if FASTFLOAT_IS_BIG_ENDIAN == 0
199203
// We expect that this loop will often take the bulk of the running time
200204
// because when a value has lots of digits, these digits often
201205
while ((p + 8 <= pend) && (answer.num_digits + 8 < max_digits)) {
@@ -208,6 +212,7 @@ fastfloat_really_inline decimal parse_decimal(const char *p, const char *pend) n
208212
answer.num_digits += 8;
209213
p += 8;
210214
}
215+
#endif
211216
while ((p != pend) && is_integer(*p)) {
212217
if (answer.num_digits < max_digits) {
213218
answer.digits[answer.num_digits] = uint8_t(*p - '0');

include/fast_float/float_common.h

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,34 @@
88
#define FASTFLOAT_VISUAL_STUDIO 1
99
#endif
1010

11+
12+
13+
#ifdef _WIN32
14+
#define FASTFLOAT_IS_BIG_ENDIAN 0
15+
#else
16+
#if defined(__APPLE__) || defined(__FreeBSD__)
17+
#include <machine/endian.h>
18+
#else
19+
#include <endian.h>
20+
#endif
21+
#
22+
#ifndef __BYTE_ORDER__
23+
// safe choice
24+
#define FASTFLOAT_IS_BIG_ENDIAN 0
25+
#endif
26+
#
27+
#ifndef __ORDER_LITTLE_ENDIAN__
28+
// safe choice
29+
#define FASTFLOAT_IS_BIG_ENDIAN 0
30+
#endif
31+
#
32+
#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
33+
#define FASTFLOAT_IS_BIG_ENDIAN 0
34+
#else
35+
#define FASTFLOAT_IS_BIG_ENDIAN 1
36+
#endif
37+
#endif
38+
1139
#ifdef FASTFLOAT_VISUAL_STUDIO
1240
#define fastfloat_really_inline __forceinline
1341
#else
@@ -154,6 +182,14 @@ struct decimal {
154182
// Note that the user is responsible to ensure that digits are
155183
// initialized to zero when there are fewer than 19.
156184
inline uint64_t to_truncated_mantissa() {
185+
#if FASTFLOAT_IS_BIG_ENDIAN == 1
186+
uint64_t mantissa = 0;
187+
for (uint32_t i = 0; i < max_digit_without_overflow;
188+
i++) {
189+
mantissa = mantissa * 10 + digits[i]; // can be accelerated
190+
}
191+
return mantissa;
192+
#else
157193
uint64_t val;
158194
// 8 first digits
159195
::memcpy(&val, digits, sizeof(uint64_t));
@@ -173,6 +209,7 @@ struct decimal {
173209
mantissa = mantissa * 10 + digits[i]; // can be accelerated
174210
}
175211
return mantissa;
212+
#endif
176213
}
177214
// Generate san exponent matching to_truncated_mantissa()
178215
inline int32_t to_truncated_exponent() {

include/fast_float/parse_number.h

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,16 @@ from_chars_result from_chars(const char *first, const char *last,
107107
word |= uint64_t(am.power2) << binary_format<T>::mantissa_explicit_bits();
108108
word = pns.negative
109109
? word | (uint64_t(1) << binary_format<T>::sign_index()) : word;
110-
::memcpy(&value, &word, sizeof(T));
110+
#if FASTFLOAT_IS_BIG_ENDIAN == 1
111+
if (std::is_same<T, float>::value) {
112+
::memcpy(&value, (char *)&word + 4, sizeof(T)); // extract value at offset 4-7 if float on big-endian
113+
} else {
114+
::memcpy(&value, &word, sizeof(T));
115+
}
116+
#else
117+
// For little-endian systems:
118+
::memcpy(&value, &word, sizeof(T));
119+
#endif
111120
return answer;
112121
}
113122

0 commit comments

Comments
 (0)