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