1 /*
2 Copyright 1999-2019 ImageMagick Studio LLC, a non-profit organization
3 dedicated to making software imaging solutions freely available.
4
5 You may not use this file except in compliance with the License. You may
6 obtain a copy of the License at
7
8 https://imagemagick.org/script/license.php
9
10 Unless required by applicable law or agreed to in writing, software
11 distributed under the License is distributed on an "AS IS" BASIS,
12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 See the License for the specific language governing permissions and
14 limitations under the License.
15
16 MagickCore quantum inline methods.
17 */
18 #ifndef MAGICKCORE_QUANTUM_PRIVATE_H
19 #define MAGICKCORE_QUANTUM_PRIVATE_H
20
21 #include "MagickCore/memory_.h"
22 #include "MagickCore/cache.h"
23 #include "MagickCore/image-private.h"
24 #include "MagickCore/pixel-accessor.h"
25
26 #if defined(__cplusplus) || defined(c_plusplus)
27 extern "C" {
28 #endif
29
30 typedef struct _QuantumState
31 {
32 double
33 inverse_scale;
34
35 unsigned int
36 pixel;
37
38 size_t
39 bits;
40
41 const unsigned int
42 *mask;
43 } QuantumState;
44
45 struct _QuantumInfo
46 {
47 size_t
48 depth,
49 quantum;
50
51 QuantumFormatType
52 format;
53
54 double
55 minimum,
56 maximum,
57 scale;
58
59 size_t
60 pad;
61
62 MagickBooleanType
63 min_is_white,
64 pack;
65
66 QuantumAlphaType
67 alpha_type;
68
69 size_t
70 number_threads;
71
72 MemoryInfo
73 **pixels;
74
75 size_t
76 extent;
77
78 EndianType
79 endian;
80
81 QuantumState
82 state;
83
84 SemaphoreInfo
85 *semaphore;
86
87 size_t
88 signature;
89 };
90
91 extern MagickPrivate void
92 ResetQuantumState(QuantumInfo *);
93
GetQuantumRange(const size_t depth)94 static inline MagickSizeType GetQuantumRange(const size_t depth)
95 {
96 MagickSizeType
97 one;
98
99 size_t
100 max_depth;
101
102 if (depth == 0)
103 return(0);
104 one=1;
105 max_depth=8*sizeof(MagickSizeType);
106 return((MagickSizeType) ((one << (MagickMin(depth,max_depth)-1))+
107 ((one << (MagickMin(depth,max_depth)-1))-1)));
108 }
109
HalfToSinglePrecision(const unsigned short half)110 static inline float HalfToSinglePrecision(const unsigned short half)
111 {
112 #define ExponentBias (127-15)
113 #define ExponentMask 0x7c00
114 #define ExponentShift 23
115 #define SignBitShift 31
116 #define SignificandShift 13
117 #define SignificandMask 0x00000400
118
119 typedef union _SinglePrecision
120 {
121 unsigned int
122 fixed_point;
123
124 float
125 single_precision;
126 } SinglePrecision;
127
128 register unsigned int
129 exponent,
130 significand,
131 sign_bit;
132
133 SinglePrecision
134 map;
135
136 unsigned int
137 value;
138
139 /*
140 The IEEE 754 standard specifies half precision as having:
141
142 Sign bit: 1 bit
143 Exponent width: 5 bits
144 Significand precision: 11 (10 explicitly stored)
145 */
146 sign_bit=(unsigned int) ((half >> 15) & 0x00000001);
147 exponent=(unsigned int) ((half >> 10) & 0x0000001f);
148 significand=(unsigned int) (half & 0x000003ff);
149 if (exponent == 0)
150 {
151 if (significand == 0)
152 value=sign_bit << SignBitShift;
153 else
154 {
155 while ((significand & SignificandMask) == 0)
156 {
157 significand<<=1;
158 exponent--;
159 }
160 exponent++;
161 significand&=(~SignificandMask);
162 exponent+=ExponentBias;
163 value=(sign_bit << SignBitShift) | (exponent << ExponentShift) |
164 (significand << SignificandShift);
165 }
166 }
167 else
168 if (exponent == SignBitShift)
169 {
170 value=(sign_bit << SignBitShift) | 0x7f800000;
171 if (significand != 0)
172 value|=(significand << SignificandShift);
173 }
174 else
175 {
176 exponent+=ExponentBias;
177 significand<<=SignificandShift;
178 value=(sign_bit << SignBitShift) | (exponent << ExponentShift) |
179 significand;
180 }
181 map.fixed_point=value;
182 return(map.single_precision);
183 }
184
PopCharPixel(const unsigned char pixel,unsigned char * pixels)185 static inline unsigned char *PopCharPixel(const unsigned char pixel,
186 unsigned char *pixels)
187 {
188 *pixels++=pixel;
189 return(pixels);
190 }
191
PopLongPixel(const EndianType endian,const unsigned int pixel,unsigned char * pixels)192 static inline unsigned char *PopLongPixel(const EndianType endian,
193 const unsigned int pixel,unsigned char *pixels)
194 {
195 register unsigned int
196 quantum;
197
198 quantum=(unsigned int) pixel;
199 if (endian == LSBEndian)
200 {
201 *pixels++=(unsigned char) (quantum);
202 *pixels++=(unsigned char) (quantum >> 8);
203 *pixels++=(unsigned char) (quantum >> 16);
204 *pixels++=(unsigned char) (quantum >> 24);
205 return(pixels);
206 }
207 *pixels++=(unsigned char) (quantum >> 24);
208 *pixels++=(unsigned char) (quantum >> 16);
209 *pixels++=(unsigned char) (quantum >> 8);
210 *pixels++=(unsigned char) (quantum);
211 return(pixels);
212 }
213
PopShortPixel(const EndianType endian,const unsigned short pixel,unsigned char * pixels)214 static inline unsigned char *PopShortPixel(const EndianType endian,
215 const unsigned short pixel,unsigned char *pixels)
216 {
217 register unsigned int
218 quantum;
219
220 quantum=pixel;
221 if (endian == LSBEndian)
222 {
223 *pixels++=(unsigned char) (quantum);
224 *pixels++=(unsigned char) (quantum >> 8);
225 return(pixels);
226 }
227 *pixels++=(unsigned char) (quantum >> 8);
228 *pixels++=(unsigned char) (quantum);
229 return(pixels);
230 }
231
PushCharPixel(const unsigned char * pixels,unsigned char * pixel)232 static inline const unsigned char *PushCharPixel(const unsigned char *pixels,
233 unsigned char *pixel)
234 {
235 *pixel=(*pixels++);
236 return(pixels);
237 }
238
PushLongPixel(const EndianType endian,const unsigned char * pixels,unsigned int * pixel)239 static inline const unsigned char *PushLongPixel(const EndianType endian,
240 const unsigned char *pixels,unsigned int *pixel)
241 {
242 register unsigned int
243 quantum;
244
245 if (endian == LSBEndian)
246 {
247 quantum=((unsigned int) *pixels++);
248 quantum|=((unsigned int) *pixels++ << 8);
249 quantum|=((unsigned int) *pixels++ << 16);
250 quantum|=((unsigned int) *pixels++ << 24);
251 *pixel=quantum;
252 return(pixels);
253 }
254 quantum=((unsigned int) *pixels++ << 24);
255 quantum|=((unsigned int) *pixels++ << 16);
256 quantum|=((unsigned int) *pixels++ << 8);
257 quantum|=((unsigned int) *pixels++);
258 *pixel=quantum;
259 return(pixels);
260 }
261
PushShortPixel(const EndianType endian,const unsigned char * pixels,unsigned short * pixel)262 static inline const unsigned char *PushShortPixel(const EndianType endian,
263 const unsigned char *pixels,unsigned short *pixel)
264 {
265 register unsigned int
266 quantum;
267
268 if (endian == LSBEndian)
269 {
270 quantum=(unsigned int) *pixels++;
271 quantum|=(unsigned int) (*pixels++ << 8);
272 *pixel=(unsigned short) (quantum & 0xffff);
273 return(pixels);
274 }
275 quantum=(unsigned int) (*pixels++ << 8);
276 quantum|=(unsigned int) *pixels++;
277 *pixel=(unsigned short) (quantum & 0xffff);
278 return(pixels);
279 }
280
PushFloatPixel(const EndianType endian,const unsigned char * pixels,MagickFloatType * pixel)281 static inline const unsigned char *PushFloatPixel(const EndianType endian,
282 const unsigned char *pixels,MagickFloatType *pixel)
283 {
284 union
285 {
286 unsigned int
287 unsigned_value;
288
289 MagickFloatType
290 float_value;
291 } quantum;
292
293 if (endian == LSBEndian)
294 {
295 quantum.unsigned_value=((unsigned int) *pixels++);
296 quantum.unsigned_value|=((unsigned int) *pixels++ << 8);
297 quantum.unsigned_value|=((unsigned int) *pixels++ << 16);
298 quantum.unsigned_value|=((unsigned int) *pixels++ << 24);
299 *pixel=quantum.float_value;
300 return(pixels);
301 }
302 quantum.unsigned_value=((unsigned int) *pixels++ << 24);
303 quantum.unsigned_value|=((unsigned int) *pixels++ << 16);
304 quantum.unsigned_value|=((unsigned int) *pixels++ << 8);
305 quantum.unsigned_value|=((unsigned int) *pixels++);
306 *pixel=quantum.float_value;
307 return(pixels);
308 }
309
ScaleAnyToQuantum(const QuantumAny quantum,const QuantumAny range)310 static inline Quantum ScaleAnyToQuantum(const QuantumAny quantum,
311 const QuantumAny range)
312 {
313 if (quantum > range)
314 return(QuantumRange);
315 #if !defined(MAGICKCORE_HDRI_SUPPORT)
316 return((Quantum) (((double) QuantumRange*quantum)*
317 PerceptibleReciprocal((double) range)+0.5));
318 #else
319 return((Quantum) (((double) QuantumRange*quantum)*
320 PerceptibleReciprocal((double) range)));
321 #endif
322 }
323
ScaleQuantumToAny(const Quantum quantum,const QuantumAny range)324 static inline QuantumAny ScaleQuantumToAny(const Quantum quantum,
325 const QuantumAny range)
326 {
327 return((QuantumAny) (((double) range*quantum)/QuantumRange+0.5));
328 }
329
330 #if (MAGICKCORE_QUANTUM_DEPTH == 8)
ScaleCharToQuantum(const unsigned char value)331 static inline Quantum ScaleCharToQuantum(const unsigned char value)
332 {
333 return((Quantum) value);
334 }
335
ScaleLongToQuantum(const unsigned int value)336 static inline Quantum ScaleLongToQuantum(const unsigned int value)
337 {
338 #if !defined(MAGICKCORE_HDRI_SUPPORT)
339 return((Quantum) ((value)/16843009UL));
340 #else
341 return((Quantum) (value/16843009.0));
342 #endif
343 }
344
ScaleLongLongToQuantum(const MagickSizeType value)345 static inline Quantum ScaleLongLongToQuantum(const MagickSizeType value)
346 {
347 #if !defined(MAGICKCORE_HDRI_SUPPORT)
348 return((Quantum) (value/MagickULLConstant(72340172838076673)));
349 #else
350 return((Quantum) (value/72340172838076673.0));
351 #endif
352 }
353
ScaleMapToQuantum(const MagickRealType value)354 static inline Quantum ScaleMapToQuantum(const MagickRealType value)
355 {
356 if (value <= 0.0)
357 return((Quantum) 0);
358 if (value >= MaxMap)
359 return(QuantumRange);
360 #if !defined(MAGICKCORE_HDRI_SUPPORT)
361 return((Quantum) (value+0.5));
362 #else
363 return((Quantum) value);
364 #endif
365 }
366
ScaleQuantumToLong(const Quantum quantum)367 static inline unsigned int ScaleQuantumToLong(const Quantum quantum)
368 {
369 #if !defined(MAGICKCORE_HDRI_SUPPORT)
370 return((unsigned int) (16843009UL*quantum));
371 #else
372 if (quantum <= 0.0)
373 return(0UL);
374 if ((16843009.0*quantum) >= 4294967295.0)
375 return(4294967295UL);
376 return((unsigned int) (16843009.0*quantum+0.5));
377 #endif
378 }
379
ScaleQuantumToLongLong(const Quantum quantum)380 static inline MagickSizeType ScaleQuantumToLongLong(const Quantum quantum)
381 {
382 #if !defined(MAGICKCORE_HDRI_SUPPORT)
383 return((MagickSizeType) (MagickULLConstant(72340172838076673)*quantum));
384 #else
385 if (quantum <= 0.0)
386 return(0UL);
387 if ((72340172838076673.0*quantum) >= 18446744073709551615.0)
388 return(MagickULLConstant(18446744073709551615));
389 return((MagickSizeType) (72340172838076673*quantum+0.5));
390 #endif
391 }
392
ScaleQuantumToMap(const Quantum quantum)393 static inline unsigned int ScaleQuantumToMap(const Quantum quantum)
394 {
395 if (quantum >= (Quantum) MaxMap)
396 return((unsigned int) MaxMap);
397 #if !defined(MAGICKCORE_HDRI_SUPPORT)
398 return((unsigned int) quantum);
399 #else
400 if (quantum < 0.0)
401 return(0UL);
402 return((unsigned int) (quantum+0.5));
403 #endif
404 }
405
ScaleQuantumToShort(const Quantum quantum)406 static inline unsigned short ScaleQuantumToShort(const Quantum quantum)
407 {
408 #if !defined(MAGICKCORE_HDRI_SUPPORT)
409 return((unsigned short) (257UL*quantum));
410 #else
411 if (quantum <= 0.0)
412 return(0);
413 if ((257.0*quantum) >= 65535.0)
414 return(65535);
415 return((unsigned short) (257.0*quantum+0.5));
416 #endif
417 }
418
ScaleShortToQuantum(const unsigned short value)419 static inline Quantum ScaleShortToQuantum(const unsigned short value)
420 {
421 #if !defined(MAGICKCORE_HDRI_SUPPORT)
422 return((Quantum) ((value+128U)/257U));
423 #else
424 return((Quantum) (value/257.0));
425 #endif
426 }
427 #elif (MAGICKCORE_QUANTUM_DEPTH == 16)
ScaleCharToQuantum(const unsigned char value)428 static inline Quantum ScaleCharToQuantum(const unsigned char value)
429 {
430 #if !defined(MAGICKCORE_HDRI_SUPPORT)
431 return((Quantum) (257U*value));
432 #else
433 return((Quantum) (257.0*value));
434 #endif
435 }
436
ScaleLongToQuantum(const unsigned int value)437 static inline Quantum ScaleLongToQuantum(const unsigned int value)
438 {
439 #if !defined(MAGICKCORE_HDRI_SUPPORT)
440 return((Quantum) ((value)/MagickULLConstant(65537)));
441 #else
442 return((Quantum) (value/65537.0));
443 #endif
444 }
445
ScaleLongLongToQuantum(const MagickSizeType value)446 static inline Quantum ScaleLongLongToQuantum(const MagickSizeType value)
447 {
448 #if !defined(MAGICKCORE_HDRI_SUPPORT)
449 return((Quantum) ((value)/MagickULLConstant(281479271743489)));
450 #else
451 return((Quantum) (value/281479271743489.0));
452 #endif
453 }
454
ScaleMapToQuantum(const MagickRealType value)455 static inline Quantum ScaleMapToQuantum(const MagickRealType value)
456 {
457 if (value <= 0.0)
458 return((Quantum) 0);
459 if (value >= MaxMap)
460 return(QuantumRange);
461 #if !defined(MAGICKCORE_HDRI_SUPPORT)
462 return((Quantum) (value+0.5));
463 #else
464 return((Quantum) value);
465 #endif
466 }
467
ScaleQuantumToLong(const Quantum quantum)468 static inline unsigned int ScaleQuantumToLong(const Quantum quantum)
469 {
470 #if !defined(MAGICKCORE_HDRI_SUPPORT)
471 return((unsigned int) (65537UL*quantum));
472 #else
473 if (quantum <= 0.0)
474 return(0UL);
475 if ((65537.0*quantum) >= 4294967295.0)
476 return(4294967295U);
477 return((unsigned int) (65537.0*quantum+0.5));
478 #endif
479 }
480
ScaleQuantumToLongLong(const Quantum quantum)481 static inline MagickSizeType ScaleQuantumToLongLong(const Quantum quantum)
482 {
483 #if !defined(MAGICKCORE_HDRI_SUPPORT)
484 return((MagickSizeType) (MagickULLConstant(281479271743489)*quantum));
485 #else
486 if (quantum <= 0.0)
487 return(0UL);
488 if ((281479271743489.0*quantum) >= 18446744073709551615.0)
489 return(MagickULLConstant(18446744073709551615));
490 return((MagickSizeType) (281479271743489.0*quantum+0.5));
491 #endif
492 }
493
ScaleQuantumToMap(const Quantum quantum)494 static inline unsigned int ScaleQuantumToMap(const Quantum quantum)
495 {
496 if (quantum >= (Quantum) MaxMap)
497 return((unsigned int) MaxMap);
498 #if !defined(MAGICKCORE_HDRI_SUPPORT)
499 return((unsigned int) quantum);
500 #else
501 if (quantum < 0.0)
502 return(0UL);
503 return((unsigned int) (quantum+0.5));
504 #endif
505 }
506
ScaleQuantumToShort(const Quantum quantum)507 static inline unsigned short ScaleQuantumToShort(const Quantum quantum)
508 {
509 #if !defined(MAGICKCORE_HDRI_SUPPORT)
510 return((unsigned short) quantum);
511 #else
512 if (quantum <= 0.0)
513 return(0);
514 if (quantum >= 65535.0)
515 return(65535);
516 return((unsigned short) (quantum+0.5));
517 #endif
518 }
519
ScaleShortToQuantum(const unsigned short value)520 static inline Quantum ScaleShortToQuantum(const unsigned short value)
521 {
522 return((Quantum) value);
523 }
524 #elif (MAGICKCORE_QUANTUM_DEPTH == 32)
ScaleCharToQuantum(const unsigned char value)525 static inline Quantum ScaleCharToQuantum(const unsigned char value)
526 {
527 #if !defined(MAGICKCORE_HDRI_SUPPORT)
528 return((Quantum) (16843009UL*value));
529 #else
530 return((Quantum) (16843009.0*value));
531 #endif
532 }
533
ScaleLongToQuantum(const unsigned int value)534 static inline Quantum ScaleLongToQuantum(const unsigned int value)
535 {
536 return((Quantum) value);
537 }
538
ScaleLongLongToQuantum(const MagickSizeType value)539 static inline Quantum ScaleLongLongToQuantum(const MagickSizeType value)
540 {
541 #if !defined(MAGICKCORE_HDRI_SUPPORT)
542 return((Quantum) ((value)/MagickULLConstant(4294967297)));
543 #else
544 return((Quantum) (value/4294967297.0));
545 #endif
546 }
547
ScaleMapToQuantum(const MagickRealType value)548 static inline Quantum ScaleMapToQuantum(const MagickRealType value)
549 {
550 if (value <= 0.0)
551 return((Quantum) 0);
552 if (value >= (Quantum) MaxMap)
553 return(QuantumRange);
554 #if !defined(MAGICKCORE_HDRI_SUPPORT)
555 return((Quantum) (65537.0*value+0.5));
556 #else
557 return((Quantum) (65537.0*value));
558 #endif
559 }
560
ScaleQuantumToLong(const Quantum quantum)561 static inline unsigned int ScaleQuantumToLong(const Quantum quantum)
562 {
563 #if !defined(MAGICKCORE_HDRI_SUPPORT)
564 return((unsigned int) quantum);
565 #else
566 if (quantum <= 0.0)
567 return(0);
568 if ((quantum) >= 4294967295.0)
569 return(4294967295);
570 return((unsigned int) (quantum+0.5));
571 #endif
572 }
573
ScaleQuantumToLongLong(const Quantum quantum)574 static inline MagickSizeType ScaleQuantumToLongLong(const Quantum quantum)
575 {
576 #if !defined(MAGICKCORE_HDRI_SUPPORT)
577 return((MagickSizeType) (MagickULLConstant(4294967297)*quantum));
578 #else
579 if (quantum <= 0.0)
580 return(0UL);
581 if ((4294967297.0*quantum) >= 18446744073709551615.0)
582 return(MagickULLConstant(18446744073709551615));
583 return((MagickSizeType) (4294967297.0*quantum+0.5));
584 #endif
585 }
586
ScaleQuantumToMap(const Quantum quantum)587 static inline unsigned int ScaleQuantumToMap(const Quantum quantum)
588 {
589 if (quantum < 0.0)
590 return(0UL);
591 if ((quantum/65537) >= (Quantum) MaxMap)
592 return((unsigned int) MaxMap);
593 #if !defined(MAGICKCORE_HDRI_SUPPORT)
594 return((unsigned int) ((quantum+MagickULLConstant(32768))/
595 MagickULLConstant(65537)));
596 #else
597 return((unsigned int) (quantum/65537.0+0.5));
598 #endif
599 }
600
ScaleQuantumToShort(const Quantum quantum)601 static inline unsigned short ScaleQuantumToShort(const Quantum quantum)
602 {
603 #if !defined(MAGICKCORE_HDRI_SUPPORT)
604 return((unsigned short) ((quantum+MagickULLConstant(32768))/
605 MagickULLConstant(65537)));
606 #else
607 if (quantum <= 0.0)
608 return(0);
609 if ((quantum/65537.0) >= 65535.0)
610 return(65535);
611 return((unsigned short) (quantum/65537.0+0.5));
612 #endif
613 }
614
ScaleShortToQuantum(const unsigned short value)615 static inline Quantum ScaleShortToQuantum(const unsigned short value)
616 {
617 #if !defined(MAGICKCORE_HDRI_SUPPORT)
618 return((Quantum) (65537UL*value));
619 #else
620 return((Quantum) (65537.0*value));
621 #endif
622 }
623 #elif (MAGICKCORE_QUANTUM_DEPTH == 64)
ScaleCharToQuantum(const unsigned char value)624 static inline Quantum ScaleCharToQuantum(const unsigned char value)
625 {
626 return((Quantum) (72340172838076673.0*value));
627 }
628
ScaleLongToQuantum(const unsigned int value)629 static inline Quantum ScaleLongToQuantum(const unsigned int value)
630 {
631 return((Quantum) (4294967297.0*value));
632 }
633
ScaleLongLongToQuantum(const MagickSizeType value)634 static inline Quantum ScaleLongLongToQuantum(const MagickSizeType value)
635 {
636 return((Quantum) (value));
637 }
638
ScaleMapToQuantum(const MagickRealType value)639 static inline Quantum ScaleMapToQuantum(const MagickRealType value)
640 {
641 if (value <= 0.0)
642 return((Quantum) 0);
643 if (value >= MaxMap)
644 return(QuantumRange);
645 return((Quantum) (281479271743489.0*value));
646 }
647
ScaleQuantumToLong(const Quantum quantum)648 static inline unsigned int ScaleQuantumToLong(const Quantum quantum)
649 {
650 return((unsigned int) (quantum/4294967297.0+0.5));
651 }
652
ScaleQuantumToLongLong(const Quantum quantum)653 static inline MagickSizeType ScaleQuantumToLongLong(const Quantum quantum)
654 {
655 #if !defined(MAGICKCORE_HDRI_SUPPORT)
656 return((MagickSizeType) quantum);
657 #else
658 if (quantum <= 0.0)
659 return(0);
660 if (quantum >= 18446744073709551615)
661 return(18446744073709551615);
662 return((MagickSizeType) (quantum+0.5));
663 #endif
664 }
665
ScaleQuantumToMap(const Quantum quantum)666 static inline unsigned int ScaleQuantumToMap(const Quantum quantum)
667 {
668 if (quantum <= 0.0)
669 return(0UL);
670 if ((quantum/281479271743489.0) >= MaxMap)
671 return((unsigned int) MaxMap);
672 return((unsigned int) (quantum/281479271743489.0+0.5));
673 }
674
ScaleQuantumToShort(const Quantum quantum)675 static inline unsigned short ScaleQuantumToShort(const Quantum quantum)
676 {
677 if (quantum <= 0.0)
678 return(0);
679 if ((quantum/281479271743489.0) >= 65535.0)
680 return(65535);
681 return((unsigned short) (quantum/281479271743489.0+0.5));
682 }
683
ScaleShortToQuantum(const unsigned short value)684 static inline Quantum ScaleShortToQuantum(const unsigned short value)
685 {
686 return((Quantum) (281479271743489.0*value));
687 }
688 #endif
689
SinglePrecisionToHalf(const float value)690 static inline unsigned short SinglePrecisionToHalf(const float value)
691 {
692 typedef union _SinglePrecision
693 {
694 unsigned int
695 fixed_point;
696
697 float
698 single_precision;
699 } SinglePrecision;
700
701 register int
702 exponent;
703
704 register unsigned int
705 significand,
706 sign_bit;
707
708 SinglePrecision
709 map;
710
711 unsigned short
712 half;
713
714 /*
715 The IEEE 754 standard specifies half precision as having:
716
717 Sign bit: 1 bit
718 Exponent width: 5 bits
719 Significand precision: 11 (10 explicitly stored)
720 */
721 map.single_precision=value;
722 sign_bit=(map.fixed_point >> 16) & 0x00008000;
723 exponent=(int) ((map.fixed_point >> ExponentShift) & 0x000000ff)-ExponentBias;
724 significand=map.fixed_point & 0x007fffff;
725 if (exponent <= 0)
726 {
727 int
728 shift;
729
730 if (exponent < -10)
731 return((unsigned short) sign_bit);
732 significand=significand | 0x00800000;
733 shift=(int) (14-exponent);
734 significand=(unsigned int) ((significand+((1 << (shift-1))-1)+
735 ((significand >> shift) & 0x01)) >> shift);
736 return((unsigned short) (sign_bit | significand));
737 }
738 else
739 if (exponent == (0xff-ExponentBias))
740 {
741 if (significand == 0)
742 return((unsigned short) (sign_bit | ExponentMask));
743 else
744 {
745 significand>>=SignificandShift;
746 half=(unsigned short) (sign_bit | significand |
747 (significand == 0) | ExponentMask);
748 return(half);
749 }
750 }
751 significand=significand+((significand >> SignificandShift) & 0x01)+0x00000fff;
752 if ((significand & 0x00800000) != 0)
753 {
754 significand=0;
755 exponent++;
756 }
757 if (exponent > 30)
758 {
759 float
760 alpha;
761
762 register int
763 i;
764
765 /*
766 Float overflow.
767 */
768 alpha=1.0e10;
769 for (i=0; i < 10; i++)
770 alpha*=alpha;
771 return((unsigned short) (sign_bit | ExponentMask));
772 }
773 half=(unsigned short) (sign_bit | (exponent << 10) |
774 (significand >> SignificandShift));
775 return(half);
776 }
777
778 #if defined(__cplusplus) || defined(c_plusplus)
779 }
780 #endif
781
782 #endif
783