std1.0.0-beta-7 SafeC docs

Source stdckdint.sc

View in the repository

// SafeC Standard Library — Checked integer arithmetic (C23)
// Pure SafeC implementation — overflow is detected before the operation.
#pragma once
#include <std/stdckdint.h>

// ── 32-bit signed ─────────────────────────────────────────────────────────────

namespace std {

inline int ckd_add_i32(&int result, int a, int b) {
    int overflow = 0;
    if (b > 0 && a > 2147483647 - b)         { overflow = 1; }
    if (b < 0 && a < (-2147483647 - 1) - b) { overflow = 1; }
    // Wrapped result computed unsigned: signed overflow is undefined.
    unsafe { *result = (int)((unsigned int)a + (unsigned int)b); }
    return overflow;
}

inline int ckd_sub_i32(&int result, int a, int b) {
    int overflow = 0;
    if (b < 0 && a > 2147483647 + b)         { overflow = 1; }
    if (b > 0 && a < (-2147483647 - 1) + b) { overflow = 1; }
    unsafe { *result = (int)((unsigned int)a - (unsigned int)b); }
    return overflow;
}

inline int ckd_mul_i32(&int result, int a, int b) {
    long long wide = (long long)a * (long long)b;
    int overflow = 0;
    if (wide > 2147483647LL || wide < (long long)(-2147483647 - 1)) {
        overflow = 1;
    }
    unsafe { *result = (int)wide; }
    return overflow;
}

// ── 64-bit signed ─────────────────────────────────────────────────────────────

inline int ckd_add_i64(&long long result, long long a, long long b) {
    int overflow = 0;
    if (b > 0LL && a > 9223372036854775807LL - b)                          { overflow = 1; }
    if (b < 0LL && a < (-9223372036854775807LL - (long long)1) - b)       { overflow = 1; }
    unsafe { *result = (long long)((unsigned long long)a + (unsigned long long)b); }
    return overflow;
}

inline int ckd_sub_i64(&long long result, long long a, long long b) {
    int overflow = 0;
    if (b < 0LL && a > 9223372036854775807LL + b)                          { overflow = 1; }
    if (b > 0LL && a < (-9223372036854775807LL - (long long)1) + b)       { overflow = 1; }
    unsafe { *result = (long long)((unsigned long long)a - (unsigned long long)b); }
    return overflow;
}

inline int ckd_mul_i64(&long long result, long long a, long long b) {
    long long llong_min = -9223372036854775807LL - (long long)1;
    long long llong_max = 9223372036854775807LL;
    int overflow = 0;
    if (a != 0LL && b != 0LL) {
        if (a > 0LL && b > 0LL && a > llong_max / b)             { overflow = 1; }
        if (a < 0LL && b < 0LL && a < llong_max / b)             { overflow = 1; }
        if (a > 0LL && b < 0LL && b < llong_min / a)             { overflow = 1; }
        if (a < 0LL && b > 0LL && a < llong_min / b)             { overflow = 1; }
    }
    unsafe { *result = (long long)((unsigned long long)a * (unsigned long long)b); }
    return overflow;
}

// ── 32-bit unsigned ───────────────────────────────────────────────────────────

inline int ckd_add_u32(&unsigned int result, unsigned int a, unsigned int b) {
    unsigned int r = a + b;
    unsafe { *result = r; }
    if (r < a) { return 1; }
    return 0;
}

inline int ckd_sub_u32(&unsigned int result, unsigned int a, unsigned int b) {
    unsafe { *result = a - b; }
    if (b > a) { return 1; }
    return 0;
}

inline int ckd_mul_u32(&unsigned int result, unsigned int a, unsigned int b) {
    unsigned long long wide = (unsigned long long)a * (unsigned long long)b;
    int overflow = 0;
    if (wide > 4294967295ULL) { overflow = 1; }
    unsafe { *result = (unsigned int)wide; }
    return overflow;
}

// ── 64-bit unsigned ───────────────────────────────────────────────────────────

inline int ckd_add_u64(&unsigned long long result, unsigned long long a, unsigned long long b) {
    unsigned long long r = a + b;
    unsafe { *result = r; }
    if (r < a) { return 1; }
    return 0;
}

inline int ckd_sub_u64(&unsigned long long result, unsigned long long a, unsigned long long b) {
    unsafe { *result = a - b; }
    if (b > a) { return 1; }
    return 0;
}

inline int ckd_mul_u64(&unsigned long long result, unsigned long long a, unsigned long long b) {
    int overflow = 0;
    if (a != 0ULL && b > 18446744073709551615ULL / a) { overflow = 1; }
    unsafe { *result = a * b; }
    return overflow;
}

} // namespace std