blob: 3d88243aa65674afcbda03061176980a8e445b15 [file] [log] [blame]
cristy3ed852e2009-09-05 21:47:34 +00001/*
2 Copyright 1999-2008 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.
6 obtain a copy of the License at
7
8 http://www.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#if defined(__cplusplus) || defined(c_plusplus)
22extern "C" {
23#endif
24
25#include "magick/cache.h"
26
27typedef struct _QuantumState
28{
29 EndianType
30 endian;
31
32 double
33 minimum,
34 scale,
35 inverse_scale;
36
37 unsigned long
38 pixel,
39 bits;
40
41 const unsigned long
42 *mask;
43} QuantumState;
44
45struct _QuantumInfo
46{
47 unsigned long
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 unsigned long
70 number_threads;
71
72 unsigned char
73 **pixels;
74
75 size_t
76 extent;
77
78 SemaphoreInfo
79 *semaphore;
80
81 unsigned long
82 signature;
83};
84
cristy2a4d01c2010-01-10 21:14:51 +000085static inline MagickSizeType GetQuantumRange(const unsigned long depth)
86{
87 return((MagickSizeType) ((MagickULLConstant(1) << (depth-1))+
88 ((MagickULLConstant(1) << (depth-1))-1)));
89}
90
91static inline float HalfToSinglePrecision(const unsigned short half)
cristy5ab5fc82010-01-05 20:52:48 +000092{
cristy8a6a9802010-04-14 13:22:18 +000093#define ExponentBias (127-15)
cristy24fb7dc2010-01-10 20:15:51 +000094#define ExponentMask 0x7c00
95#define ExponentShift 23
cristybccb64f2010-01-10 21:16:36 +000096#define SignBitShift 31
cristy24fb7dc2010-01-10 20:15:51 +000097#define SignificandShift 13
98#define SignificandMask 0x00000400
cristy5ab5fc82010-01-05 20:52:48 +000099
cristy24fb7dc2010-01-10 20:15:51 +0000100 typedef union _SinglePrecision
101 {
102 unsigned int
103 fixed_point;
104
105 float
106 single_precision;
107 } SinglePrecision;
108
109 register unsigned int
110 exponent,
111 significand,
112 sign_bit;
113
114 SinglePrecision
115 map;
116
117 unsigned int
118 value;
119
120 /*
cristybccb64f2010-01-10 21:16:36 +0000121 The IEEE 754 standard specifies half precision as having:
cristy24fb7dc2010-01-10 20:15:51 +0000122
123 Sign bit: 1 bit
124 Exponent width: 5 bits
125 Significand precision: 11 (10 explicitly stored)
126 */
cristy2a4d01c2010-01-10 21:14:51 +0000127 sign_bit=(unsigned int) ((half >> 15) & 0x00000001);
128 exponent=(unsigned int) ((half >> 10) & 0x0000001f);
129 significand=(unsigned int) (half & 0x000003ff);
cristy24fb7dc2010-01-10 20:15:51 +0000130 if (exponent == 0)
131 {
cristy92caafa2010-05-10 12:56:29 +0000132 if (significand == 0)
cristy24fb7dc2010-01-10 20:15:51 +0000133 value=sign_bit << SignBitShift;
cristy92caafa2010-05-10 12:56:29 +0000134 else
135 {
cristy24fb7dc2010-01-10 20:15:51 +0000136 while ((significand & SignificandMask) == 0)
137 {
138 significand<<=1;
139 exponent--;
140 }
cristy92caafa2010-05-10 12:56:29 +0000141 exponent++;
cristy24fb7dc2010-01-10 20:15:51 +0000142 significand&=(~SignificandMask);
143 exponent+=ExponentBias;
144 value=(sign_bit << SignBitShift) | (exponent << ExponentShift) |
145 (significand << SignificandShift);
cristy92caafa2010-05-10 12:56:29 +0000146 }
cristy24fb7dc2010-01-10 20:15:51 +0000147 }
148 else
149 if (exponent == SignBitShift)
150 {
151 value=(sign_bit << SignBitShift) | 0x7f800000;
152 if (significand != 0)
153 value|=(significand << SignificandShift);
154 }
155 else
156 {
157 exponent+=ExponentBias;
158 significand<<=SignificandShift;
159 value=(sign_bit << SignBitShift) | (exponent << ExponentShift) |
160 significand;
161 }
162 map.fixed_point=value;
163 return(map.single_precision);
164}
cristy5ab5fc82010-01-05 20:52:48 +0000165
cristy3ed852e2009-09-05 21:47:34 +0000166static inline void InitializeQuantumState(const QuantumInfo *quantum_info,
167 const EndianType endian,QuantumState *quantum_state)
168{
169 static const unsigned long mask[32] =
170 {
171 0x00000000UL, 0x00000001UL, 0x00000003UL, 0x00000007UL, 0x0000000fUL,
172 0x0000001fUL, 0x0000003fUL, 0x0000007fUL, 0x000000ffUL, 0x000001ffUL,
173 0x000003ffUL, 0x000007ffUL, 0x00000fffUL, 0x00001fffUL, 0x00003fffUL,
174 0x00007fffUL, 0x0000ffffUL, 0x0001ffffUL, 0x0003ffffUL, 0x0007ffffUL,
175 0x000fffffUL, 0x001fffffUL, 0x003fffffUL, 0x007fffffUL, 0x00ffffffUL,
176 0x01ffffffUL, 0x03ffffffUL, 0x07ffffffUL, 0x0fffffffUL, 0x1fffffffUL,
177 0x3fffffffUL, 0x7fffffffUL
178 };
179
cristy3ed852e2009-09-05 21:47:34 +0000180 quantum_state->endian=endian;
181 quantum_state->minimum=quantum_info->minimum;
182 quantum_state->scale=quantum_info->scale;
cristy842f8822010-03-10 20:41:27 +0000183 quantum_state->inverse_scale=1.0;
cristy3ed852e2009-09-05 21:47:34 +0000184 if (quantum_state->scale != 0.0)
cristy09bee022010-03-10 20:45:09 +0000185 quantum_state->inverse_scale/=quantum_state->scale;
cristy842f8822010-03-10 20:41:27 +0000186 quantum_state->pixel=0UL;
187 quantum_state->bits=0UL;
cristy3ed852e2009-09-05 21:47:34 +0000188 quantum_state->mask=mask;
189}
190
cristy3ed852e2009-09-05 21:47:34 +0000191static inline unsigned char *PopCharPixel(const unsigned char pixel,
192 unsigned char *pixels)
193{
194 *pixels++=pixel;
195 return(pixels);
196}
197
198static inline unsigned char *PopLongPixel(const EndianType endian,
199 const unsigned long pixel,unsigned char *pixels)
200{
201 register unsigned int
202 quantum;
203
204 quantum=(unsigned int) pixel;
205 if (endian != LSBEndian)
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 *pixels++=(unsigned char) (quantum);
214 *pixels++=(unsigned char) (quantum >> 8);
215 *pixels++=(unsigned char) (quantum >> 16);
216 *pixels++=(unsigned char) (quantum >> 24);
217 return(pixels);
218}
219
220static inline unsigned char *PopShortPixel(const EndianType endian,
221 const unsigned short pixel,unsigned char *pixels)
222{
223 register unsigned int
224 quantum;
225
226 quantum=pixel;
227 if (endian != LSBEndian)
228 {
229 *pixels++=(unsigned char) (quantum >> 8);
230 *pixels++=(unsigned char) (quantum);
231 return(pixels);
232 }
233 *pixels++=(unsigned char) (quantum);
234 *pixels++=(unsigned char) (quantum >> 8);
235 return(pixels);
236}
237
238static inline const unsigned char *PushCharPixel(const unsigned char *pixels,
239 unsigned char *pixel)
240{
241 *pixel=(*pixels++);
242 return(pixels);
243}
244
245static inline const unsigned char *PushLongPixel(const EndianType endian,
246 const unsigned char *pixels,unsigned long *pixel)
247{
248 register unsigned int
249 quantum;
250
251 if (endian != LSBEndian)
252 {
253 quantum=(unsigned int) (*pixels++ << 24);
254 quantum|=(unsigned int) (*pixels++ << 16);
255 quantum|=(unsigned int) (*pixels++ << 8);
256 quantum|=(unsigned int) (*pixels++);
257 }
258 else
259 {
260 quantum=(unsigned int) (*pixels++);
261 quantum|=(unsigned int) (*pixels++ << 8);
262 quantum|=(unsigned int) (*pixels++ << 16);
263 quantum|=(unsigned int) (*pixels++ << 24);
264 }
265 *pixel=(unsigned long) (quantum & 0xffffffff);
266 return(pixels);
267}
268
269static inline const unsigned char *PushShortPixel(const EndianType endian,
270 const unsigned char *pixels,unsigned short *pixel)
271{
272 register unsigned int
273 quantum;
274
275 if (endian != LSBEndian)
276 {
277 quantum=(unsigned int) (*pixels++ << 8);
278 quantum|=(unsigned int) *pixels++;
279 }
280 else
281 {
282 quantum=(unsigned int) *pixels++;
283 quantum|=(unsigned int) (*pixels++ << 8);
284 }
285 *pixel=(unsigned short) (quantum & 0xffff);
286 return(pixels);
287}
288
289static inline Quantum ScaleAnyToQuantum(const QuantumAny quantum,
290 const QuantumAny range)
291{
cristyb3963e62010-05-09 21:36:40 +0000292#if !defined(MAGICKCORE_HDRI_SUPPORT)
cristy3ed852e2009-09-05 21:47:34 +0000293 return((Quantum) (((MagickRealType) QuantumRange*quantum)/range+0.5));
cristyb3963e62010-05-09 21:36:40 +0000294#else
cristydd2fd9f2010-05-10 01:43:37 +0000295 return((Quantum) (((MagickRealType) QuantumRange*quantum)/range));
cristyb3963e62010-05-09 21:36:40 +0000296#endif
cristy3ed852e2009-09-05 21:47:34 +0000297}
298
cristy3ed852e2009-09-05 21:47:34 +0000299static inline QuantumAny ScaleQuantumToAny(const Quantum quantum,
300 const QuantumAny range)
301{
cristy3ed852e2009-09-05 21:47:34 +0000302 return((QuantumAny) (((MagickRealType) range*quantum)/QuantumRange+0.5));
cristy3ed852e2009-09-05 21:47:34 +0000303}
304
305#if (MAGICKCORE_QUANTUM_DEPTH == 8)
306static inline Quantum ScaleCharToQuantum(const unsigned char value)
307{
308 return((Quantum) value);
309}
310
311static inline Quantum ScaleLongToQuantum(const unsigned long value)
312{
313#if !defined(MAGICKCORE_HDRI_SUPPORT)
314 return((Quantum) ((value+8421504UL)/16843009UL));
315#else
316 return((Quantum) (value/16843009.0));
317#endif
318}
319
320static inline Quantum ScaleMapToQuantum(const MagickRealType value)
321{
cristya45da3b2010-03-31 02:06:45 +0000322 if (value <= 0.0)
323 return((Quantum) 0);
cristya45da3b2010-03-31 02:06:45 +0000324 if (value >= MaxMap)
325 return((Quantum) QuantumRange);
cristydd2fd9f2010-05-10 01:43:37 +0000326#if !defined(MAGICKCORE_HDRI_SUPPORT)
327 return((Quantum) (value+0.5));
cristy3ed852e2009-09-05 21:47:34 +0000328#else
cristydd2fd9f2010-05-10 01:43:37 +0000329 return((Quantum) value);
cristy3ed852e2009-09-05 21:47:34 +0000330#endif
331}
332
333static inline unsigned long ScaleQuantumToLong(const Quantum quantum)
334{
335#if !defined(MAGICKCORE_HDRI_SUPPORT)
336 return((unsigned long) (16843009UL*quantum));
337#else
338 if (quantum <= 0.0)
339 return(0UL);
340 if ((16843009.0*quantum) >= 4294967295.0)
341 return(4294967295UL);
342 return((unsigned long) (16843009.0*quantum+0.5));
343#endif
344}
345
346static inline unsigned long ScaleQuantumToMap(const Quantum quantum)
347{
348 if (quantum >= (Quantum) MaxMap)
349 return((unsigned long) MaxMap);
350#if !defined(MAGICKCORE_HDRI_SUPPORT)
351 return((unsigned long) quantum);
352#else
cristydd2fd9f2010-05-10 01:43:37 +0000353 if (quantum < 0.0)
354 return(0UL);
cristy3ed852e2009-09-05 21:47:34 +0000355 return((unsigned long) (quantum+0.5));
356#endif
357}
358
359static inline unsigned short ScaleQuantumToShort(const Quantum quantum)
360{
361#if !defined(MAGICKCORE_HDRI_SUPPORT)
362 return((unsigned short) (257UL*quantum));
363#else
364 if (quantum <= 0.0)
365 return(0);
cristycd817db2010-05-09 03:05:41 +0000366 if ((257.0*quantum) >= 65535.0)
cristy3ed852e2009-09-05 21:47:34 +0000367 return(65535);
cristycd817db2010-05-09 03:05:41 +0000368 return((unsigned short) (257.0*quantum+0.5));
cristy3ed852e2009-09-05 21:47:34 +0000369#endif
370}
371
372static inline Quantum ScaleShortToQuantum(const unsigned short value)
373{
374#if !defined(MAGICKCORE_HDRI_SUPPORT)
cristye90d7402010-03-14 18:21:29 +0000375 return((Quantum) ((value+128U)/257U));
cristy3ed852e2009-09-05 21:47:34 +0000376#else
cristydd2fd9f2010-05-10 01:43:37 +0000377 return((Quantum) (value/257.0));
cristy3ed852e2009-09-05 21:47:34 +0000378#endif
379}
380#elif (MAGICKCORE_QUANTUM_DEPTH == 16)
381static inline Quantum ScaleCharToQuantum(const unsigned char value)
382{
383#if !defined(MAGICKCORE_HDRI_SUPPORT)
cristye90d7402010-03-14 18:21:29 +0000384 return((Quantum) (257U*value));
cristy3ed852e2009-09-05 21:47:34 +0000385#else
cristydd2fd9f2010-05-10 01:43:37 +0000386 return((Quantum) (257.0*value));
cristy3ed852e2009-09-05 21:47:34 +0000387#endif
388}
389
390static inline Quantum ScaleLongToQuantum(const unsigned long value)
391{
392#if !defined(MAGICKCORE_HDRI_SUPPORT)
393 return((Quantum) ((value+MagickULLConstant(32768))/
394 MagickULLConstant(65537)));
395#else
cristydd2fd9f2010-05-10 01:43:37 +0000396 return((Quantum) (value/65537.0));
cristy3ed852e2009-09-05 21:47:34 +0000397#endif
398}
399
400static inline Quantum ScaleMapToQuantum(const MagickRealType value)
401{
cristya45da3b2010-03-31 02:06:45 +0000402 if (value <= 0.0)
403 return((Quantum) 0);
cristya45da3b2010-03-31 02:06:45 +0000404 if (value >= MaxMap)
405 return((Quantum) QuantumRange);
cristydd2fd9f2010-05-10 01:43:37 +0000406#if !defined(MAGICKCORE_HDRI_SUPPORT)
407 return((Quantum) (value+0.5));
cristy3ed852e2009-09-05 21:47:34 +0000408#else
cristydd2fd9f2010-05-10 01:43:37 +0000409 return((Quantum) value);
cristy3ed852e2009-09-05 21:47:34 +0000410#endif
411}
412
413static inline unsigned long ScaleQuantumToLong(const Quantum quantum)
414{
415#if !defined(MAGICKCORE_HDRI_SUPPORT)
416 return((unsigned long) (65537UL*quantum));
417#else
418 if (quantum <= 0.0)
419 return(0UL);
cristycd817db2010-05-09 03:05:41 +0000420 if ((65537.0*quantum) >= 4294967295.0)
cristy3ed852e2009-09-05 21:47:34 +0000421 return(4294967295UL);
cristycd817db2010-05-09 03:05:41 +0000422 return((unsigned long) (65537.0*quantum+0.5));
cristy3ed852e2009-09-05 21:47:34 +0000423#endif
424}
425
426static inline unsigned long ScaleQuantumToMap(const Quantum quantum)
427{
428 if (quantum >= (Quantum) MaxMap)
429 return((unsigned long) MaxMap);
430#if !defined(MAGICKCORE_HDRI_SUPPORT)
431 return((unsigned long) quantum);
432#else
cristya8307572010-03-31 14:24:19 +0000433 if (quantum < 0.0)
434 return(0UL);
cristy3ed852e2009-09-05 21:47:34 +0000435 return((unsigned long) (quantum+0.5));
436#endif
437}
438
439static inline unsigned short ScaleQuantumToShort(const Quantum quantum)
440{
441#if !defined(MAGICKCORE_HDRI_SUPPORT)
442 return((unsigned short) quantum);
443#else
444 if (quantum <= 0.0)
445 return(0);
446 if (quantum >= 65535.0)
447 return(65535);
448 return((unsigned short) (quantum+0.5));
449#endif
450}
451
452static inline Quantum ScaleShortToQuantum(const unsigned short value)
453{
454 return((Quantum) value);
455}
456#elif (MAGICKCORE_QUANTUM_DEPTH == 32)
457static inline Quantum ScaleCharToQuantum(const unsigned char value)
458{
459#if !defined(MAGICKCORE_HDRI_SUPPORT)
460 return((Quantum) (16843009UL*value));
461#else
cristydd2fd9f2010-05-10 01:43:37 +0000462 return((Quantum) (16843009.0*value));
cristy3ed852e2009-09-05 21:47:34 +0000463#endif
464}
465
466static inline Quantum ScaleLongToQuantum(const unsigned long value)
467{
468 return((Quantum) value);
469}
470
471static inline Quantum ScaleMapToQuantum(const MagickRealType value)
472{
cristya45da3b2010-03-31 02:06:45 +0000473 if (value <= 0.0)
474 return((Quantum) 0);
cristydd2fd9f2010-05-10 01:43:37 +0000475 if (value >= (Quantum) MaxMap)
cristya45da3b2010-03-31 02:06:45 +0000476 return(QuantumRange);
cristydd2fd9f2010-05-10 01:43:37 +0000477#if !defined(MAGICKCORE_HDRI_SUPPORT)
478 return((Quantum) (65537.0*value+0.5));
cristy3ed852e2009-09-05 21:47:34 +0000479#else
cristydd2fd9f2010-05-10 01:43:37 +0000480 return((Quantum) (65537.0*value));
cristy3ed852e2009-09-05 21:47:34 +0000481#endif
482}
483
484static inline unsigned long ScaleQuantumToLong(const Quantum quantum)
485{
cristy0402ad32010-05-11 13:57:55 +0000486#if !defined(MAGICKCORE_HDRI_SUPPORT)
cristy3ed852e2009-09-05 21:47:34 +0000487 return((unsigned long) quantum);
cristy0402ad32010-05-11 13:57:55 +0000488#else
489 return((unsigned long) (quantum+0.5));
490#endif
cristy3ed852e2009-09-05 21:47:34 +0000491}
492
493static inline unsigned long ScaleQuantumToMap(const Quantum quantum)
494{
cristya45da3b2010-03-31 02:06:45 +0000495 if (quantum < 0.0)
496 return(0UL);
cristydd2fd9f2010-05-10 01:43:37 +0000497 if ((quantum/65537) >= (Quantum) MaxMap)
cristy3ed852e2009-09-05 21:47:34 +0000498 return((unsigned long) MaxMap);
499#if !defined(MAGICKCORE_HDRI_SUPPORT)
500 return((unsigned long) ((quantum+MagickULLConstant(32768))/
501 MagickULLConstant(65537)));
502#else
cristycd817db2010-05-09 03:05:41 +0000503 return((unsigned long) (quantum/65537.0+0.5));
cristy3ed852e2009-09-05 21:47:34 +0000504#endif
505}
506
507static inline unsigned short ScaleQuantumToShort(const Quantum quantum)
508{
509#if !defined(MAGICKCORE_HDRI_SUPPORT)
510 return((unsigned short) ((quantum+MagickULLConstant(32768))/
511 MagickULLConstant(65537)));
512#else
513 if (quantum <= 0.0)
514 return(0);
cristycd817db2010-05-09 03:05:41 +0000515 if ((quantum/65537.0) >= 65535.0)
cristy3ed852e2009-09-05 21:47:34 +0000516 return(65535);
cristycd817db2010-05-09 03:05:41 +0000517 return((unsigned short) (quantum/65537.0+0.5));
cristy3ed852e2009-09-05 21:47:34 +0000518#endif
519}
520
521static inline Quantum ScaleShortToQuantum(const unsigned short value)
522{
523#if !defined(MAGICKCORE_HDRI_SUPPORT)
524 return((Quantum) (65537UL*value));
525#else
cristy41f82a62010-05-10 13:05:18 +0000526 return((Quantum) (65537.0*value));
cristy3ed852e2009-09-05 21:47:34 +0000527#endif
528}
529#elif (MAGICKCORE_QUANTUM_DEPTH == 64)
530static inline Quantum ScaleCharToQuantum(const unsigned char value)
531{
cristydd2fd9f2010-05-10 01:43:37 +0000532 return((Quantum) (72340172838076673.0*value));
cristy3ed852e2009-09-05 21:47:34 +0000533}
534
535static inline Quantum ScaleLongToQuantum(const unsigned long value)
536{
cristydd2fd9f2010-05-10 01:43:37 +0000537 return((Quantum) (4294967295.0*value));
cristy3ed852e2009-09-05 21:47:34 +0000538}
539
540static inline Quantum ScaleMapToQuantum(const MagickRealType value)
541{
cristya45da3b2010-03-31 02:06:45 +0000542 if (value <= 0.0)
543 return((Quantum) 0);
cristya45da3b2010-03-31 02:06:45 +0000544 if (value >= MaxMap)
545 return(QuantumRange);
cristydd2fd9f2010-05-10 01:43:37 +0000546 return((Quantum) (281479271743489.0*value));
cristy3ed852e2009-09-05 21:47:34 +0000547}
548
549static inline unsigned long ScaleQuantumToLong(const Quantum quantum)
550{
cristycd817db2010-05-09 03:05:41 +0000551 return((unsigned long) (quantum/4294967297.0+0.5));
cristy3ed852e2009-09-05 21:47:34 +0000552}
553
554static inline unsigned long ScaleQuantumToMap(const Quantum quantum)
555{
cristy41f82a62010-05-10 13:05:18 +0000556 if (quantum <= 0.0)
cristydd2fd9f2010-05-10 01:43:37 +0000557 return(0UL);
cristy43513522010-05-11 13:46:36 +0000558 if ((quantum/281479271743489.0) >= MaxMap)
cristyfd891c52010-05-10 19:57:14 +0000559 return((unsigned long) MaxMap);
cristy43513522010-05-11 13:46:36 +0000560 return((unsigned long) (quantum/281479271743489.0+0.5));
cristy3ed852e2009-09-05 21:47:34 +0000561}
562
563static inline unsigned short ScaleQuantumToShort(const Quantum quantum)
564{
cristy43513522010-05-11 13:46:36 +0000565 return((unsigned short) (quantum/281479271743489.0+0.5));
cristy3ed852e2009-09-05 21:47:34 +0000566}
567
568static inline Quantum ScaleShortToQuantum(const unsigned short value)
569{
cristyb3963e62010-05-09 21:36:40 +0000570 return((Quantum) (281479271743489.0*value));
cristy3ed852e2009-09-05 21:47:34 +0000571}
572#endif
573
cristy2a4d01c2010-01-10 21:14:51 +0000574static inline unsigned short SinglePrecisionToHalf(const float value)
cristy24fb7dc2010-01-10 20:15:51 +0000575{
576 typedef union _SinglePrecision
577 {
578 unsigned int
579 fixed_point;
580
581 float
582 single_precision;
583 } SinglePrecision;
584
585 register int
586 exponent;
587
588 register unsigned int
589 significand,
590 sign_bit;
591
592 SinglePrecision
593 map;
594
595 unsigned short
cristy2a4d01c2010-01-10 21:14:51 +0000596 half;
cristy24fb7dc2010-01-10 20:15:51 +0000597
598 /*
cristybccb64f2010-01-10 21:16:36 +0000599 The IEEE 754 standard specifies half precision as having:
cristy24fb7dc2010-01-10 20:15:51 +0000600
601 Sign bit: 1 bit
602 Exponent width: 5 bits
603 Significand precision: 11 (10 explicitly stored)
604 */
605 map.single_precision=value;
606 sign_bit=(map.fixed_point >> 16) & 0x00008000;
607 exponent=(int) ((map.fixed_point >> ExponentShift) & 0x000000ff)-ExponentBias;
608 significand=map.fixed_point & 0x007fffff;
609 if (exponent <= 0)
610 {
611 long
612 shift;
613
614 if (exponent < -10)
615 return((unsigned short) sign_bit);
616 significand=significand | 0x00800000;
617 shift=14-exponent;
618 significand=(unsigned int) ((significand+((1 << (shift-1))-1)+
619 ((significand >> shift) & 0x01)) >> shift);
620 return((unsigned short) (sign_bit | significand));
621 }
622 else
623 if (exponent == (0xff-ExponentBias))
624 {
625 if (significand == 0)
626 return((unsigned short) (sign_bit | ExponentMask));
627 else
628 {
629 significand>>=SignificandShift;
cristy2a4d01c2010-01-10 21:14:51 +0000630 half=(unsigned short) (sign_bit | significand |
cristy24fb7dc2010-01-10 20:15:51 +0000631 (significand == 0) | ExponentMask);
cristy2a4d01c2010-01-10 21:14:51 +0000632 return(half);
cristy24fb7dc2010-01-10 20:15:51 +0000633 }
634 }
635 significand=significand+((significand >> SignificandShift) & 0x01)+0x00000fff;
636 if ((significand & 0x00800000) != 0)
637 {
638 significand=0;
639 exponent++;
640 }
641 if (exponent > 30)
642 {
643 float
644 alpha;
645
646 register long
647 i;
648
649 /*
650 Float overflow.
651 */
652 alpha=1.0e10;
653 for (i=0; i < 10; i++)
654 alpha*=alpha;
655 return((unsigned short) (sign_bit | ExponentMask));
656 }
cristy2a4d01c2010-01-10 21:14:51 +0000657 half=(unsigned short) (sign_bit | (exponent << 10) |
cristy24fb7dc2010-01-10 20:15:51 +0000658 (significand >> SignificandShift));
cristy2a4d01c2010-01-10 21:14:51 +0000659 return(half);
cristy24fb7dc2010-01-10 20:15:51 +0000660}
661
cristy3ed852e2009-09-05 21:47:34 +0000662#if defined(__cplusplus) || defined(c_plusplus)
663}
664#endif
665
666#endif