diff options
| author | Bruce Hill <bruce@bruce-hill.com> | 2025-02-13 15:03:22 -0500 |
|---|---|---|
| committer | Bruce Hill <bruce@bruce-hill.com> | 2025-02-13 15:03:22 -0500 |
| commit | 5be955904682300153af0abdfd6b711b9da2ac8f (patch) | |
| tree | e616bc83904817fdefa43354fa815f13daf18739 /stdlib/integers.c | |
| parent | 8e0f1fa227be762cab19234abc106ba4c572077d (diff) | |
Deprecate Range datatype in favor of using iterator methods
Diffstat (limited to 'stdlib/integers.c')
| -rw-r--r-- | stdlib/integers.c | 45 |
1 files changed, 36 insertions, 9 deletions
diff --git a/stdlib/integers.c b/stdlib/integers.c index e5344370..858025fa 100644 --- a/stdlib/integers.c +++ b/stdlib/integers.c @@ -32,6 +32,11 @@ public Text_t Int$as_text(const void *i, bool colorize, const TypeInfo_t*) { return text; } +static bool Int$is_none(const void *i, const TypeInfo_t*) +{ + return ((Int_t*)i)->small == 0; +} + public PUREFUNC int32_t Int$compare_value(const Int_t x, const Int_t y) { if (likely(x.small & y.small & 1)) return (x.small > y.small) - (x.small < y.small); @@ -330,8 +335,31 @@ public OptionalInt_t Int$sqrt(Int_t i) return Int$from_mpz(result); } -public PUREFUNC Range_t Int$to(Int_t from, Int_t to) { - return (Range_t){from, to, Int$compare_value(to, from) >= 0 ? (Int_t){.small=(1<<2)|1} : (Int_t){.small=(-1>>2)|1}}; +typedef struct { + OptionalInt_t current, last; + Int_t step; +} IntRange_t; + +static OptionalInt_t _next_int(IntRange_t *info) +{ + OptionalInt_t i = info->current; + if (!Int$is_none(&i, &Int$info)) { + Int_t next = Int$plus(i, info->step); + if (!Int$is_none(&info->last, &Int$info) && Int$compare_value(next, info->last) == Int$compare_value(info->step, I(0))) + next = NONE_INT; + info->current = next; + } + return i; +} + +public PUREFUNC Closure_t Int$to(Int_t first, Int_t last, OptionalInt_t step) { + IntRange_t *range = GC_MALLOC(sizeof(IntRange_t)); + range->current = first; + range->last = last; + range->step = Int$is_none(&step, &Int$info) ? + Int$compare_value(last, first) >= 0 ? (Int_t){.small=(1<<2)|1} : (Int_t){.small=(-1>>2)|1} + : step; + return (Closure_t){.fn=_next_int, .userdata=range}; } public Int_t Int$from_str(const char *str) { @@ -415,11 +443,6 @@ public Int_t Int$factorial(Int_t n) return Int$from_mpz(ret); } -static bool Int$is_none(const void *i, const TypeInfo_t*) -{ - return ((Int_t*)i)->small == 0; -} - static void Int$serialize(const void *obj, FILE *out, Table_t *pointers, const TypeInfo_t*) { Int_t i = *(Int_t*)obj; @@ -545,8 +568,12 @@ public void Int32$deserialize(FILE *in, void *outval, Array_t*, const TypeInfo_t } \ return bit_array; \ } \ - public to_attr Range_t KindOfInt ## $to(c_type from, c_type to) { \ - return (Range_t){Int64_to_Int(from), Int64_to_Int(to), to >= from ? I_small(1): I_small(-1)}; \ + public to_attr Closure_t KindOfInt ## $to(c_type first, c_type last, Optional ## KindOfInt ## _t step) { \ + IntRange_t *range = GC_MALLOC(sizeof(IntRange_t)); \ + range->current = KindOfInt##_to_Int(first); \ + range->last = KindOfInt##_to_Int(last); \ + range->step = step.is_none ? (last >= first ? I_small(1) : I_small(-1)) : KindOfInt##_to_Int(step.i); \ + return (Closure_t){.fn=_next_int, .userdata=range}; \ } \ public PUREFUNC Optional ## KindOfInt ## _t KindOfInt ## $parse(Text_t text) { \ OptionalInt_t full_int = Int$parse(text); \ |
