C Utils for Yzena
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

1163 lines
39 KiB

/*
* ***** BEGIN LICENSE BLOCK *****
*
* Copyright 2017-2021 Yzena Tech
*
* Licensed under the Apache License, Version 2.0 (the "Apache License")
* with the following modification; you may not use this file except in
* compliance with the Apache License and the following modification to it:
* Section 6. Trademarks. is deleted and replaced with:
*
* 6. Trademarks. This License does not grant permission to use the trade
* names, trademarks, service marks, or product names of the Licensor
* and its affiliates, except as required to comply with Section 4(c) of
* the License and to reproduce the content of the NOTICE file.
*
* You may obtain a copy of the Apache License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the Apache License with the above modification is
* distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the Apache License for the specific
* language governing permissions and limitations under the Apache License.
*
* ****** END LICENSE BLOCK ******
*
* *****************************************************************
*
* ******* BEGIN FILE DESCRIPTION *******
*
* Public header file for safe arithmetic.
*
* ******** END FILE DESCRIPTION ********
*/
#ifndef YC_ARITH_H
#define YC_ARITH_H
/* For C++ compatibility */
#ifdef __cplusplus
extern "C" {
#endif
/**
* @file yc/arith.h
*/
/**
* @defgroup arith arith
* Public function definitions and types for Yc's safe arithmetic.
* @{
*/
//! @cond Doxygen suppress.
#include <stdint.h>
#include <stdbool.h>
#include <limits.h>
#include <stdlib.h>
//! @endcond
#include <yc/yc.h>
#include <yc/assert.h>
//! @cond Doxygen suppress.
// Workarounds for AIX's POSIX incompatibility
#ifndef SIZE_MAX
#define SIZE_MAX __SIZE_MAX__
#endif // SIZE_MAX
#ifndef UINTMAX_C
#define UINTMAX_C __UINTMAX_C
#endif // UINTMAX_C
#ifndef UINT32_C
#define UINT32_C __UINT32_C
#endif // UINT32_C
#ifndef UINT_FAST32_MAX
#define UINT_FAST32_MAX __UINT_FAST32_MAX__
#endif // UINT_FAST32_MAX
#ifndef UINT16_MAX
#define UINT16_MAX __UINT16_MAX__
#endif // UINT16_MAX
#ifndef SIG_ATOMIC_MAX
#define SIG_ATOMIC_MAX __SIG_ATOMIC_MAX__
#endif // SIG_ATOMIC_MAX
#if YC_64BIT
#ifndef __SIZEOF_INT128__
#error Need 128 bit numbers
#else // __SIZEOF_INT128__
#if __SIZEOF_INT128__ == 0
#error Need 128 bit numbers
#endif // __SIZEOF_INT128__ == 0
#endif // __SIZEOF_INT128__
/**
* @typedef uint128_t
* A 128-bit integer.
*/
typedef __uint128_t uint128_t;
#endif // YC_64BIT
//! @endcond
/**
* @typedef llong
* A single word typedef for long long.
*/
typedef long long llong;
//! @cond Doxygen suppress.
#define YC_MAX_8 (255ULL)
#define YC_MAX_16 (65535ULL)
#define YC_MAX_32 (4294967295ULL)
#define YC_MAX_64 (18446744073709551615ULL)
#define YC_MAX_128 (340282366920938463463374607431768211455ULL)
#define yc_int1(a, s) \
typedef uint ## s ## _t a; \
typedef struct { uint ## s ## _t n; uint ## s ## _t o; } a ## o; \
typedef struct { uint ## s ## _t q; uint ## s ## _t r; } a ## dres; \
typedef struct { uint ## s ## _t q; uint ## s ## _t r; bool o; } a ## dreso; \
const extern size_t a ## _bits;
#define yc_sn(t, z) \
yinline static inline \
t \
t ## sn(const t a) \
{ \
return a >= t ## _min; \
}
#define yc_eq(t) \
yinline static inline \
bool \
t ## eq(const t a, const t b) \
{ \
return a == b; \
}
#define yc_ne(t) \
yinline static inline \
bool \
t ## ne(const t a, const t b) \
{ \
return a != b; \
}
#define yc_slt(t, z) \
yinline static inline \
bool \
t ## slt(const t a, const t b) \
{ \
if (a >= t ## _min) \
{ \
return b >= t ## _min ? a < b : true; \
} \
else \
{ \
return b >= t ## _min ? false : a < b; \
} \
}
#define yc_ult(t) \
yinline static inline \
bool \
t ## ult(const t a, const t b) \
{ \
return a < b; \
}
#define yc_sle(t, z) \
yinline static inline \
bool \
t ## sle(const t a, const t b) \
{ \
if (a >= t ## _min) \
{ \
return b >= t ## _min ? a <= b : true; \
} \
else \
{ \
return b >= t ## _min ? false : a <= b; \
} \
}
#define yc_ule(t) \
yinline static inline \
bool \
t ## ule(const t a, const t b) \
{ \
return a <= b; \
}
#define yc_sgt(t, z) \
yinline static inline \
bool \
t ## sgt(const t a, const t b) \
{ \
if (a >= t ## _min) \
{ \
return b >= t ## _min ? a > b : false; \
} \
else \
{ \
return b >= t ## _min ? true : a > b; \
} \
}
#define yc_ugt(t) \
yinline static inline \
bool \
t ## ugt(const t a, const t b) \
{ \
return a > b; \
}
#define yc_sge(t, z) \
yinline static inline \
bool \
t ## sge(const t a, const t b) \
{ \
if (a >= t ## _min) \
{ \
return b >= t ## _min ? a >= b : false; \
} \
else \
{ \
return b >= t ## _min ? true : a >= b; \
} \
}
#define yc_uge(t) \
yinline static inline \
bool \
t ## uge(const t a, const t b) \
{ \
return a >= b; \
}
#define yc_neg(t) \
yinline static inline \
t \
t ## neg(const t a) \
{ \
return (~(a)); \
}
#define yc_sneg(t) \
yinline static inline \
t \
t ## sneg(const t a) \
{ \
return (~(a)) + 1; \
}
#define yc_shl(t, z) \
yinline static inline \
t \
t ## shl(const t a, const t b) \
{ \
t i; \
if (b >= z) i = 0; \
else i = a << b; \
return i; \
}
#define yc_sshr(t, z) \
yinline static inline \
t \
t ## shr(const t a, const t b) \
{ \
t i; \
bool sign = ((a & t ## _min) != 0); \
if (b >= z) i = sign ? ((t) 0) - 1 : 0; \
else \
{ \
i = a >> b; \
if (sign) \
{ \
uint ## z ## _t ext = ((((t) 1) << b) - 1) << (z - b); \
i |= ext; \
} \
} \
return i; \
}
#define yc_ushr(t, z) \
yinline static inline \
t \
t ## shr(const t a, const t b) \
{ \
t i; \
if (b >= z) i = 0; \
else i = a >> b; \
return i; \
}
#define yc_and(t) \
yinline static inline \
t \
t ## and(const t a, const t b) \
{ \
return a & b; \
}
#define yc_or(t) \
yinline static inline \
t \
t ## or(const t a, const t b) \
{ \
return a | b; \
}
#define yc_xor(t) \
yinline static inline \
t \
t ## xor(const t a, const t b) \
{ \
return a ^ b; \
}
#define yc_trunc(t, z, z2) \
yinline static inline \
t \
t ## trunc(const t a) \
{ \
return (uint ## z ## _t) (uint ## z2 ## _t) a; \
}
#define yc_sext(t, z, z2) \
yinline static inline \
uint ## z2 ## _t \
t ## sext(const t a) \
{ \
const uint ## z2 ## _t bit = \
(uint ## z2 ## _t) (t ## _min & a ? t ## _min : 0); \
const uint ## z2 ## _t sext = ((bit << 1) - 1) << z; \
return sext | ((uint ## z2 ## _t) a); \
}
#define yc_uext(t, z2) \
yinline static inline \
uint ## z2 ## _t \
t ## uext(const t a) \
{ \
return (uint ## z2 ## _t) a; \
}
#define yc_addw(t) \
yinline static inline \
t \
t ## aw(const t a, const t b) \
{ \
return a + b; \
}
#define yc_saddo(t, z) \
yinline static inline \
t ## o \
t ## ao(const t a, const t b) \
{ \
t ## o i; \
i.n = t ## aw(a, b); \
i.o = ((a & t ## _min) == (b & t ## _min)) & \
((i.n & t ## _min) != (a & t ## _min)); \
return i; \
}
#define yc_uaddo(t) \
yinline static inline \
t ## o \
t ## ao(const t a, const t b) \
{ \
t ## o i; \
i.n = t ## aw(a, b); \
i.o = (a >= i.n); \
return i; \
}
#define yc_sadds(t, z) \
yinline static inline \
t \
t ## as(const t a, const t b) \
{ \
t ## o i; \
i = t ## ao(a, b); \
if (i.o) i.n = t ## _min - ((a & t ## _min) == 0); \
return i.n; \
}
#define yc_uadds(t, z) \
yinline static inline \
t \
t ## as(const t a, const t b) \
{ \
t ## o i; \
i = t ## ao(a, b); \
if (i.o) i.n = ((t) 0) - 1; \
return i.n; \
}
#define yc_sadd(t) \
yinline static inline \
t \
t ## a(const t a, const t b) \
{ \
t ## o i; \
i = t ## ao(a, b); \
if (i.o) ypanic("signed overflow"); \
return i.n; \
}
#define yc_uadd(t) \
yinline static inline \
t \
t ## a(const t a, const t b) \
{ \
t ## o i; \
i = t ## ao(a, b); \
if (i.o) ypanic("unsigned overflow"); \
return i.n; \
}
#define yc_subw(t) \
yinline static inline \
t \
t ## sw(const t a, const t b) \
{ \
return a - b; \
}
#define yc_ssubo(t, z) \
yinline static inline \
t ## o \
t ## so(const t a, const t b) \
{ \
t ## o i; \
i.n = t ## sw(a, b); \
i.o = ((a & t ## _min) != (b & t ## _min)) & \
((i.n & t ## _min) != (a & t ## _min)); \
return i; \
}
#define yc_usubo(t) \
yinline static inline \
t ## o \
t ## so(const t a, const t b) \
{ \
t ## o i; \
i.n = t ## sw(a, b); \
i.o = (a <= i.n); \
return i; \
}
#define yc_ssubs(t, z) \
yinline static inline \
t \
t ## ss(const t a, const t b) \
{ \
t ## o i; \
i = t ## so(a, b); \
if (i.o) i.n = t ## _min - ((a & t ## _min) == 0); \
return i.n; \
}
#define yc_usubs(t, z) \
yinline static inline \
t \
t ## ss(const t a, const t b) \
{ \
t ## o i; \
i = t ## so(a, b); \
if (i.o) i.n = 0; \
return i.n; \
}
#define yc_ssub(t) \
yinline static inline \
t \
t ## s(const t a, const t b) \
{ \
t ## o i; \
i = t ## ao(a, b); \
if (i.o) ypanic("signed overflow"); \
return i.n; \
}
#define yc_usub(t) \
yinline static inline \
t \
t ## s(const t a, const t b) \
{ \
t ## o i; \
i = t ## ao(a, b); \
if (i.o) ypanic("unsigned overflow"); \
return i.n; \
}
#define yc_mulw(t) \
yinline static inline \
t \
t ## mw(const t a, const t b) \
{ \
t i; \
i = a * b; \
return i; \
}
#define yc_smulo(t, z, z2) \
yinline static inline \
t ## o \
t ## mo(const t a, const t b) \
{ \
const uint ## z2 ## _t r = ((uint ## z2 ## _t) a) * b; \
const uint ## z2 ## _t r2 = (((uint ## z2 ## _t) 1) << z) - 1; \
t ## o i; \
i.n = (uint ## z ## _t) (r & r2); \
i.o = (r >= r2) || ((a & t ## _min) == (b & t ## _min)) & \
((i.n & t ## _min) != (a & t ## _min)); \
return i; \
}
#define yc_umulo(t, z, z2) \
yinline static inline \
t ## o \
t ## mo(const t a, const t b) \
{ \
const uint ## z2 ## _t r = ((uint ## z2 ## _t) a) * b; \
const uint ## z2 ## _t r2 = (((uint ## z2 ## _t) 1ULL) << z) - 1; \
t ## o i; \
i.n = (uint ## z ## _t) (r & r2); \
i.o = (uint ## z ## _t) (r >> z); \
return i; \
}
#define yc_smuls(t, z) \
yinline static inline \
t \
t ## ms(const t a, const t b) \
{ \
t ## o i; \
i = t ## mo(a, b); \
if (i.o) i.n = t ## _min - ((a & t ## _min) == 0); \
return i.n; \
}
#define yc_umuls(t, z) \
yinline static inline \
t \
t ## ms(const t a, const t b) \
{ \
t ## o i; \
i = t ## mo(a, b); \
if (i.o) i.n = ((t) 0) - 1; \
return i.n; \
}
#define yc_smul(t) \
yinline static inline \
t \
t ## m(const t a, const t b) \
{ \
t ## o i; \
i = t ## mo(a, b); \
if (i.o) ypanic("signed overflow"); \
return i.n; \
}
#define yc_umul(t) \
yinline static inline \
t \
t ## m(const t a, const t b) \
{ \
t ## o i; \
i = t ## mo(a, b); \
if (i.o) ypanic("unsigned overflow"); \
return i.n; \
}
#define yc_sdivo(t, z) \
yinline static inline \
t ## o \
t ## do(t a, t b) \
{ \
t ## o i; \
if (b == 0) ypanic("division by zero"); \
const bool aneg = (a >= t ## _min); \
const bool bneg = (b >= t ## _min); \
if (aneg) a = t ## sneg(a); \
if (bneg) b = t ## sneg(b); \
i.n = a / b; \
if (aneg != bneg) i.n = (~(i.n)) + 1; \
i.o = (a == t ## _min && \
b == (uint ## z ## _t) (((uint ## z ## _t) 0) - 1)); \
return i; \
}
#define yc_sremo(t, z) \
yinline static inline \
t ## o \
t ## remo(t a, t b) \
{ \
t ## o i; \
if (b == 0) ypanic("division by zero"); \
const bool aneg = (a >= t ## _min); \
const bool bneg = (b >= t ## _min); \
if (aneg) a = t ## sneg(a); \
if (bneg) b = t ## sneg(b); \
i.n = a % b; \
if (aneg != bneg) i.n = (~(i.n)) + 1; \
i.o = (a == t ## _min && \
b == (uint ## z ## _t) (((uint ## z ## _t) 0) - 1)); \
return i; \
}
#define yc_smodo(t, z) \
yinline static inline \
t ## o \
t ## modo(t a, t b) \
{ \
t ## o i; \
if (b == 0) ypanic("division by zero"); \
const bool aneg = (a >= t ## _min); \
const bool bneg = (b >= t ## _min); \
if (aneg) a = t ## sneg(a); \
if (bneg) b = t ## sneg(b); \
i.n = a % b; \
if (aneg != bneg && i.n) i.n = b - i.n; \
if (bneg) i.n = (~(i.n)) + 1; \
i.o = (a == t ## _min && \
b == (uint ## z ## _t) (((uint ## z ## _t) 0) - 1)); \
return i; \
}
#define yc_sdiv(t) \
yinline static inline \
t \
t ## d(const t a, const t b) \
{ \
t ## o i; \
i = t ## do(a, b); \
if (i.o) ypanic("signed overflow"); \
return i.n; \
}
#define yc_srem(t) \
yinline static inline \
t \
t ## rem(const t a, const t b) \
{ \
t ## o i; \
i = t ## remo(a, b); \
if (i.o) ypanic("signed overflow"); \
return i.n; \
}
#define yc_smod(t) \
yinline static inline \
t \
t ## mod(const t a, const t b) \
{ \
t ## o i; \
i = t ## mo(a, b); \
if (i.o) ypanic("signed overflow"); \
return i.n; \
}
#define yc_sdivremo(t, z) \
yinline static inline \
t ## dreso \
t ## dro(t a, t b) \
{ \
t ## dreso i; \
if (b == 0) ypanic("division by zero"); \
const bool aneg = (a >= t ## _min); \
const bool bneg = (b >= t ## _min); \
if (aneg) a = t ## sneg(a); \
if (bneg) b = t ## sneg(b); \
i.q = a / b; \
i.r = a % b; \
if (aneg != bneg) i.q = (~(i.q)) + 1; \
i.o = (a == t ## _min && \
b == (uint ## z ## _t) (((uint ## z ## _t) 0) - 1)); \
return i; \
}
#define yc_sdivmodo(t, z) \
yinline static inline \
t ## dreso \
t ## dmo(t a, t b) \
{ \
t ## dreso i; \
if (b == 0) ypanic("division by zero"); \
const bool aneg = (a >= t ## _min); \
const bool bneg = (b >= t ## _min); \
if (aneg) a = t ## sneg(a); \
if (bneg) b = t ## sneg(b); \
i.q = a / b; \
i.r = a % b; \
if (aneg != bneg) \
{ \
i.q = (~(i.q)) + 1; \
if (i.r) i.r = b - i.r; \
} \
if (bneg) i.r = (~(i.r)) + 1; \
i.o = (a == t ## _min && \
b == (uint ## z ## _t) (((uint ## z ## _t) 0) - 1)); \
return i; \
}
#define yc_sdivrem(t) \
yinline static inline \
t ## dres \
t ## dr(const t a, const t b) \
{ \
t ## dres i; \
t ## dreso j; \
j = t ## dro(a, b); \
if (j.o) ypanic("signed overflow"); \
i.q = j.q; \
i.r = j.r; \
return i; \
}
#define yc_sdivmod(t) \
yinline static inline \
t ## dres \
t ## dm(const t a, const t b) \
{ \
t ## dres i; \
t ## dreso j; \
j = t ## dmo(a, b); \
if (j.o) ypanic("signed overflow"); \
i.q = j.q; \
i.r = j.r; \
return i; \
}
#define yc_sdivw(t, z) \
yinline static inline \
t \
t ## dw(t a, t b) \
{ \
t i; \
if (b == 0) ypanic("division by zero"); \
const bool aneg = (a >= t ## _min); \
const bool bneg = (b >= t ## _min); \
if (aneg) a = t ## sneg(a); \
if (bneg) b = t ## sneg(b); \
i = a / b; \
if (aneg != bneg) i = (~(i)) + 1; \
return i; \
}
#define yc_sremw(t, z) \
yinline static inline \
t \
t ## remw(t a, t b) \
{ \
t i; \
if (b == 0) ypanic("division by zero"); \
const bool aneg = (a >= t ## _min); \
const bool bneg = (b >= t ## _min); \
if (aneg) a = t ## sneg(a); \
if (bneg) b = t ## sneg(b); \
i = a % b; \
if (aneg != bneg) i = (~(i)) + 1; \
return i; \
}
#define yc_smodw(t, z) \
yinline static inline \
t \
t ## modw(t a, t b) \
{ \
t i; \
if (b == 0) ypanic("division by zero"); \
const bool aneg = (a >= t ## _min); \
const bool bneg = (b >= t ## _min); \
if (aneg) a = t ## sneg(a); \
if (bneg) b = t ## sneg(b); \
i = a % b; \
if (aneg != bneg && i) i = b - i; \
if (bneg) i = (~(i)) + 1; \
return i; \
}
#define yc_sdivremw(t, z) \
yinline static inline \
t ## dres \
t ## drw(t a, t b) \
{ \
t ## dres i; \
if (b == 0) ypanic("division by zero"); \
const bool aneg = (a >= t ## _min); \
const bool bneg = (b >= t ## _min); \
if (aneg) a = t ## sneg(a); \
if (bneg) b = t ## sneg(b); \
i.q = a / b; \
i.r = a % b; \
if (aneg != bneg) i.q = (~(i.q)) + 1; \
return i; \
}
#define yc_sdivmodw(t, z) \
yinline static inline \
t ## dres \
t ## dmw(t a, t b) \
{ \
t ## dres i; \
if (b == 0) ypanic("division by zero"); \
const bool aneg = (a >= t ## _min); \
const bool bneg = (b >= t ## _min); \
if (aneg) a = t ## sneg(a); \
if (bneg) b = t ## sneg(b); \
i.q = a / b; \
i.r = a % b; \
if (aneg != bneg) \
{ \
i.q = (~(i.q)) + 1; \
if (i.r) i.r = b - i.r; \
} \
if (bneg) i.r = (~(i.r)) + 1; \
return i; \
}
#define yc_udiv(t) \
yinline static inline \
t \
t ## d(const t a, const t b) \
{ \
if (b == 0) ypanic("division by zero"); \
return a / b; \
}
#define yc_udivrem(t) \
yinline static inline \
t ## dres \
t ## dr(const t a, const t b) \
{ \
t ## dres i; \
if (b == 0) ypanic("division by zero"); \
i.q = a / b; \
i.r = a % b; \
return i; \
}
#define yc_urem(t) \
yinline static inline \
t \
t ## r(const t a, const t b) \
{ \
if (b == 0) ypanic("division by zero"); \
return a % b; \
}
#define yc_sint(a, s, s2, s12) \
yc_int1(a, s) \
const extern a a ## _min; \
const extern a a ## _max; \
yc_sn(a, s) \
yc_eq(a) \
yc_ne(a) \
yc_slt(a, s) \
yc_sle(a, s) \
yc_sgt(a, s) \
yc_sge(a, s) \
yc_neg(a) \
yc_sneg(a) \
yc_shl(a, s) \
yc_sshr(a, s) \
yc_and(a) \
yc_or(a) \
yc_xor(a) \
yc_trunc(a, s, s12) \
yc_sext(a, s, s2) \
yc_addw(a) \
yc_saddo(a, s) \
yc_sadds(a, s) \
yc_sadd(a) \
yc_subw(a) \
yc_ssubo(a, s) \
yc_ssubs(a, s) \
yc_ssub(a) \
yc_mulw(a) \
yc_smulo(a, s, s2) \
yc_smuls(a, s) \
yc_smul(a) \
yc_sdivo(a, s) \
yc_sremo(a, s) \
yc_smodo(a, s) \
yc_sdivremo(a, s) \
yc_sdivmodo(a, s) \
yc_sdiv(a) \
yc_srem(a) \
yc_smod(a) \
yc_sdivrem(a) \
yc_sdivmod(a) \
yc_sdivw(a, s) \
yc_sremw(a, s) \
yc_smodw(a, s) \
yc_sdivremw(a, s) \
yc_sdivmodw(a, s) \
#define yc_uint(a, s, s2, s12) \
yc_int1(a, s) \
const extern a a ## _min; \
const extern a a ## _max; \
yc_eq(a) \
yc_ne(a) \
yc_ult(a) \
yc_ule(a) \
yc_ugt(a) \
yc_uge(a) \
yc_neg(a) \
yc_sneg(a) \
yc_shl(a, s) \
yc_ushr(a, s) \
yc_and(a) \
yc_or(a) \
yc_xor(a) \
yc_trunc(a, s, s12) \
yc_uext(a, s2) \
yc_addw(a) \
yc_uaddo(a) \
yc_uadds(a, s) \
yc_uadd(a) \
yc_subw(a) \
yc_usubo(a) \
yc_usubs(a, s) \
yc_usub(a) \
yc_mulw(a) \
yc_umulo(a, s, s2) \
yc_umuls(a, s) \
yc_umul(a) \
yc_udiv(a) \
yc_udivrem(a) \
yc_urem(a) \
yc_sint(ys8, 8, 16, 8)
yc_uint(yu8, 8, 16, 8)
yc_sint(ys16, 16, 32, 8)
yc_uint(yu16, 16, 32, 8)
yc_sint(ys32, 32, 64, 16)
yc_uint(yu32, 32, 64, 16)
yc_sint(ys64, 64, 128, 32)
yc_uint(yu64, 64, 128, 32)
yc_sint(yschar, CHAR_BIT, 16, 8)
yc_uint(yuchar, CHAR_BIT, 16, 8)
#if USHRT_MAX == YC_MAX_16
#define YSHORT_BITS (16)
yc_sint(ysshort, 16, 32, 8)
yc_uint(yushort, 16, 32, 8)
#elif USHRT_MAX == YC_MAX_32
#define YSHORT_BITS (32)
yc_sint(ysshort, 32, 64, 16)
yc_uint(yushort, 32, 64, 16)
#else
#error shorts must be 16 or 32 bits
#endif // USHRT_MAX
#if UINT_MAX == YC_MAX_16
#define YINT_BITS (16)
yc_sint(ysint, 16, 32, 8)
yc_uint(yuint, 16, 32, 8)
#elif UINT_MAX == YC_MAX_32
#define YINT_BITS (32)
yc_sint(ysint, 32, 64, 16)
yc_uint(yuint, 32, 64, 16)
#elif UINT_MAX == YC_MAX_64
#define YINT_BITS (64)
yc_sint(ysint, 64, 128, 32)
yc_uint(yuint, 64, 128, 32)
#else
#error ints must be 16, 32, or 64 bits
#endif // UINT_MAX
#if ULONG_MAX == YC_MAX_32
#define YLONG_BITS (32)
yc_sint(yslong, 32, 64, 16)
yc_uint(yulong, 32, 64, 16)
#elif ULONG_MAX == YC_MAX_64
#define YLONG_BITS (64)
yc_sint(yslong, 64, 128, 32)
yc_uint(yulong, 64, 128, 32)
#else
#error longs must be 32 or 64 bits
#endif // ULONG_MAX
#if ULLONG_MAX == YC_MAX_64
#define YLLONG_BITS (64)
yc_sint(ysllong, 64, 128, 32)
yc_uint(yullong, 64, 128, 32)
#elif ULLONG_MAX == YC_MAX_128
#define YLLONG_BITS (128)
yc_sint(ysllong, 128, 256, 64)
yc_uint(yullong, 128, 256, 64)
#else
#error long longs must be 64 or 128 bits
#endif // ULLONG_MAX
#if SIZE_MAX == YC_MAX_16
#define YSIZE_BITS (16)
yc_sint(yssize, 16, 32, 8)
yc_uint(yusize, 16, 32, 8)
#elif SIZE_MAX == YC_MAX_32
#define YSIZE_BITS (32)
yc_sint(yssize, 32, 64, 16)
yc_uint(yusize, 32, 64, 16)
#elif SIZE_MAX == YC_MAX_64
#define YSIZE_BITS (64)
yc_sint(yssize, 64, 128, 32)
yc_uint(yusize, 64, 128, 32)
#else
#error size_t must be 16, 32, or 64 bits
#endif // SIZE_MAX
#if UINTPTR_MAX == YC_MAX_16
#define YINTPTR_BITS (16)
yc_sint(ysptr, 16, 32, 8)
yc_uint(yuptr, 16, 32, 8)
#elif UINTPTR_MAX == YC_MAX_32
#define YINTPTR_BITS (32)
yc_sint(ysptr, 32, 64, 16)
yc_uint(yuptr, 32, 64, 16)
#elif UINTPTR_MAX == YC_MAX_64
#define YINTPTR_BITS (64)
yc_sint(ysptr, 64, 128, 32)
yc_uint(yuptr, 64, 128, 32)
#else
#error uintptr_t must be 16, 32, or 64 bits
#endif // UINTPTR_MAX
#if UINTMAX_MAX == YC_MAX_16
#define YINTMAX_BITS (16)
yc_sint(ysmax, 16, 32, 8)
yc_uint(yumax, 16, 32, 8)
#elif UINTMAX_MAX == YC_MAX_32
#define YINTMAX_BITS (32)
yc_sint(ysmax, 32, 64, 16)
yc_uint(yumax, 32, 64, 16)
#elif UINTMAX_MAX == YC_MAX_64
#define YINTMAX_BITS (64)
yc_sint(ysmax, 64, 128, 32)
yc_uint(yumax, 64, 128, 32)
#else
#error uintmax_t must be 16, 32, or 64 bits
#endif // UINTMAX_MAX
yinline static inline void*
int2ptr(const yuptr a)
{
return (void*) a;
}
yinline static inline yuptr
ptr2int(const void* a)
{
return (yuptr) a;
}
#define yc_2y(ts, tu) \
yinline static inline \
tu \
ts ## 2y(const ts s) \
{ \
return (tu) s; \
}
yc_2y(char, yschar)
yc_2y(short, ysshort)
yc_2y(int, ysint)
yc_2y(long, yslong)
yc_2y(llong, ysllong)
yc_2y(int8_t, ys8)
yc_2y(int16_t, ys16)
yc_2y(int32_t, ys32)
yc_2y(int64_t, ys64)
yc_2y(ssize_t, yssize)
yc_2y(intmax_t, ysmax)
yc_2y(intptr_t, ysptr)
#undef YC_MAX_8
#undef YC_MAX_16
#undef YC_MAX_32
#undef YC_MAX_64
#undef YC_MAX_128
#undef yc_neg
#undef yc_sneg
#undef yc_sshl
#undef yc_ushl
#undef yc_sshr
#undef yc_ushr
#undef yc_and
#undef yc_or
#undef yc_xor
#undef yc_trunc
#undef yc_addw
#undef yc_saddo
#undef yc_uaddo
#undef yc_sadds
#undef yc_uadds
#undef yc_sadd
#undef yc_uadd
#undef yc_subw
#undef yc_ssubo
#undef yc_usubo
#undef yc_ssubs
#undef yc_usubs
#undef yc_ssub
#undef yc_usub
#undef yc_mulw
#undef yc_smulo
#undef yc_umulo
#undef yc_smuls
#undef yc_umuls
#undef yc_smul
#undef yc_umul
#undef yc_sdivo
#undef yc_sremo
#undef yc_smodo
#undef yc_sdiv
#undef yc_srem
#undef yc_smod
#undef yc_sdivremo
#undef yc_sdivmodo
#undef yc_sdivrem
#undef yc_sdivmod
#undef yc_sdivw
#undef yc_sremw
#undef yc_smodw
#undef yc_sdivremw
#undef yc_sdivmodw
#undef yc_udiv
#undef yc_udivrem
#undef yc_urem
#undef yc_int1
#undef yc_sint
#undef yc_uint
#undef yc_s2u
//! @endcond Doxygen suppress.
/**
* @}
*/
#ifdef __cplusplus
}
#endif
#endif // YC_ARITH_H