Coverage Report

Created: 2026-01-20 07:37

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/graphicsmagick/magick/floats.c
Line
Count
Source
1
/*
2
  Copyright (C) 2008 - 2015 GraphicsMagick Group
3
4
  This program is covered by multiple licenses, which are described in
5
  Copyright.txt. You should have received a copy of Copyright.txt with this
6
  package; otherwise see http://www.graphicsmagick.org/www/Copyright.html.
7
8
  16/24 bit floating point conversion functions
9
10
  Written by Richard Nolde, 2008
11
12
*/
13

14
/*
15
  Include declarations.
16
*/
17
#include "magick/studio.h"
18
#include "magick/floats.h"
19

20
0
#define FP16_MANT_BITS 10
21
0
#define FP24_MANT_BITS 16
22
#define FP32_MANT_BITS 23
23
#define FP64_MANT_BITS 52
24
25
MagickExport
26
int _Gm_convert_fp16_to_fp32 (const fp_16bits *fp16, float *fp32)
27
1.76M
{
28
1.76M
  unsigned char  sbit; /* sign bit */
29
1.76M
  unsigned char  expt; /* exponent bits */
30
1.76M
  unsigned char  m2, m1;  /* MSB to LSB of mantissa */
31
1.76M
  unsigned char  new_expt;
32
1.76M
  unsigned char  new_m3, new_m2, new_m1;
33
1.76M
  unsigned char *src;
34
1.76M
  unsigned char *dst;
35
36
#ifdef DEBUG32
37
  /* Debugging variables */
38
  int            i, j, bit;
39
  unsigned int  mant;
40
  double         test  = 0.0;
41
  double         test2 = 0.0;
42
  double         accum = 0.0;
43
44
  errno = 0;
45
#endif
46
47
1.76M
  assert (sizeof(int) == 4);
48
1.76M
  if ((fp16 == NULL) || (fp32 == NULL))
49
0
    {
50
0
      fprintf (stderr, "Invalid src or destination pointers\n");
51
0
      return (1);
52
0
    }
53
1.76M
  sbit=0;
54
1.76M
  src = (unsigned char *)fp16;
55
1.76M
  dst = (unsigned char *)fp32;
56
1.76M
  new_expt = expt = 0;
57
1.76M
  new_m3 = new_m2 = new_m1 = m2 = m1 = 0;
58
59
  /* For zero, all bits except possibly sbit are zero */
60
1.76M
  if ((src[0] | src[1]) != 0U)
61
1.34M
    {
62
1.34M
#if !defined(WORDS_BIGENDIAN)
63
1.34M
        {
64
1.34M
          sbit =  *(src + 1) & 0x80;
65
1.34M
          expt = (*(src + 1) & 0x7F) >> 2;
66
1.34M
          m2 =    *(src + 1) & 0x03;
67
1.34M
          m1 = *src;
68
1.34M
        }
69
#else
70
        {
71
          sbit =  *src & 0x80;
72
          expt = (*src & 0x7F) >> 2;
73
          m2 =    *src & 0x03;
74
          m1 =  *(src + 1);
75
        }
76
#endif /* !defined(WORDS_BIGENDIAN) */
77
78
1.34M
      if (expt != 0)
79
197k
        new_expt = expt - 15 + 127;
80
1.34M
      new_m3  =  (m2 << 5) | (m1 & 0xF8) >> 3;
81
1.34M
      new_m2  =  (m1 & 7) << 5;
82
1.34M
      new_m1  = 0;
83
1.34M
    }
84
1.76M
#if !defined(WORDS_BIGENDIAN)
85
1.76M
    {
86
1.76M
      *dst = new_m1;
87
1.76M
      *(dst + 1) = new_m2;
88
1.76M
      *(dst + 2) = ((new_expt & 1) << 7) | new_m3;
89
1.76M
      *(dst + 3) = sbit | (new_expt >> 1);
90
1.76M
    }
91
#else
92
    {
93
      *dst = sbit | (new_expt >> 1);
94
      *(dst + 1) = ((new_expt & 1) << 7) | new_m3;
95
      *(dst + 2) = new_m2;
96
      *(dst + 3) = new_m1;
97
    }
98
#endif /* !defined(WORDS_BIGENDIAN) */
99
100
  /* Underflow and overflow will not be a problem
101
   * since target has more significant bits that
102
   * the source.
103
   */
104
#ifdef DEBUG32
105
  /* Debugging code for display only */
106
  mant = ((unsigned int)new_m3 << 16) | ((unsigned int)new_m2 << 8) | (unsigned int)new_m1;
107
  if (new_expt == 0)
108
    {
109
      test = 0.0;
110
      test2 = 0.0;
111
      accum = 0.0;
112
    }
113
  else
114
    {
115
      accum = 0.0;
116
      for (i = 22, j = 1; i >= 0; i--, j++)
117
        {
118
          bit = mant & ((unsigned int)1 << i);
119
          if (bit)
120
            accum += (1.0 / ((unsigned int)1 << j));
121
        }
122
      accum += 1.0;
123
      test = pow (2.0, 1.0 * (new_expt - 127));
124
      switch (errno)
125
        {
126
        case 0:     break;
127
        case EDOM:
128
        case ERANGE:
129
        default: perror ("Invalid value");
130
          break;
131
        }
132
      test2 = accum * test;
133
      if (sbit)
134
        test2 *= -1.0;
135
    }
136
  printf ("              Sign bit: %u, Expt biased to %5u,  2^%-5d = %8.1f  *  %10.8f = %18.10f\n\n",
137
          sbit > 0 ? 1 : 0, new_expt, new_expt > 0 ? new_expt - 127 : 0, test, accum, test2);
138
#endif
139
1.76M
  return (0);
140
1.76M
} /* end convertfp16_to_fp32 */
141
142
MagickExport
143
int _Gm_convert_fp32_to_fp16 (const float *fp32, fp_16bits *fp16, const int mode)
144
0
{
145
0
  int            i, bit, rbits, rshift;
146
0
  unsigned char  sbit = 0;   /* sign bit */
147
0
  unsigned char  expt = 0;   /* exponent bits */
148
0
  unsigned char  m3, m2, m1; /* MSB to LSB of mantissa */
149
0
  signed   short new_expt;
150
0
  unsigned short new_mant;
151
0
  unsigned short mant;
152
0
  unsigned char *src;
153
0
  unsigned char *dst;
154
0
  unsigned char *mp;
155
156
#ifdef DEBUG16
157
  int     j, k;
158
  double  test = 0.0;
159
  double  test2 = 0.0;
160
  double  accum = 0.0;
161
  double  roundup = 0.0;
162
163
  errno = 0;
164
#endif
165
166
0
  assert (sizeof(int) == 4);
167
0
  if ((fp32 == NULL) || (fp16 == NULL))
168
0
    {
169
0
      fprintf (stderr, "Invalid src or destination pointers\n");
170
0
      return (1);
171
0
    }
172
173
0
  src = (unsigned char *)fp32;
174
0
  dst = (unsigned char *)fp16;
175
0
  mp  = (unsigned char *)&mant;
176
177
0
  new_expt = expt = 0;
178
0
  mant = new_mant = 0;
179
0
  m2 = m1 = 0;
180
0
  rbits = 0;
181
182
  /* For zero, all bits except possibly sbit are zero */
183
0
  if (*fp32 == 0)
184
0
    *dst = 0;
185
0
  else
186
0
    {
187
0
#if !defined(WORDS_BIGENDIAN)
188
0
        {
189
0
          sbit =   *(src + 3) & 0x80;
190
0
          expt = ((*(src + 3) & 0x7F) << 1) |
191
0
            ((*(src + 2) & 0x80) >> 7);
192
          /* Extract mantissa and left align bits */
193
0
          m3  = (((*(src + 2) & 0x7F)) << 1) |
194
0
            ((*(src + 1) & 0x80) >> 7);
195
0
          m2  = (((*(src + 1) & 0x7F)) << 1)  |
196
0
            ((*src & 0x80) >> 7);
197
0
          m1  =  (*src & 0x7F) << 1;
198
0
        }
199
#else
200
        {
201
          sbit =   *src & 0x80;
202
          expt = ((*src & 0x7F) << 1) |
203
            ((*(src + 1) & 0x80) >> 7);
204
          /* Extract mantissa and left align bits */
205
          m3  = (((*(src + 1) & 0x7F)) << 1) |
206
            ((*(src + 2) & 0x80) >> 7);
207
          m2  = (((*(src + 2) & 0x7F)) << 1)  |
208
            ((*(src + 3) & 0x80) >> 7);
209
          m1  =  (*(src + 3) & 0x7F) << 1;
210
        }
211
#endif /* !defined(WORDS_BIGENDIAN) */
212
213
      /* Extract the 16 MSB from the mantissa */
214
0
      mant = (m3 << 8) | m2;
215
0
      if (expt != 0)  /* Normal number */
216
0
        new_expt = expt - 127 + 15;
217
218
      /* Even if the new exponent is too small to represent,
219
       * the mantissa could have significant digits that can
220
       * be represented in the new value as a subnormal.
221
       */
222
0
      if (new_expt <= 0) /* Underflow */
223
0
        {
224
0
          rshift = 1 - new_expt;
225
0
          switch (mode)
226
0
            {
227
0
            case STRICT_IEEE: /* NaN has all 1s in exponent plus 2 bits in Mantissa */
228
0
              if (rshift > FP16_MANT_BITS)
229
0
                {
230
0
                  new_expt = 31;
231
0
                  new_mant = 513;
232
0
                  errno = ERANGE;
233
0
                  fflush (stdout);
234
0
                  fprintf (stderr, "Underflow. Result clipped\n");
235
0
                  fflush (stderr);
236
0
                  return (1);  /* The number cannot be represented as fp16 */
237
0
                }
238
0
              break;
239
0
            case RANGE_LIMITED: /* Clamp to smallest subnormal */
240
0
              new_expt = 0;
241
0
              new_mant = mant >> rshift;;
242
0
              mp = (unsigned char *)&new_mant;
243
#ifdef DEBUG16
244
              if (mant != 0)
245
                {
246
                  fflush (stdout);
247
                  fprintf (stderr, "Underflow. %18.10f Result clippped to subnormal value\n", *fp32);
248
                  fflush (stderr);
249
                }
250
#endif
251
0
              break;
252
0
            case ZERO_LIMITED:  /* Clamp to zero instead of using a subnormal */
253
0
              new_expt = 0;
254
0
              new_mant = 0;
255
0
              mp = (unsigned char *)&new_mant;
256
#ifdef DEBUG16
257
              if (mant != 0)
258
                {
259
                  fflush (stdout);
260
                  fprintf (stderr, "Underflow. %18.10f Result clippped to zero\n", *fp32);
261
                  fflush (stderr);
262
                }
263
#endif
264
0
              break;
265
0
            }
266
0
        }
267
0
      else /* Take the MSB from the old mantissa and left justify them */
268
0
        {
269
0
          if (new_expt > 30) /* Overflow */
270
0
            {
271
0
              switch (mode)
272
0
                {
273
0
                case STRICT_IEEE: /* NaN has all 1s in exponent plus 2 bits in Mantissa */
274
0
                  new_expt = 31;
275
0
                  new_mant = 513;
276
0
                  errno = ERANGE;
277
0
                  fflush (stdout);
278
0
                  fprintf (stderr, "Overflow. %18.10f Result clipped\n", *fp32);
279
0
                  fflush (stderr);
280
0
                  return (1);
281
0
                case ZERO_LIMITED:
282
0
                case RANGE_LIMITED:  /* Clamp to maximum allowed value for fp16 */
283
0
                  new_expt = 30;
284
0
                  new_mant = 1023;
285
0
                  mp = (unsigned char *)&new_mant;
286
#ifdef DEBUG16
287
                  fflush (stdout);
288
                  fprintf (stderr, "Overflow. %18.10f Result clippped\n", *fp32);
289
                  fflush (stderr);
290
#endif
291
0
                  break;
292
0
                }
293
0
            }
294
0
          else /* Normal value within range of target type */
295
0
            {
296
              /* Check bits to the right of unit in last significant place
297
               * for destination, eg first digit that cannot be stored.
298
               * Rounding of least significant retained bit falls to value
299
               * which will produce a zero in the LSB if the bounding values
300
               * are equidistant from the unrounded value.
301
               */
302
0
              rbits = mant & 0x3F;
303
0
              if (rbits >= 0x20)  /* Greater than or equal to 0.5 times LSB */
304
0
                {
305
0
                  if (rbits > 0x20) /* Rbits is greater than half of LSB */
306
0
                    {
307
                      /* Round up to next higher value of LSB */
308
0
                      for (i = 6; i < 16; i++)
309
0
                        {
310
0
                          bit = mant & (1 << i);
311
0
                          if (bit == 0)
312
0
                            {
313
0
                              new_mant = (mant | ((unsigned short)1 << i)) & (0xFFFFU << i);
314
0
                              mp  = (unsigned char *)&new_mant;
315
0
                              break;
316
0
                            }
317
0
                        }
318
0
                    }
319
0
                  else    /* Rbits is exactly half of LSB */
320
0
                    {
321
0
                      if ((mant & 0x40)) /* LSB is one so we round up */
322
0
                        {
323
                          /* Round up to next higher value of LSB */
324
0
                          for (i = 6; i < 10; i++)
325
0
                            {
326
0
                              bit = mant & (1 << i);
327
0
                              if (bit == 0)
328
0
                                {
329
0
                                  new_mant = (mant | ((unsigned short)1 << i)) & (0xFFFFU << i);
330
0
                                  mp  = (unsigned char *)&new_mant;
331
0
                                  break;
332
0
                                }
333
0
                            }
334
0
                        }
335
0
                    }
336
0
                }
337
0
            }
338
0
        }
339
340
      /* Extract bits into contiguous positions in bytes */
341
0
#if !defined(WORDS_BIGENDIAN)
342
0
        {
343
0
          m2 =  (*(mp + 1) & 0xC0) >> 6;
344
0
          m1 = ((*(mp + 1) & 0x3F) << 2) |
345
0
            ((*mp & 0xC0) >> 6);
346
0
          *dst = m1;
347
0
          *(dst + 1) = sbit | ((new_expt & 0x1F) << 2) | m2;
348
0
        }
349
#else
350
        {
351
          m2 = (*mp & 0xC0) >> 6;
352
          m1 = ((*mp & 0x3F) << 2) |
353
            ((*(mp + 1) & 0xC0) >> 6);
354
          *dst = sbit | ((new_expt & 0x1F) << 2) | m2;
355
          *(dst + 1) = m1;
356
        }
357
#endif /* !defined(WORDS_BIGENDIAN) */
358
0
    }
359
360
#ifdef DEBUG16
361
  /* Debugging code to display the result */
362
  new_mant = (m2 << 8) | m1;
363
  printf ("%10.10f mant%s ", *fp32, (rbits & 0x20) ? "+" : "-");
364
  for (j = 0, k = 15; j < 16; j++, k--)
365
    {
366
      bit = mant & (1 << k);
367
      printf ("%d", bit ? 1 : 0);
368
      if (j == 9)
369
        printf (" ");
370
      if (bit && (j > 9))
371
        roundup += (1.0 / (double)(1 << (j - 9)));
372
    }
373
  if (new_mant == 0)
374
    {
375
      printf (" Fract: %8.6f  m2m1 ", roundup);
376
      for (j = 0, k = 1; j < 2; j++, k--)
377
        {
378
          bit = m2 & (1 << k);
379
          printf ("%d", bit ? 1 : 0);
380
        }
381
      for (j = 0, k = 7; j < 8; j++, k--)
382
        {
383
          bit = m1 & (1 << k);
384
          printf ("%d", bit ? 1 : 0);
385
        }
386
    }
387
  else
388
    {
389
      printf (" Fract: %8.6f  Rbits Mant ", roundup);
390
      for (j = 0, k = 9; j < 10; j++, k--)
391
        {
392
          bit = new_mant & (1 << k);
393
          printf ("%d", bit ? 1 : 0);
394
        }
395
    }
396
  printf (" Sbit + Exp ");
397
#if !defined(WORDS_BIGENDIAN)
398
    {
399
      for (i = 1; i >= 0; i--)
400
        {
401
          for (j = 0, k = 7; j < 8; j++, k--)
402
            {
403
              bit = *(dst + i) & (1 << k);
404
              printf ("%d", bit ? 1 : 0);
405
              if (i == 1 && j == 5)
406
                printf ("  Mant: ");
407
            }
408
        }
409
    }
410
#else
411
    {
412
      for (i = 0; i < 2; i++)
413
        {
414
          for (j = 0, k = 7; j < 8; j++, k--)
415
            {
416
              bit = *(dst + i) & (1 << k);
417
              printf ("%d", bit ? 1 : 0);
418
              if (i == 0 && j == 5)
419
                printf ("  Mant: ");
420
            }
421
        }
422
    }
423
#endif /* !defined(WORDS_BIGENDIAN) */
424
  printf ("\n");
425
426
  mant = ((unsigned short)m2 << 8) | (unsigned short)m1;
427
  if (*fp32 == 0)
428
    {
429
      test = 0.0;
430
      test2 = 0.0;
431
      accum = 0.0;
432
    }
433
  else
434
    {
435
      accum = 0.0;
436
      for (i = 9, j = 1; i >= 0; i--, j++)
437
        {
438
          bit = mant & ((unsigned int)1 << i);
439
          if (bit)
440
            accum += (1.0 / ((unsigned int)1 << j));
441
        }
442
      if (new_expt == 0)
443
        {
444
          accum += 2.0;
445
          test = pow (2.0, 1.0 * (-15 - rshift));
446
        }
447
      else
448
        {
449
          accum += 1.0;
450
          test = pow (2.0, 1.0 * (new_expt - 15));
451
        }
452
      switch (errno)
453
        {
454
        case 0:     break;
455
        case EDOM:
456
        case ERANGE:
457
        default: perror ("Invalid value");
458
          break;
459
        }
460
      test2 = accum * test;
461
      if (sbit)
462
        test2 *= -1.0;
463
    }
464
  printf ("              Sign bit: %u, Expt biased to %5u,  2^%-5d = %8.10f  *  %10.8f = %18.10f\n\n",
465
          sbit > 0 ? 1 : 0, new_expt, new_expt > 0 ? new_expt - 15 : 0, test, accum, test2);
466
#endif
467
0
  return (0);
468
0
} /* end _Gm_convert_fp32_to_fp16 */
469
470
MagickExport
471
int _Gm_convert_fp24_to_fp32 (const fp_24bits *fp24, float *fp32, const int mode)
472
557k
{
473
557k
  unsigned char  sbit = 0;           /* sign bit */
474
557k
  unsigned char  expt = 0, new_expt; /* exponent bits */
475
557k
  unsigned char  m2, m1;    /* MSB to LSB of mantissa */
476
557k
  unsigned char  new_m3, new_m2, new_m1;
477
  /* unsigned short mant; */
478
  /* unsigned int   new_mant; */
479
  /* unsigned char *mp; */
480
557k
  unsigned char *src;
481
557k
  unsigned char *dst;
482
483
#ifdef DEBUG32
484
  int      i, j, k, bit;
485
  double   test  = 0.0;
486
  double   test2 = 0.0;
487
  double   accum = 0.0;
488
  errno = 0;
489
#endif
490
491
557k
  (void) mode;
492
557k
  assert (sizeof(int) == 4);
493
557k
  if ((fp24 == NULL) || (fp32 == NULL))
494
0
    {
495
0
      fprintf (stderr, "Invalid src or destination pointers\n");
496
0
      return (1);
497
0
    }
498
499
557k
  src = (unsigned char *)fp24;
500
557k
  dst = (unsigned char *)fp32;
501
  /* mp  = (unsigned char *)&mant; */
502
503
557k
  new_expt = expt = 0;
504
  /* new_mant = mant = 0; */
505
557k
  new_m3 = new_m2 = new_m1 = m2 = m1 = 0;
506
507
  /* For zero, all bits except possibly sbit are zero */
508
557k
  if ((src[0] | src[1] | src[2]) == 0U)
509
132k
    {
510
132k
      *dst = 0;
511
132k
      *(dst + 1) = 0;
512
132k
      *(dst + 2) = 0;
513
132k
      *(dst + 3) = 0;
514
132k
    }
515
424k
  else
516
424k
    {
517
424k
#if !defined(WORDS_BIGENDIAN)
518
424k
        {
519
424k
          sbit = *(src + 2) & 0x80;
520
424k
          expt = *(src + 2) & 0x7F;
521
424k
          m2  =  *(src + 1);
522
424k
          m1  =  *src;
523
424k
        }
524
#else
525
        {
526
          sbit = *src & 0x80;
527
          expt = *src & 0x7F;
528
          m2  =  *(src + 1);
529
          m1  =  *(src + 2);
530
        }
531
#endif /* !defined(WORDS_BIGENDIAN) */
532
533
424k
      if (expt != 0)
534
343k
        new_expt = expt - 63 + 127;
535
      /* mant = (m2 << 8) | m1; */
536
424k
      new_m3  =  (m2 & 0xFE) >> 1;
537
424k
      new_m2  = ((m2 & 0x01) << 7) | ((m1 & 0xFE) >> 1);
538
424k
      new_m1  =  (m1 & 0x01) << 7;
539
424k
    }
540
  /* We do not have to worry about underflow or overflow
541
   * since the target has more significant bits in the
542
   * exponent and the significand.
543
   */
544
557k
#if !defined(WORDS_BIGENDIAN)
545
557k
    {
546
557k
      *dst = new_m1;
547
557k
      *(dst + 1) = new_m2;
548
557k
      *(dst + 2) = ((new_expt & 1) << 7) | new_m3;
549
557k
      *(dst + 3) = sbit | (new_expt >> 1);
550
557k
    }
551
#else
552
    {
553
      *dst = sbit | (new_expt >> 1);
554
      *(dst + 1) = ((new_expt & 1) << 7) | new_m3;
555
      *(dst + 2) = new_m2;
556
      *(dst + 3) = new_m1;
557
    }
558
#endif /* !defined(WORDS_BIGENDIAN) */
559
560
#ifdef DEBUG32
561
  /* Debugging code for display only */
562
  new_mant = (new_m3 << 16) | (new_m2 << 8) | new_m1;
563
  printf ("  mant ");
564
  for (j = 0, k = 15; j < 16; j++, k--)
565
    {
566
      bit = mant & (1 << k);
567
      if ((j % 8) == 0)
568
        printf(" ");
569
      printf ("%d", bit ? 1 : 0);
570
    }
571
572
  printf (" New Mant ");
573
  for (j = 0, k = 22; j < 23; j++, k--)
574
    {
575
      bit = new_mant & (1 << k);
576
      printf ("%d", bit ? 1 : 0);
577
      if ((k % 8) == 0)
578
        printf(" ");
579
    }
580
581
  printf (" Sbit + Exp ");
582
#if !defined(WORDS_BIGENDIAN)
583
    {
584
      for (i = 3; i >= 0; i--)
585
        {
586
          for (j = 0, k = 7; j < 8; j++, k--)
587
            {
588
              bit = *(dst + i) & (1 << k);
589
              if (i == 2 && j == 1)
590
                printf ("  Mant: ");
591
              printf ("%d", bit ? 1 : 0);
592
            }
593
        }
594
    }
595
#else
596
    {
597
      for (i = 0; i < 4; i++)
598
        {
599
          for (j = 0, k = 7; j < 8; j++, k--)
600
            {
601
              bit = *(dst + i) & (1 << k);
602
              if (i == 1 && j == 1)
603
                printf ("  Mant: ");
604
              printf ("%d", bit ? 1 : 0);
605
            }
606
        }
607
    }
608
#endif /* !defined(WORDS_BIGENDIAN) */
609
  printf ("\n");
610
611
  new_mant = ((unsigned int)new_m3 << 16) | ((unsigned int)new_m2 << 8) | new_m1;
612
  if ((int)*fp24 == 0.0)
613
    {
614
      test = 0.0;
615
      test2 = 0.0;
616
      accum = 0.0;
617
    }
618
  else
619
    {
620
      accum = 0.0;
621
      for (i = 22, j = 1; i >= 0; i--, j++)
622
        {
623
          bit = new_mant & ((unsigned int)1 << i);
624
          if (bit)
625
            accum += (1.0 / ((unsigned int)1 << j));
626
        }
627
      accum += 1.0;
628
      test = pow (2.0, 1.0 * (new_expt - 127));
629
      switch (errno)
630
        {
631
        case 0:     break;
632
        case EDOM:
633
        case ERANGE:
634
        default: perror ("Invalid value");
635
          break;
636
        }
637
      test2 = accum * test;
638
      if (sbit)
639
        test2 *= -1.0;
640
    }
641
  printf ("              Sign bit: %u, Expt biased to %5u,  2^%-5d = %8.1f  *  %10.8f = %18.10f\n\n",
642
          sbit > 0 ? 1 : 0, new_expt, new_expt > 0 ? new_expt - 127 : 0, test, accum, test2);
643
#endif
644
645
557k
  return (0);
646
557k
} /* end convertfp24_to_fp32 */
647
648
MagickExport
649
int _Gm_convert_fp32_to_fp24 (const float *fp32, fp_24bits *fp24, const int mode)
650
0
{
651
0
  int            i = 1;
652
0
  int            rbits, rshift, bit;
653
0
  unsigned char  sbit = 0;           /* sign bit */
654
0
  unsigned char  expt = 0; /* exponent bits */
655
0
  unsigned char  m3;   /* high order bits of mantissa */
656
0
  unsigned char  m2;
657
0
  unsigned char  m1;   /* low order bits of mantissa */
658
0
  unsigned char  new_m2, new_m1;
659
0
  signed   short new_expt;
660
0
  magick_uint64_t mant, new_mant; /* Mantissa, with rounding */
661
0
  unsigned char *mp;
662
0
  unsigned char *src;
663
0
  unsigned char *dst;
664
665
#ifdef DEBUG24
666
  int      j, k;
667
  double   test  = 0.0;
668
  double   test2 = 0.0;
669
  double   accum = 0.0;
670
  double   roundup = 0.0;
671
#endif
672
673
0
  errno = 0;
674
0
  assert (sizeof(int) == 4);
675
0
  if ((fp32 == NULL) || (fp24 == NULL))
676
0
    {
677
0
      fprintf (stderr, "Invalid src or destination pointers\n");
678
0
      return (1);
679
0
    }
680
681
0
  src = (unsigned char *)fp32;
682
0
  dst = (unsigned char *)fp24;
683
0
  mp  = (unsigned char *)&mant;
684
685
0
  new_expt = expt = 0;
686
0
  mant = new_mant = 0;
687
0
  m2 = m1 = 0;
688
0
  rbits = 0;
689
690
0
  if (*fp32 != 0)
691
0
    {
692
0
#if !defined(WORDS_BIGENDIAN)
693
0
        {
694
0
          sbit =   *(src + 3) & 0x80;
695
0
          expt = ((*(src + 3) & 0x7F) << 1) |
696
0
            ((*(src + 2) & 0x80) >> 7);
697
0
          m3  = (((*(src + 2) & 0x7F)) << 1) |
698
0
            ((*(src + 1) & 0x80) >> 7);
699
0
          m2  = (((*(src + 1) & 0x7F)) << 1)  |
700
0
            ((*src & 0x80) >> 7);
701
0
          m1  =  (*src & 0x7F) << 1;
702
0
        }
703
#else
704
        {
705
          sbit =   *src & 0x80;
706
          expt = ((*src & 0x7F) << 1) |
707
            ((*(src + 1) & 0x80) >> 7);
708
          m3  = (((*(src + 1) & 0x7F)) << 1) |
709
            ((*(src + 2) & 0x80) >> 7);
710
          m2  = (((*(src + 2) & 0x7F)) << 1)  |
711
            ((*(src + 3) & 0x80) >> 7);
712
          m1  =  (*(src + 3) & 0x7F) << 1;
713
        }
714
#endif /* !defined(WORDS_BIGENDIAN) */
715
716
0
      mant = ((magick_uint64_t) m3 << 24) | (m2 << 16) |( m1 << 8);
717
0
      if (expt != 0)
718
0
        new_expt = expt - 127 + 63;
719
720
      /* Even if the new exponent is too small to represent,
721
       * the mantissa could have significant digits that can
722
       * be represented in the new value as a subnormal.
723
       */
724
0
      if (new_expt <= 0) /* Underflow */
725
0
        {
726
0
          rshift = 0 - new_expt;
727
0
          switch (mode)
728
0
            {
729
0
            case STRICT_IEEE: /* NaN has all 1s in exponent plus 2 bits in Mantissa */
730
0
              if (rshift > FP24_MANT_BITS)
731
0
                {
732
0
                  new_expt = 0x7F;
733
0
                  new_mant = 0x80010000;
734
0
                  errno = ERANGE;
735
0
                  fflush (stdout);
736
0
                  fprintf (stderr, "Underflow. %18.10f Result clipped\n", *fp32);
737
0
                  fflush (stderr);
738
0
                  return (1);  /* The number cannot be represented as fp24 */
739
0
                }
740
0
              break;
741
0
            case RANGE_LIMITED: /* Clamp to smallest subnormal */
742
0
              new_expt = 0;
743
0
              new_mant = mant >> rshift;;
744
0
              mp = (unsigned char *)&new_mant;
745
#ifdef DEBUG24
746
              fflush (stdout);
747
              fprintf (stderr, "Underflow. %18.10f Result clippped to subnormal value\n", *fp32);
748
              fflush (stderr);
749
#endif
750
0
              break;
751
0
            case ZERO_LIMITED:  /* Clamp to zero instead of using a subnormal */
752
0
              new_expt = 0;
753
0
              new_mant = 0;
754
0
              mp = (unsigned char *)&new_mant;
755
#ifdef DEBUG24
756
              fflush (stdout);
757
              fprintf (stderr, "Underflow. %18.10f Result clippped to zero\n", *fp32);
758
              fflush (stderr);
759
#endif
760
0
              break;
761
0
            }
762
0
        }
763
0
      else /* Take the MSB from the old mantissa and left justify them */
764
0
        {
765
0
          if (new_expt > 126) /* Overflow */
766
0
            {
767
0
              switch (mode)
768
0
                {
769
0
                case STRICT_IEEE: /* NaN has all 1s in exponent plus 2 bits in Mantissa */
770
0
                  new_expt = 0x7F;
771
0
                  mant = 0x80010000;
772
0
                  errno = ERANGE;
773
0
                  fflush (stdout);
774
0
                  fprintf (stderr, "Overflow. Result clipped\n");
775
0
                  fflush (stderr);
776
0
                  return (1);
777
0
                case ZERO_LIMITED:
778
0
                case RANGE_LIMITED:  /* Clamp to maximum allowed value for fp24 */
779
0
                  new_expt = 126;
780
0
                  new_mant = 0xFFFF0000;
781
0
                  mp = (unsigned char *)&new_mant;
782
#ifdef DEBUG24
783
                  fflush (stdout);
784
                  fprintf (stderr, "Overflow. Result clippped\n");
785
                  fflush (stderr);
786
#endif
787
0
                  break;
788
0
                }
789
0
            }
790
0
          else /* Normal value within range of target type */
791
0
            { /* Remove the bits to the left of the binary point
792
               * by shifting the fractional bits into the leftmost position
793
               */
794
              /* Check bits to the right of Unit in last significant place.
795
               * Rounding of least significant retained bit falls to value
796
               * which will produce a zero in the LSB if the bounding values
797
               * are equidistant from the unrounded value.
798
               */
799
800
0
              rbits = mant & 0x0000FFFF;
801
0
              if (rbits >= 0x8000)  /* Greater than or equal to 0.5 times LSB */
802
0
                {
803
0
                  if (rbits > 0x8000) /* Rbits is greater than half of LSB */
804
0
                    {
805
                      /* Round up to next higher value of LSB */
806
0
                      for (i = 16; i < 32; i++)
807
0
                        {
808
0
                          bit = mant & ((magick_uint64_t) 1U << i);
809
0
                          if (bit == 0)
810
0
                            {
811
                              /* Round up by inserting a 1 at first zero and
812
                               * clearing bits to the right
813
                               */
814
0
                              new_mant = (mant | ((magick_uint64_t) 1 << i)) &
815
0
                                ((magick_uint64_t) 0xFFFFU << i);
816
0
                              mp  = (unsigned char *)&new_mant;
817
0
                              break;
818
0
                            }
819
0
                        }
820
0
                    }
821
0
                  else    /* Rbits is exactly half of LSB */
822
0
                    {
823
0
                      if ((mant & 0x010000)) /* LSB is one so we round up */
824
0
                        {
825
                          /* Round up to next higher value of LSB */
826
0
                          for (i = 16; i < 32; i++)
827
0
                            {
828
0
                              bit = mant & ((magick_uint64_t) 1 << i);
829
0
                              if (bit == 0)
830
0
                                {
831
0
                                  new_mant = (mant | ((magick_uint64_t) 1 << i)) &
832
0
                                    ((magick_uint64_t) 0xFFFFU << i);
833
0
                                  mp  = (unsigned char *)&new_mant;
834
0
                                  break;
835
0
                                }
836
0
                            }
837
0
                        }
838
0
                    }
839
0
                }
840
0
            }
841
0
        }
842
0
    }
843
0
#if !defined(WORDS_BIGENDIAN)
844
0
    {
845
0
      new_m2 = *(mp + 3);
846
0
      new_m1 = *(mp + 2);
847
0
      *dst = new_m1;
848
0
      *(dst + 1) = new_m2;
849
0
      *(dst + 2) = sbit | (new_expt & 0x7F);
850
0
    }
851
#else
852
    {
853
      new_m2 = *mp;
854
      new_m1 = *(mp + 1);
855
      *dst = sbit | (new_expt & 0x7F);
856
      *(dst + 1) = new_m2;
857
      *(dst + 2) = new_m1;
858
    }
859
#endif /* !defined(WORDS_BIGENDIAN) */
860
861
#ifdef DEBUG24
862
  /* Debugging code for display only */
863
  printf ("%10.10f mant%s ", *fp32, (rbits & 0x8000) ? "+" : "-");
864
  for (j = 0, k = 31; j < 23; j++, k--)
865
    {
866
      bit = mant & ((magick_uint64_t) 1 << k);
867
      if ((j % 8) == 0)
868
        printf(" ");
869
      printf ("%d", bit ? 1 : 0);
870
      if (bit && (j > 15))
871
        roundup += (1.0 / (double)(1 << (j - 15)));
872
    }
873
874
  if (new_mant == 0)
875
    {
876
      printf (" Fract: %8.6f  m2m1 ", roundup);
877
      for (j = 0, k = 7; j < 8; j++, k--)
878
        {
879
          bit = new_m2 & (1 << k);
880
          printf ("%d", bit ? 1 : 0);
881
        }
882
      printf(" ");
883
      for (j = 0, k = 7; j < 8; j++, k--)
884
        {
885
          bit = new_m1 & (1 << k);
886
          printf ("%d", bit ? 1 : 0);
887
        }
888
    }
889
  else
890
    {
891
      printf (" Fract: %8.6f  Rbits Mant ", roundup);
892
      for (j = 0, k = 31; j < 16; j++, k--)
893
        {
894
          bit = new_mant & (1 << k);
895
          if (j == 8)
896
            printf(" ");
897
          printf ("%d", bit ? 1 : 0);
898
        }
899
    }
900
  printf (" Sbit + Exp ");
901
#if !defined(WORDS_BIGENDIAN)
902
    {
903
      for (i = 2; i >= 0; i--)
904
        {
905
          for (j = 0, k = 7; j < 8; j++, k--)
906
            {
907
              bit = *(dst + i) & (1 << k);
908
              if (i == 1 && j == 0)
909
                printf ("  Mant: ");
910
              printf ("%d", bit ? 1 : 0);
911
            }
912
        }
913
    }
914
#else
915
    {
916
      for (i = 0; i < 3; i++)
917
        {
918
          for (j = 0, k = 7; j < 8; j++, k--)
919
            {
920
              bit = *(dst + i) & (1 << k);
921
              if (i == 1 && j == 0)
922
                printf ("  Mant: ");
923
              printf ("%d", bit ? 1 : 0);
924
            }
925
        }
926
    }
927
#endif /* !defined(WORDS_BIGENDIAN) */
928
  printf ("\n");
929
930
  mant = ((magick_uint64_t)new_m2 << 8) | (magick_uint64_t)new_m1;
931
  if (*fp32 == 0.0)
932
    {
933
      test = 0.0;
934
      test2 = 0.0;
935
      accum = 0.0;
936
    }
937
  else
938
    {
939
      accum = 0.0;
940
      for (i = 15, j = 1; i >= 0; i--, j++)
941
        {
942
          bit = mant & ((magick_uint64_t)1 << i);
943
          if (bit)
944
            accum += (1.0 / ((magick_uint64_t)1 << j));
945
        }
946
      if (new_expt != 0)
947
        accum += 1.0;
948
      test = pow (2.0, 1.0 * (new_expt - 63));
949
      switch (errno)
950
        {
951
        case 0:     break;
952
        case EDOM:
953
        case ERANGE:
954
        default: perror ("Invalid value");
955
          break;
956
        }
957
      test2 = accum * test;
958
      if (sbit)
959
        test2 *= -1.0;
960
    }
961
  printf ("              Sign bit: %u, Expt biased to %5u,  2^%-5d = %8.10f  *  %10.8f = %18.10f\n\n",
962
          sbit > 0 ? 1 : 0, new_expt, new_expt > 0 ? new_expt - 63 : 0, test, accum, test2);
963
#endif
964
965
0
  return (0);
966
0
} /* end convertfp32_to_fp24 */