rearrange squeeze.c and make num_squeeze & chr_squeeze more sane

This commit is contained in:
dzaima 2025-05-13 02:14:37 +03:00
parent a32c0c1722
commit 6c4eae5e28
5 changed files with 231 additions and 171 deletions

View File

@ -102,7 +102,7 @@ Namespace of various internal functions. May change at any time.
| `•internal.HeapDump` | Create a heap dump file; saves to `•wdpath`-relative path `𝕩` or `CBQNHeapDump` if `𝕩` isn't an array | | `•internal.HeapDump` | Create a heap dump file; saves to `•wdpath`-relative path `𝕩` or `CBQNHeapDump` if `𝕩` isn't an array |
| `•internal.HeapStats` | If argument is `@`, returns `⟨total heap size ⋄ used heap size⟩`. If argument is a string, prints the equivalent of `)mem the-string` | | `•internal.HeapStats` | If argument is `@`, returns `⟨total heap size ⋄ used heap size⟩`. If argument is a string, prints the equivalent of `)mem the-string` |
| `•internal.HasFill` | Returns whether the argument has a fill element (may give `0` even if `1↑0⥊𝕩` doesn't error in some CBQN configurations) | | `•internal.HasFill` | Returns whether the argument has a fill element (may give `0` even if `1↑0⥊𝕩` doesn't error in some CBQN configurations) |
| `•internal.Squeeze` | Try to convert the argument to its most compact representation | | `•internal.Squeeze` | Try to convert the argument to its most compact representation; result may have fill updated to `0` or `' '`. (input is left unchanged) |
| `•internal.DeepSqueeze` | Try to convert the argument and all its subarrays to its most compact representation; won't squeeze namespace fields | | `•internal.DeepSqueeze` | Try to convert the argument and all its subarrays to its most compact representation; won't squeeze namespace fields |
| `•internal.ListVariations` | List the possible type variations of the argument array | | `•internal.ListVariations` | List the possible type variations of the argument array |
| `•internal.Variation` | Convert `𝕩` to the variation specified in `𝕨` | | `•internal.Variation` | Convert `𝕩` to the variation specified in `𝕨` |

View File

