diff options
| author | Bruce Hill <bruce@bruce-hill.com> | 2024-08-14 14:57:01 -0400 |
|---|---|---|
| committer | Bruce Hill <bruce@bruce-hill.com> | 2024-08-14 14:57:01 -0400 |
| commit | 9c2d7c437d7576b44f4cf0e6b6a293acd7188a5d (patch) | |
| tree | f77b86d59c258f2e1d9834f8acc7c68da68af01a /builtins | |
| parent | c8af1ac9c12073776fda6af7ae58f9d6e2d81e66 (diff) | |
Fix up type conversions with ints and nums
Diffstat (limited to 'builtins')
| -rw-r--r-- | builtins/array.c | 16 | ||||
| -rw-r--r-- | builtins/array.h | 4 | ||||
| -rw-r--r-- | builtins/channel.c | 2 | ||||
| -rw-r--r-- | builtins/integers.c | 44 | ||||
| -rw-r--r-- | builtins/integers.h | 109 | ||||
| -rw-r--r-- | builtins/nums.c | 8 | ||||
| -rw-r--r-- | builtins/text.c | 2 |
7 files changed, 128 insertions, 57 deletions
diff --git a/builtins/array.c b/builtins/array.c index 96a218f5..a6e0dca2 100644 --- a/builtins/array.c +++ b/builtins/array.c @@ -50,7 +50,7 @@ public void Array$compact(array_t *arr, int64_t padded_item_size) public void Array$insert(array_t *arr, const void *item, Int_t int_index, int64_t padded_item_size) { - int64_t index = Int$as_i64(int_index); + int64_t index = Int_to_Int64(int_index, false); if (index <= 0) index = arr->length + index + 1; if (index < 1) index = 1; @@ -82,7 +82,7 @@ public void Array$insert(array_t *arr, const void *item, Int_t int_index, int64_ public void Array$insert_all(array_t *arr, array_t to_insert, Int_t int_index, int64_t padded_item_size) { - int64_t index = Int$as_i64(int_index); + int64_t index = Int_to_Int64(int_index, false); if (to_insert.length == 0) return; @@ -154,10 +154,10 @@ public void Array$insert_all(array_t *arr, array_t to_insert, Int_t int_index, i public void Array$remove(array_t *arr, Int_t int_index, Int_t int_count, int64_t padded_item_size) { - int64_t index = Int$as_i64(int_index); + int64_t index = Int_to_Int64(int_index, false); if (index < 1) index = arr->length + index + 1; - int64_t count = Int$as_i64(int_count); + int64_t count = Int_to_Int64(int_count, false); if (index < 1 || index > (int64_t)arr->length || count < 1) return; if (count > arr->length - index + 1) @@ -240,7 +240,7 @@ public table_t Array$counts(array_t arr, const TypeInfo *type) public array_t Array$sample(array_t arr, Int_t int_n, array_t weights, int64_t padded_item_size) { - int64_t n = Int$as_i64(int_n); + int64_t n = Int_to_Int64(int_n, false); if (arr.length == 0 || n <= 0) return (array_t){}; @@ -319,7 +319,7 @@ public array_t Array$sample(array_t arr, Int_t int_n, array_t weights, int64_t p public array_t Array$from(array_t array, Int_t int_first) { - int64_t first = Int$as_i64(int_first); + int64_t first = Int_to_Int64(int_first, false); if (first < 0) first = array.length + first + 1; @@ -337,7 +337,7 @@ public array_t Array$from(array_t array, Int_t int_first) public array_t Array$to(array_t array, Int_t int_last) { - int64_t last = Int$as_i64(int_last); + int64_t last = Int_to_Int64(int_last, false); if (last < 0) last = array.length + last + 1; @@ -358,7 +358,7 @@ public array_t Array$to(array_t array, Int_t int_last) public array_t Array$by(array_t array, Int_t int_stride, int64_t padded_item_size) { - int64_t stride = Int$as_i64(int_stride); + int64_t stride = Int_to_Int64(int_stride, false); // In the unlikely event that the stride value would be too large to fit in // a 15-bit integer, fall back to creating a copy of the array: if (__builtin_expect(array.stride*stride < ARRAY_MIN_STRIDE || array.stride*stride > ARRAY_MAX_STRIDE, 0)) { diff --git a/builtins/array.h b/builtins/array.h index 6da84afd..a3305ca3 100644 --- a/builtins/array.h +++ b/builtins/array.h @@ -13,13 +13,13 @@ // Convert negative indices to back-indexed without branching: index0 = index + (index < 0)*(len+1)) - 1 #define Array_get(item_type, arr_expr, index_expr, filename, start, end) *({ \ - const array_t arr = arr_expr; int64_t index = Int$as_i64(index_expr); \ + const array_t arr = arr_expr; int64_t index = Int_to_Int64(index_expr, false); \ int64_t off = index + (index < 0) * (arr.length + 1) - 1; \ if (__builtin_expect(off < 0 || off >= arr.length, 0)) \ fail_source(filename, start, end, "Invalid array index: %r (array has length %ld)\n", Int64$as_text(&index, no, NULL), arr.length); \ (item_type*)(arr.data + arr.stride * off);}) #define Array_lvalue(item_type, arr_expr, index_expr, padded_item_size, filename, start, end) *({ \ - array_t *arr = arr_expr; int64_t index = Int$as_i64(index_expr); \ + array_t *arr = arr_expr; int64_t index = Int_to_Int64(index_expr, false); \ int64_t off = index + (index < 0) * (arr->length + 1) - 1; \ if (__builtin_expect(off < 0 || off >= arr->length, 0)) \ fail_source(filename, start, end, "Invalid array index: %r (array has length %ld)\n", Int64$as_text(&index, no, NULL), arr->length); \ diff --git a/builtins/channel.c b/builtins/channel.c index dba50115..dd49163c 100644 --- a/builtins/channel.c +++ b/builtins/channel.c @@ -26,7 +26,7 @@ public channel_t *Channel$new(Int_t max_size) channel->items = (array_t){}; channel->mutex = (pthread_mutex_t)PTHREAD_MUTEX_INITIALIZER; channel->cond = (pthread_cond_t)PTHREAD_COND_INITIALIZER; - channel->max_size = Int$as_i64(max_size); + channel->max_size = Int_to_Int64(max_size, false); return channel; } diff --git a/builtins/integers.c b/builtins/integers.c index 0783f16d..bb82fab6 100644 --- a/builtins/integers.c +++ b/builtins/integers.c @@ -21,30 +21,6 @@ public void Int$init_random(long seed) gmp_randseed_ui(Int_rng, (unsigned long)seed); } -public Int_t Int$from_i64(int64_t i) -{ - int64_t z = i<<2; - if (z == (int32_t)z) return (Int_t){.small=z+1}; - mpz_t result; - mpz_init_set_si(result, i); - return Int$from_mpz(result); -} - -public Int_t Int$from_num(double n) -{ - mpz_t result; - mpz_init_set_d(result, n); - return Int$from_mpz(result); -} - -public double Int$as_num(Int_t i) -{ - if (__builtin_expect(i.small & 1, 1)) - return (double)(i.small >> 2); - - return mpz_get_d(*i.big); -} - public CORD Int$as_text(const Int_t *i, bool colorize, const TypeInfo *type) { (void)type; if (!i) return "Int"; @@ -93,7 +69,7 @@ public uint32_t Int$hash(const Int_t *x, const TypeInfo *type) { public CORD Int$format(Int_t i, Int_t digits_int) { - int64_t digits = Int$as_i64(digits_int); + int64_t digits = Int_to_Int64(digits_int, false); if (__builtin_expect(i.small & 1, 1)) { return CORD_asprintf("%0.*ld", digits, (i.small)>>2); } else { @@ -110,7 +86,7 @@ public CORD Int$format(Int_t i, Int_t digits_int) } public CORD Int$hex(Int_t i, Int_t digits_int, bool uppercase, bool prefix) { - int64_t digits = Int$as_i64(digits_int); + int64_t digits = Int_to_Int64(digits_int, false); const char *hex_fmt = uppercase ? (prefix ? "0x%0.*lX" : "%0.*lX") : (prefix ? "0x%0.*lx" : "%0.*lx"); if (__builtin_expect(i.small & 1, 1)) { return CORD_asprintf(hex_fmt, digits, (i.small)>>2); @@ -125,7 +101,7 @@ public CORD Int$hex(Int_t i, Int_t digits_int, bool uppercase, bool prefix) { } public CORD Int$octal(Int_t i, Int_t digits_int, bool prefix) { - int64_t digits = Int$as_i64(digits_int); + int64_t digits = Int_to_Int64(digits_int, false); const char *octal_fmt = prefix ? "0o%0.*lo" : "%0.*lo"; if (__builtin_expect(i.small & 1, 1)) { return CORD_asprintf(octal_fmt, (int)digits, (uint64_t)(i.small >> 2)); @@ -213,7 +189,7 @@ public Int_t Int$slow_modulo1(Int_t x, Int_t modulus) public Int_t Int$slow_left_shifted(Int_t x, Int_t y) { - mp_bitcnt_t bits = (mp_bitcnt_t)Int$as_i64(y); + mp_bitcnt_t bits = (mp_bitcnt_t)Int_to_Int64(y, false); mpz_t result; mpz_init_set_int(result, x); mpz_mul_2exp(result, result, bits); @@ -222,7 +198,7 @@ public Int_t Int$slow_left_shifted(Int_t x, Int_t y) public Int_t Int$slow_right_shifted(Int_t x, Int_t y) { - mp_bitcnt_t bits = (mp_bitcnt_t)Int$as_i64(y); + mp_bitcnt_t bits = (mp_bitcnt_t)Int_to_Int64(y, false); mpz_t result; mpz_init_set_int(result, x); mpz_tdiv_q_2exp(result, result, bits); @@ -292,7 +268,7 @@ public Int_t Int$abs(Int_t x) public Int_t Int$power(Int_t base, Int_t exponent) { - int64_t exp = Int$as_i64(exponent); + int64_t exp = Int_to_Int64(exponent, false); if (__builtin_expect(exp < 0, 0)) fail("Cannot take a negative power of an integer!"); mpz_t result; @@ -382,16 +358,16 @@ public const TypeInfo $Int = { return *x == *y; \ } \ public CORD KindOfInt ## $format(c_type i, Int_t digits_int) { \ - int64_t digits = Int$as_i64(digits_int); \ + int64_t digits = Int_to_Int64(digits_int, false); \ return CORD_asprintf("%0*" fmt, (int)digits, i); \ } \ public CORD KindOfInt ## $hex(c_type i, Int_t digits_int, bool uppercase, bool prefix) { \ - int64_t digits = Int$as_i64(digits_int); \ + int64_t digits = Int_to_Int64(digits_int, false); \ const char *hex_fmt = uppercase ? (prefix ? "0x%0.*lX" : "%0.*lX") : (prefix ? "0x%0.*lx" : "%0.*lx"); \ return CORD_asprintf(hex_fmt, (int)digits, (uint64_t)i); \ } \ public CORD KindOfInt ## $octal(c_type i, Int_t digits_int, bool prefix) { \ - int64_t digits = Int$as_i64(digits_int); \ + int64_t digits = Int_to_Int64(digits_int, false); \ const char *octal_fmt = prefix ? "0o%0.*lo" : "%0.*lo"; \ return CORD_asprintf(octal_fmt, (int)digits, (uint64_t)i); \ } \ @@ -422,7 +398,7 @@ public const TypeInfo $Int = { return (c_type)((uint64_t)min + (r % range)); \ } \ public Range_t KindOfInt ## $to(c_type from, c_type to) { \ - return (Range_t){Int$from_i64(from), Int$from_i64(to), to >= from ? (Int_t){.small=(1<<2)&1} : (Int_t){.small=(1<<2)&1}}; \ + return (Range_t){Int64_to_Int(from), Int64_to_Int(to), to >= from ? (Int_t){.small=(1<<2)&1} : (Int_t){.small=(1<<2)&1}}; \ } \ public c_type KindOfInt ## $from_text(CORD text, CORD *the_rest) { \ const char *str = CORD_to_const_char_star(text); \ diff --git a/builtins/integers.h b/builtins/integers.h index 98b58b0f..05085175 100644 --- a/builtins/integers.h +++ b/builtins/integers.h @@ -9,7 +9,10 @@ #include <gmp.h> #include "datatypes.h" +#include "functions.h" +#include "nums.h" #include "types.h" +#include "util.h" #define Int64_t int64_t #define Int32_t int32_t @@ -78,13 +81,7 @@ Int_t Int$sqrt(Int_t i); else mpz_init_set(mpz, *(i).big); \ } while (0) -#define Int$as_i64(i) (__builtin_expect((i).small & 1, 1) ? (int64_t)((i).small >> 2) : \ - ({ if (!__builtin_expect(mpz_fits_slong_p(*(i).big), 1)) fail("Integer is too big to fit in a 64-bit integer!"); \ - mpz_get_si(*(i).big); })) -Int_t Int$from_i64(int64_t i); -Int_t Int$from_num(double n); -double Int$as_num(Int_t i); -#define I(i) ((int64_t)(i) == (int32_t)(i) ? ((Int_t){.small=((uint64_t)(i)<<2)|1}) : Int$from_i64(i)) +#define I(i) ((int64_t)(i) == (int32_t)(i) ? ((Int_t){.small=((uint64_t)(i)<<2)|1}) : Int64_to_Int(i)) Int_t Int$slow_plus(Int_t x, Int_t y); Int_t Int$slow_minus(Int_t x, Int_t y); @@ -207,4 +204,102 @@ static inline Int_t Int$negative(Int_t x) return Int$slow_negative(x); } +// Conversion functions: + +static inline Int_t Int64_to_Int(int64_t i) +{ + int64_t z = i<<2; + if (__builtin_expect(z == (int32_t)z, 1)) + return (Int_t){.small=z+1}; + mpz_t result; + mpz_init_set_si(result, i); + return Int$from_mpz(result); +} + +#define Int32_to_Int(i) Int64_to_Int(i) +#define Int16_to_Int(i) Int64_to_Int(i) +#define Int8_to_Int(i) Int64_to_Int(i) + +static inline Int64_t Int_to_Int64(Int_t i, bool truncate) { + if (__builtin_expect(i.small & 1, 1)) + return (int64_t)(i.small >> 2); + if (__builtin_expect(!truncate && !mpz_fits_slong_p(*i.big), 0)) + fail("Integer is too big to fit in a 64-bit integer!"); + return mpz_get_si(*i.big); +} + +static inline Int32_t Int_to_Int32(Int_t i, bool truncate) { + int64_t i64 = Int_to_Int64(i, truncate); + int32_t i32 = (int32_t)i64; + if (__builtin_expect(i64 != i32 && !truncate, 0)) + fail("Integer is too big to fit in a 32-bit integer!"); + return i32; +} + +static inline Int16_t Int_to_Int16(Int_t i, bool truncate) { + int64_t i64 = Int_to_Int64(i, truncate); + int16_t i16 = (int16_t)i64; + if (__builtin_expect(i64 != i16 && !truncate, 0)) + fail("Integer is too big to fit in a 16-bit integer!"); + return i16; +} + +static inline Int8_t Int_to_Int8(Int_t i, bool truncate) { + int64_t i64 = Int_to_Int64(i, truncate); + int8_t i8 = (int8_t)i64; + if (__builtin_expect(i64 != i8 && !truncate, 0)) + fail("Integer is too big to fit in an 8-bit integer!"); + return i8; +} + +static inline Int_t Num_to_Int(double n) +{ + mpz_t result; + mpz_init_set_d(result, n); + return Int$from_mpz(result); +} + +static inline double Int_to_Num(Int_t i) +{ + if (__builtin_expect(i.small & 1, 1)) + return (double)(i.small >> 2); + + return mpz_get_d(*i.big); +} + +#define Int_to_Num32(i) (Num32_t)Int_to_Num(i) + +#define CONVERSION_FUNC(hi, lo) \ + static inline int##lo##_t Int##hi##_to_Int##lo(int##hi##_t i, bool truncate) { \ + if (__builtin_expect(!truncate && (i != (int##lo##_t)i), 0)) \ + fail("Cannot truncate the Int" #hi " %ld to an Int" #lo, (int64_t)i); \ + return (int##lo##_t)i; \ + } + +CONVERSION_FUNC(64, 32) +CONVERSION_FUNC(64, 16) +CONVERSION_FUNC(64, 8) +CONVERSION_FUNC(32, 16) +CONVERSION_FUNC(32, 8) +CONVERSION_FUNC(16, 8) +#undef CONVERSION_FUNC + +#define CONVERSION_FUNC(num, int_type) \ + static inline int_type##_t num##_to_##int_type(num##_t n, bool truncate) { \ + num##_t rounded = round(n); \ + if (__builtin_expect(!truncate && (num##_t)(int_type##_t)rounded != rounded, 0)) \ + fail("Cannot truncate the " #num " %g to an " #int_type, rounded); \ + return (int_type##_t)rounded; \ + } + +CONVERSION_FUNC(Num, Int64) +CONVERSION_FUNC(Num, Int32) +CONVERSION_FUNC(Num, Int16) +CONVERSION_FUNC(Num, Int8) +CONVERSION_FUNC(Num32, Int64) +CONVERSION_FUNC(Num32, Int32) +CONVERSION_FUNC(Num32, Int16) +CONVERSION_FUNC(Num32, Int8) +#undef CONVERSION_FUNC + // vim: ts=4 sw=0 et cino=L2,l1,(0,W4,m1,\:0 diff --git a/builtins/nums.c b/builtins/nums.c index f1635fd5..2efd4cbc 100644 --- a/builtins/nums.c +++ b/builtins/nums.c @@ -48,11 +48,11 @@ public bool Num$near(double a, double b, double ratio, double absolute) { } public CORD Num$format(double f, Int_t precision) { - return CORD_asprintf("%.*f", (int)Int$as_i64(precision), f); + return CORD_asprintf("%.*f", (int)Int_to_Int64(precision, false), f); } public CORD Num$scientific(double f, Int_t precision) { - return CORD_asprintf("%.*e", (int)Int$as_i64(precision), f); + return CORD_asprintf("%.*e", (int)Int_to_Int64(precision, false), f); } public double Num$mod(double num, double modulus) { @@ -130,11 +130,11 @@ public bool Num32$near(float a, float b, float ratio, float absolute) { } public CORD Num32$format(float f, Int_t precision) { - return CORD_asprintf("%.*f", (int)Int$as_i64(precision), f); + return CORD_asprintf("%.*f", (int)Int_to_Int64(precision, false), f); } public CORD Num32$scientific(float f, Int_t precision) { - return CORD_asprintf("%.*e", (int)Int$as_i64(precision), f); + return CORD_asprintf("%.*e", (int)Int_to_Int64(precision, false), f); } public float Num32$mod(float num, float modulus) { diff --git a/builtins/text.c b/builtins/text.c index 754eef91..22784a34 100644 --- a/builtins/text.c +++ b/builtins/text.c @@ -255,7 +255,7 @@ public CORD Text$replace(CORD text, CORD pat, CORD replacement, Int_t int_limit) if (!text || !pat) return text; CORD ret = CORD_EMPTY; size_t pos = 0, pat_len = CORD_len(pat); - int64_t limit = Int$as_i64(int_limit); + int64_t limit = Int_to_Int64(int_limit, false); for (size_t found; limit != 0 && (found=CORD_str(text, pos, pat)) != CORD_NOT_FOUND; --limit) { ret = CORD_all(ret, CORD_substr(text, pos, found - pos), replacement); pos = found + pat_len; |
