/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 |