File tree Expand file tree Collapse file tree 6 files changed +177
-28
lines changed Expand file tree Collapse file tree 6 files changed +177
-28
lines changed Original file line number Diff line number Diff line change @@ -42,6 +42,14 @@ static long double generate_ldexpl_mult(int expon) {
42
42
* subnormal values.
43
43
*/
44
44
static long double _ldexpl_c_positive (long double x , int expon ) {
45
+ /* clamps the exponent to avoid signed overflow bugs */
46
+ /* hopefully these can also remove call pe, __setflag from the assembly output */
47
+ if (expon > 4095 ) {
48
+ expon = 4095 ;
49
+ }
50
+ if (expon < -4096 ) {
51
+ expon = -4096 ;
52
+ }
45
53
F64_pun val ;
46
54
val .flt = x ;
47
55
/* expon == 0 || iszero(x) */
Load Diff This file was deleted.
Original file line number Diff line number Diff line change
1
+ assume adl=1
2
+
3
+ section .text
4
+
5
+ public _scalblnf, _scalbln
6
+
7
+ ; float _scalblnf(float, long)
8
+ _scalbln:
9
+ _scalblnf:
10
+ ; We need to cast the int32_t scale to int24_t via saturation.
11
+ ; scalblnf will always overflow/underflow if the scale is larger than +-280.
12
+ ld hl, 12
13
+ add hl, sp
14
+ ld a, (hl)
15
+ dec hl
16
+ ; If bits [16, 23] match bits [24, 31] then we don't need to do anything.
17
+ ; It implies that the scale is either already [-65536, +65535] and can
18
+ ; be safely truncated, or that the original and truncated scale values
19
+ ; are both larger than +-65535 and have the same sign.
20
+ .overflow:
21
+ cp a, (hl)
22
+ jp z, _scalbnf
23
+ ; We need modify the scale value to ensure that overflow/underflow still occurs.
24
+ ; Ensure that bits[16, 23] are not all zeros/ones to set the scale to a large magnitude.
25
+ or a, $03
26
+ dec a
27
+ ; bit 23 = bit 31, bit 16 is cleared, and bit 17 is set
28
+ ld (hl), a ; store the new scale
29
+ ; cp a, a ; set Z flag
30
+ jr .overflow
31
+
32
+ extern _scalbnf
Original file line number Diff line number Diff line change
1
+ assume adl=1
2
+
3
+ section .text
4
+
5
+ public _scalblnl
6
+
7
+ ; long double _scalblnl(long double, long)
8
+ _scalblnl:
9
+ ; We need to cast the int32_t scale to int24_t via saturation.
10
+ ; scalblnl will always overflow/underflow if the scale is larger than +-2100.
11
+ ld hl, 15
12
+ add hl, sp
13
+ ld a, (hl)
14
+ dec hl
15
+ ; If bits [16, 23] match bits [24, 31] then we don't need to do anything.
16
+ ; It implies that the scale is either already [-65536, +65535] and can
17
+ ; be safely truncated, or that the original and truncated scale values
18
+ ; are both larger than +-65535 and have the same sign.
19
+ .overflow:
20
+ cp a, (hl)
21
+ jp z, _scalbnl
22
+ ; We need modify the scale value to ensure that overflow/underflow still occurs.
23
+ ; Ensure that bits[16, 23] are not all zeros/ones to set the scale to a large magnitude.
24
+ or a, $03
25
+ dec a
26
+ ; bit 23 = bit 31, bit 16 is cleared, and bit 17 is set
27
+ ld (hl), a ; store the new scale
28
+ ; cp a, a
29
+ jr .overflow
30
+
31
+ extern _scalbnl
Original file line number Diff line number Diff line change 2
2
#include <stddef.h>
3
3
#include <stdint.h>
4
4
#include <stdio.h>
5
+ #include <limits.h>
6
+ #include <string.h>
5
7
#include <math.h>
6
8
#include <fenv.h>
7
9
#include <errno.h>
@@ -92,8 +94,58 @@ size_t run_test(void) {
92
94
return SIZE_MAX ;
93
95
}
94
96
97
+ static int32_t rand_i32_expon () {
98
+ union {
99
+ struct {
100
+ uint16_t part [2 ];
101
+ };
102
+ int32_t full ;
103
+ } ret ;
104
+ ret .part [0 ] = rand () & 0x03FF ;
105
+ ret .part [1 ] = rand () & 0xC0C0 ;
106
+ return ret .full ;
107
+ }
108
+
109
+ static float rand_f32 () {
110
+ union {
111
+ struct {
112
+ uint16_t part [2 ];
113
+ };
114
+ float full ;
115
+ } ret ;
116
+ ret .part [0 ] = rand ();
117
+ ret .part [1 ] = rand ();
118
+ return ret .full ;
119
+ }
120
+
121
+ static int clamp_exponent (long expon ) {
122
+ if (expon > INT_MAX ) {
123
+ return INT_MAX ;
124
+ }
125
+ if (expon < INT_MIN ) {
126
+ return INT_MIN ;
127
+ }
128
+ return (int )expon ;
129
+ }
130
+
131
+ void run_edge_case (void ) {
132
+ srand (0x7184CE );
133
+ float input , output_i24 , output_i32 ;
134
+ for (size_t i = 0 ; i < 512 ; i ++ ) {
135
+ input = rand_f32 ();
136
+ int32_t expon = rand_i32_expon ();
137
+ output_i24 = scalbnf (input , clamp_exponent (expon ));
138
+ output_i32 = scalblnf (input , expon );
139
+ if (memcmp (& output_i24 , & output_i32 , sizeof (float )) != 0 ) {
140
+ fputs ("Failed edge case\n" , stdout );
141
+ return ;
142
+ }
143
+ }
144
+ }
145
+
95
146
int main (void ) {
96
147
os_ClrHome ();
148
+ run_edge_case ();
97
149
size_t fail_index = run_test ();
98
150
if (fail_index == SIZE_MAX ) {
99
151
fputs ("All tests passed" , stdout );
Original file line number Diff line number Diff line change 2
2
#include <stddef.h>
3
3
#include <stdint.h>
4
4
#include <stdio.h>
5
+ #include <limits.h>
6
+ #include <string.h>
5
7
#include <math.h>
6
8
#include <assert.h>
7
9
#include <ti/screen.h>
@@ -40,8 +42,60 @@ size_t run_test(void) {
40
42
return SIZE_MAX ;
41
43
}
42
44
45
+ static int32_t rand_i32_expon () {
46
+ union {
47
+ struct {
48
+ uint16_t part [2 ];
49
+ };
50
+ int32_t full ;
51
+ } ret ;
52
+ ret .part [0 ] = rand () & 0x1FFF ;
53
+ ret .part [1 ] = rand () & 0xC0C0 ;
54
+ return ret .full ;
55
+ }
56
+
57
+ static long double rand_f64 () {
58
+ union {
59
+ struct {
60
+ uint16_t part [4 ];
61
+ };
62
+ long double full ;
63
+ } ret ;
64
+ ret .part [0 ] = rand ();
65
+ ret .part [1 ] = rand ();
66
+ ret .part [2 ] = rand ();
67
+ ret .part [3 ] = rand ();
68
+ return ret .full ;
69
+ }
70
+
71
+ static int clamp_exponent (long expon ) {
72
+ if (expon > INT_MAX ) {
73
+ return INT_MAX ;
74
+ }
75
+ if (expon < INT_MIN ) {
76
+ return INT_MIN ;
77
+ }
78
+ return (int )expon ;
79
+ }
80
+
81
+ void run_edge_case (void ) {
82
+ srand (0x7184CE );
83
+ long double input , output_i24 , output_i32 ;
84
+ for (size_t i = 0 ; i < 512 ; i ++ ) {
85
+ input = rand_f64 ();
86
+ int32_t expon = rand_i32_expon ();
87
+ output_i24 = scalbnl (input , clamp_exponent (expon ));
88
+ output_i32 = scalblnl (input , expon );
89
+ if (memcmp (& output_i24 , & output_i32 , sizeof (long double )) != 0 ) {
90
+ fputs ("Failed edge case\n" , stdout );
91
+ return ;
92
+ }
93
+ }
94
+ }
95
+
43
96
int main (void ) {
44
97
os_ClrHome ();
98
+ run_edge_case ();
45
99
size_t fail_index = run_test ();
46
100
if (fail_index == SIZE_MAX ) {
47
101
fputs ("All tests passed" , stdout );
You can’t perform that action at this time.
0 commit comments