Skip to content

Commit

Permalink
Sync with jtckdint
Browse files Browse the repository at this point in the history
  • Loading branch information
jart committed Nov 20, 2024
1 parent 5c3f854 commit abdf6c9
Showing 1 changed file with 26 additions and 34 deletions.
60 changes: 26 additions & 34 deletions libc/stdckdint.h
Original file line number Diff line number Diff line change
Expand Up @@ -38,14 +38,13 @@
* Instead, you'll get a pretty good pure C11 and C++11 implementation.
*
* @see https://www.open-std.org/jtc1/sc22/wg14/www/docs/n3096.pdf
* @version 0.1 (2023-07-22)
* @see https://github.com/jart/jtckdint
* @version 0.2 (2024-11-20)
*/

#define __STDC_VERSION_STDCKDINT_H__ 202311L

#if ((defined(__llvm__) || \
(defined(__GNUC__) && __GNUC__ * 100 + __GNUC_MINOR__ >= 406)) && \
!defined(__STRICT_ANSI__))
#if (!defined(__STRICT_ANSI__) && defined(__SIZEOF_INT128__))
#define __ckd_have_int128
#define __ckd_intmax __int128
#elif ((defined(__cplusplus) && __cplusplus >= 201103L) || \
Expand All @@ -58,19 +57,22 @@
typedef signed __ckd_intmax __ckd_intmax_t;
typedef unsigned __ckd_intmax __ckd_uintmax_t;

#if (!defined(__STRICT_ANSI__) && \
((defined(__GNUC__) && __GNUC__ >= 5 && \
!defined(__chibicc__) && !defined(__ICC)) || \
(__has_builtin(__builtin_add_overflow) && \
__has_builtin(__builtin_sub_overflow) && \
#if (!defined(__STRICT_ANSI__) && \
((defined(__GNUC__) && __GNUC__ >= 5 && !defined(__ICC)) || \
(__has_builtin(__builtin_add_overflow) && \
__has_builtin(__builtin_sub_overflow) && \
__has_builtin(__builtin_mul_overflow))))
#define ckd_add(res, x, y) __builtin_add_overflow((x), (y), (res))
#define ckd_sub(res, x, y) __builtin_sub_overflow((x), (y), (res))
#define ckd_mul(res, x, y) __builtin_mul_overflow((x), (y), (res))

#elif defined(__cplusplus) && __cplusplus >= 201103L
#include "third_party/libcxx/type_traits"
#include "third_party/libcxx/limits"
#elif (defined(__cplusplus) && \
(__cplusplus >= 201103L || \
(defined(_MSC_VER) && __cplusplus >= 199711L && \
__ckd_has_include(<type_traits>) && \
__ckd_has_include(<limits>))))
#include <type_traits>
#include <limits>

