|
1 " |
|
2 COPYRIGHT (c) 2014 by Claus Gittinger |
|
3 All Rights Reserved |
|
4 |
|
5 This software is furnished under a license and may be used |
|
6 only in accordance with the terms of that license and with the |
|
7 inclusion of the above copyright notice. This software may not |
|
8 be provided or otherwise made available to, or used by, any |
|
9 other person. No title to or ownership of the software is |
|
10 hereby transferred. |
|
11 " |
|
12 "{ Package: 'stx:libbasic2' }" |
|
13 |
|
14 AbstractNumberVector variableWordSubclass:#HalfFloatArray |
|
15 instanceVariableNames:'' |
|
16 classVariableNames:'' |
|
17 poolDictionaries:'' |
|
18 category:'Collections-Arrayed' |
|
19 ! |
|
20 |
|
21 !HalfFloatArray primitiveFunctions! |
|
22 |
|
23 %{ |
|
24 typedef unsigned short halffloat; |
|
25 typedef unsigned short uint16; |
|
26 typedef unsigned int uint32; |
|
27 |
|
28 // |
|
29 // convert a halffloat (16-bit float) to a float |
|
30 // |
|
31 float |
|
32 __STX_halffloat_to_float(halffloat h) { |
|
33 int e; |
|
34 uint16 hs, he, hm; |
|
35 uint32 xs, xe, xm; |
|
36 int32 xes; |
|
37 union { |
|
38 uint32 u32; |
|
39 float f32; |
|
40 } u; |
|
41 |
|
42 if( (h & 0x7FFFu) == 0 ) { // Signed zero |
|
43 u.u32 = ((uint32) h) << 16; // Return the signed zero |
|
44 } else { // Not zero |
|
45 hs = h & 0x8000u; // Pick off sign bit |
|
46 he = h & 0x7C00u; // Pick off exponent bits |
|
47 hm = h & 0x03FFu; // Pick off mantissa bits |
|
48 if( he == 0 ) { // Denormal will convert to normalized |
|
49 e = -1; // The following loop figures out how much extra to adjust the exponent |
|
50 do { |
|
51 e++; |
|
52 hm <<= 1; |
|
53 } while( (hm & 0x0400u) == 0 ); // Shift until leading bit overflows into exponent bit |
|
54 xs = ((uint32) hs) << 16; // Sign bit |
|
55 xes = ((uint32) (he >> 10)) - 15 + 127 - e; // Exponent unbias the halfp, then bias the single |
|
56 xe = (uint32) (xes << 23); // Exponent |
|
57 xm = ((uint32) (hm & 0x03FFu)) << 13; // Mantissa |
|
58 u.u32 = (xs | xe | xm); // Combine sign bit, exponent bits, and mantissa bits |
|
59 } else if( he == 0x7C00u ) { // Inf or NaN (all the exponent bits are set) |
|
60 if( hm == 0 ) { // If mantissa is zero ... |
|
61 u.u32 = (((uint32) hs) << 16) | ((uint32) 0x7F800000u); // Signed Inf |
|
62 } else { |
|
63 u.u32 = (uint32) 0xFFC00000u; // NaN, only 1st mantissa bit set |
|
64 } |
|
65 } else { // Normalized number |
|
66 xs = ((uint32) hs) << 16; // Sign bit |
|
67 xes = ((uint32) (he >> 10)) - 15 + 127; // Exponent unbias the halfp, then bias the single |
|
68 xe = (uint32) (xes << 23); // Exponent |
|
69 xm = ((uint32) hm) << 13; // Mantissa |
|
70 u.u32 = (xs | xe | xm); // Combine sign bit, exponent bits, and mantissa bits |
|
71 } |
|
72 } |
|
73 return u.f32; |
|
74 } |
|
75 |
|
76 // |
|
77 // convert a float to a halffloat (16-bit float) |
|
78 // |
|
79 halffloat |
|
80 __STX_float_to_halffloat(float f32) { |
|
81 uint16 hs, he, hm; |
|
82 uint32 x, xs, xe, xm; |
|
83 int hes; |
|
84 union { |
|
85 uint32 u32; |
|
86 float f32; |
|
87 } u; |
|
88 halffloat h; |
|
89 |
|
90 u.f32 = f32; |
|
91 x = u.u32; |
|
92 if( (x & 0x7FFFFFFFu) == 0 ) { // Signed zero |
|
93 h = (uint16) (x >> 16); // Return the signed zero |
|
94 } else { // Not zero |
|
95 xs = x & 0x80000000u; // Pick off sign bit |
|
96 xe = x & 0x7F800000u; // Pick off exponent bits |
|
97 xm = x & 0x007FFFFFu; // Pick off mantissa bits |
|
98 if( xe == 0 ) { // Denormal will underflow, return a signed zero |
|
99 h = (uint16) (xs >> 16); |
|
100 } else if( xe == 0x7F800000u ) { // Inf or NaN (all the exponent bits are set) |
|
101 if( xm == 0 ) { // If mantissa is zero ... |
|
102 h = (uint16) ((xs >> 16) | 0x7C00u); // Signed Inf |
|
103 } else { |
|
104 h = (uint16) 0xFE00u; // NaN, only 1st mantissa bit set |
|
105 } |
|
106 } else { // Normalized number |
|
107 hs = (uint16) (xs >> 16); // Sign bit |
|
108 hes = ((int)(xe >> 23)) - 127 + 15; // Exponent unbias the single, then bias the halfp |
|
109 if( hes >= 0x1F ) { // Overflow |
|
110 h = (uint16) ((xs >> 16) | 0x7C00u); // Signed Inf |
|
111 } else if( hes <= 0 ) { // Underflow |
|
112 if( (14 - hes) > 24 ) { // Mantissa shifted all the way off & no rounding possibility |
|
113 hm = (uint16) 0u; // Set mantissa to zero |
|
114 } else { |
|
115 xm |= 0x00800000u; // Add the hidden leading bit |
|
116 hm = (uint16) (xm >> (14 - hes)); // Mantissa |
|
117 if( (xm >> (13 - hes)) & 0x00000001u ) // Check for rounding |
|
118 hm += (uint16) 1u; // Round, might overflow into exp bit, but this is OK |
|
119 } |
|
120 h = (hs | hm); // Combine sign bit and mantissa bits, biased exponent is zero |
|
121 } else { |
|
122 he = (uint16) (hes << 10); // Exponent |
|
123 hm = (uint16) (xm >> 13); // Mantissa |
|
124 if( xm & 0x00001000u ) // Check for rounding |
|
125 h = (hs | he | hm) + (uint16) 1u; // Round, might overflow to inf, this is OK |
|
126 else |
|
127 h = (hs | he | hm); // No rounding |
|
128 } |
|
129 } |
|
130 } |
|
131 return h; |
|
132 } |
|
133 |
|
134 %} |
|
135 ! |
|
136 |
|
137 !HalfFloatArray class methodsFor:'documentation'! |
|
138 |
|
139 copyright |
|
140 " |
|
141 COPYRIGHT (c) 1993 by Claus Gittinger |
|
142 All Rights Reserved |
|
143 |
|
144 This software is furnished under a license and may be used |
|
145 only in accordance with the terms of that license and with the |
|
146 inclusion of the above copyright notice. This software may not |
|
147 be provided or otherwise made available to, or used by, any |
|
148 other person. No title to or ownership of the software is |
|
149 hereby transferred. |
|
150 " |
|
151 ! |
|
152 |
|
153 documentation |
|
154 " |
|
155 HalfFloatArrays store half precision (16bit) floats (and nothing else). |
|
156 HalfFloats were trditionally seldom used, but seem to become more popular |
|
157 these days, as some 3D graphics accelerators and game engines use them |
|
158 for very dens and compact storage. |
|
159 Notice, that when accessing a HalfFloats elements via getters/setters, |
|
160 shortFloat (i.e. single precision 32bit floats are exchanged). |
|
161 HalfFloats are not supported as first class objects by the st/x system (yet?). |
|
162 |
|
163 [memory requirements:] |
|
164 OBJ-HEADER + (size * 2) |
|
165 |
|
166 [See also:] |
|
167 FloatArray DoubleArray Array |
|
168 |
|
169 [author:] |
|
170 Claus Gittinger |
|
171 " |
|
172 ! ! |
|
173 |
|
174 !HalfFloatArray class methodsFor:'queries'! |
|
175 |
|
176 elementByteSize |
|
177 ^ 2 |
|
178 ! ! |
|
179 |
|
180 |
|
181 !HalfFloatArray methodsFor:'accessing'! |
|
182 |
|
183 at:index |
|
184 %{ /* NOCONTEXT */ |
|
185 if (__isSmallInteger(index)) { |
|
186 int i = __intVal(index); |
|
187 |
|
188 if ((unsigned int)i <= __wordArraySize(self)) { |
|
189 unsigned short h; |
|
190 OBJ newFloat; |
|
191 float f; |
|
192 |
|
193 h = __WordArrayInstPtr(self)->s_element[i]; |
|
194 |
|
195 f = __STX_halffloat_to_float(h); |
|
196 __qMKSFLOAT(newFloat, f); |
|
197 RETURN ( newFloat ); |
|
198 } |
|
199 } |
|
200 %}. |
|
201 self primitiveFailed |
|
202 ! |
|
203 |
|
204 at:index put:aFloat |
|
205 %{ |
|
206 if (__isSmallInteger(index)) { |
|
207 int i = __intVal(index); |
|
208 |
|
209 if ((unsigned)i <= __wordArraySize(self)) { |
|
210 unsigned short h; |
|
211 float f; |
|
212 |
|
213 if (__isFloat(aFloat)) { |
|
214 f = (float)(__floatVal(aFloat)); |
|
215 } else if (__isShortFloat(aFloat)) { |
|
216 f = __shortFloatVal(aFloat); |
|
217 } else if (__isSmallInteger(aFloat)) { |
|
218 f = (float)(__intVal(aFloat)); |
|
219 } else |
|
220 goto error; |
|
221 |
|
222 h = __STX_float_to_halffloat(f); |
|
223 __WordArrayInstPtr(self)->s_element[i] = h; |
|
224 RETURN (aFloat); |
|
225 } |
|
226 } |
|
227 error: ; |
|
228 %}. |
|
229 self primitiveFailed |
|
230 ! ! |
|
231 |
|
232 !HalfFloatArray methodsFor:'queries'! |
|
233 |
|
234 defaultElement |
|
235 ^ ShortFloat zero |
|
236 ! |
|
237 |
|
238 numFloats |
|
239 ^ self size |
|
240 ! ! |
|
241 |
|
242 !HalfFloatArray class methodsFor:'documentation'! |
|
243 |
|
244 version_CVS |
|
245 ^ '$Header: /cvs/stx/stx/libbasic2/HalfFloatArray.st,v 1.1 2014-02-04 17:05:02 cg Exp $' |
|
246 ! ! |