Skip to content

Commit 11c9640

Browse files
committed
Add BE and LE versions of IEEE float packing
1 parent a041415 commit 11c9640

File tree

5 files changed

+200
-53
lines changed

5 files changed

+200
-53
lines changed

exec/cnex/exclude.txt

+1
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ gc2.neon # Object Count
77
gc3.neon # Object Count
88
gc-two-pointers.neon # garbage collection
99
math-test.neon # math.powmod()
10+
struct-test.neon # iEEE big endian packing
1011

1112
extsample-test.neon # cell_set_pointer
1213
http-test.neon # string$split

exec/pynex/pynex.py

+14-4
Original file line numberDiff line numberDiff line change
@@ -2346,14 +2346,24 @@ def neon_builtin_string__toString(self):
23462346
s = self.stack.pop()
23472347
self.stack.append(s)
23482348

2349-
def neon_struct_packIEEE64(self):
2349+
def neon_struct_packIEEE64BE(self):
23502350
n = self.stack.pop()
2351-
r = struct.pack("d", n)
2351+
r = struct.pack(">d", n)
23522352
self.stack.append(r)
23532353

2354-
def neon_struct_unpackIEEE64(self):
2354+
def neon_struct_packIEEE64LE(self):
2355+
n = self.stack.pop()
2356+
r = struct.pack("<d", n)
2357+
self.stack.append(r)
2358+
2359+
def neon_struct_unpackIEEE64BE(self):
2360+
b = self.stack.pop()
2361+
r = decimal.Decimal(struct.unpack(">d", b)[0])
2362+
self.stack.append(r)
2363+
2364+
def neon_struct_unpackIEEE64LE(self):
23552365
b = self.stack.pop()
2356-
r = decimal.Decimal(struct.unpack("d", b)[0])
2366+
r = decimal.Decimal(struct.unpack("<d", b)[0])
23572367
self.stack.append(r)
23582368

23592369
def neon_substring(self):

lib/struct.cpp

