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) {
4242 * subnormal values.
4343 */
4444static 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+ }
4553 F64_pun val ;
4654 val .flt = x ;
4755 /* 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 22#include <stddef.h>
33#include <stdint.h>
44#include <stdio.h>
5+ #include <limits.h>
6+ #include <string.h>
57#include <math.h>
68#include <fenv.h>
79#include <errno.h>
@@ -92,8 +94,58 @@ size_t run_test(void) {
9294 return SIZE_MAX ;
9395}
9496
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+
95146int main (void ) {
96147 os_ClrHome ();
148+ run_edge_case ();
97149 size_t fail_index = run_test ();
98150 if (fail_index == SIZE_MAX ) {
99151 fputs ("All tests passed" , stdout );
Original file line number Diff line number Diff line change 22#include <stddef.h>
33#include <stdint.h>
44#include <stdio.h>
5+ #include <limits.h>
6+ #include <string.h>
57#include <math.h>
68#include <assert.h>
79#include <ti/screen.h>
@@ -40,8 +42,60 @@ size_t run_test(void) {
4042 return SIZE_MAX ;
4143}
4244
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+
4396int main (void ) {
4497 os_ClrHome ();
98+ run_edge_case ();
4599 size_t fail_index = run_test ();
46100 if (fail_index == SIZE_MAX ) {
47101 fputs ("All tests passed" , stdout );
You can’t perform that action at this time.
0 commit comments