Skip to content

Commit e3a4eac

Browse files
authored
feat(stdlib): Implement reinterpret between float and int values (#2257)
1 parent d95f61c commit e3a4eac

File tree

20 files changed

+569
-20
lines changed

20 files changed

+569
-20
lines changed

compiler/test/stdlib/float32.test.gr

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,18 @@ assert fromNumber(0) == 0.0f
2626
assert toNumber(555.0f) == 555
2727
assert toNumber(0.0f) == 0
2828

29+
// Float32.reinterpretInt32
30+
assert Float32.reinterpretInt32(0l) == 0.0f
31+
assert Float32.reinterpretInt32(1065353216l) == 1.0f
32+
assert Float32.reinterpretInt32(-1082130432l) == -1.0f
33+
assert Float32.reinterpretInt32(1109917696l) == 42.0f
34+
35+
// Float32.reinterpretUint32
36+
assert Float32.reinterpretUint32(0ul) == 0.0f
37+
assert Float32.reinterpretUint32(1065353216ul) == 1.0f
38+
assert Float32.reinterpretUint32(3212836864ul) == -1.0f
39+
assert Float32.reinterpretUint32(1109917696ul) == 42.0f
40+
2941
// Float32.pow tests are based on test cases from libc-test: http://nsz.repo.hu/git/?p=libc-test
3042
/*
3143
libc-test is licensed under the following standard MIT license:

compiler/test/stdlib/float64.test.gr

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,17 @@ assert fromNumber(-1.7976931348623157e+309) == -Infinityd
3838
assert toNumber(555.0d) == 555
3939
assert toNumber(0.0d) == 0
4040

41+
// Float64.reinterpretInt64
42+
assert Float64.reinterpretInt64(0L) == 0.0d
43+
assert Float64.reinterpretInt64(4607182418800017408L) == 1.0d
44+
assert Float64.reinterpretInt64(-4616189618054758400L) == -1.0d
45+
assert Float64.reinterpretInt64(4631107791820423168L) == 42.0d
46+
// Float64.reinterpretUint64
47+
assert Float64.reinterpretUint64(0uL) == 0.0d
48+
assert Float64.reinterpretUint64(4607182418800017408uL) == 1.0d
49+
assert Float64.reinterpretUint64(13830554455654793216uL) == -1.0d
50+
assert Float64.reinterpretUint64(4631107791820423168uL) == 42.0d
51+
4152
// Float64.pow tests are based on test cases from libc-test: http://nsz.repo.hu/git/?p=libc-test
4253
/*
4354
libc-test is licensed under the following standard MIT license:

compiler/test/stdlib/int32.test.gr

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,13 @@ assert fromUint32(0xfffffffful) == -1l
1919

2020
use Int32.{ (==) }
2121

22+
// Int32.reinterpretFloat32
23+
assert Int32.reinterpretFloat32(0.0f) == 0l
24+
assert Int32.reinterpretFloat32(1.0f) == 1065353216l
25+
assert Int32.reinterpretFloat32(-1.0f) == -1082130432l
26+
assert Int32.reinterpretFloat32(42.0f) == 1109917696l
27+
assert Int32.reinterpretFloat32(0.5f) == 1056964608l
28+
2229
assert lnot(0xffffffffl) == 0l
2330
assert lnot(0l) == 0xffffffffl
2431
assert lnot(0xf0f0f0f0l) == 0x0f0f0f0fl

compiler/test/stdlib/int64.test.gr

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,13 @@ use Int64.{ (==) }
1717
assert fromUint64(1uL) == 1L
1818
assert fromUint64(0xffffffffffffffffuL) == -1L
1919

20+
// Int64.reinterpretFloat64
21+
assert Int64.reinterpretFloat64(0.0d) == 0L
22+
assert Int64.reinterpretFloat64(1.0d) == 4607182418800017408L
23+
assert Int64.reinterpretFloat64(-1.0d) == -4616189618054758400L
24+
assert Int64.reinterpretFloat64(42.0d) == 4631107791820423168L
25+
assert Int64.reinterpretFloat64(0.5d) == 4602678819172646912L
26+
2027
assert lnot(0xffffffffffffffffL) == 0L
2128
assert lnot(0L) == 0xffffffffffffffffL
2229
assert lnot(0xf0f0f0f0f0f0f0f0L) == 0x0f0f0f0f0f0f0f0fL

compiler/test/stdlib/uint32.test.gr

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,13 @@ assert toNumber(0x7ffffffful) == 0x7fffffff
3636
assert fromInt32(1l) == 1ul
3737
assert fromInt32(-1l) == 0xfffffffful
3838

39+
// UInt32.reinterpretFloat32
40+
assert Uint32.reinterpretFloat32(0.0f) == 0ul
41+
assert Uint32.reinterpretFloat32(1.0f) == 1065353216ul
42+
assert Uint32.reinterpretFloat32(-1.0f) == 3212836864ul
43+
assert Uint32.reinterpretFloat32(42.0f) == 1109917696ul
44+
assert Uint32.reinterpretFloat32(0.5f) == 1056964608ul
45+
3946
assert lnot(0xfffffffful) == 0ul
4047
assert lnot(0ul) == 0xfffffffful
4148
assert lnot(0xf0f0f0f0ul) == 0x0f0f0f0ful

compiler/test/stdlib/uint64.test.gr

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,13 @@ assert toNumber(0x7fffffffuL) == 0x7fffffff
3838
assert fromInt64(1L) == 1uL
3939
assert fromInt64(-1L) == 0xffffffffffffffffuL
4040

41+
// UInt64.reinterpretFloat64
42+
assert Uint64.reinterpretFloat64(0.0d) == 0uL
43+
assert Uint64.reinterpretFloat64(1.0d) == 4607182418800017408uL
44+
assert Uint64.reinterpretFloat64(-1.0d) == 13830554455654793216uL
45+
assert Uint64.reinterpretFloat64(42.0d) == 4631107791820423168uL
46+
assert Uint64.reinterpretFloat64(0.5d) == 4602678819172646912uL
47+
4148
assert lnot(0xffffffffffffffffuL) == 0uL
4249
assert lnot(0uL) == 0xffffffffffffffffuL
4350
assert lnot(0xf0f0f0f0f0f0f0f0uL) == 0x0f0f0f0f0f0f0f0fuL

stdlib/float32.gr

Lines changed: 41 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,12 @@
1212
*/
1313
module Float32
1414

15+
from "runtime/unsafe/offsets" include Offsets
16+
use Offsets.{
17+
_FLOAT32_VALUE_OFFSET as _VALUE_OFFSET,
18+
_INT32_VALUE_OFFSET,
19+
_UINT32_VALUE_OFFSET,
20+
}
1521
from "runtime/unsafe/wasmi32" include WasmI32
1622
from "runtime/unsafe/wasmf32" include WasmF32
1723
from "runtime/unsafe/wasmf64" include WasmF64
@@ -27,9 +33,6 @@ use Numbers.{
2733
from "runtime/math/trig" include Trig
2834
use Trig.{ sin, cos, tan }
2935

30-
@unsafe
31-
let _VALUE_OFFSET = 4n
32-
3336
/**
3437
* Infinity represented as a Float32 value.
3538
* This is an alternative to the `Infinityf` literal.
@@ -71,6 +74,41 @@ provide let e = 2.7182817f
7174

7275
provide { fromNumber, toNumber }
7376

77+
/**
78+
* Interprets an Int32 as a Float32.
79+
*
80+
* @param value: The value to convert
81+
* @returns The Int32 interpreted as an Float32
82+
*
83+
* @example assert Float32.reinterpretInt32(1065353216l) == 1.0f
84+
* @example assert Float32.reinterpretInt32(-1082130432l) == -1.0f
85+
* @since v0.7.0
86+
*/
87+
@unsafe
88+
provide let reinterpretInt32 = (value: Int32) => {
89+
let x = WasmF32.load(WasmI32.fromGrain(value), _INT32_VALUE_OFFSET)
90+
let result = newFloat32(x)
91+
WasmI32.toGrain(result): Float32
92+
}
93+
94+
/**
95+
* Interprets an Uint32 as a Float32.
96+
*
97+
* @param value: The value to convert
98+
* @returns The Uint32 interpreted as an Float32
99+
*
100+
* @example assert Float32.reinterpretUint32(1065353216ul) == 1.0f
101+
* @example assert Float32.reinterpretUint32(3212836864ul) == -1.0f
102+
*
103+
* @since v0.7.0
104+
*/
105+
@unsafe
106+
provide let reinterpretUint32 = (value: Uint32) => {
107+
let x = WasmF32.load(WasmI32.fromGrain(value), _UINT32_VALUE_OFFSET)
108+
let result = newFloat32(x)
109+
WasmI32.toGrain(result): Float32
110+
}
111+
74112
/**
75113
* Computes the sum of its operands.
76114
*

stdlib/float32.md

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -150,6 +150,76 @@ Returns:
150150
|----|-----------|
151151
|`Number`|The Float32 represented as a Number|
152152

153+
### Float32.**reinterpretInt32**
154+
155+
<details disabled>
156+
<summary tabindex="-1">Added in <code>next</code></summary>
157+
No other changes yet.
158+
</details>
159+
160+
```grain
161+
reinterpretInt32 : (value: Int32) => Float32
162+
```
163+
164+
Interprets an Int32 as a Float32.
165+
166+
Parameters:
167+
168+
|param|type|description|
169+
|-----|----|-----------|
170+
|`value`|`Int32`|The value to convert|
171+
172+
Returns:
173+
174+
|type|description|
175+
|----|-----------|
176+
|`Float32`|The Int32 interpreted as an Float32|
177+
178+
Examples:
179+
180+
```grain
181+
assert Float32.reinterpretInt32(1065353216l) == 1.0f
182+
```
183+
184+
```grain
185+
assert Float32.reinterpretInt32(-1082130432l) == -1.0f
186+
```
187+
188+
### Float32.**reinterpretUint32**
189+
190+
<details disabled>
191+
<summary tabindex="-1">Added in <code>next</code></summary>
192+
No other changes yet.
193+
</details>
194+
195+
```grain
196+
reinterpretUint32 : (value: Uint32) => Float32
197+
```
198+
199+
Interprets an Uint32 as a Float32.
200+
201+
Parameters:
202+
203+
|param|type|description|
204+
|-----|----|-----------|
205+
|`value`|`Uint32`|The value to convert|
206+
207+
Returns:
208+
209+
|type|description|
210+
|----|-----------|
211+
|`Float32`|The Uint32 interpreted as an Float32|
212+
213+
Examples:
214+
215+
```grain
216+
assert Float32.reinterpretUint32(1065353216ul) == 1.0f
217+
```
218+
219+
```grain
220+
assert Float32.reinterpretUint32(3212836864ul) == -1.0f
221+
```
222+
153223
### Float32.**(+)**
154224

155225
<details>

stdlib/float64.gr

Lines changed: 42 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,12 @@
1212
*/
1313
module Float64
1414

15+
from "runtime/unsafe/offsets" include Offsets
16+
use Offsets.{
17+
_FLOAT64_VALUE_OFFSET as _VALUE_OFFSET,
18+
_INT64_VALUE_OFFSET,
19+
_UINT64_VALUE_OFFSET,
20+
}
1521
from "runtime/unsafe/wasmi32" include WasmI32
1622
from "runtime/unsafe/wasmf64" include WasmF64
1723
use WasmF64.{ (-), (+), (*), (/), (<), (<=), (>), (>=) }
@@ -26,9 +32,6 @@ use Numbers.{
2632
from "runtime/math/trig" include Trig
2733
use Trig.{ sin, cos, tan }
2834

29-
@unsafe
30-
let _VALUE_OFFSET = 8n
31-
3235
/**
3336
* Infinity represented as a Float64 value.
3437
* This is an alternative to the `Infinityd` literal.
@@ -70,6 +73,42 @@ provide let e = 2.718281828459045d
7073

7174
provide { fromNumber, toNumber }
7275

76+
/**
77+
* Interprets an Int64 as a Float64.
78+
*
79+
* @param value: The value to convert
80+
* @returns The Int64 interpreted as an Float64
81+
*
82+
* @example assert Float64.reinterpretInt64(4607182418800017408L) == 1.0d
83+
* @example assert Float64.reinterpretInt64(-4616189618054758400L) == -1.0d
84+
*
85+
* @since v0.7.0
86+
*/
87+
@unsafe
88+
provide let reinterpretInt64 = (value: Int64) => {
89+
let x = WasmF64.load(WasmI32.fromGrain(value), _INT64_VALUE_OFFSET)
90+
let result = newFloat64(x)
91+
WasmI32.toGrain(result): Float64
92+
}
93+
94+
/**
95+
* Interprets an Uint64 as a Float64.
96+
*
97+
* @param value: The value to convert
98+
* @returns The Uint64 interpreted as an Float64
99+
*
100+
* @example assert Float64.reinterpretUint64(4607182418800017408uL) == 1.0d
101+
* @example assert Float64.reinterpretUint64(13830554455654793216uL) == -1.0d
102+
*
103+
* @since v0.7.0
104+
*/
105+
@unsafe
106+
provide let reinterpretUint64 = (value: Uint64) => {
107+
let x = WasmF64.load(WasmI32.fromGrain(value), _UINT64_VALUE_OFFSET)
108+
let result = newFloat64(x)
109+
WasmI32.toGrain(result): Float64
110+
}
111+
73112
/**
74113
* Computes the sum of its operands.
75114
*

stdlib/float64.md

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -150,6 +150,76 @@ Returns:
150150
|----|-----------|
151151
|`Number`|The Float64 represented as a Number|
152152

153+
### Float64.**reinterpretInt64**
154+
155+
<details disabled>
156+
<summary tabindex="-1">Added in <code>next</code></summary>
157+
No other changes yet.
158+
</details>
159+
160+
```grain
161+
reinterpretInt64 : (value: Int64) => Float64
162+
```
163+
164+
Interprets an Int64 as a Float64.
165+
166+
Parameters:
167+
168+
|param|type|description|
169+
|-----|----|-----------|
170+
|`value`|`Int64`|The value to convert|
171+
172+
Returns:
173+
174+
|type|description|
175+
|----|-----------|
176+
|`Float64`|The Int64 interpreted as an Float64|
177+
178+
Examples:
179+
180+
```grain
181+
assert Float64.reinterpretInt64(4607182418800017408L) == 1.0d
182+
```
183+
184+
```grain
185+
assert Float64.reinterpretInt64(-4616189618054758400L) == -1.0d
186+
```
187+
188+
### Float64.**reinterpretUint64**
189+
190+
<details disabled>
191+
<summary tabindex="-1">Added in <code>next</code></summary>
192+
No other changes yet.
193+
</details>
194+
195+
```grain
196+
reinterpretUint64 : (value: Uint64) => Float64
197+
```
198+
199+
Interprets an Uint64 as a Float64.
200+
201+
Parameters:
202+
203+
|param|type|description|
204+
|-----|----|-----------|
205+
|`value`|`Uint64`|The value to convert|
206+
207+
Returns:
208+
209+
|type|description|
210+
|----|-----------|
211+
|`Float64`|The Uint64 interpreted as an Float64|
212+
213+
Examples:
214+
215+
```grain
216+
assert Float64.reinterpretUint64(4607182418800017408uL) == 1.0d
217+
```
218+
219+
```grain
220+
assert Float64.reinterpretUint64(13830554455654793216uL) == -1.0d
221+
```
222+
153223
### Float64.**(+)**
154224

155225
<details>

0 commit comments

Comments
 (0)