Skip to content

Commit 9e3a789

Browse files
committed
Merge pull request #29 from WebAssembly/float32
Implement accurate float32 semantics
2 parents 200d5d9 + 56f8f56 commit 9e3a789

File tree

6 files changed

+81
-13
lines changed

6 files changed

+81
-13
lines changed

ml-proto/src/arithmetic.ml

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,7 @@ struct
8080
let of_big_int_u = of_big_int_u_for size Big_int.int64_of_big_int
8181
end
8282

83-
module IntOp (IntOpSyntax : module type of Ast.IntOp ()) (Int : INT) =
83+
module IntOp (IntOpSyntax : module type of Ast.IntOp()) (Int : INT) =
8484
struct
8585
open IntOpSyntax
8686
open Big_int
@@ -133,13 +133,14 @@ struct
133133
| ToInt32U -> fun i -> Int32 (Int32X.of_big_int_u (Int.to_big_int_u i))
134134
| ToInt64S -> fun i -> Int64 (Int.to_int64 i)
135135
| ToInt64U -> fun i -> Int64 (Int64X.of_big_int_u (Int.to_big_int_u i))
136-
| ToFloat32S -> fun i -> Float32 (Int.to_float i)
137-
| ToFloat32U -> fun i -> Float32 (float_of_big_int (Int.to_big_int_u i))
136+
| ToFloat32S -> fun i -> Float32 (float32 (Int.to_float i))
137+
| ToFloat32U -> fun i ->
138+
Float32 (float32 (float_of_big_int (Int.to_big_int_u i)))
138139
| ToFloat64S -> fun i -> Float64 (Int.to_float i)
139140
| ToFloat64U -> fun i -> Float64 (float_of_big_int (Int.to_big_int_u i))
140141
| ToFloatCast -> fun i ->
141142
if Int.size = 32
142-
then Float32 (Int.float_of_bits i)
143+
then Float32 (float32 (Int.float_of_bits i))
143144
else Float64 (Int.float_of_bits i)
144145
in fun v -> f (Int.of_value 1 v)
145146
end
@@ -160,7 +161,7 @@ end
160161
module Float32X =
161162
struct
162163
let size = 32
163-
let to_value z = Float32 z
164+
let to_value z = Float32 (float32 z)
164165
let of_value n =
165166
function Float32 z -> z | v -> raise (TypeError (n, v, Float32Type))
166167
end
@@ -173,8 +174,7 @@ struct
173174
function Float64 z -> z | v -> raise (TypeError (n, v, Float64Type))
174175
end
175176

176-
module FloatOp (FloatOpSyntax : module type of Ast.FloatOp ())
177-
(Float : FLOAT) =
177+
module FloatOp (FloatOpSyntax : module type of Ast.FloatOp()) (Float : FLOAT) =
178178
struct
179179
open FloatOpSyntax
180180

@@ -194,7 +194,6 @@ struct
194194
| Sub -> (-.)
195195
| Mul -> ( *.)
196196
| Div -> (/.)
197-
| Mod -> mod_float
198197
| CopySign -> copysign
199198
in
200199
fun v1 v2 -> Float.to_value (f (Float.of_value 1 v1) (Float.of_value 2 v2))
@@ -227,7 +226,7 @@ struct
227226
if x < limit then Int64.of_float x else
228227
Int64.add (Int64.of_float (x -. limit +. 1.0)) Int64.max_int
229228
in Int64 i
230-
| ToFloat32 -> fun x -> Float32 x
229+
| ToFloat32 -> fun x -> Float32 (float32 x)
231230
| ToFloat64 -> fun x -> Float64 x
232231
| ToIntCast -> fun x ->
233232
if Float.size = 32

ml-proto/src/ast.ml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ end
4444
module FloatOp () =
4545
struct
4646
type unop = Neg | Abs | Ceil | Floor | Trunc | Round
47-
type binop = Add | Sub | Mul | Div | Mod | CopySign
47+
type binop = Add | Sub | Mul | Div | CopySign
4848
type relop = Eq | Neq | Lt | Le | Gt | Ge
4949
type cvt = ToInt32S | ToInt32U | ToInt64S | ToInt64U | ToIntCast
5050
| ToFloat32 | ToFloat64

ml-proto/src/lexer.mll

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -104,7 +104,7 @@ let character = [^'"''\\''\n'] | '\\'escape | '\\'hexdigit hexdigit
104104

