Coverage Report

Created: 2025-07-23 08:18

/work/include/jasper/jas_math.h
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * Copyright (c) 1999-2000 Image Power, Inc. and the University of
3
 *   British Columbia.
4
 * Copyright (c) 2001-2002 Michael David Adams.
5
 * All rights reserved.
6
 */
7
8
/* __START_OF_JASPER_LICENSE__
9
 * 
10
 * JasPer License Version 2.0
11
 * 
12
 * Copyright (c) 2001-2006 Michael David Adams
13
 * Copyright (c) 1999-2000 Image Power, Inc.
14
 * Copyright (c) 1999-2000 The University of British Columbia
15
 * 
16
 * All rights reserved.
17
 * 
18
 * Permission is hereby granted, free of charge, to any person (the
19
 * "User") obtaining a copy of this software and associated documentation
20
 * files (the "Software"), to deal in the Software without restriction,
21
 * including without limitation the rights to use, copy, modify, merge,
22
 * publish, distribute, and/or sell copies of the Software, and to permit
23
 * persons to whom the Software is furnished to do so, subject to the
24
 * following conditions:
25
 * 
26
 * 1.  The above copyright notices and this permission notice (which
27
 * includes the disclaimer below) shall be included in all copies or
28
 * substantial portions of the Software.
29
 * 
30
 * 2.  The name of a copyright holder shall not be used to endorse or
31
 * promote products derived from the Software without specific prior
32
 * written permission.
33
 * 
34
 * THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL PART OF THIS
35
 * LICENSE.  NO USE OF THE SOFTWARE IS AUTHORIZED HEREUNDER EXCEPT UNDER
36
 * THIS DISCLAIMER.  THE SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS
37
 * "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
38
 * BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
39
 * PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS.  IN NO
40
 * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL
41
 * INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING
42
 * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
43
 * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
44
 * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.  NO ASSURANCES ARE
45
 * PROVIDED BY THE COPYRIGHT HOLDERS THAT THE SOFTWARE DOES NOT INFRINGE
46
 * THE PATENT OR OTHER INTELLECTUAL PROPERTY RIGHTS OF ANY OTHER ENTITY.
47
 * EACH COPYRIGHT HOLDER DISCLAIMS ANY LIABILITY TO THE USER FOR CLAIMS
48
 * BROUGHT BY ANY OTHER ENTITY BASED ON INFRINGEMENT OF INTELLECTUAL
49
 * PROPERTY RIGHTS OR OTHERWISE.  AS A CONDITION TO EXERCISING THE RIGHTS
50
 * GRANTED HEREUNDER, EACH USER HEREBY ASSUMES SOLE RESPONSIBILITY TO SECURE
51
 * ANY OTHER INTELLECTUAL PROPERTY RIGHTS NEEDED, IF ANY.  THE SOFTWARE
52
 * IS NOT FAULT-TOLERANT AND IS NOT INTENDED FOR USE IN MISSION-CRITICAL
53
 * SYSTEMS, SUCH AS THOSE USED IN THE OPERATION OF NUCLEAR FACILITIES,
54
 * AIRCRAFT NAVIGATION OR COMMUNICATION SYSTEMS, AIR TRAFFIC CONTROL
55
 * SYSTEMS, DIRECT LIFE SUPPORT MACHINES, OR WEAPONS SYSTEMS, IN WHICH
56
 * THE FAILURE OF THE SOFTWARE OR SYSTEM COULD LEAD DIRECTLY TO DEATH,
57
 * PERSONAL INJURY, OR SEVERE PHYSICAL OR ENVIRONMENTAL DAMAGE ("HIGH
58
 * RISK ACTIVITIES").  THE COPYRIGHT HOLDERS SPECIFICALLY DISCLAIM ANY
59
 * EXPRESS OR IMPLIED WARRANTY OF FITNESS FOR HIGH RISK ACTIVITIES.
60
 * 
61
 * __END_OF_JASPER_LICENSE__
62
 */
63
64
/*!
65
 * @file jas_math.h
66
 * @brief Math-Related Code
67
 */
