1 /*
2   Copyright 1999-2021 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   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 * magick_restrict pixels)185 static inline unsigned char *PopCharPixel(const unsigned char pixel,
186   unsigned char *magick_restrict pixels)
187 {
188   *pixels++=pixel;
189   return(pixels);
190 }
191 
PopLongPixel(const EndianType endian,const unsigned int pixel,unsigned char * magick_restrict pixels)192 static inline unsigned char *PopLongPixel(const EndianType endian,
193   const unsigned int pixel,unsigned char *magick_restrict pixels)
194 {
195   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 * magick_restrict pixels)214 static inline unsigned char *PopShortPixel(const EndianType endian,
215   const unsigned short pixel,unsigned char *magick_restrict pixels)
216 {
217   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 * magick_restrict pixels,unsigned char * magick_restrict pixel)232 static inline const unsigned char *PushCharPixel(
233   const unsigned char *magick_restrict pixels,
234   unsigned char *magick_restrict pixel)
235 {
236   *pixel=(*pixels++);
237   return(pixels);
238 }
239 
PushLongPixel(const EndianType endian,const unsigned char * magick_restrict pixels,unsigned int * magick_restrict pixel)240 static inline const unsigned char *PushLongPixel(const EndianType endian,
241   const unsigned char *magick_restrict pixels,
242   unsigned int *magick_restrict pixel)
243 {
244   unsigned int
245     quantum;
246 
247   if (endian == LSBEndian)
248     {
249       quantum=((unsigned int) *pixels++);
250       quantum|=((unsigned int) *pixels++ << 8);
251       quantum|=((unsigned int) *pixels++ << 16);
252       quantum|=((unsigned int) *pixels++ << 24);
253       *pixel=quantum;
254       return(pixels);
255     }
256   quantum=((unsigned int) *pixels++ << 24);
257   quantum|=((unsigned int) *pixels++ << 16);
258   quantum|=((unsigned int) *pixels++ << 8);
259   quantum|=((unsigned int) *pixels++);
260   *pixel=quantum;
261   return(pixels);
262 }
263 
PushShortPixel(const EndianType endian,const unsigned char * magick_restrict pixels,unsigned short * magick_restrict pixel)264 static inline const unsigned char *PushShortPixel(const EndianType endian,
265   const unsigned char *magick_restrict pixels,
266   unsigned short *magick_restrict pixel)
267 {
268   unsigned int
269     quantum;
270 
271   if (endian == LSBEndian)
272     {
273       quantum=(unsigned int) *pixels++;
274       quantum|=(unsigned int) (*pixels++ << 8);
275       *pixel=(unsigned short) (quantum & 0xffff);
276       return(pixels);
277     }
278   quantum=(unsigned int) (*pixels++ << 8);
279   quantum|=(unsigned int) *pixels++;
280   *pixel=(unsigned short) (quantum & 0xffff);
281   return(pixels);
282 }
283 
PushFloatPixel(const EndianType endian,const unsigned char * magick_restrict pixels,MagickFloatType * magick_restrict pixel)284 static inline const unsigned char *PushFloatPixel(const EndianType endian,
285   const unsigned char *magick_restrict pixels,
286   MagickFloatType *magick_restrict pixel)
287 {
288   union
289   {
290     unsigned int
291       unsigned_value;
292 
293     MagickFloatType
294       float_value;
295   } quantum;
296 
297   if (endian == LSBEndian)
298     {
299       quantum.unsigned_value=((unsigned int) *pixels++);
300       quantum.unsigned_value|=((unsigned int) *pixels++ << 8);
301       quantum.unsigned_value|=((unsigned int) *pixels++ << 16);
302       quantum.unsigned_value|=((unsigned int) *pixels++ << 24);
303       *pixel=quantum.float_value;
304       return(pixels);
305     }
306   quantum.unsigned_value=((unsigned int) *pixels++ << 24);
307   quantum.unsigned_value|=((unsigned int) *pixels++ << 16);
308   quantum.unsigned_value|=((unsigned int) *pixels++ << 8);
309   quantum.unsigned_value|=((unsigned int) *pixels++);
310   *pixel=quantum.float_value;
311   return(pixels);
312 }
313 
ScaleAnyToQuantum(const QuantumAny quantum,const QuantumAny range)314 static inline Quantum ScaleAnyToQuantum(const QuantumAny quantum,
315   const QuantumAny range)
316 {
317   if (quantum > range)
318     return(QuantumRange);
319 #if !defined(MAGICKCORE_HDRI_SUPPORT)
320   return((Quantum) ((double) QuantumRange*(quantum*
321     PerceptibleReciprocal((double) range))+0.5));
322 #else
323   return((Quantum) ((double) QuantumRange*(quantum*
324     PerceptibleReciprocal((double) range))));
325 #endif
326 }
327 
ScaleQuantumToAny(const Quantum quantum,const QuantumAny range)328 static inline QuantumAny ScaleQuantumToAny(const Quantum quantum,
329   const QuantumAny range)
330 {
331 #if !defined(MAGICKCORE_HDRI_SUPPORT)
332   return((QuantumAny) ((double) range*quantum/QuantumRange));
333 #else
334   if ((IsNaN(quantum) != 0) || (quantum <= 0.0))
335     return((QuantumAny) 0UL);
336   if (((double) range*quantum/QuantumRange) >= 18446744073709551615.0)
337     return((QuantumAny) MagickULLConstant(18446744073709551615));
338   return((QuantumAny) ((double) range*quantum/QuantumRange+0.5));
339 #endif
340 }
341 
342 #if (MAGICKCORE_QUANTUM_DEPTH == 8)
ScaleCharToQuantum(const unsigned char value)343 static inline Quantum ScaleCharToQuantum(const unsigned char value)
344 {
345   return((Quantum) value);
346 }
347 
ScaleLongToQuantum(const unsigned int value)348 static inline Quantum ScaleLongToQuantum(const unsigned int value)
349 {
350 #if !defined(MAGICKCORE_HDRI_SUPPORT)
351   return((Quantum) ((value)/16843009UL));
352 #else
353   return((Quantum) (value/16843009.0));
354 #endif
355 }
356 
ScaleLongLongToQuantum(const MagickSizeType value)357 static inline Quantum ScaleLongLongToQuantum(const MagickSizeType value)
358 {
359 #if !defined(MAGICKCORE_HDRI_SUPPORT)
360   return((Quantum) (value/MagickULLConstant(72340172838076673)));
361 #else
362   return((Quantum) (value/72340172838076673.0));
363 #endif
364 }
365 
ScaleMapToQuantum(const MagickRealType value)366 static inline Quantum ScaleMapToQuantum(const MagickRealType value)
367 {
368   if (value <= 0.0)
369     return((Quantum) 0);
370   if (value >= MaxMap)
371     return(QuantumRange);
372 #if !defined(MAGICKCORE_HDRI_SUPPORT)
373   return((Quantum) (value+0.5));
374 #else
375   return((Quantum) value);
376 #endif
377 }
378 
ScaleQuantumToLong(const Quantum quantum)379 static inline unsigned int ScaleQuantumToLong(const Quantum quantum)
380 {
381 #if !defined(MAGICKCORE_HDRI_SUPPORT)
382   return((unsigned int) (16843009UL*quantum));
383 #else
384   if ((IsNaN(quantum) != 0) || (quantum <= 0.0))
385     return(0U);
386   if ((16843009.0*quantum) >= 4294967295.0)
387     return(4294967295UL);
388   return((unsigned int) (16843009.0*quantum+0.5));
389 #endif
390 }
391 
ScaleQuantumToLongLong(const Quantum quantum)392 static inline MagickSizeType ScaleQuantumToLongLong(const Quantum quantum)
393 {
394 #if !defined(MAGICKCORE_HDRI_SUPPORT)
395   return((MagickSizeType) (MagickULLConstant(72340172838076673)*quantum));
396 #else
397   if ((IsNaN(quantum) != 0) || (quantum <= 0.0))
398     return(0UL);
399   if ((72340172838076673.0*quantum) >= 18446744073709551615.0)
400     return(MagickULLConstant(18446744073709551615));
401   return((MagickSizeType) (72340172838076673*quantum+0.5));
402 #endif
403 }
404 
ScaleQuantumToMap(const Quantum quantum)405 static inline unsigned int ScaleQuantumToMap(const Quantum quantum)
406 {
407   if (quantum >= (Quantum) MaxMap)
408     return((unsigned int) MaxMap);
409 #if !defined(MAGICKCORE_HDRI_SUPPORT)
410   return((unsigned int) quantum);
411 #else
412   if ((IsNaN(quantum) != 0) || (quantum <= 0.0))
413     return(0U);
414   return((unsigned int) (quantum+0.5));
415 #endif
416 }
417 
ScaleQuantumToShort(const Quantum quantum)418 static inline unsigned short ScaleQuantumToShort(const Quantum quantum)
419 {
420 #if !defined(MAGICKCORE_HDRI_SUPPORT)
421   return((unsigned short) (257UL*quantum));
422 #else
423   if ((IsNaN(quantum) != 0) || (quantum <= 0.0))
424     return(0);
425   if ((257.0*quantum) >= 65535.0)
426     return(65535);
427   return((unsigned short) (257.0*quantum+0.5));
428 #endif
429 }
430 
ScaleShortToQuantum(const unsigned short value)431 static inline Quantum ScaleShortToQuantum(const unsigned short value)
432 {
433 #if !defined(MAGICKCORE_HDRI_SUPPORT)
434   return((Quantum) ((value+128U)/257U));
435 #else
436   return((Quantum) (value/257.0));
437 #endif
438 }
439 #elif (MAGICKCORE_QUANTUM_DEPTH == 16)
ScaleCharToQuantum(const unsigned char value)440 static inline Quantum ScaleCharToQuantum(const unsigned char value)
441 {
442 #if !defined(MAGICKCORE_HDRI_SUPPORT)
443   return((Quantum) (257U*value));
444 #else
445   return((Quantum) (257.0*value));
446 #endif
447 }
448 
ScaleLongToQuantum(const unsigned int value)449 static inline Quantum ScaleLongToQuantum(const unsigned int value)
450 {
451 #if !defined(MAGICKCORE_HDRI_SUPPORT)
452   return((Quantum) ((value)/MagickULLConstant(65537)));
453 #else
454   return((Quantum) (value/65537.0));
455 #endif
456 }
457 
ScaleLongLongToQuantum(const MagickSizeType value)458 static inline Quantum ScaleLongLongToQuantum(const MagickSizeType value)
459 {
460 #if !defined(MAGICKCORE_HDRI_SUPPORT)
461   return((Quantum) ((value)/MagickULLConstant(281479271743489)));
462 #else
463   return((Quantum) (value/281479271743489.0));
464 #endif
465 }
466 
ScaleMapToQuantum(const MagickRealType value)467 static inline Quantum ScaleMapToQuantum(const MagickRealType value)
468 {
469   if (value <= 0.0)
470     return((Quantum) 0);
471   if (value >= MaxMap)
472     return(QuantumRange);
473 #if !defined(MAGICKCORE_HDRI_SUPPORT)
474   return((Quantum) (value+0.5));
475 #else
476   return((Quantum) value);
477 #endif
478 }
479 
ScaleQuantumToLong(const Quantum quantum)480 static inline unsigned int ScaleQuantumToLong(const Quantum quantum)
481 {
482 #if !defined(MAGICKCORE_HDRI_SUPPORT)
483   return((unsigned int) (65537UL*quantum));
484 #else
485   if ((IsNaN(quantum) != 0) || (quantum <= 0.0))
486     return(0U);
487   if ((65537.0*quantum) >= 4294967295.0)
488     return(4294967295U);
489   return((unsigned int) (65537.0*quantum+0.5));
490 #endif
491 }
492 
ScaleQuantumToLongLong(const Quantum quantum)493 static inline MagickSizeType ScaleQuantumToLongLong(const Quantum quantum)
494 {
495 #if !defined(MAGICKCORE_HDRI_SUPPORT)
496   return((MagickSizeType) (MagickULLConstant(281479271743489)*quantum));
497 #else
498   if ((IsNaN(quantum) != 0) || (quantum <= 0.0))
499     return(0UL);
500   if ((281479271743489.0*quantum) >= 18446744073709551615.0)
501     return(MagickULLConstant(18446744073709551615));
502   return((MagickSizeType) (281479271743489.0*quantum+0.5));
503 #endif
504 }
505 
ScaleQuantumToMap(const Quantum quantum)506 static inline unsigned int ScaleQuantumToMap(const Quantum quantum)
507 {
508   if (quantum >= (Quantum) MaxMap)
509     return((unsigned int) MaxMap);
510 #if !defined(MAGICKCORE_HDRI_SUPPORT)
511   return((unsigned int) quantum);
512 #else
513   if ((IsNaN(quantum) != 0) || (quantum <= 0.0))
514     return(0U);
515   return((unsigned int) (quantum+0.5));
516 #endif
517 }
518 
ScaleQuantumToShort(const Quantum quantum)519 static inline unsigned short ScaleQuantumToShort(const Quantum quantum)
520 {
521 #if !defined(MAGICKCORE_HDRI_SUPPORT)
522   return((unsigned short) quantum);
523 #else
524   if ((IsNaN(quantum) != 0) || (quantum <= 0.0))
525     return(0);
526   if (quantum >= 65535.0)
527     return(65535);
528   return((unsigned short) (quantum+0.5));
529 #endif
530 }
531 
ScaleShortToQuantum(const unsigned short value)532 static inline Quantum ScaleShortToQuantum(const unsigned short value)
533 {
534   return((Quantum) value);
535 }
536 #elif (MAGICKCORE_QUANTUM_DEPTH == 32)
ScaleCharToQuantum(const unsigned char value)537 static inline Quantum ScaleCharToQuantum(const unsigned char value)
538 {
539 #if !defined(MAGICKCORE_HDRI_SUPPORT)
540   return((Quantum) (16843009UL*value));
541 #else
542   return((Quantum) (16843009.0*value));
543 #endif
544 }
545 
ScaleLongToQuantum(const unsigned int value)546 static inline Quantum ScaleLongToQuantum(const unsigned int value)
547 {
548   return((Quantum) value);
549 }
550 
ScaleLongLongToQuantum(const MagickSizeType value)551 static inline Quantum ScaleLongLongToQuantum(const MagickSizeType value)
552 {
553 #if !defined(MAGICKCORE_HDRI_SUPPORT)
554   return((Quantum) ((value)/MagickULLConstant(4294967297)));
555 #else
556   return((Quantum) (value/4294967297.0));
557 #endif
558 }
559 
ScaleMapToQuantum(const MagickRealType value)560 static inline Quantum ScaleMapToQuantum(const MagickRealType value)
561 {
562   if (value <= 0.0)
563     return((Quantum) 0);
564   if (value >= (Quantum) MaxMap)
565     return(QuantumRange);
566 #if !defined(MAGICKCORE_HDRI_SUPPORT)
567   return((Quantum) (65537.0*value+0.5));
568 #else
569   return((Quantum) (65537.0*value));
570 #endif
571 }
572 
ScaleQuantumToLong(const Quantum quantum)573 static inline unsigned int ScaleQuantumToLong(const Quantum quantum)
574 {
575 #if !defined(MAGICKCORE_HDRI_SUPPORT)
576   return((unsigned int) quantum);
577 #else
578   if ((IsNaN(quantum) != 0) || (quantum <= 0.0))
579     return(0U);
580   if ((quantum) >= 4294967295.0)
581     return(4294967295);
582   return((unsigned int) (quantum+0.5));
583 #endif
584 }
585 
ScaleQuantumToLongLong(const Quantum quantum)586 static inline MagickSizeType ScaleQuantumToLongLong(const Quantum quantum)
587 {
588 #if !defined(MAGICKCORE_HDRI_SUPPORT)
589   return((MagickSizeType) (MagickULLConstant(4294967297)*quantum));
590 #else
591   if ((IsNaN(quantum) != 0) || (quantum <= 0.0))
592     return(0UL);
593   if ((4294967297.0*quantum) >= 18446744073709551615.0)
594     return(MagickULLConstant(18446744073709551615));
595   return((MagickSizeType) (4294967297.0*quantum+0.5));
596 #endif
597 }
598 
ScaleQuantumToMap(const Quantum quantum)599 static inline unsigned int ScaleQuantumToMap(const Quantum quantum)
600 {
601   if ((quantum/65537) >= (Quantum) MaxMap)
602     return((unsigned int) MaxMap);
603 #if !defined(MAGICKCORE_HDRI_SUPPORT)
604   return((unsigned int) ((quantum+MagickULLConstant(32768))/
605     MagickULLConstant(65537)));
606 #else
607   if ((IsNaN(quantum) != 0) || (quantum <= 0.0))
608     return(0U);
609   return((unsigned int) (quantum/65537.0+0.5));
610 #endif
611 }
612 
ScaleQuantumToShort(const Quantum quantum)613 static inline unsigned short ScaleQuantumToShort(const Quantum quantum)
614 {
615 #if !defined(MAGICKCORE_HDRI_SUPPORT)
616   return((unsigned short) ((quantum+MagickULLConstant(32768))/
617     MagickULLConstant(65537)));
618 #else
619   if ((IsNaN(quantum) != 0) || (quantum <= 0.0))
620     return(0);
621   if ((quantum/65537.0) >= 65535.0)
622     return(65535);
623   return((unsigned short) (quantum/65537.0+0.5));
624 #endif
625 }
626 
ScaleShortToQuantum(const unsigned short value)627 static inline Quantum ScaleShortToQuantum(const unsigned short value)
628 {
629 #if !defined(MAGICKCORE_HDRI_SUPPORT)
630   return((Quantum) (65537UL*value));
631 #else
632   return((Quantum) (65537.0*value));
633 #endif
634 }
635 #elif (MAGICKCORE_QUANTUM_DEPTH == 64)
ScaleCharToQuantum(const unsigned char value)636 static inline Quantum ScaleCharToQuantum(const unsigned char value)
637 {
638   return((Quantum) (72340172838076673.0*value));
639 }
640 
ScaleLongToQuantum(const unsigned int value)641 static inline Quantum ScaleLongToQuantum(const unsigned int value)
642 {
643   return((Quantum) (4294967297.0*value));
644 }
645 
ScaleLongLongToQuantum(const MagickSizeType value)646 static inline Quantum ScaleLongLongToQuantum(const MagickSizeType value)
647 {
648   return((Quantum) (value));
649 }
650 
ScaleMapToQuantum(const MagickRealType value)651 static inline Quantum ScaleMapToQuantum(const MagickRealType value)
652 {
653   if (value <= 0.0)
654     return((Quantum) 0);
655   if (value >= MaxMap)
656     return(QuantumRange);
657   return((Quantum) (281479271743489.0*value));
658 }
659 
ScaleQuantumToLong(const Quantum quantum)660 static inline unsigned int ScaleQuantumToLong(const Quantum quantum)
661 {
662   return((unsigned int) (quantum/4294967297.0+0.5));
663 }
664 
ScaleQuantumToLongLong(const Quantum quantum)665 static inline MagickSizeType ScaleQuantumToLongLong(const Quantum quantum)
666 {
667 #if !defined(MAGICKCORE_HDRI_SUPPORT)
668   return((MagickSizeType) quantum);
669 #else
670   if ((IsNaN(quantum) != 0) || (quantum <= 0.0))
671     return(0UL);
672   if (quantum >= 18446744073709551615.0)
673     return(MagickULLConstant(18446744073709551615));
674   return((MagickSizeType) (quantum+0.5));
675 #endif
676 }
677 
ScaleQuantumToMap(const Quantum quantum)678 static inline unsigned int ScaleQuantumToMap(const Quantum quantum)
679 {
680   if ((IsNaN(quantum) != 0) || (quantum <= 0.0))
681     return(0U);
682   if ((quantum/281479271743489.0) >= MaxMap)
683     return((unsigned int) MaxMap);
684   return((unsigned int) (quantum/281479271743489.0+0.5));
685 }
686 
ScaleQuantumToShort(const Quantum quantum)687 static inline unsigned short ScaleQuantumToShort(const Quantum quantum)
688 {
689   if ((IsNaN(quantum) != 0) || (quantum <= 0.0))
690     return(0);
691   if ((quantum/281479271743489.0) >= 65535.0)
692     return(65535);
693   return((unsigned short) (quantum/281479271743489.0+0.5));
694 }
695 
ScaleShortToQuantum(const unsigned short value)696 static inline Quantum ScaleShortToQuantum(const unsigned short value)
697 {
698   return((Quantum) (281479271743489.0*value));
699 }
700 #endif
701 
SinglePrecisionToHalf(const float value)702 static inline unsigned short SinglePrecisionToHalf(const float value)
703 {
704   typedef union _SinglePrecision
705   {
706     unsigned int
707       fixed_point;
708 
709     float
710       single_precision;
711   } SinglePrecision;
712 
713   int
714     exponent;
715 
716   unsigned int
717     significand,
718     sign_bit;
719 
720   SinglePrecision
721     map;
722 
723   unsigned short
724     half;
725 
726   /*
727     The IEEE 754 standard specifies half precision as having:
728 
729       Sign bit: 1 bit
730       Exponent width: 5 bits
731       Significand precision: 11 (10 explicitly stored)
732   */
733   map.single_precision=value;
734   sign_bit=(map.fixed_point >> 16) & 0x00008000;
735   exponent=(int) ((map.fixed_point >> ExponentShift) & 0x000000ff)-ExponentBias;
736   significand=map.fixed_point & 0x007fffff;
737   if (exponent <= 0)
738     {
739       int
740         shift;
741 
742       if (exponent < -10)
743         return((unsigned short) sign_bit);
744       significand=significand | 0x00800000;
745       shift=(int) (14-exponent);
746       significand=(unsigned int) ((significand+((1 << (shift-1))-1)+
747         ((significand >> shift) & 0x01)) >> shift);
748       return((unsigned short) (sign_bit | significand));
749     }
750   else
751     if (exponent == (0xff-ExponentBias))
752       {
753         if (significand == 0)
754           return((unsigned short) (sign_bit | ExponentMask));
755         else
756           {
757             significand>>=SignificandShift;
758             half=(unsigned short) (sign_bit | significand |
759               (significand == 0) | ExponentMask);
760             return(half);
761           }
762       }
763   significand=significand+((significand >> SignificandShift) & 0x01)+0x00000fff;
764   if ((significand & 0x00800000) != 0)
765     {
766       significand=0;
767       exponent++;
768     }
769   if (exponent > 30)
770     {
771       float
772         alpha;
773 
774       int
775         i;
776 
777       /*
778         Float overflow.
779       */
780       alpha=1.0e10;
781       for (i=0; i < 10; i++)
782         alpha*=alpha;
783       return((unsigned short) (sign_bit | ExponentMask));
784     }
785   half=(unsigned short) (sign_bit | (exponent << 10) |
786     (significand >> SignificandShift));
787   return(half);
788 }
789 
790 #if defined(__cplusplus) || defined(c_plusplus)
791 }
792 #endif
793 
794 #endif
795