blob: d033117a1042ff851c3d96946933b8d749ac2e5a [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{
486 return((unsigned long) quantum);
487}
488
489static inline unsigned long ScaleQuantumToMap(const Quantum quantum)
490{
cristya45da3b2010-03-31 02:06:45 +0000491 if (quantum < 0.0)
492 return(0UL);
cristydd2fd9f2010-05-10 01:43:37 +0000493 if ((quantum/65537) >= (Quantum) MaxMap)
cristy3ed852e2009-09-05 21:47:34 +0000494 return((unsigned long) MaxMap);
495#if !defined(MAGICKCORE_HDRI_SUPPORT)
496 return((unsigned long) ((quantum+MagickULLConstant(32768))/
497 MagickULLConstant(65537)));
498#else
cristycd817db2010-05-09 03:05:41 +0000499 return((unsigned long) (quantum/65537.0+0.5));
cristy3ed852e2009-09-05 21:47:34 +0000500#endif
501}
502
503static inline unsigned short ScaleQuantumToShort(const Quantum quantum)
504{
505#if !defined(MAGICKCORE_HDRI_SUPPORT)
506 return((unsigned short) ((quantum+MagickULLConstant(32768))/
507 MagickULLConstant(65537)));
508#else
509 if (quantum <= 0.0)
510 return(0);
cristycd817db2010-05-09 03:05:41 +0000511 if ((quantum/65537.0) >= 65535.0)
cristy3ed852e2009-09-05 21:47:34 +0000512 return(65535);
cristycd817db2010-05-09 03:05:41 +0000513 return((unsigned short) (quantum/65537.0+0.5));
cristy3ed852e2009-09-05 21:47:34 +0000514#endif
515}
516
517static inline Quantum ScaleShortToQuantum(const unsigned short value)
518{
519#if !defined(MAGICKCORE_HDRI_SUPPORT)
520 return((Quantum) (65537UL*value));
521#else
cristy41f82a62010-05-10 13:05:18 +0000522 return((Quantum) (65537.0*value));
cristy3ed852e2009-09-05 21:47:34 +0000523#endif
524}
525#elif (MAGICKCORE_QUANTUM_DEPTH == 64)
526static inline Quantum ScaleCharToQuantum(const unsigned char value)
527{
cristydd2fd9f2010-05-10 01:43:37 +0000528 return((Quantum) (72340172838076673.0*value));
cristy3ed852e2009-09-05 21:47:34 +0000529}
530
531static inline Quantum ScaleLongToQuantum(const unsigned long value)
532{
cristydd2fd9f2010-05-10 01:43:37 +0000533 return((Quantum) (4294967295.0*value));
cristy3ed852e2009-09-05 21:47:34 +0000534}
535
536static inline Quantum ScaleMapToQuantum(const MagickRealType value)
537{
cristya45da3b2010-03-31 02:06:45 +0000538 if (value <= 0.0)
539 return((Quantum) 0);
cristya45da3b2010-03-31 02:06:45 +0000540 if (value >= MaxMap)
541 return(QuantumRange);
cristydd2fd9f2010-05-10 01:43:37 +0000542 return((Quantum) (281479271743489.0*value));
cristy3ed852e2009-09-05 21:47:34 +0000543}
544
545static inline unsigned long ScaleQuantumToLong(const Quantum quantum)
546{
cristycd817db2010-05-09 03:05:41 +0000547 return((unsigned long) (quantum/4294967297.0+0.5));
cristy3ed852e2009-09-05 21:47:34 +0000548}
549
550static inline unsigned long ScaleQuantumToMap(const Quantum quantum)
551{
cristy41f82a62010-05-10 13:05:18 +0000552 if (quantum <= 0.0)
cristydd2fd9f2010-05-10 01:43:37 +0000553 return(0UL);
cristy43513522010-05-11 13:46:36 +0000554 if ((quantum/281479271743489.0) >= MaxMap)
cristyfd891c52010-05-10 19:57:14 +0000555 return((unsigned long) MaxMap);
cristy43513522010-05-11 13:46:36 +0000556 return((unsigned long) (quantum/281479271743489.0+0.5));
cristy3ed852e2009-09-05 21:47:34 +0000557}
558
559static inline unsigned short ScaleQuantumToShort(const Quantum quantum)
560{
cristy43513522010-05-11 13:46:36 +0000561 return((unsigned short) (quantum/281479271743489.0+0.5));
cristy3ed852e2009-09-05 21:47:34 +0000562}
563
564static inline Quantum ScaleShortToQuantum(const unsigned short value)
565{
cristyb3963e62010-05-09 21:36:40 +0000566 return((Quantum) (281479271743489.0*value));
cristy3ed852e2009-09-05 21:47:34 +0000567}
568#endif
569
cristy2a4d01c2010-01-10 21:14:51 +0000570static inline unsigned short SinglePrecisionToHalf(const float value)
cristy24fb7dc2010-01-10 20:15:51 +0000571{
572 typedef union _SinglePrecision
573 {
574 unsigned int
575 fixed_point;
576
577 float
578 single_precision;
579 } SinglePrecision;
580
581 register int
582 exponent;
583
584 register unsigned int
585 significand,
586 sign_bit;
587
588 SinglePrecision
589 map;
590
591 unsigned short
cristy2a4d01c2010-01-10 21:14:51 +0000592 half;
cristy24fb7dc2010-01-10 20:15:51 +0000593
594 /*
cristybccb64f2010-01-10 21:16:36 +0000595 The IEEE 754 standard specifies half precision as having:
cristy24fb7dc2010-01-10 20:15:51 +0000596
597 Sign bit: 1 bit
598 Exponent width: 5 bits
599 Significand precision: 11 (10 explicitly stored)
600 */
601 map.single_precision=value;
602 sign_bit=(map.fixed_point >> 16) & 0x00008000;
603 exponent=(int) ((map.fixed_point >> ExponentShift) & 0x000000ff)-ExponentBias;
604 significand=map.fixed_point & 0x007fffff;
605 if (exponent <= 0)
606 {
607 long
608 shift;
609
610 if (exponent < -10)
611 return((unsigned short) sign_bit);
612 significand=significand | 0x00800000;
613 shift=14-exponent;
614 significand=(unsigned int) ((significand+((1 << (shift-1))-1)+
615 ((significand >> shift) & 0x01)) >> shift);
616 return((unsigned short) (sign_bit | significand));
617 }
618 else
619 if (exponent == (0xff-ExponentBias))
620 {
621 if (significand == 0)
622 return((unsigned short) (sign_bit | ExponentMask));
623 else
624 {
625 significand>>=SignificandShift;
cristy2a4d01c2010-01-10 21:14:51 +0000626 half=(unsigned short) (sign_bit | significand |
cristy24fb7dc2010-01-10 20:15:51 +0000627 (significand == 0) | ExponentMask);
cristy2a4d01c2010-01-10 21:14:51 +0000628 return(half);
cristy24fb7dc2010-01-10 20:15:51 +0000629 }
630 }
631 significand=significand+((significand >> SignificandShift) & 0x01)+0x00000fff;
632 if ((significand & 0x00800000) != 0)
633 {
634 significand=0;
635 exponent++;
636 }
637 if (exponent > 30)
638 {
639 float
640 alpha;
641
642 register long
643 i;
644
645 /*
646 Float overflow.
647 */
648 alpha=1.0e10;
649 for (i=0; i < 10; i++)
650 alpha*=alpha;
651 return((unsigned short) (sign_bit | ExponentMask));
652 }
cristy2a4d01c2010-01-10 21:14:51 +0000653 half=(unsigned short) (sign_bit | (exponent << 10) |
cristy24fb7dc2010-01-10 20:15:51 +0000654 (significand >> SignificandShift));
cristy2a4d01c2010-01-10 21:14:51 +0000655 return(half);
cristy24fb7dc2010-01-10 20:15:51 +0000656}
657
cristy3ed852e2009-09-05 21:47:34 +0000658#if defined(__cplusplus) || defined(c_plusplus)
659}
660#endif
661
662#endif