44#include <stdio.h>
55#include <wasm_simd128.h>
66
7+ // SIMD True/False lane values.
8+ #define TRUE 0xFFFF
9+ #define FALSE 0
10+
711// Not used below, but helpful for debugging.
812void print_f16x8 (v128_t v1 ) {
913 printf ("[%g, %g, %g, %g, %g, %g, %g, %g]\n" ,
@@ -45,24 +49,51 @@ void assert_lanes_eq_float(v128_t v,
4549 float l5 ,
4650 float l6 ,
4751 float l7 ) {
48- assert (wasm_f16x8_extract_lane (v , 0 ) == l0 );
49- assert (wasm_f16x8_extract_lane (v , 1 ) == l1 );
50- assert (wasm_f16x8_extract_lane (v , 2 ) == l2 );
51- assert (wasm_f16x8_extract_lane (v , 3 ) == l3 );
52- assert (wasm_f16x8_extract_lane (v , 4 ) == l4 );
53- assert (wasm_f16x8_extract_lane (v , 5 ) == l5 );
54- assert (wasm_f16x8_extract_lane (v , 6 ) == l6 );
55- assert (wasm_f16x8_extract_lane (v , 7 ) == l7 );
52+ // We can't do a direct comparision since there may be quiet or signaling nan
53+ // values, so if the expected value is nan check that the actual value is nan
54+ // too.
55+ float actual ;
56+ actual = wasm_f16x8_extract_lane (v , 0 );
57+ assert (isnan (l0 ) ? isnan (actual ) : actual == l0 );
58+ actual = wasm_f16x8_extract_lane (v , 1 );
59+ assert (isnan (l1 ) ? isnan (actual ) : actual == l1 );
60+ actual = wasm_f16x8_extract_lane (v , 2 );
61+ assert (isnan (l2 ) ? isnan (actual ) : actual == l2 );
62+ actual = wasm_f16x8_extract_lane (v , 3 );
63+ assert (isnan (l3 ) ? isnan (actual ) : actual == l3 );
64+ actual = wasm_f16x8_extract_lane (v , 4 );
65+ assert (isnan (l4 ) ? isnan (actual ) : actual == l4 );
66+ actual = wasm_f16x8_extract_lane (v , 5 );
67+ assert (isnan (l5 ) ? isnan (actual ) : actual == l5 );
68+ actual = wasm_f16x8_extract_lane (v , 6 );
69+ assert (isnan (l6 ) ? isnan (actual ) : actual == l6 );
70+ actual = wasm_f16x8_extract_lane (v , 7 );
71+ assert (isnan (l7 ) ? isnan (actual ) : actual == l7 );
5672}
5773
5874void assert_all_lanes_eq (v128_t v , float value ) {
5975 assert_lanes_eq_float (
6076 v , value , value , value , value , value , value , value , value );
6177}
6278
63- void assert_all_lanes_eq_uint16 (v128_t v , uint16_t value ) {
64- assert_lanes_eq_uint16 (
65- v , value , value , value , value , value , value , value , value );
79+ v128_t create_f16x8 (float l0 ,
80+ float l1 ,
81+ float l2 ,
82+ float l3 ,
83+ float l4 ,
84+ float l5 ,
85+ float l6 ,
86+ float l7 ) {
87+ v128_t v ;
88+ v = wasm_f16x8_replace_lane (v , 0 , l0 );
89+ v = wasm_f16x8_replace_lane (v , 1 , l1 );
90+ v = wasm_f16x8_replace_lane (v , 2 , l2 );
91+ v = wasm_f16x8_replace_lane (v , 3 , l3 );
92+ v = wasm_f16x8_replace_lane (v , 4 , l4 );
93+ v = wasm_f16x8_replace_lane (v , 5 , l5 );
94+ v = wasm_f16x8_replace_lane (v , 6 , l6 );
95+ v = wasm_f16x8_replace_lane (v , 7 , l7 );
96+ return v ;
6697}
6798
6899int main () {
@@ -75,80 +106,105 @@ int main() {
75106 a = wasm_f16x8_replace_lane (a , 7 , 99.0f );
76107 assert_lanes_eq_float (a , 99.0f , 1.0f , 1.0f , 1.0f , 1.0f , 1.0f , 1.0f , 99.0f );
77108
78- a = wasm_f16x8_abs ( wasm_f16x8_splat ( -2.0f ));
79- assert_all_lanes_eq ( a , 2.0f );
109+ // The following tests are not exhaustive, but try to hit some interesting
110+ // floats and how they interact.
80111
81- a = wasm_f16x8_neg ( wasm_f16x8_splat ( 2 .0f ));
82- assert_all_lanes_eq (a , -2 .0f );
112+ a = wasm_f16x8_abs ( create_f16x8 ( -1 .0f, 1.0f , 0.0f , -0.0f , INFINITY , - INFINITY , NAN , - NAN ));
113+ assert_lanes_eq_float (a , 1 .0f, 1.0f , 0.0f , 0.0f , INFINITY , INFINITY , NAN , NAN );
83114
84- a = wasm_f16x8_sqrt ( wasm_f16x8_splat ( 4 .0f ));
85- assert_all_lanes_eq (a , 2 .0f );
115+ a = wasm_f16x8_neg ( create_f16x8 ( -1 .0f, 1.0f , 0.0f , -0.0f , INFINITY , - INFINITY , NAN , - NAN ));
116+ assert_lanes_eq_float (a , 1 .0f, -1.0f , -0.0f , 0.0f , - INFINITY , INFINITY , NAN , NAN );
86117
87- a = wasm_f16x8_ceil ( wasm_f16x8_splat ( 1.2f ));
88- assert_all_lanes_eq (a , 2.0f );
118+ a = wasm_f16x8_sqrt ( create_f16x8 ( -1.0f , 1.0f , 0.0f , 4.0f , INFINITY , - INFINITY , NAN , - NAN ));
119+ assert_lanes_eq_float (a , NAN , 1.0f , 0.0f , 2.0f , INFINITY , NAN , NAN , NAN );
89120
90- a = wasm_f16x8_floor ( wasm_f16x8_splat ( 1.2f ));
91- assert_all_lanes_eq (a , 1.0f );
121+ a = wasm_f16x8_ceil ( create_f16x8 ( -1.0f , 1.0f , -1.2f , 1.2f , -1.7f , 1.7f , INFINITY , - INFINITY ));
122+ assert_lanes_eq_float (a , - 1.0f, 1.0f , -1.0f , 2.0f , -1.0f , 2.0f , INFINITY , - INFINITY );
92123
93- a = wasm_f16x8_trunc ( wasm_f16x8_splat ( 1.2f ));
94- assert_all_lanes_eq (a , 1.0f );
124+ a = wasm_f16x8_floor ( create_f16x8 ( -1.0f , 1.0f , -1.2f , 1.2f , -1.7f , 1.7f , INFINITY , - INFINITY ));
125+ assert_lanes_eq_float (a , - 1.0f, 1.0f , -2.0f , 1.0f , -2.0f , 1.0f , INFINITY , - INFINITY );
95126
96- a = wasm_f16x8_nearest ( wasm_f16x8_splat ( 1.5f ));
97- assert_all_lanes_eq (a , 2 .0f );
127+ a = wasm_f16x8_trunc ( create_f16x8 ( -1.0f , 1.0f , -1.2f , 1.2f , -1.7f , 1.7f , INFINITY , - INFINITY ));
128+ assert_lanes_eq_float (a , -1 .0f, 1.0f , -1.0f , 1.0f , -1.0f , 1.0f , INFINITY , - INFINITY );
98129
99- a = wasm_f16x8_eq ( wasm_f16x8_splat ( 2 .0f), wasm_f16x8_splat ( 3 .0f ));
100- assert_all_lanes_eq_uint16 (a , 0 );
130+ a = wasm_f16x8_nearest ( create_f16x8 ( -1 .0f, 1 .0f, -1.2f , 1.2f , -1.7f , 1.7f , INFINITY , - INFINITY ));
131+ assert_lanes_eq_float (a , -1.0f , 1.0f , -1.0f , 1.0f , -2.0f , 2.0f , INFINITY , - INFINITY );
101132
102- a = wasm_f16x8_ne (wasm_f16x8_splat (2.0f ), wasm_f16x8_splat (3.0f ));
103- assert_all_lanes_eq_uint16 (a , 0xFFFF );
133+ a = wasm_f16x8_eq (create_f16x8 (-1.0f , 1.0f , 1.0f , -0.0f , INFINITY , - INFINITY , NAN , - NAN ),
134+ create_f16x8 ( 1.0f , -1.0f , 1.0f , -0.0f , INFINITY , - INFINITY , NAN , - NAN ));
135+ assert_lanes_eq_uint16 (a , FALSE, FALSE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE);
104136
105- a = wasm_f16x8_lt (wasm_f16x8_splat (2.0f ), wasm_f16x8_splat (3.0f ));
106- assert_all_lanes_eq_uint16 (a , 0xFFFF );
137+ a = wasm_f16x8_ne (create_f16x8 (-1.0f , 1.0f , 1.0f , -0.0f , INFINITY , - INFINITY , NAN , - NAN ),
138+ create_f16x8 ( 1.0f , -1.0f , 1.0f , -0.0f , INFINITY , - INFINITY , NAN , - NAN ));
139+ assert_lanes_eq_uint16 (a , TRUE, TRUE, FALSE, FALSE, FALSE, FALSE, TRUE, TRUE);
107140
108- a = wasm_f16x8_gt (wasm_f16x8_splat (2.0f ), wasm_f16x8_splat (3.0f ));
109- assert_all_lanes_eq_uint16 (a , 0 );
141+ a = wasm_f16x8_lt (create_f16x8 (-1.0f , 1.0f , 1.0f , -0.0f , INFINITY , - INFINITY , NAN , - NAN ),
142+ create_f16x8 ( 1.0f , -1.0f , 1.0f , -0.0f , INFINITY , - INFINITY , NAN , - NAN ));
143+ assert_lanes_eq_uint16 (a , TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE);
110144
111- a = wasm_f16x8_le (wasm_f16x8_splat (2.0f ), wasm_f16x8_splat (3.0f ));
112- assert_all_lanes_eq_uint16 (a , 0xFFFF );
145+ a = wasm_f16x8_gt (create_f16x8 ( -1.0f , 1.0f , 1.0f , -0.0f , INFINITY , - INFINITY , NAN , - NAN ),
146+ create_f16x8 ( 1.0f , -1.0f , 1.0f , -0.0f , INFINITY , - INFINITY , NAN , - NAN ));
147+ assert_lanes_eq_uint16 (a , FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE);
113148
114- a = wasm_f16x8_ge (wasm_f16x8_splat (2.0f ), wasm_f16x8_splat (3.0f ));
115- assert_all_lanes_eq_uint16 (a , 0 );
149+ a = wasm_f16x8_le (create_f16x8 (-1.0f , 1.0f , 1.0f , -0.0f , INFINITY , - INFINITY , NAN , - NAN ),
150+ create_f16x8 ( 1.0f , -1.0f , 1.0f , -0.0f , INFINITY , - INFINITY , NAN , - NAN ));
151+ assert_lanes_eq_uint16 (a , TRUE, FALSE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE);
116152
117- a = wasm_f16x8_add (wasm_f16x8_splat (2.0f ), wasm_f16x8_splat (3.0f ));
118- assert_all_lanes_eq (a , 5.0f );
153+ a = wasm_f16x8_ge (create_f16x8 (-1.0f , 1.0f , 1.0f , -0.0f , INFINITY , - INFINITY , NAN , - NAN ),
154+ create_f16x8 ( 1.0f , -1.0f , 1.0f , -0.0f , INFINITY , - INFINITY , NAN , - NAN ));
155+ assert_lanes_eq_uint16 (a , FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE);
119156
120- a = wasm_f16x8_sub (wasm_f16x8_splat (5.0f ), wasm_f16x8_splat (3.0f ));
121- assert_all_lanes_eq (a , 2.0f );
157+ a = wasm_f16x8_add (create_f16x8 (-1.0f , 1.0f , 1.0f , 1.0f , INFINITY , INFINITY , NAN , NAN ),
158+ create_f16x8 ( 1.0f , -1.0f , 1.0f , 0.0f , 1.0f , INFINITY , 1.0f , NAN ));
159+ assert_lanes_eq_float (a , 0.0f , 0.0f , 2.0f , 1.0f , INFINITY , INFINITY , NAN , NAN );
122160
123- a = wasm_f16x8_mul (wasm_f16x8_splat (5.0f ), wasm_f16x8_splat (3.0f ));
124- assert_all_lanes_eq (a , 15.0f );
161+ a = wasm_f16x8_sub (create_f16x8 (-1.0f , 1.0f , 1.0f , 1.0f , INFINITY , INFINITY , NAN , NAN ),
162+ create_f16x8 ( 1.0f , -1.0f , 1.0f , 0.0f , 1.0f , INFINITY , 1.0f , NAN ));
163+ assert_lanes_eq_float (a , -2.0f , 2.0f , 0.0f , 1.0f , INFINITY , NAN , NAN , NAN );
125164
126- a = wasm_f16x8_div (wasm_f16x8_splat (10.0f ), wasm_f16x8_splat (5.0f ));
127- assert_all_lanes_eq (a , 2.0f );
165+ a = wasm_f16x8_mul (create_f16x8 (-1.0f , 1.0f , 1.0f , 1.0f , INFINITY , INFINITY , NAN , NAN ),
166+ create_f16x8 ( 1.0f , -1.0f , 1.0f , 0.0f , 1.0f , INFINITY , 1.0f , NAN ));
167+ assert_lanes_eq_float (a , -1.0f , -1.0f , 1.0f , 0.0f , INFINITY , INFINITY , NAN , NAN );
128168
129- a = wasm_f16x8_min (wasm_f16x8_splat (10.0f ), wasm_f16x8_splat (5.0f ));
130- assert_all_lanes_eq (a , 5.0f );
169+ a = wasm_f16x8_div (create_f16x8 (-1.0f , 1.0f , 1.0f , 1.0f , INFINITY , INFINITY , NAN , NAN ),
170+ create_f16x8 ( 1.0f , -1.0f , 1.0f , 0.0f , 1.0f , INFINITY , 1.0f , NAN ));
171+ assert_lanes_eq_float (a , -1.0f , -1.0f , 1.0f , INFINITY , INFINITY , NAN , NAN , NAN );
131172
132- a = wasm_f16x8_max (wasm_f16x8_splat (10.0f ), wasm_f16x8_splat (5.0f ));
133- assert_all_lanes_eq (a , 10.0f );
173+ a = wasm_f16x8_min (create_f16x8 (-1.0f , 1.0f , 1.0f , 1.0f , INFINITY , INFINITY , NAN , NAN ),
174+ create_f16x8 ( 1.0f , -1.0f , 1.0f , 0.0f , 1.0f , INFINITY , 1.0f , NAN ));
175+ assert_lanes_eq_float (a , -1.0f , -1.0f , 1.0f , 0.0f , 1.0f , INFINITY , NAN , NAN );
134176
135- a = wasm_f16x8_pmin (wasm_f16x8_splat (10.0f ), wasm_f16x8_splat (5.0f ));
136- assert_all_lanes_eq (a , 5.0f );
177+ a = wasm_f16x8_max (create_f16x8 (-1.0f , 1.0f , 1.0f , 1.0f , INFINITY , INFINITY , NAN , NAN ),
178+ create_f16x8 ( 1.0f , -1.0f , 1.0f , 0.0f , 1.0f , INFINITY , 1.0f , NAN ));
179+ assert_lanes_eq_float (a , 1.0f , 1.0f , 1.0f , 1.0f , INFINITY , INFINITY , NAN , NAN );
137180
138- a = wasm_f16x8_pmax (wasm_f16x8_splat (10.0f ), wasm_f16x8_splat (5.0f ));
139- assert_all_lanes_eq (a , 10.0f );
181+ a = wasm_f16x8_pmin (create_f16x8 (-1.0f , 1.0f , 1.0f , 1.0f , INFINITY , INFINITY , NAN , NAN ),
182+ create_f16x8 ( 1.0f , -1.0f , 1.0f , 0.0f , 1.0f , INFINITY , 1.0f , NAN ));
183+ assert_lanes_eq_float (a , -1.0f , -1.0f , 1.0f , 0.0f , 1.0f , INFINITY , NAN , NAN );
184+
185+ a = wasm_f16x8_pmax (create_f16x8 (-1.0f , 1.0f , 1.0f , 1.0f , INFINITY , INFINITY , NAN , NAN ),
186+ create_f16x8 ( 1.0f , -1.0f , 1.0f , 0.0f , 1.0f , INFINITY , 1.0f , NAN ));
187+ assert_lanes_eq_float (a , 1.0f , 1.0f , 1.0f , 1.0f , INFINITY , INFINITY , NAN , NAN );
140188
141189 // TODO needed in binaryen
142190 // wasm_i16x8_trunc_sat_f16x8;
143191 // wasm_u16x8_trunc_sat_f16x8
144192 // wasm_f16x8_convert_i16x8
145193 // wasm_f16x8_convert_u16x8
146194
147- a = wasm_f16x8_relaxed_madd (
148- wasm_f16x8_splat (2 ), wasm_f16x8_splat (3 ), wasm_f16x8_splat (4 ));
149- assert_all_lanes_eq (a , 10.0f );
150-
151- a = wasm_f16x8_relaxed_nmadd (
152- wasm_f16x8_splat (2 ), wasm_f16x8_splat (3 ), wasm_f16x8_splat (4 ));
153- assert_all_lanes_eq (a , -2.0f );
195+ // Lane 0 illustrates the difference between fused/unfused. e.g.
196+ // fused: (positive overflow) + -inf = -inf
197+ // unfused: (inf) + -inf = NaN
198+ a = wasm_f16x8_relaxed_madd (create_f16x8 ( 1e4 , INFINITY , -1.0f , 0.0f , 1.0f , 1.5f , -2.0f , 1.0f ),
199+ create_f16x8 ( 1e4 , INFINITY , -1.0f , 0.0f , 1.0f , 1.5f , 4.0f , 1.0f ),
200+ create_f16x8 (- INFINITY , INFINITY , -1.0f , 0.0f , 1.0f , 2.0f , 1.0f , -1.0f ));
201+ assert_lanes_eq_float (a , - INFINITY , INFINITY , 0.0f , 0.0f , 2.0f , 4.25f , -7.0f , 0.0f );
202+
203+ // Lane 0 illustrates the difference between fused/unfused. e.g.
204+ // fused: -(positive overflow) + inf = inf
205+ // unfused: (-inf) + -inf = NaN
206+ a = wasm_f16x8_relaxed_nmadd (create_f16x8 ( 1e4 , - INFINITY , -1.0f , 0.0f , 1.0f , 1.5f , -2.0f , 1.0f ),
207+ create_f16x8 ( 1e4 , INFINITY , -1.0f , 0.0f , 1.0f , 1.5f , 4.0f , 1.0f ),
208+ create_f16x8 (INFINITY , INFINITY , -1.0f , 0.0f , 1.0f , 2.0f , 1.0f , -1.0f ));
209+ assert_lanes_eq_float (a , INFINITY , INFINITY , -2.0f , 0.0f , 0.0f , -0.25f , 9.0f , -2.0f );
154210}
0 commit comments