@ -1,210 +1,268 @@
#include "../core.h" #include "../core.h"
#define SQFN_START assert(xa == a(x) && ia==IA(x) && ia>0 && TY(x)==type && a(x)==xa)
typedef B (*SqueezeFn)(B x, Arr* xa, u8 type, ux ia);
static B squeeze_smallest(B x, Arr* xa, u8 type, ux ia) {
SQFN_START;
assert(TI(x,elType)==el_bit || TI(x,elType)==el_c8);
FLV_SET(xa, fl_squoze);
return x;
}
static B squeeze_nope(B x, Arr* xa, u8 type, ux ia) {
SQFN_START;
return x;
}
#define SQFN_NUM_RET \
mostI32:MAYBE_UNUSED; if(or>I16_MAX) goto r_i32; \
mostI16:MAYBE_UNUSED; if(or>I8_MAX ) goto r_i16; \
mostI8: MAYBE_UNUSED; if(or>0 ) goto r_i8; \
mostBit:MAYBE_UNUSED; goto r_bit; \
r_f64:MAYBE_UNUSED; xa = cpyF64Arr(x); goto tag; \
r_i32: xa = cpyI32Arr(x); goto tag; \
r_i16: xa = cpyI16Arr(x); goto tag; \
r_i8: xa = cpyI8Arr (x); goto tag; \
r_bit: xa = cpyBitArr(x); goto tag; \
tag: x = taga(xa); \
squeezed: FLV_SET(xa, fl_squoze); \
return x;
#define SQFN_CHR_RET \
r_c32:MAYBE_UNUSED; xa = cpyC32Arr(x); goto tag; \
r_c16:MAYBE_UNUSED; xa = cpyC16Arr(x); goto tag; \
r_c8: MAYBE_UNUSED; xa = cpyC8Arr (x); goto tag; \
tag: x = taga(xa); \
squeezed: FLV_SET(xa, fl_squoze); \
return x;
#define SQFN_NUM(T, CORE) static B squeeze_##T(B x, Arr* xa, u8 type, ux ia) { \
SQFN_START; \
u32 or=0; CORE; \
SQFN_NUM_RET; \
}
#define SQFN_CHR(T, CORE) static B squeeze_##T(B x, Arr* xa, u8 type, ux ia) { \
SQFN_START; \
CORE; \
SQFN_CHR_RET; \
}
#if SINGELI_SIMD #if SINGELI_SIMD
#define SINGELI_FILE squeeze #define SINGELI_FILE squeeze
#include "../utils/includeSingeli.h" #include "../utils/includeSingeli.h"
#endif
NOINLINE B num_squeezeF(B x, usz ia) {
u32 or = 0;
SGetU(x)
Arr* a;
for (usz i = 0; i < ia; i++) {
B cr = GetU(x,i);
if (RARE(!q_i32(cr))) {
while (i<ia) if (!isF64(GetU(x,i++))) return FL_SET(x, fl_squoze);
a = (Arr*) cpyF64Arr(x);
goto retn;
}
i32 c = o2iG(cr);
or|= ((u32)c & ~1) ^ (u32)(c>>31);
}
a = or==0? (Arr*)cpyBitArr(x)
: or<=(u32)I8_MAX? (Arr*)cpyI8Arr (x)
: or<=(u32)I16_MAX? (Arr*)cpyI16Arr(x)
: (Arr*)cpyI32Arr(x);
retn: SQFN_NUM(i8, or = si_squeeze_i8 ( i8anyv_ptr(xa), ia); if(or> 1) goto squeezed; else goto mostBit;)
FLV_SET(a, fl_squoze); SQFN_NUM(i16, or = si_squeeze_i16(i16anyv_ptr(xa), ia); if(or> I8_MAX) goto squeezed; else goto mostI8;)
return taga(a); SQFN_NUM(i32, or = si_squeeze_i32(i32anyv_ptr(xa), ia); if(or> I16_MAX) goto squeezed; else goto mostI16;)
} SQFN_NUM(f64, or = si_squeeze_f64(f64anyv_ptr(xa), ia); if(-1==(u32)or) goto squeezed; else goto mostI32;)
B num_squeeze(B x) {
usz ia = IA(x);
u8 xe = TI(x,elType);
if (ia==0) {
if (xe==el_bit) return x;
goto r_bit;
}
#if !SINGELI_SIMD SQFN_CHR(c16, u32 t = si_squeeze_c16(c16anyv_ptr(xa), ia); if (t==0) goto r_c8; else goto squeezed;)
usz i = 0; SQFN_CHR(c32, u32 t = si_squeeze_c32(c32anyv_ptr(xa), ia); if (t==0) goto r_c8; else if (t==1) goto r_c16; else if (t==2) goto squeezed; else UD;)
#endif #else
SQFN_NUM(i8, i8* xp = i8anyv_ptr (xa); for (ux i=0; i<ia; i++) { i32 c = xp[i]; or|= (u8)c; } if(or> 1) goto squeezed; goto mostBit;)
u32 or = 0; // using bitwise or as an approximate ⌈´ SQFN_NUM(i16, i16* xp = i16anyv_ptr(xa); for (ux i=0; i<ia; i++) { i32 c = xp[i]; or|= ((u32)c & ~1) ^ (u32)(c>>31); } if(or> I8_MAX) goto squeezed; goto mostI8;)
switch (xe) { default: UD; SQFN_NUM(i32, i32* xp = i32anyv_ptr(xa); for (ux i=0; i<ia; i++) { i32 c = xp[i]; or|= ((u32)c & ~1) ^ (u32)(c>>31); } if(or>I16_MAX) goto squeezed; goto mostI16;)
case el_bit: goto r_x; SQFN_NUM(f64,
#if SINGELI_SIMD f64* xp = f64anyv_ptr(xa);
case el_i8: { or = si_squeeze_i8 (i8any_ptr (x), ia); if(or> 1) goto r_x; else goto mostBit; } for (ux i = 0; i < ia; i++) {
case el_i16: { or = si_squeeze_i16(i16any_ptr(x), ia); if(or> I8_MAX) goto r_x; else goto mostI8; } f64 cf = xp[i];
case el_i32: { or = si_squeeze_i32(i32any_ptr(x), ia); if(or> I16_MAX) goto r_x; else goto mostI16; } i32 c = (i32)cf;
case el_f64: { or = si_squeeze_f64(f64any_ptr(x), ia); if(-1==(u32)or) goto r_x; else goto mostI32; } if (c!=cf) goto squeezed;
#else
case el_i8: { i8* xp = i8any_ptr (x); for (; i < ia; i++) { i32 c = xp[i]; or|= (u8)c; } if(or> 1) goto r_x; goto mostBit; }
case el_i16: { i16* xp = i16any_ptr(x); for (; i < ia; i++) { i32 c = xp[i]; or|= ((u32)c & ~1) ^ (u32)(c>>31); } if(or> I8_MAX) goto r_x; goto mostI8; }
case el_i32: { i32* xp = i32any_ptr(x); for (; i < ia; i++) { i32 c = xp[i]; or|= ((u32)c & ~1) ^ (u32)(c>>31); } if(or>I16_MAX) goto r_x; goto mostI16; }
case el_f64: {
f64* xp = f64any_ptr(x);
for (; i < ia; i++) {
f64 cf = xp[i];
i32 c = (i32)cf;
if (c!=cf) goto r_x; // already f64
or|= ((u32)c & ~1) ^ (u32)(c>>31);
}
goto mostI32;
}
#endif
case el_B: case el_c8: case el_c16: case el_c32:; /*fallthrough*/
}
B* xp = arr_bptr(x);
if (xp==NULL) goto r_f;
#if SINGELI_SIMD
or = si_squeeze_numB(xp, ia);
if (-2==(i32)or) goto r_x;
if (-1==(i32)or) goto r_f64;
goto mostI32;
#else
for (; i < ia; i++) {
if (RARE(!q_i32(xp[i]))) {
while (i<ia) if (!isF64(xp[i++])) goto r_x;
goto r_f64;
}
i32 c = o2iG(xp[i]);
or|= ((u32)c & ~1) ^ (u32)(c>>31); or|= ((u32)c & ~1) ^ (u32)(c>>31);
} }
goto mostI32; goto mostI32;
#endif )
mostI32: if(or>I16_MAX ) goto r_i32; SQFN_CHR(c16,
mostI16: if(or>I8_MAX ) goto r_i16; u16* xp = c16anyv_ptr(xa);
mostI8: if(or>0 ) goto r_i8; for (ux i = 0; i < ia; i++) if (xp[i] != (u8)xp[i]) goto squeezed;
mostBit: goto r_bit;
B rb; Arr* ra;
r_f: return num_squeezeF(x, ia); // rb = num_squeezeF(x,ia); goto retn;
r_x: ra = a(x); rb = x; goto retn;
r_f64: ra = (Arr*)cpyF64Arr(x); goto tag;
r_i32: ra = (Arr*)cpyI32Arr(x); goto tag;
r_i16: ra = (Arr*)cpyI16Arr(x); goto tag;
r_i8: ra = (Arr*)cpyI8Arr (x); goto tag;
r_bit: ra = (Arr*)cpyBitArr(x); goto tag;
tag:
rb = taga(ra);
retn:
FLV_SET(ra, fl_squoze);
return rb;
}
B chr_squeeze(B x) {
usz ia = IA(x);
u8 xe = TI(x,elType);
if (ia==0) {
if (xe==el_c8) return x;
goto r_c8; goto r_c8;
} )
usz i = 0; SQFN_CHR(c32,
i32 or = 0; u32* xp = c32anyv_ptr(xa);
switch(xe) { default: UD; bool c8 = true;
case el_c8: goto r_x; for (ux i = 0; i < ia; i++) {
#if SINGELI_SIMD if (xp[i] != (u16)xp[i]) goto squeezed;
case el_c16: { u32 t = si_squeeze_c16(c16any_ptr(x), ia); if (t==0) goto r_c8; else goto r_x; } if (xp[i] != (u8 )xp[i]) c8 = false;
case el_c32: { u32 t = si_squeeze_c32(c32any_ptr(x), ia); if (t==0) goto r_c8; else if (t==1) goto r_c16; else if (t==2) goto r_x; else UD; }
#else
case el_c16: {
u16* xp = c16any_ptr(x);
for (; i < ia; i++) if (xp[i] != (u8)xp[i]) goto r_x;
goto r_c8;
} }
case el_c32: { if (c8) goto r_c8;
u32* xp = c32any_ptr(x); else goto r_c16;
bool c8 = true; )
for (; i < ia; i++) { #endif
if (xp[i] != (u16)xp[i]) goto r_x;
if (xp[i] != (u8 )xp[i]) c8 = false;
}
if (c8) goto r_c8; #define SQUEEZE_NUM_B_LOOP(GET) \
else goto r_c16; u32 or = 0; \
} for (ux i = 0; i < ia; i++) { \
#endif B c = GET; \
case el_bit: case el_i8: case el_i16: case el_i32: case el_f64: case el_B:; /*fallthrough*/ if (RARE(!q_i32(c))) { \
} while (i<ia) { if (!isF64(GET)) goto not_num; i++; } \
goto r_f64; \
} \
i32 ci = o2iG(c); \
or|= ((u32)ci & ~1) ^ (u32)(ci>>31); \
} \
goto mostI32;
#define SQFN_NUM_B \
not_num: \
if (notChar) goto squeezed; \
else return x; \
SQFN_NUM_RET;
B* xp = arr_bptr(x); NOINLINE B squeeze_B_numSlow(B x, Arr* xa, u8 type, usz ia, bool notChar) {
if (xp!=NULL) { SQFN_START;
#if SINGELI_SIMD SGetU(x)
SQUEEZE_NUM_B_LOOP(GetU(x,i))
SQFN_NUM_B;
}
SHOULD_INLINE B squeeze_BV_numImpl(B x, Arr* xa, u8 type, ux ia, B* xp, bool notChar) {
SQFN_START;
#if SINGELI_SIMD
u32 or = si_squeeze_numB(xp, ia);
if (-2==(i32)or) goto not_num;
if (-1==(i32)or) goto r_f64;
goto mostI32;
#else
SQUEEZE_NUM_B_LOOP(xp[i])
#endif
SQFN_NUM_B;
}
#define SQFN_CHR_B \
if (or>U16_MAX) goto r_c32; \
if (or>U8_MAX ) goto r_c16; \
goto r_c8; \
not_chr: \
if (notNum) goto squeezed; \
else return x; \
SQFN_CHR_RET;
NOINLINE B squeeze_B_chrSlow(B x, Arr* xa, u8 type, usz ia, bool notNum) {
SQFN_START;
u32 or = 0;
SGetU(x)
for (ux i = 0; i < ia; i++) {
B cr = GetU(x,i);
if (!isC32(cr)) goto not_chr;
or|= o2cG(cr);
}
SQFN_CHR_B;
}
SHOULD_INLINE B squeeze_BV_chrImpl(B x, Arr* xa, u8 type, usz ia, B* xp, bool notNum) {
SQFN_START;
u32 or = 0;
#if SINGELI_SIMD
u32 t = si_squeeze_chrB(xp, ia); u32 t = si_squeeze_chrB(xp, ia);
if (t==0) goto r_c8; if (t==0) goto r_c8;
else if (t==1) goto r_c16; else if (t==1) goto r_c16;
else if (t==2) goto r_c32; else if (t==2) goto r_c32;
else if (t==3) goto r_x; else if (t==3) goto not_chr;
else UD; else UD;
#else #else
for (; i < ia; i++) { for (ux i = 0; i < ia; i++) {
if (!isC32(xp[i])) goto r_x; if (!isC32(xp[i])) goto not_chr;
or|= o2cG(xp[i]); or|= o2cG(xp[i]);
} }
#endif #endif
} else { SQFN_CHR_B;
SGetU(x)
for (; i < ia; i++) {
B cr = GetU(x,i);
if (!isC32(cr)) goto r_x;
or|= o2cG(cr);
}
}
if (or<=U8_MAX ) r_c8: return FL_SET(toC8Any(x), fl_squoze);
else if (or<=U16_MAX) r_c16: return FL_SET(toC16Any(x), fl_squoze);
else { goto r_c32; } r_c32: return FL_SET(toC32Any(x), fl_squoze);
/*when known typed:*/ r_x: return FL_SET(x, fl_squoze);
} }
SHOULD_INLINE B squeeze_B_chrImpl(B x, Arr* xa, u8 type, ux ia, bool notNum) {
B* xp = arrv_bptr(xa);
if (xp!=NULL) return squeeze_BV_chrImpl(x, xa, type, ia, xp, notNum);
else return squeeze_B_chrSlow(x, xa, type, ia, notNum);
}
SHOULD_INLINE B squeeze_B_numImpl(B x, Arr* xa, u8 type, ux ia, bool notNum) {
B* xp = arrv_bptr(xa);
if (xp!=NULL) return squeeze_BV_numImpl(x, xa, type, ia, xp, notNum);
else return squeeze_B_numSlow(x, xa, type, ia, notNum);
}
static B squeeze_B_numMaybe(B x, Arr* xa, u8 type, ux ia) { return squeeze_B_numImpl(x, xa, type, ia, false); }
static B squeeze_B_chrMaybe(B x, Arr* xa, u8 type, ux ia) { return squeeze_B_chrImpl(x, xa, type, ia, false); }
NOINLINE B squeeze_BGeneric(B x, Arr* xa, u8 type, ux ia) {
SQFN_START;
B x0 = IGetU(x,0);
if (isNum(x0)) return squeeze_B_numSlow(x, xa, type, ia, true);
if (isC32(x0)) return squeeze_B_chrSlow(x, xa, type, ia, true);
FLV_SET(xa, fl_squoze);
return x;
}
static B squeeze_B(B x, Arr* xa, u8 type, ux ia) {
SQFN_START;
B* xp = arrv_bptr(xa);
if (xp == NULL) return squeeze_BGeneric(x, xa, type, ia);
B x0 = xp[0];
if (isNum(x0)) return squeeze_BV_numImpl(x, xa, type, ia, xp, true);
if (isC32(x0)) return squeeze_BV_chrImpl(x, xa, type, ia, xp, true);
FLV_SET(xa, fl_squoze);
return x;
}
// el_bit el_i8 el_i16 el_i32 el_f64 el_c8 el_c16 el_c32 el_B
SqueezeFn squeeze_numFns[el_MAX] = {squeeze_smallest, squeeze_i8, squeeze_i16, squeeze_i32, squeeze_f64, squeeze_smallest, squeeze_nope, squeeze_nope, squeeze_B_numMaybe};
SqueezeFn squeeze_chrFns[el_MAX] = {squeeze_smallest, squeeze_nope, squeeze_nope, squeeze_nope, squeeze_nope, squeeze_smallest, squeeze_c16, squeeze_c32, squeeze_B_chrMaybe};
SqueezeFn squeeze_anyFns[el_MAX] = {squeeze_smallest, squeeze_i8, squeeze_i16, squeeze_i32, squeeze_f64, squeeze_smallest, squeeze_c16, squeeze_c32, squeeze_B};
NOINLINE B int_squeeze_sorted(B x) { NOINLINE B int_squeeze_sorted(B x) {
usz xia = IA(x); assert(elInt(TI(x,elType)));
if (xia==0) { usz ia = IA(x);
already_squoze:; if (ia==0) {
already_squoze:
return FL_SET(x, fl_squoze); return FL_SET(x, fl_squoze);
} }
SGetU(x); SGetU(x);
u8 x0e = selfElType_i32(o2iG(GetU(x, 0))); u8 x0e = selfElType_i32(o2iG(GetU(x, 0)));
u8 x1e = selfElType_i32(o2iG(GetU(x, xia-1))); u8 x1e = selfElType_i32(o2iG(GetU(x, ia-1)));
u8 xse = x0e>x1e? x0e : x1e; u8 xse = x0e>x1e? x0e : x1e;
u8 xe = TI(x,elType); u8 xe = TI(x,elType);
if (xe == xse) goto already_squoze; if (xe == xse) goto already_squoze;
Arr* ra; Arr* ra;
switch (xse) { default: UD; switch (xse) { default: UD;
case el_i16: ra = (Arr*)cpyI16Arr(x); break; case el_i16: ra = cpyI16Arr(x); break;
case el_i8: ra = (Arr*)cpyI8Arr (x); break; case el_i8: ra = cpyI8Arr (x); break;
case el_bit: ra = (Arr*)cpyBitArr(x); break; case el_bit: ra = cpyBitArr(x); break;
} }
return taga(FLV_SET(ra, fl_squoze)); return taga(FLV_SET(ra, fl_squoze));
} }
NOINLINE B any_squeeze(B x) { NOINLINE B any_squeeze(B x) {
assert(isArr(x)); assert(isArr(x));
if (FL_HAS(x, fl_squoze|fl_asc|fl_dsc)) { if (FL_HAS(x, fl_squoze|fl_asc|fl_dsc)) {
if (FL_HAS(x, fl_squoze)) return x; if (FL_HAS(x, fl_squoze)) return x;
u8 xe = TI(x,elType); if (elInt(TI(x,elType))) return int_squeeze_sorted(x);
if (elInt(xe)) return int_squeeze_sorted(x);
// could check for sorted character arrays (even from a TI(x,el_B) input) but sorted character arrays aren't worth it // could check for sorted character arrays (even from a TI(x,el_B) input) but sorted character arrays aren't worth it
} }
if (IA(x)==0) return FL_SET(x, fl_squoze); // TODO return a version of the smallest type? usz ia = IA(x);
B x0 = IGetU(x, 0); if (ia==0) return FL_SET(x, fl_squoze); // TODO return a version of the smallest type?
if (isNum(x0)) return num_squeeze(x); return squeeze_anyFns[TI(x,elType)](x, a(x), TY(x), ia);
else if (isC32(x0)) return chr_squeeze(x);
return FL_SET(x, fl_squoze);
} }
NOINLINE B num_squeeze(B x) {
assert(isArr(x));
u8 xe = TI(x,elType);
if (IA(x) == 0) return xe==el_bit? x : taga(cpyBitArr(x));
return squeeze_numFns[xe](x,a(x),TY(x),IA(x));
}
NOINLINE B chr_squeeze(B x) {
assert(isArr(x));
u8 xe = TI(x,elType);
if (IA(x) == 0) return xe==el_c8? x : taga(cpyC8Arr(x));
return squeeze_chrFns[xe](x,a(x),TY(x),IA(x));
}
B squeeze_deep(B x) { B squeeze_deep(B x) {
if (!isArr(x)) return x; if (!isArr(x)) return x;
x = any_squeeze(x); x = any_squeeze(x);
@ -214,10 +272,10 @@ B squeeze_deep(B x) {
B* xp = arr_bptr(x); B* xp = arr_bptr(x);
B xf = getFillR(x); B xf = getFillR(x);
if (xp!=NULL) { if (xp!=NULL) {
for (usz i=0; i<ia; i++) { HARR_ADD(r, i, squeeze_deep(inc(xp[i]))); } for (ux i=0; i<ia; i++) { HARR_ADD(r, i, squeeze_deep(inc(xp[i]))); }
} else { } else {
SGet(x); SGet(x);
for (usz i=0; i<ia; i++) { HARR_ADD(r, i, squeeze_deep(Get(x,i))); } for (ux i=0; i<ia; i++) { HARR_ADD(r, i, squeeze_deep(Get(x,i))); }
} }
return any_squeeze(qWithFill(HARR_FCD(r, x), xf)); return any_squeeze(qWithFill(HARR_FCD(r, x), xf));
} }

View File

@ -275,11 +275,11 @@ B bqn_merge(B x, u32 type); // consumes
B any_squeeze(B x); // consumes; accepts any array, returns one with the smallest type (doesn't recurse!) B any_squeeze(B x); // consumes; accepts any array, returns one with the smallest type (doesn't recurse!)
B squeeze_deep(B x); // consumes; accepts any object, returns an object with all parts necessary for equality checking & hashing squeezed; if this function errors due to OOM, the argument won't yet be consumed B squeeze_deep(B x); // consumes; accepts any object, returns an object with all parts necessary for equality checking & hashing squeezed; if this function errors due to OOM, the argument won't yet be consumed
B num_squeeze(B x); // consumes; see note below
B chr_squeeze(B x); // consumes; see note below B num_squeeze(B x); // consumes; always returns a bitarr on empty input
// Note that num_squeeze & chr_squeeze don't check for fl_squoze, and unconditionally set it. Thus, don't call it on an array if it could be squeezable by the opposite method. B chr_squeeze(B x); // consumes; always returns a c8arr on empty input
// or, if you do want to, if TI(x,elType) isn't of the squeezed type, either remove fl_squoze or call the other squeeze function.
// The functions below can be used as direct replacements of (num|chr)_squeeze if the argument might already be squeezed. // these return an arbitrary-type array on empty input
static inline B num_squeezeChk(B x) { return FL_HAS(x,fl_squoze)? x : num_squeeze(x); } static inline B num_squeezeChk(B x) { return FL_HAS(x,fl_squoze)? x : num_squeeze(x); }
static inline B chr_squeezeChk(B x) { return FL_HAS(x,fl_squoze)? x : chr_squeeze(x); } static inline B chr_squeezeChk(B x) { return FL_HAS(x,fl_squoze)? x : chr_squeeze(x); }

View File

@ -296,6 +296,7 @@ a←↕2 ⋄ ! "e" ≡ (↕10){b←a‿a‿a‿a‿a‿a‿a‿a‿a‿a ⋄
123 4444256 %% F{(4|𝕨+4)𝕩} 3 F2 2 F˘ 1 F 4444256 123 4444256 %% F{(4|𝕨+4)𝕩} 3 F2 2 F˘ 1 F 4444256
(1+1e15) 10 %% (1+9)0 (1+1e15) 10 %% (1+9)0
(-1+1e15) 10 %% 99 (-1+1e15) 10 %% 99
b11a"hello" b 'e' 12 5 a •Hash b %% 1
# ↑𝕩 & ↓𝕩 # ↑𝕩 & ↓𝕩
!"↑𝕩: 𝕩 must have rank at least 1" % 0 !"↑𝕩: 𝕩 must have rank at least 1" % 0

View File

@ -209,6 +209,7 @@ v←1 ⋄ ! •BQN∘•Repr⊸≡ ⟨+,1‿2,+¨,(+V)(V+V),2‿2⥊↕4⟩
•Repr•ParseFloat¨ "1.23516411460311636e-323", "1.23516411460311637e-323" %% "1e¯323","1.5e¯323" •Repr•ParseFloat¨ "1.23516411460311636e-323", "1.23516411460311637e-323" %% "1e¯323","1.5e¯323"
•Repr•ParseFloat¨ "1.235164114603116360e-323", "1.235164114603116361e-323" %% "1e¯323","1e¯323" •Repr•ParseFloat¨ "1.235164114603116360e-323", "1.235164114603116361e-323" %% "1e¯323","1e¯323"
•Repr•ParseFloat¨ "1.2351641146031163604e-323", "1.2351641146031163605e-323" %% "1e¯323","1e¯323" •Repr•ParseFloat¨ "1.2351641146031163604e-323", "1.2351641146031163605e-323" %% "1e¯323","1e¯323"
a1@3 •ParseFloat"err" a / a, 1, a, 3 %% 31, 13
!"•ParseFloat 𝕩: Input was empty" % •ParseFloat "" !"•ParseFloat 𝕩: Input was empty" % •ParseFloat ""
!"•ParseFloat 𝕩: Input was empty" % •ParseFloat 0 !"•ParseFloat 𝕩: Input was empty" % •ParseFloat 0
!"•ParseFloat 𝕩: Expected a character list argument" % •ParseFloat 3 !"•ParseFloat 𝕩: Expected a character list argument" % •ParseFloat 3