Skip to content

Commit

Permalink
[test] Integrate tests for 64x2 arithmetic ops from WAVM (WebAssembly…
Browse files Browse the repository at this point in the history
…#135)

This PR also centralizes the processing of float-point ops
in one file named simd_float_op.py,
see WAVM PR: WAVM/WAVM#209
  • Loading branch information
Honry authored and tlively committed Nov 7, 2019
1 parent a78672c commit 07a4fe6
Show file tree
Hide file tree
Showing 10 changed files with 5,610 additions and 189 deletions.
2 changes: 2 additions & 0 deletions test/core/simd/meta/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ Currently it only support following simd test files generation.
- 'simd_i16x8_arith.wast'
- 'simd_i32x4_arith.wast'
- 'simd_f32x4_arith.wast'
- 'simd_i64x2_arith.wast'
- 'simd_f64x2_arith.wast'
- 'simd_bitwise.wast'
- 'simd_i8x16_sat_arith.wast'
- 'simd_i16x8_sat_arith.wast'
Expand Down
2 changes: 2 additions & 0 deletions test/core/simd/meta/gen_tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@
'simd_i16x8_arith',
'simd_i32x4_arith',
'simd_f32x4_arith',
'simd_i64x2_arith',
'simd_f64x2_arith',
'simd_sat_arith',
'simd_bitwise',
'simd_f32x4',
Expand Down
58 changes: 5 additions & 53 deletions test/core/simd/meta/simd_f32x4.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,63 +5,15 @@
"""

from simd_f32x4_arith import Simdf32x4ArithmeticCase
from simd_float_op import FloatingPointSimpleOp
from simd import SIMD
from test_assert import AssertReturn


def binary_op(op: str, p1: str, p2: str) -> str:
"""Binary operation on p1 and p2 with the operation specified by op
:param op: min, max,
:param p1: float number in hex
:param p2: float number in hex
:return:
"""
f1 = float.fromhex(p1)
f2 = float.fromhex(p2)

if '-nan' in [p1, p2] and 'nan' in [p1, p2]:
return p1

if 'nan' in [p1, p2]:
return 'nan'

if '-nan' in [p1, p2]:
return '-nan'

if op == 'min':
if '-0x0p+0' in [p1, p2] and '0x0p+0' in [p1, p2]:
return '-0x0p+0'
result = min(f1, f2)

elif op == 'max':
if '-0x0p+0' in [p1, p2] and '0x0p+0' in [p1, p2]:
return '0x0p+0'
result = max(f1, f2)

else:
raise Exception('Unknown binary operation: {}'.format(op))

return result.hex()


def unary_op(op: str, p1: str) -> str:
"""Unnary operation on p1 with the operation specified by op
:param op: abs,
:param p1: float number in hex
:return:
"""
f1 = float.fromhex(p1)
if op == 'abs':
return abs(f1).hex()

raise Exception('Unknown unary operation: {}'.format(op))


class Simdf32x4Case(Simdf32x4ArithmeticCase):
UNARY_OPS = ('abs',)
BINARY_OPS = ('min', 'max',)
floatOp = FloatingPointSimpleOp()

FLOAT_NUMBERS = (
'0x0p+0', '-0x0p+0', '0x1p-149', '-0x1p-149', '0x1p-126', '-0x1p-126', '0x1p-1', '-0x1p-1', '0x1p+0', '-0x1p+0',
Expand Down Expand Up @@ -367,7 +319,7 @@ def get_normal_case(self):
op_name = self.full_op_name(op)
for p1 in self.FLOAT_NUMBERS:
for p2 in self.FLOAT_NUMBERS:
result = binary_op(op, p1, p2)
result = self.floatOp.binary_op(op, p1, p2)
if 'nan' not in result:
# Normal floating point numbers as the results
binary_test_data.append(['assert_return', op_name, p1, p2, result])
Expand Down Expand Up @@ -443,7 +395,7 @@ def get_normal_case(self):

for p in self.FLOAT_NUMBERS:
op_name = self.full_op_name('abs')
result = unary_op('abs', p)
result = self.floatOp.unary_op('abs', p)
# Abs operation is valid for all the floating point numbers
unary_test_data.append(['assert_return', op_name, p, result])

Expand Down Expand Up @@ -486,4 +438,4 @@ def gen_test_cases():


if __name__ == '__main__':
gen_test_cases()
gen_test_cases()
102 changes: 12 additions & 90 deletions test/core/simd/meta/simd_f32x4_arith.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,100 +4,21 @@
Generate f32x4 floating-point arithmetic operation cases.
"""

import math
from simd_arithmetic import SimdArithmeticCase
from simd_float_op import FloatingPointArithOp


def binary_op(op: str, p1: str, p2: str) -> str:
"""Binary operation on p1 and p2 with the operation specified by op
:param op: add, sub, mul,
:param p1: float number in hex
:param p2: float number in hex
:return:
"""
f1 = float.fromhex(p1)
f2 = float.fromhex(p2)
if op == 'add':
if 'inf' in p1 and 'inf' in p2 and p1 != p2:
return '-nan'
result = f1 + f2

elif op == 'sub':
if 'inf' in p1 and 'inf' in p2 and p1 == p2:
return '-nan'
result = f1 - f2

elif op == 'mul':
if '0x0p+0' in p1 and 'inf' in p2 or 'inf' in p1 and '0x0p+0' in p2:
return '-nan'
result = f1 * f2

elif op == 'div':
if '0x0p+0' in p1 and '0x0p+0' in p2:
return '-nan'
if 'inf' in p1 and 'inf' in p2:
return '-nan'

try:
result = f1 / f2
return get_valid_float(result)
except ZeroDivisionError:
if p1[0] == p2[0]:
return 'inf'
elif p1 == 'inf' and p2 == '0x0p+0':
return 'inf'
else:
return '-inf'

else:
raise Exception('Unknown binary operation')

return get_valid_float(result)


def get_valid_float(value):
if value > float.fromhex('0x1.fffffep+127'):
return 'inf'
if value < float.fromhex('-0x1.fffffep+127'):
return '-inf'
return value.hex()


def float_sqrt(p):
if p == '-0x0p+0':
return '-0x0p+0'

try:
p = float.fromhex(p)
result = float.hex(math.sqrt(p))
except ValueError:
result = '-nan'

return result


def float_neg(p):
if p == 'nan':
return '-nan'
try:
p = float.fromhex(p)
result = float.hex(-p)
except ValueError:
if p.startswith('nan:'):
return '-' + p
if p.startswith('-nan:'):
return p[1:]

return result
class F32ArithOp(FloatingPointArithOp):
maximum = '0x1.fffffep+127'


class Simdf32x4ArithmeticCase(SimdArithmeticCase):
LANE_LEN = 4
LANE_TYPE = 'f32x4'

floatOp = F32ArithOp()
UNARY_OPS = ('neg', 'sqrt')
BINARY_OPS = ('add', 'sub', 'mul', 'div',)
BINARY_OPS = ('add', 'sub', 'mul', 'div')

FLOAT_NUMBERS = (
'0x0p+0', '-0x0p+0', '0x1p-149', '-0x1p-149', '0x1p-126', '-0x1p-126', '0x1p-1', '-0x1p-1', '0x1p+0', '-0x1p+0',
Expand Down Expand Up @@ -250,7 +171,7 @@ def get_normal_case(self):
op_name = self.full_op_name(op)
for p1 in self.FLOAT_NUMBERS:
for p2 in self.FLOAT_NUMBERS:
result = binary_op(op, p1, p2)
result = self.floatOp.binary_op(op, p1, p2)
if 'nan' not in result:
# Normal floating point numbers as the results
binary_test_data.append(['assert_return', op_name, p1, p2, result])
Expand Down Expand Up @@ -290,7 +211,7 @@ def get_normal_case(self):
else:
# Normal floating point numbers for sqrt operation
op_name = self.full_op_name('sqrt')
result = float_sqrt(p)
result = self.floatOp.float_sqrt(p)
if 'nan' not in result:
# Get the sqrt value correctly
unary_test_data.append(['assert_return', op_name, p, result])
Expand All @@ -300,7 +221,7 @@ def get_normal_case(self):

for p in self.FLOAT_NUMBERS + self.NAN_NUMBERS:
op_name = self.full_op_name('neg')
result = float_neg(p)
result = self.floatOp.float_neg(p)
# Neg operation is valid for all the floating point numbers
unary_test_data.append(['assert_return', op_name, p, result])

Expand Down Expand Up @@ -363,9 +284,10 @@ def mixed_nan_test(self, cases):
cases.append(template.format(
'assert_return_arithmetic_nan', test_type, i))
else:
cases.append('({} (invoke "f32x4_extract_lane_{}_{}") '.format(
'assert_return', test_type, i) +
'(f32.const {}))'.format(result))
cases.append(''.join([
'({} (invoke "f32x4_extract_lane_{}_{}") '.format(
'assert_return', test_type, i),
'(f32.const {}))'.format(result)]))


def gen_test_cases():
Expand Down
Loading

0 comments on commit 07a4fe6

Please sign in to comment.