/src/graphicsmagick/magick/floats.c
Line | Count | Source |
1 | | /* |
2 | | Copyright (C) 2008 - 2015 GraphicsMagick Group |
3 | | |
4 | | This program is covered by multiple licenses, which are described in |
5 | | Copyright.txt. You should have received a copy of Copyright.txt with this |
6 | | package; otherwise see http://www.graphicsmagick.org/www/Copyright.html. |
7 | | |
8 | | 16/24 bit floating point conversion functions |
9 | | |
10 | | Written by Richard Nolde, 2008 |
11 | | |
12 | | */ |
13 | | |
14 | | /* |
15 | | Include declarations. |
16 | | */ |
17 | | #include "magick/studio.h" |
18 | | #include "magick/floats.h" |
19 | | |
20 | 0 | #define FP16_MANT_BITS 10 |
21 | 0 | #define FP24_MANT_BITS 16 |
22 | | #define FP32_MANT_BITS 23 |
23 | | #define FP64_MANT_BITS 52 |
24 | | |
25 | | MagickExport |
26 | | int _Gm_convert_fp16_to_fp32 (const fp_16bits *fp16, float *fp32) |
27 | 1.76M | { |
28 | 1.76M | unsigned char sbit; /* sign bit */ |
29 | 1.76M | unsigned char expt; /* exponent bits */ |
30 | 1.76M | unsigned char m2, m1; /* MSB to LSB of mantissa */ |
31 | 1.76M | unsigned char new_expt; |
32 | 1.76M | unsigned char new_m3, new_m2, new_m1; |
33 | 1.76M | unsigned char *src; |
34 | 1.76M | unsigned char *dst; |
35 | | |
36 | | #ifdef DEBUG32 |
37 | | /* Debugging variables */ |
38 | | int i, j, bit; |
39 | | unsigned int mant; |
40 | | double test = 0.0; |
41 | | double test2 = 0.0; |
42 | | double accum = 0.0; |
43 | | |
44 | | errno = 0; |
45 | | #endif |
46 | | |
47 | 1.76M | assert (sizeof(int) == 4); |
48 | 1.76M | if ((fp16 == NULL) || (fp32 == NULL)) |
49 | 0 | { |
50 | 0 | fprintf (stderr, "Invalid src or destination pointers\n"); |
51 | 0 | return (1); |
52 | 0 | } |
53 | 1.76M | sbit=0; |
54 | 1.76M | src = (unsigned char *)fp16; |
55 | 1.76M | dst = (unsigned char *)fp32; |
56 | 1.76M | new_expt = expt = 0; |
57 | 1.76M | new_m3 = new_m2 = new_m1 = m2 = m1 = 0; |
58 | | |
59 | | /* For zero, all bits except possibly sbit are zero */ |
60 | 1.76M | if ((src[0] | src[1]) != 0U) |
61 | 1.34M | { |
62 | 1.34M | #if !defined(WORDS_BIGENDIAN) |
63 | 1.34M | { |
64 | 1.34M | sbit = *(src + 1) & 0x80; |
65 | 1.34M | expt = (*(src + 1) & 0x7F) >> 2; |
66 | 1.34M | m2 = *(src + 1) & 0x03; |
67 | 1.34M | m1 = *src; |
68 | 1.34M | } |
69 | | #else |
70 | | { |
71 | | sbit = *src & 0x80; |
72 | | expt = (*src & 0x7F) >> 2; |
73 | | m2 = *src & 0x03; |
74 | | m1 = *(src + 1); |
75 | | } |
76 | | #endif /* !defined(WORDS_BIGENDIAN) */ |
77 | | |
78 | 1.34M | if (expt != 0) |
79 | 197k | new_expt = expt - 15 + 127; |
80 | 1.34M | new_m3 = (m2 << 5) | (m1 & 0xF8) >> 3; |
81 | 1.34M | new_m2 = (m1 & 7) << 5; |
82 | 1.34M | new_m1 = 0; |
83 | 1.34M | } |
84 | 1.76M | #if !defined(WORDS_BIGENDIAN) |
85 | 1.76M | { |
86 | 1.76M | *dst = new_m1; |
87 | 1.76M | *(dst + 1) = new_m2; |
88 | 1.76M | *(dst + 2) = ((new_expt & 1) << 7) | new_m3; |
89 | 1.76M | *(dst + 3) = sbit | (new_expt >> 1); |
90 | 1.76M | } |
91 | | #else |
92 | | { |
93 | | *dst = sbit | (new_expt >> 1); |
94 | | *(dst + 1) = ((new_expt & 1) << 7) | new_m3; |
95 | | *(dst + 2) = new_m2; |
96 | | *(dst + 3) = new_m1; |
97 | | } |
98 | | #endif /* !defined(WORDS_BIGENDIAN) */ |
99 | | |
100 | | /* Underflow and overflow will not be a problem |
101 | | * since target has more significant bits that |
102 | | * the source. |
103 | | */ |
104 | | #ifdef DEBUG32 |
105 | | /* Debugging code for display only */ |
106 | | mant = ((unsigned int)new_m3 << 16) | ((unsigned int)new_m2 << 8) | (unsigned int)new_m1; |
107 | | if (new_expt == 0) |
108 | | { |
109 | | test = 0.0; |
110 | | test2 = 0.0; |
111 | | accum = 0.0; |
112 | | } |
113 | | else |
114 | | { |
115 | | accum = 0.0; |
116 | | for (i = 22, j = 1; i >= 0; i--, j++) |
117 | | { |
118 | | bit = mant & ((unsigned int)1 << i); |
119 | | if (bit) |
120 | | accum += (1.0 / ((unsigned int)1 << j)); |
121 | | } |
122 | | accum += 1.0; |
123 | | test = pow (2.0, 1.0 * (new_expt - 127)); |
124 | | switch (errno) |
125 | | { |
126 | | case 0: break; |
127 | | case EDOM: |
128 | | case ERANGE: |
129 | | default: perror ("Invalid value"); |
130 | | break; |
131 | | } |
132 | | test2 = accum * test; |
133 | | if (sbit) |
134 | | test2 *= -1.0; |
135 | | } |
136 | | printf (" Sign bit: %u, Expt biased to %5u, 2^%-5d = %8.1f * %10.8f = %18.10f\n\n", |
137 | | sbit > 0 ? 1 : 0, new_expt, new_expt > 0 ? new_expt - 127 : 0, test, accum, test2); |
138 | | #endif |
139 | 1.76M | return (0); |
140 | 1.76M | } /* end convertfp16_to_fp32 */ |
141 | | |
142 | | MagickExport |
143 | | int _Gm_convert_fp32_to_fp16 (const float *fp32, fp_16bits *fp16, const int mode) |
144 | 0 | { |
145 | 0 | int i, bit, rbits, rshift; |
146 | 0 | unsigned char sbit = 0; /* sign bit */ |
147 | 0 | unsigned char expt = 0; /* exponent bits */ |
148 | 0 | unsigned char m3, m2, m1; /* MSB to LSB of mantissa */ |
149 | 0 | signed short new_expt; |
150 | 0 | unsigned short new_mant; |
151 | 0 | unsigned short mant; |
152 | 0 | unsigned char *src; |
153 | 0 | unsigned char *dst; |
154 | 0 | unsigned char *mp; |
155 | |
|
156 | | #ifdef DEBUG16 |
157 | | int j, k; |
158 | | double test = 0.0; |
159 | | double test2 = 0.0; |
160 | | double accum = 0.0; |
161 | | double roundup = 0.0; |
162 | | |
163 | | errno = 0; |
164 | | #endif |
165 | |
|
166 | 0 | assert (sizeof(int) == 4); |
167 | 0 | if ((fp32 == NULL) || (fp16 == NULL)) |
168 | 0 | { |
169 | 0 | fprintf (stderr, "Invalid src or destination pointers\n"); |
170 | 0 | return (1); |
171 | 0 | } |
172 | | |
173 | 0 | src = (unsigned char *)fp32; |
174 | 0 | dst = (unsigned char *)fp16; |
175 | 0 | mp = (unsigned char *)&mant; |
176 | |
|
177 | 0 | new_expt = expt = 0; |
178 | 0 | mant = new_mant = 0; |
179 | 0 | m2 = m1 = 0; |
180 | 0 | rbits = 0; |
181 | | |
182 | | /* For zero, all bits except possibly sbit are zero */ |
183 | 0 | if (*fp32 == 0) |
184 | 0 | *dst = 0; |
185 | 0 | else |
186 | 0 | { |
187 | 0 | #if !defined(WORDS_BIGENDIAN) |
188 | 0 | { |
189 | 0 | sbit = *(src + 3) & 0x80; |
190 | 0 | expt = ((*(src + 3) & 0x7F) << 1) | |
191 | 0 | ((*(src + 2) & 0x80) >> 7); |
192 | | /* Extract mantissa and left align bits */ |
193 | 0 | m3 = (((*(src + 2) & 0x7F)) << 1) | |
194 | 0 | ((*(src + 1) & 0x80) >> 7); |
195 | 0 | m2 = (((*(src + 1) & 0x7F)) << 1) | |
196 | 0 | ((*src & 0x80) >> 7); |
197 | 0 | m1 = (*src & 0x7F) << 1; |
198 | 0 | } |
199 | | #else |
200 | | { |
201 | | sbit = *src & 0x80; |
202 | | expt = ((*src & 0x7F) << 1) | |
203 | | ((*(src + 1) & 0x80) >> 7); |
204 | | /* Extract mantissa and left align bits */ |
205 | | m3 = (((*(src + 1) & 0x7F)) << 1) | |
206 | | ((*(src + 2) & 0x80) >> 7); |
207 | | m2 = (((*(src + 2) & 0x7F)) << 1) | |
208 | | ((*(src + 3) & 0x80) >> 7); |
209 | | m1 = (*(src + 3) & 0x7F) << 1; |
210 | | } |
211 | | #endif /* !defined(WORDS_BIGENDIAN) */ |
212 | | |
213 | | /* Extract the 16 MSB from the mantissa */ |
214 | 0 | mant = (m3 << 8) | m2; |
215 | 0 | if (expt != 0) /* Normal number */ |
216 | 0 | new_expt = expt - 127 + 15; |
217 | | |
218 | | /* Even if the new exponent is too small to represent, |
219 | | * the mantissa could have significant digits that can |
220 | | * be represented in the new value as a subnormal. |
221 | | */ |
222 | 0 | if (new_expt <= 0) /* Underflow */ |
223 | 0 | { |
224 | 0 | rshift = 1 - new_expt; |
225 | 0 | switch (mode) |
226 | 0 | { |
227 | 0 | case STRICT_IEEE: /* NaN has all 1s in exponent plus 2 bits in Mantissa */ |
228 | 0 | if (rshift > FP16_MANT_BITS) |
229 | 0 | { |
230 | 0 | new_expt = 31; |
231 | 0 | new_mant = 513; |
232 | 0 | errno = ERANGE; |
233 | 0 | fflush (stdout); |
234 | 0 | fprintf (stderr, "Underflow. Result clipped\n"); |
235 | 0 | fflush (stderr); |
236 | 0 | return (1); /* The number cannot be represented as fp16 */ |
237 | 0 | } |
238 | 0 | break; |
239 | 0 | case RANGE_LIMITED: /* Clamp to smallest subnormal */ |
240 | 0 | new_expt = 0; |
241 | 0 | new_mant = mant >> rshift;; |
242 | 0 | mp = (unsigned char *)&new_mant; |
243 | | #ifdef DEBUG16 |
244 | | if (mant != 0) |
245 | | { |
246 | | fflush (stdout); |
247 | | fprintf (stderr, "Underflow. %18.10f Result clippped to subnormal value\n", *fp32); |
248 | | fflush (stderr); |
249 | | } |
250 | | #endif |
251 | 0 | break; |
252 | 0 | case ZERO_LIMITED: /* Clamp to zero instead of using a subnormal */ |
253 | 0 | new_expt = 0; |
254 | 0 | new_mant = 0; |
255 | 0 | mp = (unsigned char *)&new_mant; |
256 | | #ifdef DEBUG16 |
257 | | if (mant != 0) |
258 | | { |
259 | | fflush (stdout); |
260 | | fprintf (stderr, "Underflow. %18.10f Result clippped to zero\n", *fp32); |
261 | | fflush (stderr); |
262 | | } |
263 | | #endif |
264 | 0 | break; |
265 | 0 | } |
266 | 0 | } |
267 | 0 | else /* Take the MSB from the old mantissa and left justify them */ |
268 | 0 | { |
269 | 0 | if (new_expt > 30) /* Overflow */ |
270 | 0 | { |
271 | 0 | switch (mode) |
272 | 0 | { |
273 | 0 | case STRICT_IEEE: /* NaN has all 1s in exponent plus 2 bits in Mantissa */ |
274 | 0 | new_expt = 31; |
275 | 0 | new_mant = 513; |
276 | 0 | errno = ERANGE; |
277 | 0 | fflush (stdout); |
278 | 0 | fprintf (stderr, "Overflow. %18.10f Result clipped\n", *fp32); |
279 | 0 | fflush (stderr); |
280 | 0 | return (1); |
281 | 0 | case ZERO_LIMITED: |
282 | 0 | case RANGE_LIMITED: /* Clamp to maximum allowed value for fp16 */ |
283 | 0 | new_expt = 30; |
284 | 0 | new_mant = 1023; |
285 | 0 | mp = (unsigned char *)&new_mant; |
286 | | #ifdef DEBUG16 |
287 | | fflush (stdout); |
288 | | fprintf (stderr, "Overflow. %18.10f Result clippped\n", *fp32); |
289 | | fflush (stderr); |
290 | | #endif |
291 | 0 | break; |
292 | 0 | } |
293 | 0 | } |
294 | 0 | else /* Normal value within range of target type */ |
295 | 0 | { |
296 | | /* Check bits to the right of unit in last significant place |
297 | | * for destination, eg first digit that cannot be stored. |
298 | | * Rounding of least significant retained bit falls to value |
299 | | * which will produce a zero in the LSB if the bounding values |
300 | | * are equidistant from the unrounded value. |
301 | | */ |
302 | 0 | rbits = mant & 0x3F; |
303 | 0 | if (rbits >= 0x20) /* Greater than or equal to 0.5 times LSB */ |
304 | 0 | { |
305 | 0 | if (rbits > 0x20) /* Rbits is greater than half of LSB */ |
306 | 0 | { |
307 | | /* Round up to next higher value of LSB */ |
308 | 0 | for (i = 6; i < 16; i++) |
309 | 0 | { |
310 | 0 | bit = mant & (1 << i); |
311 | 0 | if (bit == 0) |
312 | 0 | { |
313 | 0 | new_mant = (mant | ((unsigned short)1 << i)) & (0xFFFFU << i); |
314 | 0 | mp = (unsigned char *)&new_mant; |
315 | 0 | break; |
316 | 0 | } |
317 | 0 | } |
318 | 0 | } |
319 | 0 | else /* Rbits is exactly half of LSB */ |
320 | 0 | { |
321 | 0 | if ((mant & 0x40)) /* LSB is one so we round up */ |
322 | 0 | { |
323 | | /* Round up to next higher value of LSB */ |
324 | 0 | for (i = 6; i < 10; i++) |
325 | 0 | { |
326 | 0 | bit = mant & (1 << i); |
327 | 0 | if (bit == 0) |
328 | 0 | { |
329 | 0 | new_mant = (mant | ((unsigned short)1 << i)) & (0xFFFFU << i); |
330 | 0 | mp = (unsigned char *)&new_mant; |
331 | 0 | break; |
332 | 0 | } |
333 | 0 | } |
334 | 0 | } |
335 | 0 | } |
336 | 0 | } |
337 | 0 | } |
338 | 0 | } |
339 | | |
340 | | /* Extract bits into contiguous positions in bytes */ |
341 | 0 | #if !defined(WORDS_BIGENDIAN) |
342 | 0 | { |
343 | 0 | m2 = (*(mp + 1) & 0xC0) >> 6; |
344 | 0 | m1 = ((*(mp + 1) & 0x3F) << 2) | |
345 | 0 | ((*mp & 0xC0) >> 6); |
346 | 0 | *dst = m1; |
347 | 0 | *(dst + 1) = sbit | ((new_expt & 0x1F) << 2) | m2; |
348 | 0 | } |
349 | | #else |
350 | | { |
351 | | m2 = (*mp & 0xC0) >> 6; |
352 | | m1 = ((*mp & 0x3F) << 2) | |
353 | | ((*(mp + 1) & 0xC0) >> 6); |
354 | | *dst = sbit | ((new_expt & 0x1F) << 2) | m2; |
355 | | *(dst + 1) = m1; |
356 | | } |
357 | | #endif /* !defined(WORDS_BIGENDIAN) */ |
358 | 0 | } |
359 | | |
360 | | #ifdef DEBUG16 |
361 | | /* Debugging code to display the result */ |
362 | | new_mant = (m2 << 8) | m1; |
363 | | printf ("%10.10f mant%s ", *fp32, (rbits & 0x20) ? "+" : "-"); |
364 | | for (j = 0, k = 15; j < 16; j++, k--) |
365 | | { |
366 | | bit = mant & (1 << k); |
367 | | printf ("%d", bit ? 1 : 0); |
368 | | if (j == 9) |
369 | | printf (" "); |
370 | | if (bit && (j > 9)) |
371 | | roundup += (1.0 / (double)(1 << (j - 9))); |
372 | | } |
373 | | if (new_mant == 0) |
374 | | { |
375 | | printf (" Fract: %8.6f m2m1 ", roundup); |
376 | | for (j = 0, k = 1; j < 2; j++, k--) |
377 | | { |
378 | | bit = m2 & (1 << k); |
379 | | printf ("%d", bit ? 1 : 0); |
380 | | } |
381 | | for (j = 0, k = 7; j < 8; j++, k--) |
382 | | { |
383 | | bit = m1 & (1 << k); |
384 | | printf ("%d", bit ? 1 : 0); |
385 | | } |
386 | | } |
387 | | else |
388 | | { |
389 | | printf (" Fract: %8.6f Rbits Mant ", roundup); |
390 | | for (j = 0, k = 9; j < 10; j++, k--) |
391 | | { |
392 | | bit = new_mant & (1 << k); |
393 | | printf ("%d", bit ? 1 : 0); |
394 | | } |
395 | | } |
396 | | printf (" Sbit + Exp "); |
397 | | #if !defined(WORDS_BIGENDIAN) |
398 | | { |
399 | | for (i = 1; i >= 0; i--) |
400 | | { |
401 | | for (j = 0, k = 7; j < 8; j++, k--) |
402 | | { |
403 | | bit = *(dst + i) & (1 << k); |
404 | | printf ("%d", bit ? 1 : 0); |
405 | | if (i == 1 && j == 5) |
406 | | printf (" Mant: "); |
407 | | } |
408 | | } |
409 | | } |
410 | | #else |
411 | | { |
412 | | for (i = 0; i < 2; i++) |
413 | | { |
414 | | for (j = 0, k = 7; j < 8; j++, k--) |
415 | | { |
416 | | bit = *(dst + i) & (1 << k); |
417 | | printf ("%d", bit ? 1 : 0); |
418 | | if (i == 0 && j == 5) |
419 | | printf (" Mant: "); |
420 | | } |
421 | | } |
422 | | } |
423 | | #endif /* !defined(WORDS_BIGENDIAN) */ |
424 | | printf ("\n"); |
425 | | |
426 | | mant = ((unsigned short)m2 << 8) | (unsigned short)m1; |
427 | | if (*fp32 == 0) |
428 | | { |
429 | | test = 0.0; |
430 | | test2 = 0.0; |
431 | | accum = 0.0; |
432 | | } |
433 | | else |
434 | | { |
435 | | accum = 0.0; |
436 | | for (i = 9, j = 1; i >= 0; i--, j++) |
437 | | { |
438 | | bit = mant & ((unsigned int)1 << i); |
439 | | if (bit) |
440 | | accum += (1.0 / ((unsigned int)1 << j)); |
441 | | } |
442 | | if (new_expt == 0) |
443 | | { |
444 | | accum += 2.0; |
445 | | test = pow (2.0, 1.0 * (-15 - rshift)); |
446 | | } |
447 | | else |
448 | | { |
449 | | accum += 1.0; |
450 | | test = pow (2.0, 1.0 * (new_expt - 15)); |
451 | | } |
452 | | switch (errno) |
453 | | { |
454 | | case 0: break; |
455 | | case EDOM: |
456 | | case ERANGE: |
457 | | default: perror ("Invalid value"); |
458 | | break; |
459 | | } |
460 | | test2 = accum * test; |
461 | | if (sbit) |
462 | | test2 *= -1.0; |
463 | | } |
464 | | printf (" Sign bit: %u, Expt biased to %5u, 2^%-5d = %8.10f * %10.8f = %18.10f\n\n", |
465 | | sbit > 0 ? 1 : 0, new_expt, new_expt > 0 ? new_expt - 15 : 0, test, accum, test2); |
466 | | #endif |
467 | 0 | return (0); |
468 | 0 | } /* end _Gm_convert_fp32_to_fp16 */ |
469 | | |
470 | | MagickExport |
471 | | int _Gm_convert_fp24_to_fp32 (const fp_24bits *fp24, float *fp32, const int mode) |
472 | 557k | { |
473 | 557k | unsigned char sbit = 0; /* sign bit */ |
474 | 557k | unsigned char expt = 0, new_expt; /* exponent bits */ |
475 | 557k | unsigned char m2, m1; /* MSB to LSB of mantissa */ |
476 | 557k | unsigned char new_m3, new_m2, new_m1; |
477 | | /* unsigned short mant; */ |
478 | | /* unsigned int new_mant; */ |
479 | | /* unsigned char *mp; */ |
480 | 557k | unsigned char *src; |
481 | 557k | unsigned char *dst; |
482 | | |
483 | | #ifdef DEBUG32 |
484 | | int i, j, k, bit; |
485 | | double test = 0.0; |
486 | | double test2 = 0.0; |
487 | | double accum = 0.0; |
488 | | errno = 0; |
489 | | #endif |
490 | | |
491 | 557k | (void) mode; |
492 | 557k | assert (sizeof(int) == 4); |
493 | 557k | if ((fp24 == NULL) || (fp32 == NULL)) |
494 | 0 | { |
495 | 0 | fprintf (stderr, "Invalid src or destination pointers\n"); |
496 | 0 | return (1); |
497 | 0 | } |
498 | | |
499 | 557k | src = (unsigned char *)fp24; |
500 | 557k | dst = (unsigned char *)fp32; |
501 | | /* mp = (unsigned char *)&mant; */ |
502 | | |
503 | 557k | new_expt = expt = 0; |
504 | | /* new_mant = mant = 0; */ |
505 | 557k | new_m3 = new_m2 = new_m1 = m2 = m1 = 0; |
506 | | |
507 | | /* For zero, all bits except possibly sbit are zero */ |
508 | 557k | if ((src[0] | src[1] | src[2]) == 0U) |
509 | 132k | { |
510 | 132k | *dst = 0; |
511 | 132k | *(dst + 1) = 0; |
512 | 132k | *(dst + 2) = 0; |
513 | 132k | *(dst + 3) = 0; |
514 | 132k | } |
515 | 424k | else |
516 | 424k | { |
517 | 424k | #if !defined(WORDS_BIGENDIAN) |
518 | 424k | { |
519 | 424k | sbit = *(src + 2) & 0x80; |
520 | 424k | expt = *(src + 2) & 0x7F; |
521 | 424k | m2 = *(src + 1); |
522 | 424k | m1 = *src; |
523 | 424k | } |
524 | | #else |
525 | | { |
526 | | sbit = *src & 0x80; |
527 | | expt = *src & 0x7F; |
528 | | m2 = *(src + 1); |
529 | | m1 = *(src + 2); |
530 | | } |
531 | | #endif /* !defined(WORDS_BIGENDIAN) */ |
532 | | |
533 | 424k | if (expt != 0) |
534 | 343k | new_expt = expt - 63 + 127; |
535 | | /* mant = (m2 << 8) | m1; */ |
536 | 424k | new_m3 = (m2 & 0xFE) >> 1; |
537 | 424k | new_m2 = ((m2 & 0x01) << 7) | ((m1 & 0xFE) >> 1); |
538 | 424k | new_m1 = (m1 & 0x01) << 7; |
539 | 424k | } |
540 | | /* We do not have to worry about underflow or overflow |
541 | | * since the target has more significant bits in the |
542 | | * exponent and the significand. |
543 | | */ |
544 | 557k | #if !defined(WORDS_BIGENDIAN) |
545 | 557k | { |
546 | 557k | *dst = new_m1; |
547 | 557k | *(dst + 1) = new_m2; |
548 | 557k | *(dst + 2) = ((new_expt & 1) << 7) | new_m3; |
549 | 557k | *(dst + 3) = sbit | (new_expt >> 1); |
550 | 557k | } |
551 | | #else |
552 | | { |
553 | | *dst = sbit | (new_expt >> 1); |
554 | | *(dst + 1) = ((new_expt & 1) << 7) | new_m3; |
555 | | *(dst + 2) = new_m2; |
556 | | *(dst + 3) = new_m1; |
557 | | } |
558 | | #endif /* !defined(WORDS_BIGENDIAN) */ |
559 | | |
560 | | #ifdef DEBUG32 |
561 | | /* Debugging code for display only */ |
562 | | new_mant = (new_m3 << 16) | (new_m2 << 8) | new_m1; |
563 | | printf (" mant "); |
564 | | for (j = 0, k = 15; j < 16; j++, k--) |
565 | | { |
566 | | bit = mant & (1 << k); |
567 | | if ((j % 8) == 0) |
568 | | printf(" "); |
569 | | printf ("%d", bit ? 1 : 0); |
570 | | } |
571 | | |
572 | | printf (" New Mant "); |
573 | | for (j = 0, k = 22; j < 23; j++, k--) |
574 | | { |
575 | | bit = new_mant & (1 << k); |
576 | | printf ("%d", bit ? 1 : 0); |
577 | | if ((k % 8) == 0) |
578 | | printf(" "); |
579 | | } |
580 | | |
581 | | printf (" Sbit + Exp "); |
582 | | #if !defined(WORDS_BIGENDIAN) |
583 | | { |
584 | | for (i = 3; i >= 0; i--) |
585 | | { |
586 | | for (j = 0, k = 7; j < 8; j++, k--) |
587 | | { |
588 | | bit = *(dst + i) & (1 << k); |
589 | | if (i == 2 && j == 1) |
590 | | printf (" Mant: "); |
591 | | printf ("%d", bit ? 1 : 0); |
592 | | } |
593 | | } |
594 | | } |
595 | | #else |
596 | | { |
597 | | for (i = 0; i < 4; i++) |
598 | | { |
599 | | for (j = 0, k = 7; j < 8; j++, k--) |
600 | | { |
601 | | bit = *(dst + i) & (1 << k); |
602 | | if (i == 1 && j == 1) |
603 | | printf (" Mant: "); |
604 | | printf ("%d", bit ? 1 : 0); |
605 | | } |
606 | | } |
607 | | } |
608 | | #endif /* !defined(WORDS_BIGENDIAN) */ |
609 | | printf ("\n"); |
610 | | |
611 | | new_mant = ((unsigned int)new_m3 << 16) | ((unsigned int)new_m2 << 8) | new_m1; |
612 | | if ((int)*fp24 == 0.0) |
613 | | { |
614 | | test = 0.0; |
615 | | test2 = 0.0; |
616 | | accum = 0.0; |
617 | | } |
618 | | else |
619 | | { |
620 | | accum = 0.0; |
621 | | for (i = 22, j = 1; i >= 0; i--, j++) |
622 | | { |
623 | | bit = new_mant & ((unsigned int)1 << i); |
624 | | if (bit) |
625 | | accum += (1.0 / ((unsigned int)1 << j)); |
626 | | } |
627 | | accum += 1.0; |
628 | | test = pow (2.0, 1.0 * (new_expt - 127)); |
629 | | switch (errno) |
630 | | { |
631 | | case 0: break; |
632 | | case EDOM: |
633 | | case ERANGE: |
634 | | default: perror ("Invalid value"); |
635 | | break; |
636 | | } |
637 | | test2 = accum * test; |
638 | | if (sbit) |
639 | | test2 *= -1.0; |
640 | | } |
641 | | printf (" Sign bit: %u, Expt biased to %5u, 2^%-5d = %8.1f * %10.8f = %18.10f\n\n", |
642 | | sbit > 0 ? 1 : 0, new_expt, new_expt > 0 ? new_expt - 127 : 0, test, accum, test2); |
643 | | #endif |
644 | | |
645 | 557k | return (0); |
646 | 557k | } /* end convertfp24_to_fp32 */ |
647 | | |
648 | | MagickExport |
649 | | int _Gm_convert_fp32_to_fp24 (const float *fp32, fp_24bits *fp24, const int mode) |
650 | 0 | { |
651 | 0 | int i = 1; |
652 | 0 | int rbits, rshift, bit; |
653 | 0 | unsigned char sbit = 0; /* sign bit */ |
654 | 0 | unsigned char expt = 0; /* exponent bits */ |
655 | 0 | unsigned char m3; /* high order bits of mantissa */ |
656 | 0 | unsigned char m2; |
657 | 0 | unsigned char m1; /* low order bits of mantissa */ |
658 | 0 | unsigned char new_m2, new_m1; |
659 | 0 | signed short new_expt; |
660 | 0 | magick_uint64_t mant, new_mant; /* Mantissa, with rounding */ |
661 | 0 | unsigned char *mp; |
662 | 0 | unsigned char *src; |
663 | 0 | unsigned char *dst; |
664 | |
|
665 | | #ifdef DEBUG24 |
666 | | int j, k; |
667 | | double test = 0.0; |
668 | | double test2 = 0.0; |
669 | | double accum = 0.0; |
670 | | double roundup = 0.0; |
671 | | #endif |
672 | |
|
673 | 0 | errno = 0; |
674 | 0 | assert (sizeof(int) == 4); |
675 | 0 | if ((fp32 == NULL) || (fp24 == NULL)) |
676 | 0 | { |
677 | 0 | fprintf (stderr, "Invalid src or destination pointers\n"); |
678 | 0 | return (1); |
679 | 0 | } |
680 | | |
681 | 0 | src = (unsigned char *)fp32; |
682 | 0 | dst = (unsigned char *)fp24; |
683 | 0 | mp = (unsigned char *)&mant; |
684 | |
|
685 | 0 | new_expt = expt = 0; |
686 | 0 | mant = new_mant = 0; |
687 | 0 | m2 = m1 = 0; |
688 | 0 | rbits = 0; |
689 | |
|
690 | 0 | if (*fp32 != 0) |
691 | 0 | { |
692 | 0 | #if !defined(WORDS_BIGENDIAN) |
693 | 0 | { |
694 | 0 | sbit = *(src + 3) & 0x80; |
695 | 0 | expt = ((*(src + 3) & 0x7F) << 1) | |
696 | 0 | ((*(src + 2) & 0x80) >> 7); |
697 | 0 | m3 = (((*(src + 2) & 0x7F)) << 1) | |
698 | 0 | ((*(src + 1) & 0x80) >> 7); |
699 | 0 | m2 = (((*(src + 1) & 0x7F)) << 1) | |
700 | 0 | ((*src & 0x80) >> 7); |
701 | 0 | m1 = (*src & 0x7F) << 1; |
702 | 0 | } |
703 | | #else |
704 | | { |
705 | | sbit = *src & 0x80; |
706 | | expt = ((*src & 0x7F) << 1) | |
707 | | ((*(src + 1) & 0x80) >> 7); |
708 | | m3 = (((*(src + 1) & 0x7F)) << 1) | |
709 | | ((*(src + 2) & 0x80) >> 7); |
710 | | m2 = (((*(src + 2) & 0x7F)) << 1) | |
711 | | ((*(src + 3) & 0x80) >> 7); |
712 | | m1 = (*(src + 3) & 0x7F) << 1; |
713 | | } |
714 | | #endif /* !defined(WORDS_BIGENDIAN) */ |
715 | |
|
716 | 0 | mant = ((magick_uint64_t) m3 << 24) | (m2 << 16) |( m1 << 8); |
717 | 0 | if (expt != 0) |
718 | 0 | new_expt = expt - 127 + 63; |
719 | | |
720 | | /* Even if the new exponent is too small to represent, |
721 | | * the mantissa could have significant digits that can |
722 | | * be represented in the new value as a subnormal. |
723 | | */ |
724 | 0 | if (new_expt <= 0) /* Underflow */ |
725 | 0 | { |
726 | 0 | rshift = 0 - new_expt; |
727 | 0 | switch (mode) |
728 | 0 | { |
729 | 0 | case STRICT_IEEE: /* NaN has all 1s in exponent plus 2 bits in Mantissa */ |
730 | 0 | if (rshift > FP24_MANT_BITS) |
731 | 0 | { |
732 | 0 | new_expt = 0x7F; |
733 | 0 | new_mant = 0x80010000; |
734 | 0 | errno = ERANGE; |
735 | 0 | fflush (stdout); |
736 | 0 | fprintf (stderr, "Underflow. %18.10f Result clipped\n", *fp32); |
737 | 0 | fflush (stderr); |
738 | 0 | return (1); /* The number cannot be represented as fp24 */ |
739 | 0 | } |
740 | 0 | break; |
741 | 0 | case RANGE_LIMITED: /* Clamp to smallest subnormal */ |
742 | 0 | new_expt = 0; |
743 | 0 | new_mant = mant >> rshift;; |
744 | 0 | mp = (unsigned char *)&new_mant; |
745 | | #ifdef DEBUG24 |
746 | | fflush (stdout); |
747 | | fprintf (stderr, "Underflow. %18.10f Result clippped to subnormal value\n", *fp32); |
748 | | fflush (stderr); |
749 | | #endif |
750 | 0 | break; |
751 | 0 | case ZERO_LIMITED: /* Clamp to zero instead of using a subnormal */ |
752 | 0 | new_expt = 0; |
753 | 0 | new_mant = 0; |
754 | 0 | mp = (unsigned char *)&new_mant; |
755 | | #ifdef DEBUG24 |
756 | | fflush (stdout); |
757 | | fprintf (stderr, "Underflow. %18.10f Result clippped to zero\n", *fp32); |
758 | | fflush (stderr); |
759 | | #endif |
760 | 0 | break; |
761 | 0 | } |
762 | 0 | } |
763 | 0 | else /* Take the MSB from the old mantissa and left justify them */ |
764 | 0 | { |
765 | 0 | if (new_expt > 126) /* Overflow */ |
766 | 0 | { |
767 | 0 | switch (mode) |
768 | 0 | { |
769 | 0 | case STRICT_IEEE: /* NaN has all 1s in exponent plus 2 bits in Mantissa */ |
770 | 0 | new_expt = 0x7F; |
771 | 0 | mant = 0x80010000; |
772 | 0 | errno = ERANGE; |
773 | 0 | fflush (stdout); |
774 | 0 | fprintf (stderr, "Overflow. Result clipped\n"); |
775 | 0 | fflush (stderr); |
776 | 0 | return (1); |
777 | 0 | case ZERO_LIMITED: |
778 | 0 | case RANGE_LIMITED: /* Clamp to maximum allowed value for fp24 */ |
779 | 0 | new_expt = 126; |
780 | 0 | new_mant = 0xFFFF0000; |
781 | 0 | mp = (unsigned char *)&new_mant; |
782 | | #ifdef DEBUG24 |
783 | | fflush (stdout); |
784 | | fprintf (stderr, "Overflow. Result clippped\n"); |
785 | | fflush (stderr); |
786 | | #endif |
787 | 0 | break; |
788 | 0 | } |
789 | 0 | } |
790 | 0 | else /* Normal value within range of target type */ |
791 | 0 | { /* Remove the bits to the left of the binary point |
792 | | * by shifting the fractional bits into the leftmost position |
793 | | */ |
794 | | /* Check bits to the right of Unit in last significant place. |
795 | | * Rounding of least significant retained bit falls to value |
796 | | * which will produce a zero in the LSB if the bounding values |
797 | | * are equidistant from the unrounded value. |
798 | | */ |
799 | |
|
800 | 0 | rbits = mant & 0x0000FFFF; |
801 | 0 | if (rbits >= 0x8000) /* Greater than or equal to 0.5 times LSB */ |
802 | 0 | { |
803 | 0 | if (rbits > 0x8000) /* Rbits is greater than half of LSB */ |
804 | 0 | { |
805 | | /* Round up to next higher value of LSB */ |
806 | 0 | for (i = 16; i < 32; i++) |
807 | 0 | { |
808 | 0 | bit = mant & ((magick_uint64_t) 1U << i); |
809 | 0 | if (bit == 0) |
810 | 0 | { |
811 | | /* Round up by inserting a 1 at first zero and |
812 | | * clearing bits to the right |
813 | | */ |
814 | 0 | new_mant = (mant | ((magick_uint64_t) 1 << i)) & |
815 | 0 | ((magick_uint64_t) 0xFFFFU << i); |
816 | 0 | mp = (unsigned char *)&new_mant; |
817 | 0 | break; |
818 | 0 | } |
819 | 0 | } |
820 | 0 | } |
821 | 0 | else /* Rbits is exactly half of LSB */ |
822 | 0 | { |
823 | 0 | if ((mant & 0x010000)) /* LSB is one so we round up */ |
824 | 0 | { |
825 | | /* Round up to next higher value of LSB */ |
826 | 0 | for (i = 16; i < 32; i++) |
827 | 0 | { |
828 | 0 | bit = mant & ((magick_uint64_t) 1 << i); |
829 | 0 | if (bit == 0) |
830 | 0 | { |
831 | 0 | new_mant = (mant | ((magick_uint64_t) 1 << i)) & |
832 | 0 | ((magick_uint64_t) 0xFFFFU << i); |
833 | 0 | mp = (unsigned char *)&new_mant; |
834 | 0 | break; |
835 | 0 | } |
836 | 0 | } |
837 | 0 | } |
838 | 0 | } |
839 | 0 | } |
840 | 0 | } |
841 | 0 | } |
842 | 0 | } |
843 | 0 | #if !defined(WORDS_BIGENDIAN) |
844 | 0 | { |
845 | 0 | new_m2 = *(mp + 3); |
846 | 0 | new_m1 = *(mp + 2); |
847 | 0 | *dst = new_m1; |
848 | 0 | *(dst + 1) = new_m2; |
849 | 0 | *(dst + 2) = sbit | (new_expt & 0x7F); |
850 | 0 | } |
851 | | #else |
852 | | { |
853 | | new_m2 = *mp; |
854 | | new_m1 = *(mp + 1); |
855 | | *dst = sbit | (new_expt & 0x7F); |
856 | | *(dst + 1) = new_m2; |
857 | | *(dst + 2) = new_m1; |
858 | | } |
859 | | #endif /* !defined(WORDS_BIGENDIAN) */ |
860 | |
|
861 | | #ifdef DEBUG24 |
862 | | /* Debugging code for display only */ |
863 | | printf ("%10.10f mant%s ", *fp32, (rbits & 0x8000) ? "+" : "-"); |
864 | | for (j = 0, k = 31; j < 23; j++, k--) |
865 | | { |
866 | | bit = mant & ((magick_uint64_t) 1 << k); |
867 | | if ((j % 8) == 0) |
868 | | printf(" "); |
869 | | printf ("%d", bit ? 1 : 0); |
870 | | if (bit && (j > 15)) |
871 | | roundup += (1.0 / (double)(1 << (j - 15))); |
872 | | } |
873 | | |
874 | | if (new_mant == 0) |
875 | | { |
876 | | printf (" Fract: %8.6f m2m1 ", roundup); |
877 | | for (j = 0, k = 7; j < 8; j++, k--) |
878 | | { |
879 | | bit = new_m2 & (1 << k); |
880 | | printf ("%d", bit ? 1 : 0); |
881 | | } |
882 | | printf(" "); |
883 | | for (j = 0, k = 7; j < 8; j++, k--) |
884 | | { |
885 | | bit = new_m1 & (1 << k); |
886 | | printf ("%d", bit ? 1 : 0); |
887 | | } |
888 | | } |
889 | | else |
890 | | { |
891 | | printf (" Fract: %8.6f Rbits Mant ", roundup); |
892 | | for (j = 0, k = 31; j < 16; j++, k--) |
893 | | { |
894 | | bit = new_mant & (1 << k); |
895 | | if (j == 8) |
896 | | printf(" "); |
897 | | printf ("%d", bit ? 1 : 0); |
898 | | } |
899 | | } |
900 | | printf (" Sbit + Exp "); |
901 | | #if !defined(WORDS_BIGENDIAN) |
902 | | { |
903 | | for (i = 2; i >= 0; i--) |
904 | | { |
905 | | for (j = 0, k = 7; j < 8; j++, k--) |
906 | | { |
907 | | bit = *(dst + i) & (1 << k); |
908 | | if (i == 1 && j == 0) |
909 | | printf (" Mant: "); |
910 | | printf ("%d", bit ? 1 : 0); |
911 | | } |
912 | | } |
913 | | } |
914 | | #else |
915 | | { |
916 | | for (i = 0; i < 3; i++) |
917 | | { |
918 | | for (j = 0, k = 7; j < 8; j++, k--) |
919 | | { |
920 | | bit = *(dst + i) & (1 << k); |
921 | | if (i == 1 && j == 0) |
922 | | printf (" Mant: "); |
923 | | printf ("%d", bit ? 1 : 0); |
924 | | } |
925 | | } |
926 | | } |
927 | | #endif /* !defined(WORDS_BIGENDIAN) */ |
928 | | printf ("\n"); |
929 | | |
930 | | mant = ((magick_uint64_t)new_m2 << 8) | (magick_uint64_t)new_m1; |
931 | | if (*fp32 == 0.0) |
932 | | { |
933 | | test = 0.0; |
934 | | test2 = 0.0; |
935 | | accum = 0.0; |
936 | | } |
937 | | else |
938 | | { |
939 | | accum = 0.0; |
940 | | for (i = 15, j = 1; i >= 0; i--, j++) |
941 | | { |
942 | | bit = mant & ((magick_uint64_t)1 << i); |
943 | | if (bit) |
944 | | accum += (1.0 / ((magick_uint64_t)1 << j)); |
945 | | } |
946 | | if (new_expt != 0) |
947 | | accum += 1.0; |
948 | | test = pow (2.0, 1.0 * (new_expt - 63)); |
949 | | switch (errno) |
950 | | { |
951 | | case 0: break; |
952 | | case EDOM: |
953 | | case ERANGE: |
954 | | default: perror ("Invalid value"); |
955 | | break; |
956 | | } |
957 | | test2 = accum * test; |
958 | | if (sbit) |
959 | | test2 *= -1.0; |
960 | | } |
961 | | printf (" Sign bit: %u, Expt biased to %5u, 2^%-5d = %8.10f * %10.8f = %18.10f\n\n", |
962 | | sbit > 0 ? 1 : 0, new_expt, new_expt > 0 ? new_expt - 63 : 0, test, accum, test2); |
963 | | #endif |
964 | |
|
965 | 0 | return (0); |
966 | 0 | } /* end convertfp32_to_fp24 */ |