#ifndef H_R128_H
#define H_R128_H
#include <stddef.h>
#if defined(_MSC_VER) && (_MSC_VER < 1600)
#define R128_S32 …
#define R128_U32 …
#define R128_S64 …
#define R128_U64 …
#define R128_LIT_S64 …
#define R128_LIT_U64 …
#else
# include <stdint.h>
#define R128_S32 …
#define R128_U32 …
#define R128_S64 …
#define R128_U64 …
#define R128_LIT_S64(x) …
#define R128_LIT_U64(x) …
#endif
#ifdef __cplusplus
extern "C" {
#endif
R128;
extern void r128FromInt(R128 *dst, R128_S64 v);
extern void r128FromFloat(R128 *dst, double v);
extern R128_S64 r128ToInt(const R128 *v);
extern double r128ToFloat(const R128 *v);
extern void r128Copy(R128 *dst, const R128 *src);
extern void r128Neg(R128 *dst, const R128 *v);
extern void r128Abs(R128* dst, const R128* v);
extern void r128Nabs(R128* dst, const R128* v);
extern void r128Not(R128 *dst, const R128 *src);
extern void r128Or(R128 *dst, const R128 *a, const R128 *b);
extern void r128And(R128 *dst, const R128 *a, const R128 *b);
extern void r128Xor(R128 *dst, const R128 *a, const R128 *b);
extern void r128Shl(R128 *dst, const R128 *src, int amount);
extern void r128Shr(R128 *dst, const R128 *src, int amount);
extern void r128Sar(R128 *dst, const R128 *src, int amount);
extern void r128Add(R128 *dst, const R128 *a, const R128 *b);
extern void r128Sub(R128 *dst, const R128 *a, const R128 *b);
extern void r128Mul(R128 *dst, const R128 *a, const R128 *b);
extern void r128Div(R128 *dst, const R128 *a, const R128 *b);
extern void r128Mod(R128 *dst, const R128 *a, const R128 *b);
extern void r128Sqrt(R128 *dst, const R128 *v);
extern void r128Rsqrt(R128 *dst, const R128 *v);
extern int r128Cmp(const R128 *a, const R128 *b);
extern void r128Min(R128 *dst, const R128 *a, const R128 *b);
extern void r128Max(R128 *dst, const R128 *a, const R128 *b);
extern void r128Floor(R128 *dst, const R128 *v);
extern void r128Ceil(R128 *dst, const R128 *v);
extern void r128Round(R128 *dst, const R128 *v);
extern int r128IsNeg(const R128 *v);
R128ToStringSign;
R128ToStringFormat;
extern int r128ToStringOpt(char *dst, size_t dstSize, const R128 *v, const R128ToStringFormat *opt);
extern int r128ToStringf(char *dst, size_t dstSize, const char *format, const R128 *v);
extern int r128ToString(char *dst, size_t dstSize, const R128 *v);
extern void r128FromString(R128 *dst, const char *s, char **endptr);
extern const R128 R128_min;
extern const R128 R128_max;
extern const R128 R128_smallest;
extern const R128 R128_zero;
extern const R128 R128_one;
extern char R128_decimal;
#ifdef __cplusplus
}
#include <limits>
namespace std {
template<>
struct numeric_limits<R128>
{
static const bool is_specialized = true;
static R128 min() throw() { return R128_min; }
static R128 max() throw() { return R128_max; }
static const int digits = 127;
static const int digits10 = 38;
static const bool is_signed = true;
static const bool is_integer = false;
static const bool is_exact = false;
static const int radix = 2;
static R128 epsilon() throw() { return R128_smallest; }
static R128 round_error() throw() { return R128_one; }
static const int min_exponent = 0;
static const int min_exponent10 = 0;
static const int max_exponent = 0;
static const int max_exponent10 = 0;
static const bool has_infinity = false;
static const bool has_quiet_NaN = false;
static const bool has_signaling_NaN = false;
static const float_denorm_style has_denorm = denorm_absent;
static const bool has_denorm_loss = false;
static R128 infinity() throw() { return R128_zero; }
static R128 quiet_NaN() throw() { return R128_zero; }
static R128 signaling_NaN() throw() { return R128_zero; }
static R128 denorm_min() throw() { return R128_zero; }
static const bool is_iec559 = false;
static const bool is_bounded = true;
static const bool is_modulo = true;
static const bool traps = numeric_limits<R128_U64>::traps;
static const bool tinyness_before = false;
static const float_round_style round_style = round_toward_zero;
};
}
inline R128::R128() {}
inline R128::R128(double v)
{
r128FromFloat(this, v);
}
inline R128::R128(int v)
{
r128FromInt(this, v);
}
inline R128::R128(R128_S64 v)
{
r128FromInt(this, v);
}
inline R128::R128(R128_U64 low, R128_U64 high)
{
lo = low;
hi = high;
}
inline R128::operator double() const
{
return r128ToFloat(this);
}
inline R128::operator R128_S64() const
{
return r128ToInt(this);
}
inline R128::operator int() const
{
return (int) r128ToInt(this);
}
inline R128::operator bool() const
{
return lo || hi;
}
inline bool R128::operator!() const
{
return !lo && !hi;
}
inline R128 R128::operator~() const
{
R128 r;
r128Not(&r, this);
return r;
}
inline R128 R128::operator-() const
{
R128 r;
r128Neg(&r, this);
return r;
}
inline R128 &R128::operator|=(const R128 &rhs)
{
r128Or(this, this, &rhs);
return *this;
}
inline R128 &R128::operator&=(const R128 &rhs)
{
r128And(this, this, &rhs);
return *this;
}
inline R128 &R128::operator^=(const R128 &rhs)
{
r128Xor(this, this, &rhs);
return *this;
}
inline R128 &R128::operator+=(const R128 &rhs)
{
r128Add(this, this, &rhs);
return *this;
}
inline R128 &R128::operator-=(const R128 &rhs)
{
r128Sub(this, this, &rhs);
return *this;
}
inline R128 &R128::operator*=(const R128 &rhs)
{
r128Mul(this, this, &rhs);
return *this;
}
inline R128 &R128::operator/=(const R128 &rhs)
{
r128Div(this, this, &rhs);
return *this;
}
inline R128 &R128::operator%=(const R128 &rhs)
{
r128Mod(this, this, &rhs);
return *this;
}
inline R128 &R128::operator<<=(int amount)
{
r128Shl(this, this, amount);
return *this;
}
inline R128 &R128::operator>>=(int amount)
{
r128Sar(this, this, amount);
return *this;
}
static inline R128 operator|(const R128 &lhs, const R128 &rhs)
{
R128 r(lhs);
return r |= rhs;
}
static inline R128 operator&(const R128 &lhs, const R128 &rhs)
{
R128 r(lhs);
return r &= rhs;
}
static inline R128 operator^(const R128 &lhs, const R128 &rhs)
{
R128 r(lhs);
return r ^= rhs;
}
static inline R128 operator+(const R128 &lhs, const R128 &rhs)
{
R128 r(lhs);
return r += rhs;
}
static inline R128 operator-(const R128 &lhs, const R128 &rhs)
{
R128 r(lhs);
return r -= rhs;
}
static inline R128 operator*(const R128 &lhs, const R128 &rhs)
{
R128 r(lhs);
return r *= rhs;
}
static inline R128 operator/(const R128 &lhs, const R128 &rhs)
{
R128 r(lhs);
return r /= rhs;
}
static inline R128 operator%(const R128 &lhs, const R128 &rhs)
{
R128 r(lhs);
return r %= rhs;
}
static inline R128 operator<<(const R128 &lhs, int amount)
{
R128 r(lhs);
return r <<= amount;
}
static inline R128 operator>>(const R128 &lhs, int amount)
{
R128 r(lhs);
return r >>= amount;
}
static inline bool operator<(const R128 &lhs, const R128 &rhs)
{
return r128Cmp(&lhs, &rhs) < 0;
}
static inline bool operator>(const R128 &lhs, const R128 &rhs)
{
return r128Cmp(&lhs, &rhs) > 0;
}
static inline bool operator<=(const R128 &lhs, const R128 &rhs)
{
return r128Cmp(&lhs, &rhs) <= 0;
}
static inline bool operator>=(const R128 &lhs, const R128 &rhs)
{
return r128Cmp(&lhs, &rhs) >= 0;
}
static inline bool operator==(const R128 &lhs, const R128 &rhs)
{
return lhs.lo == rhs.lo && lhs.hi == rhs.hi;
}
static inline bool operator!=(const R128 &lhs, const R128 &rhs)
{
return lhs.lo != rhs.lo || lhs.hi != rhs.hi;
}
#endif
#endif
#ifdef R128_IMPLEMENTATION
#ifdef R128_DEBUG_VIS
#define R128_DEBUG_SET …
#else
#define R128_DEBUG_SET(x) …
#endif
#define R128_SET2(x, l, h) …
#define R128_R0(x) …
#define R128_R2(x) …
#if defined(_M_IX86)
#define R128_SET4 …
#define R128_R1 …
#define R128_R3 …
#else
#define R128_SET4(x, r0, r1, r2, r3) …
#define R128_R1(x) …
#define R128_R3(x) …
#endif
#if defined(_M_X64)
#define R128_INTEL …
#define R128_64BIT …
# ifndef R128_STDC_ONLY
# include <intrin.h>
# endif
#elif defined(__x86_64__)
#define R128_INTEL …
#define R128_64BIT …
# ifndef R128_STDC_ONLY
# include <x86intrin.h>
# endif
#elif defined(_M_IX86)
#define R128_INTEL …
# ifndef R128_STDC_ONLY
# include <intrin.h>
# endif
#elif defined(__i386__)
#define R128_INTEL …
# ifndef R128_STDC_ONLY
# include <x86intrin.h>
# endif
#elif defined(_M_ARM)
# ifndef R128_STDC_ONLY
# include <intrin.h>
# endif
#elif defined(_M_ARM64)
#define R128_64BIT …
# ifndef R128_STDC_ONLY
# include <intrin.h>
# endif
#elif defined(__aarch64__)
#define R128_64BIT …
#endif
#ifndef R128_INTEL
#define R128_INTEL …
#endif
#ifndef R128_64BIT
#define R128_64BIT …
#endif
#ifndef R128_ASSERT
# include <assert.h>
#define R128_ASSERT(x) …
#endif
#include <stdlib.h>
static const R128ToStringFormat R128__defaultFormat = …;
const R128 R128_min = …;
const R128 R128_max = …;
const R128 R128_smallest = …;
const R128 R128_zero = …;
const R128 R128_one = …;
char R128_decimal = …;
#ifdef R128_DEBUG_VIS
char R128_last[42];
#endif
static int r128__clz64(R128_U64 x)
{ … }
#if !R128_64BIT
static R128_U64 r128__umul64(R128_U32 a, R128_U32 b)
{
# if defined(_M_IX86) && !defined(R128_STDC_ONLY) && !defined(__MINGW32__)
return __emulu(a, b);
# elif defined(_M_ARM) && !defined(R128_STDC_ONLY)
return _arm_umull(a, b);
# else
return a * (R128_U64)b;
# endif
}
static R128_U32 r128__udiv64(R128_U32 nlo, R128_U32 nhi, R128_U32 d, R128_U32 *rem)
{
# if defined(_M_IX86) && (_MSC_VER >= 1920) && !defined(R128_STDC_ONLY)
unsigned __int64 n = ((unsigned __int64)nhi << 32) | nlo;
return _udiv64(n, d, rem);
# elif defined(_M_IX86) && !defined(R128_STDC_ONLY) && !defined(__MINGW32__)
__asm {
mov eax, nlo
mov edx, nhi
div d
mov ecx, rem
mov dword ptr [ecx], edx
}
# elif defined(__i386__) && !defined(R128_STDC_ONLY)
R128_U32 q, r;
__asm("divl %4"
: "=a"(q), "=d"(r)
: "a"(nlo), "d"(nhi), "X"(d));
*rem = r;
return q;
# else
R128_U64 n64 = ((R128_U64)nhi << 32) | nlo;
*rem = (R128_U32)(n64 % d);
return (R128_U32)(n64 / d);
# endif
}
#elif defined(R128_STDC_ONLY) || !R128_INTEL
#define r128__umul64 …
static R128_U32 r128__udiv64(R128_U32 nlo, R128_U32 nhi, R128_U32 d, R128_U32 *rem)
{
R128_U64 n64 = ((R128_U64)nhi << 32) | nlo;
*rem = (R128_U32)(n64 % d);
return (R128_U32)(n64 / d);
}
#endif
static void r128__neg(R128 *dst, const R128 *src)
{ … }
static void r128__umul128(R128 *dst, R128_U64 a, R128_U64 b)
{ … }
#if defined(_M_X64) && (_MSC_VER < 1920) && !defined(R128_STDC_ONLY) && !defined(__MINGW32__)
#pragma code_seg(".text")
__declspec(allocate(".text") align(16)) static const unsigned char r128__udiv128Code[] = {
0x48, 0x8B, 0xC1,
0x49, 0xF7, 0xF0,
0x49, 0x89, 0x11,
0xC3
};
typedef R128_U64 (*r128__udiv128Proc)(R128_U64 nlo, R128_U64 nhi, R128_U64 d, R128_U64 *rem);
static const r128__udiv128Proc r128__udiv128 = (r128__udiv128Proc)(void*)r128__udiv128Code;
#else
static R128_U64 r128__udiv128(R128_U64 nlo, R128_U64 nhi, R128_U64 d, R128_U64 *rem)
{ … }
#endif
static int r128__ucmp(const R128 *a, const R128 *b)
{ … }
static void r128__umul(R128 *dst, const R128 *a, const R128 *b)
{ … }
static int r128__norm(R128 *n, R128 *d, R128_U64 *n2)
{ … }
static void r128__udiv(R128 *quotient, const R128 *dividend, const R128 *divisor)
{ … }
static R128_U64 r128__umod(R128 *n, R128 *d)
{ … }
static int r128__format(char *dst, size_t dstSize, const R128 *v, const R128ToStringFormat *format)
{ … }
void r128FromInt(R128 *dst, R128_S64 v)
{ … }
void r128FromFloat(R128 *dst, double v)
{ … }
void r128FromString(R128 *dst, const char *s, char **endptr)
{ … }
R128_S64 r128ToInt(const R128 *v)
{ … }
double r128ToFloat(const R128 *v)
{ … }
int r128ToStringOpt(char *dst, size_t dstSize, const R128 *v, const R128ToStringFormat *opt)
{ … }
int r128ToStringf(char *dst, size_t dstSize, const char *format, const R128 *v)
{ … }
int r128ToString(char *dst, size_t dstSize, const R128 *v)
{ … }
void r128Copy(R128 *dst, const R128 *src)
{ … }
void r128Neg(R128 *dst, const R128 *v)
{ … }
void r128Abs(R128* dst, const R128* v)
{ … }
void r128Nabs(R128* dst, const R128* v)
{ … }
void r128Not(R128 *dst, const R128 *src)
{ … }
void r128Or(R128 *dst, const R128 *a, const R128 *b)
{ … }
void r128And(R128 *dst, const R128 *a, const R128 *b)
{ … }
void r128Xor(R128 *dst, const R128 *a, const R128 *b)
{ … }
void r128Shl(R128 *dst, const R128 *src, int amount)
{ … }
void r128Shr(R128 *dst, const R128 *src, int amount)
{ … }
void r128Sar(R128 *dst, const R128 *src, int amount)
{ … }
void r128Add(R128 *dst, const R128 *a, const R128 *b)
{ … }
void r128Sub(R128 *dst, const R128 *a, const R128 *b)
{ … }
void r128Mul(R128 *dst, const R128 *a, const R128 *b)
{ … }
void r128Div(R128 *dst, const R128 *a, const R128 *b)
{ … }
void r128Mod(R128 *dst, const R128 *a, const R128 *b)
{ … }
void r128Rsqrt(R128 *dst, const R128 *v)
{ … }
void r128Sqrt(R128 *dst, const R128 *v)
{ … }
int r128Cmp(const R128 *a, const R128 *b)
{ … }
int r128IsNeg(const R128 *v)
{ … }
void r128Min(R128 *dst, const R128 *a, const R128 *b)
{ … }
void r128Max(R128 *dst, const R128 *a, const R128 *b)
{ … }
void r128Floor(R128 *dst, const R128 *v)
{ … }
void r128Ceil(R128 *dst, const R128 *v)
{ … }
void r128Round(R128* dst, const R128* v)
{ … }
#endif