1+ // Copyright (C) <2024>, Gary Sims
2+ // All rights reserved.
3+ //
4+ // Redistribution and use in source and binary forms, with or without
5+ // modification, are permitted provided that the following conditions are met:
6+ //
7+ // 1. Redistributions of source code must retain the above copyright notice, this
8+ // list of conditions and the following disclaimer.
9+ // 2. Redistributions in binary form must reproduce the above copyright notice,
10+ // this list of conditions and the following disclaimer in the documentation
11+ // and/or other materials provided with the distribution.
12+ //
13+ // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
14+ // ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
15+ // WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
16+ // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
17+ // ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
18+ // (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
19+ // LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
20+ // ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
21+ // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
22+ // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
23+ //
24+
25+ #include <stdio.h>
26+ #include <stdint.h>
27+ #include <string.h>
28+
29+ // ------------------------------
30+
31+ #define FIXED_FACTOR 100000000000000000
32+ #define FIXED_PLACES 17
33+
34+ void print_fixed_point_r (uint64_t n , int i ) {
35+ uint64_t num = n ;
36+ int c ;
37+
38+ c = num % 10 ;
39+ num = num / 10 ;
40+ if ((i < FIXED_PLACES ) || (num > 0 ))
41+ print_fixed_point_r (num , i + 1 );
42+ if (i == FIXED_PLACES ) {
43+ if (num == 0 )
44+ printf ("0" );
45+ printf ("." );
46+ }
47+ printf ("%c" , c + '0' );
48+ }
49+
50+ void print_fixed_point (uint64_t n ) {
51+ print_fixed_point_r (n , 1 );
52+ }
53+
54+ uint64_t set_fixed_point_int (uint64_t n ) {
55+ return n * FIXED_FACTOR ;
56+ }
57+
58+ // decimal expansion for positive fixed point rational numbers
59+ uint64_t fixed_point_dec_expansion (uint64_t dividend , uint64_t divisor ) {
60+ uint64_t result = 0 ;
61+ if (divisor == 0 )
62+ return 0 ;
63+
64+ uint64_t quotient = dividend / divisor ;
65+ result = result + quotient ;
66+ result = result * 10 ;
67+
68+ // Start calculating the fractional part
69+ uint64_t remainder = dividend % divisor ;
70+
71+ for (int i = 0 ; i < FIXED_PLACES - 1 ; i ++ ) {
72+ // Multiply the remainder by 10 for the next digit
73+ remainder = remainder * 10 ;
74+ int digit = remainder / divisor ;
75+ result = result + digit ;
76+ result = result * 10 ;
77+ remainder = remainder % divisor ;
78+ }
79+ return result ;
80+ }
81+ // ---------------------------------
82+
83+ void print_bin32_fraction_expansion (uint32_t frac ) {
84+ uint32_t p = frac ;
85+ uint64_t f = 2 ;
86+
87+ printf ("1 " );
88+ for (int i = 0 ;i < 23 ;i ++ ) {
89+ if ( (p & 0x400000 ) != 0 ) {
90+ printf (" + " );
91+ print_fixed_point (fixed_point_dec_expansion (1 , f ));
92+ }
93+ p = (p << 1 );
94+ f = f << 1 ;
95+ }
96+ printf ("\n" );
97+ }
98+
99+
100+ uint64_t calc_bin32_fraction_fixed (uint32_t frac ) {
101+ uint32_t p = frac ;
102+ uint64_t f = 2 ;
103+ uint64_t fraction = set_fixed_point_int (1 );
104+
105+ for (int i = 0 ;i < 23 ;i ++ ) {
106+ if ( (p & 0x400000 ) != 0 ) {
107+ fraction = fraction + fixed_point_dec_expansion (1 , f );
108+ }
109+ p = p << 1 ;
110+ f = f << 1 ;
111+ }
112+ return fraction ;
113+ }
114+
115+ uint64_t calc_bin32_expo_fixed (uint32_t e ) {
116+ int32_t shift = e - 127 ;
117+ uint64_t expo = set_fixed_point_int (1 );
118+
119+ if (shift > 0 ) {
120+ for (int i = 0 ;i < shift ;i ++ ) {
121+ expo = expo << 1 ;
122+ }
123+ } else {
124+ int f = 1 ;
125+ for (int i = 0 ;i < shift * -1 ;i ++ ) {
126+ f = f << 1 ;
127+ }
128+ expo = fixed_point_dec_expansion (1 , f );
129+ }
130+ return expo ;
131+ }
132+
133+ uint64_t calc_expo_fixed (uint64_t f , int e ) {
134+
135+ if (e > 0 ) {
136+ for (int i = 0 ;i < e ;i ++ ) {
137+ f = f << 1 ;
138+ }
139+ } else {
140+ for (int i = 0 ;i < e * -1 ;i ++ ) {
141+ f = f >> 1 ;
142+ }
143+ }
144+ return f ;
145+ }
146+
147+ void decode_binary32 (float f ) {
148+ uint32_t p ;
149+ uint32_t sign ;
150+ uint32_t expo = 0 ;
151+ uint32_t fraction = 0 ;
152+
153+ printf ("\n%f decodes to:\nBinary Representation: " , f );
154+ memcpy (& p , & f , 4 );
155+ sign = (p & 0x80000000 );
156+ printf ("%c" , (sign == 0 ) ? '0' : '1' );
157+ p = (p << 1 );
158+
159+ for (int i = 0 ;i < 8 ;i ++ ) {
160+ if ( (p & 0x80000000 ) == 0 ) {
161+ printf ("0" );
162+ } else {
163+ printf ("1" );
164+ expo = expo | 0x1 ;
165+ }
166+ expo = (expo << 1 );
167+ p = (p << 1 );
168+ }
169+ expo = (expo >> 1 );
170+
171+ for (int i = 0 ;i < 23 ;i ++ ) {
172+ if ( (p & 0x80000000 ) == 0 ) {
173+ printf ("0" );
174+ } else {
175+ printf ("1" );
176+ fraction = fraction | 0x1 ;
177+ }
178+ fraction = (fraction << 1 );
179+ p = (p << 1 );
180+ }
181+ fraction = (fraction >> 1 );
182+
183+ printf ("\nSign: %c\n" , (sign == 0 ) ? '+' : '-' );
184+ printf ("Expo: %d\n" , (int ) (expo - 127 ));
185+ printf ("Frac: " );
186+ print_bin32_fraction_expansion (fraction );
187+ printf ("Fixed point fraction: " );
188+ print_fixed_point (calc_bin32_fraction_fixed (fraction ));
189+ printf ("\n" );
190+ printf ("Fixed point expo: " );
191+ print_fixed_point (calc_bin32_expo_fixed (expo ));
192+ printf ("\n" );
193+ printf ("Fixed point reconstructed float is: " );
194+ print_fixed_point (calc_expo_fixed (calc_bin32_fraction_fixed (fraction ), (int ) (expo - 127 )));
195+ printf ("\n" );
196+ }
197+
198+ void main (void ) {
199+ decode_binary32 ((float ) 0.15625 );
200+ decode_binary32 ((float ) 0.12 );
201+ decode_binary32 ((float ) 12.334 );
202+ decode_binary32 ((float ) 121.009 );
203+ }
0 commit comments