68
69
#ifndef JAS_MATH_H
70
#define JAS_MATH_H
71
72
/******************************************************************************\
73
* Includes
74
\******************************************************************************/
75
76
/* The configuration header file should be included first. */
77
#include <jasper/jas_config.h>
78
79
#include <jasper/jas_compiler.h>
80
#include <jasper/jas_types.h>
81
82
#include <assert.h>
83
#include <string.h>
84
#include <stdint.h>
85
#include <limits.h>
86
87
#ifdef __cplusplus
88
extern "C" {
89
#endif
90
91
/******************************************************************************\
92
* Macros
93
\******************************************************************************/
94
95
#define JAS_KIBI  JAS_CAST(size_t, 1024)
96
#define JAS_MEBI  (JAS_KIBI * JAS_KIBI)
97
98
/* Compute the absolute value. */
99
#define JAS_ABS(x) \
100
  (((x) >= 0) ? (x) : (-(x)))
101
102
/* Compute the minimum of two values. */
103
#define JAS_MIN(x, y) \
104
  (((x) < (y)) ? (x) : (y))
105
106
/* Compute the maximum of two values. */
107
#define JAS_MAX(x, y) \
108
  (((x) > (y)) ? (x) : (y))
109
110
/* Compute the remainder from division (where division is defined such
111
  that the remainder is always nonnegative). */
112
#define JAS_MOD(x, y) \
113
  (((x) < 0) ? (((-x) % (y)) ? ((y) - ((-(x)) % (y))) : (0)) : ((x) % (y)))
114
115
/* Compute the integer with the specified number of least significant bits
116
  set to one. */
117
#define JAS_ONES(n) \
118
  ((1 << (n)) - 1)
119
#if 0
120
#define JAS_ONES_X(type, n) \
121
  ((JAS_CAST(type, 1) << (n)) - 1)
122
#endif
123
#define JAS_POW2_X(type, n) \
124
  (JAS_CAST(type, 1) << (n))
125
126
/******************************************************************************\
127
*
128
\******************************************************************************/
129
130
#if defined(__clang__) || (defined(__GNUC__) && __GNUC__ > 6)
131
/* suppress clang warning "shifting a negative signed value is
132
   undefined" in the assertions below */
133
#pragma GCC diagnostic push
134
#pragma GCC diagnostic ignored "-Wshift-negative-value"
135
#endif
136
137
JAS_ATTRIBUTE_CONST
138
JAS_ATTRIBUTE_DISABLE_UBSAN
139
inline static int jas_int_asr(int x, unsigned n)
140
0
{
141
0
  // Ensure that the shift of a negative value appears to behave as a
142
0
  // signed arithmetic shift.
143
0
  assert(((-1) >> 1) == -1);
144
0
  // The behavior is undefined when x is negative.
145
0
  // We tacitly assume the behavior is equivalent to a signed
146
0
  // arithmetic right shift.
147
0
  return x >> n;
148
0
}
149
150
JAS_ATTRIBUTE_CONST
151
JAS_ATTRIBUTE_DISABLE_UBSAN
152
inline static int jas_int_asl(int x, unsigned n)
153
0
{
154
0
  // Ensure that the shift of a negative value appears to behave as a
155
0
  // signed arithmetic shift.
156
0
  assert(((-1) << 1) == -2);
157
0
  // The behavior is undefined when x is negative.
158
0
  // We tacitly assume the behavior is equivalent to a signed
159
0
  // arithmetic left shift.
160
0
  return x << n;
161
0
}
162
163
JAS_ATTRIBUTE_CONST
164
JAS_ATTRIBUTE_DISABLE_UBSAN
165
inline static int_least32_t jas_least32_asr(int_least32_t x, unsigned n)
166
0
{
167
0
  // Ensure that the shift of a negative value appears to behave as a
168
0
  // signed arithmetic shift.
169
0
  assert(((JAS_CAST(int_least32_t, -1)) >> 1) == JAS_CAST(int_least32_t, -1));
170
0
  // The behavior is undefined when x is negative.
171
0
  // We tacitly assume the behavior is equivalent to a signed
172
0
  // arithmetic right shift.
173
0
  return x >> n;
174
0
}
175
176
JAS_ATTRIBUTE_CONST
177
JAS_ATTRIBUTE_DISABLE_UBSAN
178
inline static int_least32_t jas_least32_asl(int_least32_t x, unsigned n)
179
0
{
180
0
  // Ensure that the shift of a negative value appears to behave as a
181
0
  // signed arithmetic shift.
182
0
  assert(((JAS_CAST(int_least32_t, -1)) << 1) == JAS_CAST(int_least32_t, -2));
183
0
  // The behavior is undefined when x is negative.
184
0
  // We tacitly assume the behavior is equivalent to a signed
185
0
  // arithmetic left shift.
186
0
  return x << n;
187
0
}
188
189
JAS_ATTRIBUTE_CONST
190
JAS_ATTRIBUTE_DISABLE_UBSAN
191
inline static int_fast32_t jas_fast32_asr(int_fast32_t x, unsigned n)
192
0
{
193
0
  // Ensure that the shift of a negative value appears to behave as a
194
0
  // signed arithmetic shift.
195
0
  assert(((JAS_CAST(int_fast32_t, -1)) >> 1) == JAS_CAST(int_fast32_t, -1));
196
0
  // The behavior is undefined when x is negative.
197
0
  // We tacitly assume the behavior is equivalent to a signed
198
0
  // arithmetic right shift.
199
0
  return x >> n;
200
0
}
201
202
JAS_ATTRIBUTE_CONST
203
JAS_ATTRIBUTE_DISABLE_UBSAN
204
inline static int_fast32_t jas_fast32_asl(int_fast32_t x, unsigned n)
205
0
{
206
0
  // Ensure that the shift of a negative value appears to behave as a
207
0
  // signed arithmetic shift.
208
0
  assert(((JAS_CAST(int_fast32_t, -1)) << 1) == JAS_CAST(int_fast32_t, -2));
209
0
  // The behavior is undefined when x is negative.
210
0
  // We tacitly assume the behavior is equivalent to a signed
211
0
  // arithmetic left shift.
212
0
  return x << n;
213
0
}
214
215
#if defined(__clang__) || (defined(__GNUC__) && __GNUC__ > 6)
216
#pragma GCC diagnostic pop
217
#endif
218
219
/******************************************************************************\
220
* Safe integer arithmetic (i.e., with overflow checking).
221
\******************************************************************************/
222
223
/* Compute the product of two size_t integers with overflow checking. */
224
inline static bool jas_safe_size_mul(size_t x, size_t y, size_t *result)
225
0
{
226
0
#if jas_has_builtin(__builtin_mul_overflow) || (defined(__GNUC__) && __GNUC__ > 5)
227
0
  size_t result_buffer;
228
0
  bool valid = !__builtin_mul_overflow(x, y, &result_buffer);
229
0
  if (valid && result) {
230
0
    *result = result_buffer;
231
0
  }
232
0
  return valid;
233
0
#else
234
0
  /* Check if overflow would occur */
235
0
  if (x && y > SIZE_MAX / x) {
236
0
    /* Overflow would occur. */
237
0
    return false;
238
0
  }
239
0
  if (result) {
240
0
    *result = x * y;
241
0
  }
242
0
  return true;
243
0
#endif
244
0
}
245
246
/* Compute the product of three size_t integers with overflow checking. */
247
inline static bool jas_safe_size_mul3(size_t a, size_t b, size_t c,
248
  size_t *result)
249
0
{
250
0
  size_t tmp;
251
0
  if (!jas_safe_size_mul(a, b, &tmp) ||
252
0
    !jas_safe_size_mul(tmp, c, &tmp)) {
253
0
    return false;
254
0
  }
255
0
  if (result) {
256
0
    *result = tmp;
257
0
  }
258
0
  return true;
259
0
}
260
261
/* Compute the sum of two size_t integers with overflow checking. */
262
inline static bool jas_safe_size_add(size_t x, size_t y, size_t *result)
263
0
{
264
0
#if jas_has_builtin(__builtin_add_overflow) || (defined(__GNUC__) && __GNUC__ > 5)
265
0
  size_t result_buffer;
266
0
  bool valid = !__builtin_add_overflow(x, y, &result_buffer);
267
0
  if (valid && result) {
268
0
    *result = result_buffer;
269
0
  }
270
0
  return valid;
271
0
#else
272
0
  if (y > SIZE_MAX - x) {
273
0
    return false;
274
0
  }
275
0
  if (result) {
276
0
    *result = x + y;
277
0
  }
278
0
  return true;
279
0
#endif
280
0
}
281
282
/* Compute the difference of two size_t integers with overflow checking. */
283
inline static bool jas_safe_size_sub(size_t x, size_t y, size_t *result)
284
0
{
285
0
#if jas_has_builtin(__builtin_sub_overflow) || (defined(__GNUC__) && __GNUC__ > 5)
286
0
  size_t result_buffer;
287
0
  bool valid = !__builtin_sub_overflow(x, y, &result_buffer);
288
0
  if (valid && result) {
289
0
    *result = result_buffer;
290
0
  }
291
0
  return valid;
292
0
#else
293
0
  if (y > x) {
294
0
    return false;
295
0
  }
296
0
  if (result) {
297
0
    *result = x - y;
298
0
  }
299
0
  return true;
300
0
#endif
301
0
}
302
303
/* Compute the product of two int_fast32_t integers with overflow checking. */
304
inline static bool jas_safe_intfast32_mul(int_fast32_t x, int_fast32_t y,
305
  int_fast32_t *result)
306
0
{
307
0
#if jas_has_builtin(__builtin_mul_overflow) || (defined(__GNUC__) && __GNUC__ > 5)
308
0
  int_fast32_t result_buffer;
309
0
  bool valid = !__builtin_mul_overflow(x, y, &result_buffer);
310
0
  if (valid && result) {
311
0
    *result = result_buffer;
312
0
  }
313
0
  return valid;
314
0
#else
315
0
  if (x > 0) {
316
0
    /* x is positive */
317
0
    if (y > 0) {
318
0
      /* x and y are positive */
319
0
      if (x > INT_FAST32_MAX / y) {
320
0
        return false;
321
0
      }
322
0
    } else {
323
0
      /* x positive, y nonpositive */
324
0
      if (y < INT_FAST32_MIN / x) {
325
0
        return false;
326
0
      }
327
0
    }
328
0
  } else {
329
0
    /* x is nonpositive */
330
0
    if (y > 0) {
331
0
      /* x is nonpositive, y is positive */
332
0
      if (x < INT_FAST32_MIN / y) {
333
0
        return false;
334
0
      }
335
0
    } else { /* x and y are nonpositive */
336
0
      if (x != 0 && y < INT_FAST32_MAX / x) {
337
0
        return false;
338
0
      }
339
0
    }
340
0
  }
341
0
342
0
  if (result) {
343
0
    *result = x * y;
344
0
  }
345
0
  return true;
346
0
#endif
347
0
}
348
349
/* Compute the product of three int_fast32_t integers with overflow checking. */
350
inline static bool jas_safe_intfast32_mul3(int_fast32_t a, int_fast32_t b,
351
  int_fast32_t c, int_fast32_t *result)
352
0
{
353
0
  int_fast32_t tmp;
354
0
  if (!jas_safe_intfast32_mul(a, b, &tmp) ||
355
0
    !jas_safe_intfast32_mul(tmp, c, &tmp)) {
356
0
    return false;
357
0
  }
358
0
  if (result) {
359
0
    *result = tmp;
360
0
  }
361
0
  return true;
362
0
}
363
364
/* Compute the sum of two int_fast32_t integers with overflow checking. */
365
inline static bool jas_safe_intfast32_add(int_fast32_t x, int_fast32_t y,
366
  int_fast32_t *result)
367
0
{
368
0
#if jas_has_builtin(__builtin_add_overflow) || (defined(__GNUC__) && __GNUC__ > 5)
369
0
  int_fast32_t result_buffer;
370
0
  bool valid = !__builtin_add_overflow(x, y, &result_buffer);
371
0
  if (valid && result) {
372
0
    *result = result_buffer;
373
0
  }
374
0
  return valid;
375
0
#else
376
0
  if ((y > 0 && x > INT_FAST32_MAX - y) ||
377
0
    (y < 0 && x < INT_FAST32_MIN - y)) {
378
0
    return false;
379
0
  }
380
0
  if (result) {
381
0
    *result = x + y;
382
0
  }
383
0
  return true;
384
0
#endif
385
0
}
386
387
#if 0
388
/*
389
This function is potentially useful but not currently used.
390
So, it is commented out.
391
*/
392
inline static bool jas_safe_uint_mul(unsigned x, unsigned y, unsigned *result)
393
{
394
  /* Check if overflow would occur */
395
  if (x && y > UINT_MAX / x) {
396
    /* Overflow would occur. */
397
    return false;
398
  }
399
  if (result) {
400
    *result = x * y;
401
  }
402
  return true;
403
}
404
#endif
405
406
/******************************************************************************\
407
* Safe 32-bit unsigned integer arithmetic (i.e., with overflow checking).
408
\******************************************************************************/
409
410
#define JAS_SAFEUI32_MAX (0xffffffffUL)
411
412
typedef struct {
413
  bool valid;
414
  uint_least32_t value;
415
} jas_safeui32_t;
416
417
JAS_ATTRIBUTE_CONST
418
static inline jas_safeui32_t jas_safeui32_from_ulong(unsigned long x)
419
0
{
420
0
  jas_safeui32_t result;
421
0
  if (x <= JAS_SAFEUI32_MAX) {
422
0
    result.valid = 1;
423
0
    result.value = JAS_CAST(uint_least32_t, x);
424
0
  } else {
425
0
    result.valid = 0;
426
0
    result.value = 0;
427
0
  }
428
0
  return result;
429
0
}
430
431
JAS_ATTRIBUTE_PURE
432
static inline bool jas_safeui32_to_intfast32(jas_safeui32_t x,
433
  int_fast32_t* y)
434
0
{
435
0
  const long I32_MAX = 0x7fffffffL;
436
0
  if (x.value <= I32_MAX) {
437
0
    *y = x.value;
438
0
    return true;
439
0
  } else {
440
0
    return false;
441
0
  }
442
0
}
443
444
JAS_ATTRIBUTE_CONST
445
static inline jas_safeui32_t jas_safeui32_add(jas_safeui32_t x,
446
  jas_safeui32_t y)
447
0
{
448
0
  jas_safeui32_t result;
449
0
  if (x.valid && y.valid && y.value <= UINT_LEAST32_MAX - x.value) {
450
0
    result.valid = true;
451
0
    result.value = x.value + y.value;
452
0
  } else {
453
0
    result.valid = false;
454
0
    result.value = 0;
455
0
  }
456
0
  return result;
457
0
}
458
459
JAS_ATTRIBUTE_CONST
460
static inline
461
jas_safeui32_t jas_safeui32_sub(jas_safeui32_t x, jas_safeui32_t y)
462
0
{
463
0
  jas_safeui32_t result;
464
0
  if (x.valid && y.valid && y.value <= x.value) {
465
0
    result.valid = true;
466
0
    result.value = x.value - y.value;
467
0
  } else {
468
0
    result.valid = false;
469
0
    result.value = 0;
470
0
  }
471
0
  return result;
472
0
}
473
474
JAS_ATTRIBUTE_CONST
475
static inline jas_safeui32_t jas_safeui32_mul(jas_safeui32_t x,
476
  jas_safeui32_t y)
477
0
{
478
0
  jas_safeui32_t result;
479
0
  if (!x.valid || !y.valid || (x.value && y.value > UINT_LEAST32_MAX /
480
0
    x.value)) {
481
0
    result.valid = false;
482
0
    result.value = 0;
483
0
  } else {
484
0
    result.valid = true;
485
0
    result.value = x.value * y.value;
486
0
  }
487
0
  return result;
488
0
}
489
490
/******************************************************************************\
491
* Safe 64-bit signed integer arithmetic (i.e., with overflow checking).
492
\******************************************************************************/
493
494
typedef struct {
495
  bool valid;
496
  int_least64_t value;
497
} jas_safei64_t;
498
499
JAS_ATTRIBUTE_CONST
500
static inline
501
jas_safei64_t jas_safei64_from_intmax(intmax_t x)
502
0
{
503
0
  jas_safei64_t result;
504
0
  if (x >= INT_LEAST64_MIN && x <= INT_LEAST64_MAX) {
505
0
    result.valid = true;
506
0
    result.value = JAS_CAST(int_least64_t, x);
507
0
  } else {
508
0
    result.valid = false;
509
0
    result.value = 0;
510
0
  }
511
0
  return result;
512
0
}
513
514
JAS_ATTRIBUTE_CONST
515
static inline
516
jas_safei64_t jas_safei64_add(jas_safei64_t x, jas_safei64_t y)
517
0
{
518
0
  jas_safei64_t result;
519
0
  if (((y.value > 0) && (x.value > (INT_LEAST64_MAX - y.value))) ||
520
0
    ((y.value < 0) && (x.value < (INT_LEAST64_MIN - y.value)))) {
521
0
    result.value = false;
522
0
    result.value = 0;
523
0
  } else {
524
0
    result.valid = true;
525
0
    result.value = x.value + y.value;
526
0
  }
527
0
  return result;
528
0
}
529
530
JAS_ATTRIBUTE_CONST
531
static inline
532
jas_safei64_t jas_safei64_sub(jas_safei64_t x, jas_safei64_t y)
533
0
{
534
0
  jas_safei64_t result;
535
0
  if ((y.value > 0 && x.value < INT_LEAST64_MIN + y.value) ||
536
0
  (y.value < 0 && x.value > INT_LEAST64_MAX + y.value)) {
537
0
    result.valid = false;
538
0
    result.value = 0;
539
0
  } else {
540
0
    result.valid = true;
541
0
    result.value = x.value - y.value;
542
0
  }
543
0
  return result;
544
0
}
545
546
JAS_ATTRIBUTE_CONST
547
static inline
548
jas_safei64_t jas_safei64_mul(jas_safei64_t x, jas_safei64_t y)
549
0
{
550
0
  jas_safei64_t result;
551
0
  if (x.value > 0) {  /* x.value is positive */
552
0
    if (y.value > 0) {  /* x.value and y.value are positive */
553
0
      if (x.value > (INT_LEAST64_MAX / y.value)) {
554
0
        goto error;
555
0
      }
556
0
    } else { /* x.value positive, y.value nonpositive */
557
0
      if (y.value < (INT_LEAST64_MIN / x.value)) {
558
0
        goto error;
559
0
      }
560
0
    } /* x.value positive, y.value nonpositive */
561
0
  } else { /* x.value is nonpositive */
562
0
    if (y.value > 0) { /* x.value is nonpositive, y.value is positive */
563
0
      if (x.value < (INT_LEAST64_MIN / y.value)) {
564
0
        goto error;
565
0
      }
566
0
    } else { /* x.value and y.value are nonpositive */
567
0
      if ( (x.value != 0) && (y.value < (INT_LEAST64_MAX / x.value))) {
568
0
        goto error;
569
0
      }
570
0
    } /* End if x.value and y.value are nonpositive */
571
0
  } /* End if x.value is nonpositive */
572
0
  result.valid = true;
573
0
  result.value = x.value * y.value;
574
0
  return result;
575
0
error:
576
0
  result.valid = false;
577
0
  result.value = 0;
578
0
  return result;
579
0
}
580
581
#if 0
582
JAS_ATTRIBUTE_CONST
583
static inline
584
jas_safei64_t jas_safei64_div(jas_safei64_t x, jas_safei64_t y)
585
{
586
  // TODO/FIXME: Not yet implemented.
587
  jas_safei64_t result;
588
  result.valid = false;
589
  result.value = 0;
590
  return result;
591
}
592
#endif
593
594
JAS_ATTRIBUTE_CONST
595
static inline
596
jas_i32_t jas_safei64_to_i32(jas_safei64_t x, jas_i32_t invalid_value)
597
0
{
598
0
  jas_i32_t result;
599
0
  if (x.valid && x.value >= JAS_I32_MIN && x.value <= JAS_I32_MAX) {
600
0
    result = JAS_CAST(jas_i32_t, x.value);
601
0
  } else {
602
0
    result = invalid_value;
603
0
  }
604
0
  return result;
605
0
}
606
607
/******************************************************************************\
608
* Safe 64-bit unsigned integer arithmetic (i.e., with overflow checking).
609
\******************************************************************************/
610
611
typedef struct {
612
  bool valid;
613
  uint_least64_t value;
614
} jas_safeui64_t;
615
616
JAS_ATTRIBUTE_CONST
617
static inline
618
jas_safeui64_t jas_safeui64_from_intmax(intmax_t x)
619
0
{
620
0
  jas_safeui64_t result;
621
0
  if (x >= 0 && x <= UINT_LEAST64_MAX) {
622
0
    result.valid = true;
623
0
    result.value = JAS_CAST(uint_least64_t, x);
624
0
  } else {
625
0
    result.valid = false;
626
0
    result.value = 0;
627
0
  }
628
0
  return result;
629
0
}
630
631
JAS_ATTRIBUTE_CONST
632
static inline
633
jas_safeui64_t jas_safeui64_add(jas_safeui64_t x, jas_safeui64_t y)
634
0
{
635
0
  jas_safeui64_t result;
636
0
  if (x.valid && y.valid && y.value <= UINT_LEAST64_MAX - x.value) {
637
0
    result.valid = true;
638
0
    result.value = x.value + y.value;
639
0
  } else {
640
0
    result.valid = false;
641
0
    result.value = 0;
642
0
  }
643
0
  return result;
644
0
}
645
646
JAS_ATTRIBUTE_CONST
647
static inline
648
jas_safeui64_t jas_safeui64_sub(jas_safeui64_t x, jas_safeui64_t y)
649
0
{
650
0
  jas_safeui64_t result;
651
0
  if (x.valid && y.valid && y.value <= x.value) {
652
0
    result.valid = true;
653
0
    result.value = x.value - y.value;
654
0
  } else {
655
0
    result.valid = false;
656
0
    result.value = 0;
657
0
  }
658
0
  return result;
659
0
}
660
661
JAS_ATTRIBUTE_CONST
662
static inline
663
jas_safeui64_t jas_safeui64_mul(jas_safeui64_t x, jas_safeui64_t y)
664
0
{
665
0
  jas_safeui64_t result;
666
0
  if (!x.valid || !y.valid || (x.value && y.value > UINT_LEAST64_MAX /
667
0
    x.value)) {
668
0
    result.valid = false;
669
0
    result.value = 0;
670
0
  } else {
671
0
    result.valid = true;
672
0
    result.value = x.value * y.value;
673
0
  }
674
0
  return result;
675
0
}
676
677
JAS_ATTRIBUTE_CONST
678
static inline
679
jas_safeui64_t jas_safeui64_div(jas_safeui64_t x, jas_safeui64_t y)
680
0
{
681
0
  jas_safeui64_t result;
682
0
  if (x.valid && y.valid && y.value) {
683
0
    result.valid = true;
684
0
    result.value = x.value / y.value;
685
0
  } else {
686
0
    result.valid = false;
687
0
    result.value = 0;
688
0
  }
689
0
  return result;
690
0
}
691
692
JAS_ATTRIBUTE_CONST
693
static inline
694
jas_safeui64_t jas_safeui64_pow2_intmax(intmax_t x)
695
0
{
696
0
  jas_safeui64_t result;
697
0
  if (x >= 0 && x < 64) {
698
0
    result.valid = true;
699
0
    result.value = JAS_CAST(uint_least64_t, 1) << x;
700
0
  } else {
701
0
    result.valid = false;
702
0
    result.value = 0;
703
0
  }
704
0
  return result;
705
0
}
706
707
JAS_ATTRIBUTE_CONST
708
static inline
709
int jas_safeui64_to_int(jas_safeui64_t x, int invalid_value)
710
0
{
711
0
  int result;
712
0
  if (x.valid && x.value <= INT_MAX) {
713
0
    result = JAS_CAST(int, x.value);
714
0
  } else {
715
0
    result = invalid_value;
716
0
  }
717
0
  return result;
718
0
}
719
720
JAS_ATTRIBUTE_CONST
721
static inline
722
jas_ui32_t jas_safeui64_to_ui32(jas_safeui64_t x, jas_ui32_t invalid_value)
723
0
{
724
0
  jas_ui32_t result;
725
0
  if (x.valid && x.value <= JAS_UI32_MAX) {
726
0
    result = JAS_CAST(jas_ui32_t, x.value);
727
0
  } else {
728
0
    result = invalid_value;
729
0
  }
730
0
  return result;
731
0
}
732
733
JAS_ATTRIBUTE_CONST
734
static inline
735
jas_i32_t jas_safeui64_to_i32(jas_safeui64_t x, jas_i32_t invalid_value)
736
0
{
737
0
  jas_i32_t result;
738
0
  if (x.valid && x.value >= JAS_I32_MIN && x.value <= JAS_I32_MAX) {
739
0
    result = JAS_CAST(jas_i32_t, x.value);
740
0
  } else {
741
0
    result = invalid_value;
742
0
  }
743
0
  return result;
744
0
}
745
746
/******************************************************************************\
747
\******************************************************************************/
748
749
#ifdef __cplusplus
750
}
751
#endif
752
753
#endif