Select Git revision
bignum.h 24.64 KiB
/*
|| This file is part of Pike. For copyright information see COPYRIGHT.
|| Pike is distributed under GPL, LGPL and MPL. See the file COPYING
|| for more information.
*/
#ifndef BIGNUM_H
#define BIGNUM_H
#include "global.h"
#include "pike_int_types.h"
/* Note: These functions assume some properties of the CPU. */
#define INT_TYPE_SIGN(x) ((x) < 0)
/*
* Arithmetic operations which try to be standard compliant when checking for overflow.
* The first set of functions uses a second larger integer type to perform computations.
* The second uses manual multiplication for unsigned multiply or checks for overflow
* as recommended in
* https://www.securecoding.cert.org/confluence/display/seccode/INT32-C.+Ensure+that+operations+on+signed+integers+do+not+result+in+overflow
* When using clang with builtin support for checking arithmetic overflow, those builtins will
* be used.
* These functions will also detect and try to avoid undefined behavior, e.g. shifts of
* negative integers.
*
* The family of DO_*_OVERFLOW functions sets the result only if no overflow occured.
*/
#define GENERIC_OVERFLOW_CHECKS(type) \
static INLINE int __attribute__((unused)) DO_## type ## _NEG_OVERFLOW(type a, type * res) { \
if (a == MIN_ ## type) return 1; \
*res = -a; \
return 0; \
} \
static INLINE int __attribute__((unused)) type ## _NEG_OVERFLOW(type a) { \
return a == MIN_ ## type; \
} \
static INLINE int __attribute__((unused)) type ## _DIV_OVERFLOW(type a, type b) { \
return a == MIN_ ## type && b == -1; \
} \
static INLINE int __attribute__((unused)) DO_ ## type ## _DIV_OVERFLOW(type a, type b, type * res) { \
if (a == MIN_ ## type && b == -1) return 1; \
*res = a/b; \
return 0; \
} \
static INLINE int __attribute__((unused)) U ## type ## _MUL_OVERFLOW(unsigned type a, unsigned type b) { \
unsigned type res; \
return DO_U ## type ## _MUL_OVERFLOW(a, b, &res); \
} \
static INLINE int __attribute__((unused)) U ## type ## _ADD_OVERFLOW(unsigned type a, unsigned type b) { \
unsigned type res; \
return DO_U ## type ## _ADD_OVERFLOW(a, b, &res); \
} \
static INLINE int __attribute__((unused)) U ## type ## _SUB_OVERFLOW(unsigned type a, unsigned type b) { \
unsigned type res; \
return DO_U ## type ## _SUB_OVERFLOW(a, b, &res); \
} \
static INLINE int __attribute__((unused)) type ## _MUL_OVERFLOW(type a, type b) { \
type res; \
return DO_ ## type ## _MUL_OVERFLOW(a, b, &res); \
} \
static INLINE int __attribute__((unused)) type ## _ADD_OVERFLOW(type a, type b) { \
type res; \
return DO_ ## type ## _ADD_OVERFLOW(a, b, &res); \
} \
static INLINE int __attribute__((unused)) type ## _SUB_OVERFLOW(type a, type b) { \
type res; \
return DO_ ## type ## _SUB_OVERFLOW(a, b, &res); \
} \