105105
let num = ('+' | '-')? digit+
106106
let int = num
107-
let float = (num '.' digit+) | num ('e' | 'E') num
107+
let float = (num '.' digit+) | num ('.' digit+)? ('e' | 'E') num
108108
let text = '"' character* '"'
109109
let name = '$' (letter | digit | '_' | tick | symbol)+
110110

@@ -189,7 +189,6 @@ rule token = parse
189189
| "sub."(fxx as t) { BINARY (floatop t F32.Sub F64.Sub) }
190190
| "mul."(fxx as t) { BINARY (floatop t F32.Mul F64.Mul) }
191191
| "div."(fxx as t) { BINARY (floatop t F32.Div F64.Div) }
192-
| "mod."(fxx as t) { BINARY (floatop t F32.Mod F64.Mod) }
193192
| "copysign."(fxx as t) { BINARY (floatop t F32.CopySign F64.CopySign) }
194193

195194
| "eq."(ixx as t) { COMPARE (intop t I32.Eq I64.Eq) }

ml-proto/src/parser.mly

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,8 @@ let literal at s t =
3636
match t with
3737
| Types.Int32Type -> Values.Int32 (Int32.of_string s) @@ at
3838
| Types.Int64Type -> Values.Int64 (Int64.of_string s) @@ at
39-
| Types.Float32Type -> Values.Float32 (float_of_string s) @@ at
39+
| Types.Float32Type ->
40+
Values.Float32 (Values.float32 (float_of_string s)) @@ at
4041
| Types.Float64Type -> Values.Float64 (float_of_string s) @@ at
4142
with _ -> Error.error at "constant out of range"
4243

ml-proto/src/values.ml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,3 +38,8 @@ let string_of_value = function
3838
let string_of_values = function
3939
| [v] -> string_of_value v
4040
| vs -> "(" ^ String.concat " " (List.map string_of_value vs) ^ ")"
41+
42+
43+
(* Float32 truncation *)
44+
45+
let float32 x = Int32.float_of_bits (Int32.bits_of_float x)

ml-proto/test/float32.wasm

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
(module
2+
(func $eq_float32 (param $x f32) (param $y f32) (result i32)
3+
(eq.f32 (getlocal $x) (getlocal $y))
4+
)
5+
6+
(func $eq_float64 (param $x f64) (param $y f64) (result i32)
7+
(eq.f64 (getlocal $x) (getlocal $y))
8+
)
9+
10+
(func $div_float32 (param $x f32) (param $y f32) (result f32)
11+
(div.f32 (getlocal $x) (getlocal $y))
12+
)
13+
14+
(func $div_float64 (param $x f64) (param $y f64) (result f64)
15+
(div.f64 (getlocal $x) (getlocal $y))
16+
)
17+
18+
(export "eq_float32" $eq_float32)
19+
(export "eq_float64" $eq_float64)
20+
(export "div_float32" $div_float32)
21+
(export "div_float64" $div_float64)
22+
)
23+
24+
(asserteq
25+
(invoke "eq_float32"
26+
(add.f32 (const.f32 1.1234567890) (const.f32 1.2345e-10))
27+
(const.f32 1.123456789)
28+
)
29+
(const.i32 1)
30+
)
31+
32+
(asserteq
33+
(invoke "eq_float64"
34+
(add.f64 (const.f64 1.1234567890) (const.f64 1.2345e-10))
35+
(const.f64 1.123456789)
36+
)
37+
(const.i32 0)
38+
)
39+
40+
(asserteq
41+
(invoke "eq_float32"
42+
(mul.f32 (const.f32 1e20) (const.f32 1e20))
43+
(mul.f32 (const.f32 1e25) (const.f32 1e25))
44+
)
45+
(const.i32 1)
46+
)
47+
48+
(asserteq
49+
(invoke "eq_float64"
50+
(mul.f64 (const.f64 1e20) (const.f64 1e20))
51+
(mul.f64 (const.f64 1e25) (const.f64 1e25))
52+
)
53+
(const.i32 0)
54+
)
55+
56+
(asserteq
57+
(invoke "div_float32" (const.f32 1.123456789) (const.f32 100))
58+
(const.f32 0.011234568432)
59+
)
60+
61+
(asserteq
62+
(invoke "div_float64" (const.f64 1.123456789) (const.f64 100))
63+
(const.f64 0.01123456789)
64+
)

0 commit comments

Comments
 (0)