+84-10
Original file line numberDiff line numberDiff line change
@@ -8,33 +8,107 @@ namespace rtl {
88

99
namespace ne_struct {
1010

11-
std::vector<unsigned char> packIEEE32(Number n)
11+
std::vector<unsigned char> packIEEE32BE(Number n)
1212
{
1313
float x = number_to_float(n);
14+
uint32_t i = *(uint32_t *)&x;
1415
std::vector<unsigned char> r(sizeof(x));
15-
memcpy(r.data(), &x, sizeof(x));
16+
r[0] = (i >> 24) & 0xff;
17+
r[1] = (i >> 16) & 0xff;
18+
r[2] = (i >> 8) & 0xff;
19+
r[3] = (i ) & 0xff;
1620
return r;
1721
}
1822

19-
std::vector<unsigned char> packIEEE64(Number n)
23+
std::vector<unsigned char> packIEEE32LE(Number n)
24+
{
25+
float x = number_to_float(n);
26+
uint32_t i = *(uint32_t *)&x;
27+
std::vector<unsigned char> r(sizeof(x));
28+
r[3] = (i >> 24) & 0xff;
29+
r[2] = (i >> 16) & 0xff;
30+
r[1] = (i >> 8) & 0xff;
31+
r[0] = (i ) & 0xff;
32+
return r;
33+
}
34+
35+
std::vector<unsigned char> packIEEE64BE(Number n)
36+
{
37+
double x = number_to_double(n);
38+
uint64_t i = *(uint64_t *)&x;
39+
std::vector<unsigned char> r(sizeof(x));
40+
r[0] = (i >> 56) & 0xff;
41+
r[1] = (i >> 48) & 0xff;
42+
r[2] = (i >> 40) & 0xff;
43+
r[3] = (i >> 32) & 0xff;
44+
r[4] = (i >> 24) & 0xff;
45+
r[5] = (i >> 16) & 0xff;
46+
r[6] = (i >> 8) & 0xff;
47+
r[7] = (i ) & 0xff;
48+
return r;
49+
}
50+
51+
std::vector<unsigned char> packIEEE64LE(Number n)
2052
{
2153
double x = number_to_double(n);
54+
uint64_t i = *(uint64_t *)&x;
2255
std::vector<unsigned char> r(sizeof(x));
23-
memcpy(r.data(), &x, sizeof(x));
56+
r[7] = (i >> 56) & 0xff;
57+
r[6] = (i >> 48) & 0xff;
58+
r[5] = (i >> 40) & 0xff;
59+
r[4] = (i >> 32) & 0xff;
60+
r[3] = (i >> 24) & 0xff;
61+
r[2] = (i >> 16) & 0xff;
62+
r[1] = (i >> 8) & 0xff;
63+
r[0] = (i ) & 0xff;
2464
return r;
2565
}
2666

27-
Number unpackIEEE32(const std::vector<unsigned char> &b)
67+
Number unpackIEEE32BE(const std::vector<unsigned char> &b)
68+
{
69+
uint32_t i = (b[0] << 24) |
70+
(b[1] << 16) |
71+
(b[2] << 8) |
72+
(b[3] );
73+
float x = *(float *)&i;
74+
return number_from_float(x);
75+
}
76+
77+
Number unpackIEEE32LE(const std::vector<unsigned char> &b)
2878
{
29-
float x;
30-
memcpy(&x, b.data(), sizeof(x));
79+
uint32_t i = (b[3] << 24) |
80+
(b[2] << 16) |
81+
(b[1] << 8) |
82+
(b[0] );
83+
float x = *(float *)&i;
3184
return number_from_float(x);
3285
}
3386

34-
Number unpackIEEE64(const std::vector<unsigned char> &b)
87+
Number unpackIEEE64BE(const std::vector<unsigned char> &b)
88+
{
89+
uint64_t i = (static_cast<uint64_t>(b[0]) << 56) |
90+
(static_cast<uint64_t>(b[1]) << 48) |
91+
(static_cast<uint64_t>(b[2]) << 40) |
92+
(static_cast<uint64_t>(b[3]) << 32) |
93+
(static_cast<uint64_t>(b[4]) << 24) |
94+
(static_cast<uint64_t>(b[5]) << 16) |
95+
(static_cast<uint64_t>(b[6]) << 8) |
96+
(static_cast<uint64_t>(b[7]) );
97+
double x = *(double *)&i;
98+
return number_from_double(x);
99+
}
100+
101+
Number unpackIEEE64LE(const std::vector<unsigned char> &b)
35102
{
36-
double x;
37-
memcpy(&x, b.data(), sizeof(x));
103+
uint64_t i = (static_cast<uint64_t>(b[7]) << 56) |
104+
(static_cast<uint64_t>(b[6]) << 48) |
105+
(static_cast<uint64_t>(b[5]) << 40) |
106+
(static_cast<uint64_t>(b[4]) << 32) |
107+
(static_cast<uint64_t>(b[3]) << 24) |
108+
(static_cast<uint64_t>(b[2]) << 16) |
109+
(static_cast<uint64_t>(b[1]) << 8) |
110+
(static_cast<uint64_t>(b[0]) );
111+
double x = *(double *)&i;
38112
return number_from_double(x);
39113
}
40114

lib/struct.neon

+100-38
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,10 @@ EXPORT Type
1111
EXPORT make
1212
EXPORT field
1313
EXPORT packBool
14-
EXPORT packIEEE32
15-
EXPORT packIEEE64
14+
EXPORT packIEEE32BE
15+
EXPORT packIEEE32LE
16+
EXPORT packIEEE64BE
17+
EXPORT packIEEE64LE
1618
EXPORT packInt8
1719
EXPORT packInt16BE
1820
EXPORT packInt16LE
@@ -28,8 +30,10 @@ EXPORT packUInt32LE
2830
EXPORT packUInt64BE
2931
EXPORT packUInt64LE
3032
EXPORT unpackBool
31-
EXPORT unpackIEEE32
32-
EXPORT unpackIEEE64
33+
EXPORT unpackIEEE32BE
34+
EXPORT unpackIEEE32LE
35+
EXPORT unpackIEEE64BE
36+
EXPORT unpackIEEE64LE
3337
EXPORT unpackInt8
3438
EXPORT unpackInt16BE
3539
EXPORT unpackInt16LE
@@ -53,8 +57,10 @@ IMPORT binary
5357
*
5458
* Values:
5559
* bool - boolean
56-
* ieee32 - IEEE 754 32 bit binary floating point
57-
* ieee64 - IEEE 754 64 bit binary floating point
60+
* ieee32BE - IEEE 754 32 bit binary floating point, big endian
61+
* ieee32LE - IEEE 754 32 bit binary floating point, little endian
62+
* ieee64BE - IEEE 754 64 bit binary floating point, big endian
63+
* ieee64LE - IEEE 754 64 bit binary floating point, little endian
5864
* int8 - signed 8 bit integer
5965
* int16BE - signed 16 bit integer, big endian
6066
* int16LE - signed 16 bit integer, little endian
@@ -74,8 +80,10 @@ IMPORT binary
7480
*/
7581
TYPE Type IS ENUM
7682
bool
77-
ieee32
78-
ieee64
83+
ieee32BE
84+
ieee32LE
85+
ieee64BE
86+
ieee64LE
7987
int8
8088
int16BE
8189
int16LE
@@ -129,9 +137,13 @@ FUNCTION field(name: String, type: Type, width: Number DEFAULT 0): Field
129137
CASE type
130138
WHEN Type.bool DO
131139
w := 1
132-
WHEN Type.ieee32 DO
140+
WHEN Type.ieee32BE DO
133141
w := 4
134-
WHEN Type.ieee64 DO
142+
WHEN Type.ieee32LE DO
143+
w := 4
144+
WHEN Type.ieee64BE DO
145+
w := 8
146+
WHEN Type.ieee64LE DO
135147
w := 8
136148
WHEN Type.int8 DO
137149
w := 1
@@ -175,17 +187,29 @@ FUNCTION packBool(b: Boolean): Bytes
175187
RETURN (IF b THEN HEXBYTES "01" ELSE HEXBYTES "00")
176188
END FUNCTION
177189

178-
/* Function: packIEEE32
190+
/* Function: packIEEE32BE
191+
*
192+
* Pack a <Number> value into a <Bytes> in IEEE 754 binary32 floating point format.
193+
*/
194+
DECLARE NATIVE FUNCTION packIEEE32BE(n: Number): Bytes
195+
196+
/* Function: packIEEE32LE
179197
*
180198
* Pack a <Number> value into a <Bytes> in IEEE 754 binary32 floating point format.
181199
*/
182-
DECLARE NATIVE FUNCTION packIEEE32(n: Number): Bytes
200+
DECLARE NATIVE FUNCTION packIEEE32LE(n: Number): Bytes
183201

184-
/* Function: packIEEE64
202+
/* Function: packIEEE64BE
185203
*
186204
* Pack a <Number> value into a <Bytes> in IEEE 754 binary64 floating point format.
187205
*/
188-
DECLARE NATIVE FUNCTION packIEEE64(n: Number): Bytes
206+
DECLARE NATIVE FUNCTION packIEEE64BE(n: Number): Bytes
207+
208+
/* Function: packIEEE64LE
209+
*
210+
* Pack a <Number> value into a <Bytes> in IEEE 754 binary64 floating point format.
211+
*/
212+
DECLARE NATIVE FUNCTION packIEEE64LE(n: Number): Bytes
189213

190214
/* Function: packInt8
191215
*
@@ -389,17 +413,29 @@ FUNCTION unpackBool(b: Bytes): Boolean
389413
RETURN a[0] <> 0
390414
END FUNCTION
391415

392-
/* Function: unpackIEEE32
416+
/* Function: unpackIEEE32BE
417+
*
418+
* Unpack a <Number> from a <Bytes> in IEEE 754 binary32 floating point format.
419+
*/
420+
DECLARE NATIVE FUNCTION unpackIEEE32BE(b: Bytes): Number
421+
422+
/* Function: unpackIEEE32LE
393423
*
394424
* Unpack a <Number> from a <Bytes> in IEEE 754 binary32 floating point format.
395425
*/
396-
DECLARE NATIVE FUNCTION unpackIEEE32(b: Bytes): Number
426+
DECLARE NATIVE FUNCTION unpackIEEE32LE(b: Bytes): Number
427+
428+
/* Function: unpackIEEE64BE
429+
*
430+
* Unpack a <Number> from a <Bytes> in IEEE 754 binary64 floating point format.
431+
*/
432+
DECLARE NATIVE FUNCTION unpackIEEE64BE(b: Bytes): Number
397433

398-
/* Function: unpackIEEE64
434+
/* Function: unpackIEEE64LE
399435
*
400436
* Unpack a <Number> from a <Bytes> in IEEE 754 binary64 floating point format.
401437
*/
402-
DECLARE NATIVE FUNCTION unpackIEEE64(b: Bytes): Number
438+
DECLARE NATIVE FUNCTION unpackIEEE64LE(b: Bytes): Number
403439

404440
/* Function: unpackInt8
405441
*
@@ -610,10 +646,14 @@ FUNCTION Struct.pack(self: Struct, values: Dictionary<Object>): Bytes
610646
CASE self.fields[f].type
611647
WHEN Type.bool DO
612648
buf.extend(packBool(v).toArray())
613-
WHEN Type.ieee32 DO
614-
buf.extend(packIEEE32(v).toArray())
615-
WHEN Type.ieee64 DO
616-
buf.extend(packIEEE64(v).toArray())
649+
WHEN Type.ieee32BE DO
650+
buf.extend(packIEEE32BE(v).toArray())
651+
WHEN Type.ieee32LE DO
652+
buf.extend(packIEEE32LE(v).toArray())
653+
WHEN Type.ieee64BE DO
654+
buf.extend(packIEEE64BE(v).toArray())
655+
WHEN Type.ieee64LE DO
656+
buf.extend(packIEEE64LE(v).toArray())
617657
WHEN Type.int8 DO
618658
buf.extend(packInt8(v).toArray())
619659
WHEN Type.int16BE DO
@@ -687,11 +727,17 @@ FUNCTION Struct.unpack(self: Struct, data: Bytes): Dictionary<Object>
687727
WHEN Type.bool DO
688728
v := unpackBool(data[i TO i])
689729
INC i
690-
WHEN Type.ieee32 DO
691-
v := unpackIEEE32(data[i TO i+3])
730+
WHEN Type.ieee32BE DO
731+
v := unpackIEEE32BE(data[i TO i+3])
692732
i := i + 4
693-
WHEN Type.ieee64 DO
694-
v := unpackIEEE64(data[i TO i+7])
733+
WHEN Type.ieee32LE DO
734+
v := unpackIEEE32LE(data[i TO i+3])
735+
i := i + 4
736+
WHEN Type.ieee64BE DO
737+
v := unpackIEEE64BE(data[i TO i+7])
738+
i := i + 8
739+
WHEN Type.ieee64LE DO
740+
v := unpackIEEE64LE(data[i TO i+7])
695741
i := i + 8
696742
WHEN Type.int8 DO
697743
v := unpackInt8(data[i TO i])
@@ -758,13 +804,21 @@ BEGIN MAIN
758804
TESTCASE packBool(FALSE) = HEXBYTES "00"
759805
TESTCASE packBool(TRUE) = HEXBYTES "01"
760806

761-
TESTCASE packIEEE32(0) = HEXBYTES "00 00 00 00"
762-
TESTCASE packIEEE32(1) = HEXBYTES "00 00 80 3f"
763-
TESTCASE packIEEE32(1e10) = HEXBYTES "f9 02 15 50"
807+
TESTCASE packIEEE32BE(0) = HEXBYTES "00 00 00 00"
808+
TESTCASE packIEEE32BE(1) = HEXBYTES "3f 80 00 00"
809+
TESTCASE packIEEE32BE(1e10) = HEXBYTES "50 15 02 f9"
810+
811+
TESTCASE packIEEE32LE(0) = HEXBYTES "00 00 00 00"
812+
TESTCASE packIEEE32LE(1) = HEXBYTES "00 00 80 3f"
813+
TESTCASE packIEEE32LE(1e10) = HEXBYTES "f9 02 15 50"
764814

765-
TESTCASE packIEEE64(0) = HEXBYTES "00 00 00 00 00 00 00 00"
766-
TESTCASE packIEEE64(1) = HEXBYTES "00 00 00 00 00 00 f0 3f"
767-
TESTCASE packIEEE64(1e100) = HEXBYTES "7d c3 94 25 ad 49 b2 54"
815+
TESTCASE packIEEE64BE(0) = HEXBYTES "00 00 00 00 00 00 00 00"
816+
TESTCASE packIEEE64BE(1) = HEXBYTES "3f f0 00 00 00 00 00 00"
817+
TESTCASE packIEEE64BE(1e100) = HEXBYTES "54 b2 49 ad 25 94 c3 7d"
818+
819+
TESTCASE packIEEE64LE(0) = HEXBYTES "00 00 00 00 00 00 00 00"
820+
TESTCASE packIEEE64LE(1) = HEXBYTES "00 00 00 00 00 00 f0 3f"
821+
TESTCASE packIEEE64LE(1e100) = HEXBYTES "7d c3 94 25 ad 49 b2 54"
768822

769823
TESTCASE packInt8(-128) = HEXBYTES "80"
770824
TESTCASE packInt8(-1) = HEXBYTES "FF"
@@ -846,13 +900,21 @@ BEGIN MAIN
846900
TESTCASE unpackBool(HEXBYTES "00") = FALSE
847901
TESTCASE unpackBool(HEXBYTES "01") = TRUE
848902

849-
TESTCASE unpackIEEE32(HEXBYTES "00 00 00 00") = 0
850-
TESTCASE unpackIEEE32(HEXBYTES "00 00 80 3f") = 1
851-
TESTCASE unpackIEEE32(HEXBYTES "f9 02 15 50") = 1e10
903+
TESTCASE unpackIEEE32BE(HEXBYTES "00 00 00 00") = 0
904+
TESTCASE unpackIEEE32BE(HEXBYTES "3f 80 00 00") = 1
905+
TESTCASE unpackIEEE32BE(HEXBYTES "50 15 02 f9") = 1e10
906+
907+
TESTCASE unpackIEEE32LE(HEXBYTES "00 00 00 00") = 0
908+
TESTCASE unpackIEEE32LE(HEXBYTES "00 00 80 3f") = 1
909+
TESTCASE unpackIEEE32LE(HEXBYTES "f9 02 15 50") = 1e10
910+
911+
TESTCASE unpackIEEE64BE(HEXBYTES "00 00 00 00 00 00 00 00") = 0
912+
TESTCASE unpackIEEE64BE(HEXBYTES "3f f0 00 00 00 00 00 00") = 1
913+
TESTCASE unpackIEEE64BE(HEXBYTES "54 b2 49 ad 25 94 c3 7d") = 1.000000000000000015902891109759918e100
852914

853-
TESTCASE unpackIEEE64(HEXBYTES "00 00 00 00 00 00 00 00") = 0
854-
TESTCASE unpackIEEE64(HEXBYTES "00 00 00 00 00 00 f0 3f") = 1
855-
TESTCASE unpackIEEE64(HEXBYTES "7d c3 94 25 ad 49 b2 54") = 1.000000000000000015902891109759918e100
915+
TESTCASE unpackIEEE64LE(HEXBYTES "00 00 00 00 00 00 00 00") = 0
916+
TESTCASE unpackIEEE64LE(HEXBYTES "00 00 00 00 00 00 f0 3f") = 1
917+
TESTCASE unpackIEEE64LE(HEXBYTES "7d c3 94 25 ad 49 b2 54") = 1.000000000000000015902891109759918e100
856918

857919
TESTCASE unpackInt8(HEXBYTES "80") = -128
858920
TESTCASE unpackInt8(HEXBYTES "FF") = -1

t/struct-test.neon

+1-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ IMPORT struct
22
VAR s: struct.Struct := struct.make([
33
struct.field("field1", struct.Type.int32BE),
44
struct.field("field2", struct.Type.string, 20),
5-
struct.field("field3", struct.Type.ieee64),
5+
struct.field("field3", struct.Type.ieee64LE),
66
])
77

88
print("\(s.sizeof())")

0 commit comments

Comments
 (0)