-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmake_from_real_algebraic_number_test_cases.sh
executable file
·131 lines (127 loc) · 5.7 KB
/
make_from_real_algebraic_number_test_cases.sh
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
#!/bin/bash
# SPDX-License-Identifier: LGPL-2.1-or-later
# See Notices.txt for copyright information
set -e
if [[ -z "$SOFTFLOAT_VERIFY" ]] && ! SOFTFLOAT_VERIFY="`which softfloat-verify`"; then
echo "can't find softfloat-verify in PATH" >&2
echo "get it from https://salsa.debian.org/Kazan-team/softfloat-verify" >&2
echo "then put built executable in PATH or set" >&2
echo "SOFTFLOAT_VERIFY to path of executable" >&2
exit 1
fi
function fail() {
echo "$*">&2
exit 1
}
function write_test_cases() {
local mantissa_start="$1"
local mantissa_end="$2"
local mantissa_step="$3"
local exponent="$4"
local rounding_mode="$5"
local exception_handling_mode="$6"
local tininess_detection_mode="$7"
local sf_rounding_mode
case "$rounding_mode" in
TiesToEven)
sf_rounding_mode=near_even
;;
TowardZero)
sf_rounding_mode=minMag
;;
TowardNegative)
sf_rounding_mode=min
;;
TowardPositive)
sf_rounding_mode=max
;;
TiesToAway)
sf_rounding_mode=near_maxMag
;;
*)
fail "invalid rounding mode: $rounding_mode"
;;
esac
local mantissa
for((mantissa=mantissa_start; mantissa<=mantissa_end; mantissa+=mantissa_step)); do
local input make_input_value
printf -v make_input_value "0x%X i64_to_f64 0x%X i64_to_f64 f64_div" $((mantissa << (exponent + 32))) $((1 << 32))
local input="softfloat_round_$sf_rounding_mode softfloat_roundingMode_write_helper"
input+=" 0x0400 f16_to_f64 $make_input_value f64_to_f16 f16_to_f64 f64_le"
input+=" $make_input_value f64_to_f16 f16_to_f64 0x8400 f16_to_f64 f64_le"
input+=" $make_input_value"
input+=" 0 softfloat_exceptionFlags_write_helper"
input+=" softfloat_tininess_${tininess_detection_mode,} softfloat_detectTininess_write_helper"
input+=" f64_to_f16"
input+=" softfloat_exceptionFlags_read_helper"
input+=" softfloat_flag_inexact"
input+=" softfloat_flag_underflow"
input+=" softfloat_flag_overflow"
input+=" softfloat_flag_infinite"
input+=" softfloat_flag_invalid"
local output
output=(`echo "$input" | "$SOFTFLOAT_VERIFY"`) || fail $'softfloat-verify failed. input:\n'"$input"
((${#output[@]} == 9)) || fail $'softfloat-verify returned invalid number of outputs. input:\n'"$input"
local gt_min_normal="${output[0]}"
local le_neg_min_normal="${output[1]}"
local result="${output[2]}"
local flags="${output[3]}"
local flag_inexact="${output[4]}"
local flag_underflow="${output[5]}"
local flag_overflow="${output[6]}"
local flag_infinite="${output[7]}"
local flag_invalid="${output[8]}"
if [[ "$exception_handling_mode" != "IgnoreExactUnderflow" ]] && ((mantissa != 0 && !gt_min_normal && !le_neg_min_normal)); then
((flags |= flag_underflow))
fi
local decoded_flags=()
((flags & flag_inexact)) && decoded_flags+=("INEXACT")
((flags & flag_underflow)) && decoded_flags+=("UNDERFLOW")
((flags & flag_overflow)) && decoded_flags+=("OVERFLOW")
((flags & flag_infinite)) && decoded_flags+=("DIVISION_BY_ZERO")
((flags & flag_invalid)) && decoded_flags+=("INVALID_OPERATION")
if (( ${#decoded_flags[@]} )); then
printf -v flags "%s|" "${decoded_flags[@]}"
flags="${flags%%|}"
else
flags="(empty)"
fi
local mantissa_str
if ((mantissa < 0)); then
printf -v mantissa_str "%s0x%X" '-' $((-mantissa))
else
printf -v mantissa_str "0x%X" $mantissa
fi
printf -v result "0x%04X" $((result))
echo "$mantissa_str $exponent $rounding_mode $exception_handling_mode $tininess_detection_mode $result $flags"
done
}
exec > "test_data/from_real_algebraic_number.txt"
for rounding_mode in TiesToEven TowardZero TowardNegative TowardPositive TiesToAway; do
lc_rounding_mode="`echo "$rounding_mode" | sed 's/\([^A-Z]\)\([A-Z]\)/\1_\2/g; s/.*/\L&/'`"
for tininess_detection_mode in BeforeRounding AfterRounding; do
for exception_handling_mode in IgnoreExactUnderflow SignalExactUnderflow; do
echo "# test the values right around zero for $rounding_mode $exception_handling_mode $tininess_detection_mode"
write_test_cases -0x20 0x20 0x4 -28 $rounding_mode $exception_handling_mode $tininess_detection_mode
echo
echo "# test the values at the transition between subnormal and normal for $rounding_mode $exception_handling_mode $tininess_detection_mode"
write_test_cases 0x3FE0 0x4020 0x2 -28 $rounding_mode $exception_handling_mode $tininess_detection_mode
write_test_cases -0x4020 -0x3FE0 0x2 -28 $rounding_mode $exception_handling_mode $tininess_detection_mode
echo
echo -n '.' >&2
done
done
echo "# test the values right around 1 and -1 for $rounding_mode"
write_test_cases -0x4020 -0x3FE0 0x4 -14 $rounding_mode IgnoreExactUnderflow BeforeRounding
write_test_cases 0x3FE0 0x4020 0x4 -14 $rounding_mode IgnoreExactUnderflow BeforeRounding
echo
echo "# test the values right around max normal for $rounding_mode"
write_test_cases -0x4010 -0x3FF0 0x2 2 $rounding_mode IgnoreExactUnderflow BeforeRounding
write_test_cases 0x3FF0 0x4010 0x2 2 $rounding_mode IgnoreExactUnderflow BeforeRounding
echo
echo "# test the values much larger than max normal for $rounding_mode"
write_test_cases -1 -1 1 20 $rounding_mode IgnoreExactUnderflow BeforeRounding
write_test_cases 1 1 1 20 $rounding_mode IgnoreExactUnderflow BeforeRounding
echo
done
echo >&2