template <typename __T, typename __U, typename __V>
inline bool ckd_add(__T *__res, __U __a, __V __b) {
Expand Down Expand Up @@ -158,16 +160,6 @@ inline bool ckd_sub(__T *__res, __U __a, __V __b) {
__ckd_uintmax_t __y = __b;
__ckd_uintmax_t __z = __x - __y;
*__res = __z;
if (sizeof(__z) > sizeof(__U) && sizeof(__z) > sizeof(__V)) {
if (sizeof(__z) > sizeof(__T) || std::is_signed<__T>::value) {
return static_cast<__ckd_intmax_t>(__z) != static_cast<__T>(__z);
} else if (!std::is_same<__T, __ckd_uintmax_t>::value) {
return (__z != static_cast<__T>(__z) ||
((std::is_signed<__U>::value ||
std::is_signed<__V>::value) &&
static_cast<__ckd_intmax_t>(__z) < 0));
}
}
bool __truncated = false;
if (sizeof(__T) < sizeof(__ckd_intmax_t)) {
__truncated = __z != static_cast<__ckd_uintmax_t>(static_cast<__T>(__z));
Expand Down Expand Up @@ -266,8 +258,8 @@ inline bool ckd_mul(__T *__res, __U __a, __V __b) {
case 3: { // u = s * s
int __o = false;
if (static_cast<__ckd_intmax_t>(__x & __y) < 0) {
__x = -__x;
__y = -__y;
__x = 0 - __x;
__y = 0 - __y;
} else if (static_cast<__ckd_intmax_t>(__x ^ __y) < 0) {
__o = __x && __y;
}
Expand All @@ -286,25 +278,25 @@ inline bool ckd_mul(__T *__res, __U __a, __V __b) {
__z != static_cast<__ckd_uintmax_t>(*__res)));
}
case 5: { // s = u * s
__ckd_uintmax_t __t = -__y;
__ckd_uintmax_t __t = 0 - __y;
__t = static_cast<__ckd_intmax_t>(__t) < 0 ? __y : __t;
__ckd_uintmax_t __p = __t * __x;
int __o = __t && __p / __t != __x;
int __n = static_cast<__ckd_intmax_t>(__y) < 0;
__ckd_uintmax_t __z = __n ? -__p : __p;
__ckd_uintmax_t __z = __n ? 0 - __p : __p;
*__res = __z;
__ckd_uintmax_t __m = std::numeric_limits<__ckd_intmax_t>::max();
return (__o | (__p > __m + __n) |
(sizeof(__T) < sizeof(__z) &&
__z != static_cast<__ckd_uintmax_t>(*__res)));
}
case 6: { // s = s * u
__ckd_uintmax_t __t = -__x;
__ckd_uintmax_t __t = 0 - __x;
__t = static_cast<__ckd_intmax_t>(__t) < 0 ? __x : __t;
__ckd_uintmax_t __p = __t * __y;
int __o = __t && __p / __t != __y;
int __n = static_cast<__ckd_intmax_t>(__x) < 0;
__ckd_uintmax_t __z = __n ? -__p : __p;
__ckd_uintmax_t __z = __n ? 0 - __p : __p;
*__res = __z;
__ckd_uintmax_t __m = std::numeric_limits<__ckd_intmax_t>::max();
return (__o | (__p > __m + __n) |
Expand Down Expand Up @@ -540,8 +532,8 @@ __ckd_declare_sub(__ckd_sub_uint128, unsigned __int128)
case 3: { /* u = s * s */ \
int __o = 0; \
if ((__ckd_intmax_t)(__x & __y) < 0) { \
__x = -__x; \
__y = -__y; \
__x = 0 - __x; \
__y = 0 - __y; \
} else if ((__ckd_intmax_t)(__x ^ __y) < 0) { \
__o = __x && __y; \
} \
Expand All @@ -560,25 +552,25 @@ __ckd_declare_sub(__ckd_sub_uint128, unsigned __int128)
__z != (__ckd_uintmax_t)*(T *)__res)); \
} \
case 5: { /* s = u * s */ \
__ckd_uintmax_t __t = -__y; \
__ckd_uintmax_t __t = 0 - __y; \
__t = (__ckd_intmax_t)(__t) < 0 ? __y : __t; \
__ckd_uintmax_t __p = __t * __x; \
int __o = __t && __p / __t != __x; \
int __n = (__ckd_intmax_t)__y < 0; \
__ckd_uintmax_t __z = __n ? -__p : __p; \
__ckd_uintmax_t __z = __n ? 0 - __p : __p; \
*(T *)__res = __z; \
__ckd_uintmax_t __m = __ckd_sign(__ckd_uintmax_t) - 1; \
return (__o | (__p > __m + __n) | \
(sizeof(T) < sizeof(__z) && \
__z != (__ckd_uintmax_t)*(T *)__res)); \
} \
case 6: { /* s = s * u */ \
__ckd_uintmax_t __t = -__x; \
__ckd_uintmax_t __t = 0 - __x; \
__t = (__ckd_intmax_t)(__t) < 0 ? __x : __t; \
__ckd_uintmax_t __p = __t * __y; \
int __o = __t && __p / __t != __y; \
int __n = (__ckd_intmax_t)__x < 0; \
__ckd_uintmax_t __z = __n ? -__p : __p; \
__ckd_uintmax_t __z = __n ? 0 - __p : __p; \
*(T *)__res = __z; \
__ckd_uintmax_t __m = __ckd_sign(__ckd_uintmax_t) - 1; \
return (__o | (__p > __m + __n) | \
Expand Down

0 comments on commit abdf6c9

Please sign in to comment.