from stdint import * import t, c import stdio # String copy function def strcpy(dest: str, src: str) -> str: if dest == None or src == None: return None original_dest: str = dest for s in src: dest[0] = s dest += 1 dest[0] = 0 return original_dest # String concatenate function def strcat(dest: str, src: str) -> str: if dest == None or src == None: return dest original_dest: str = dest # Find end of dest while dest[0] != '\0': dest += 1 # Copy src for s in src: dest[0] = s dest += 1 dest[0] = 0 return original_dest # String copy function with limited length def strncpy(dest: str, src: str, n: t.CSizeT) -> str: if dest == None or src == None or n == 0: return dest original_dest: str = dest i: t.CSizeT = 0 for s in src: if i >= n: break dest[0] = s dest += 1 i += 1 # Fill remaining space with '\0' while i < n: dest[0] = 0 dest += 1 i += 1 return original_dest # String concatenate function with limited length def strncat(dest: str, src: str, n: t.CSizeT) -> str: if dest == None or src == None or n == 0: return dest original_dest: str = dest # Find end of dest while dest[0] != '\0': dest += 1 # Copy up to n chars from src i: t.CSizeT = 0 for s in src: if i >= n: break dest[0] = s dest += 1 i += 1 dest[0] = 0 return original_dest # String length function export def strlen(src: str) -> t.CSizeT: length: t.CSizeT = 0 for _ in src: length += 1 return length # String comparison function # 注意:str1[0] - str2[0] 是 i8 减法会回绕(0xFF 表示 -1),返回前必须 # int() 提升到 i32 再相减(与下方 memcmp 的 int(p1[i]) - int(p2[i]) 一致), # 否则 strcmp("abc","abd") 返回 255 而非 -1(StringTest Test 4 根因)。 def strcmp(str1: str, str2: str) -> int: while str1[0] != '\0' and str2[0] != '\0': if str1[0] != str2[0]: return int(str1[0]) - int(str2[0]) str1 += 1 str2 += 1 return int(str1[0]) - int(str2[0]) def samestr(str1: str, str2: str) -> bool: return strcmp(str1, str2) == 0 # String compare function with limited length def strncmp(str1: str, str2: str, n: t.CSizeT) -> int: i: t.CSizeT = 0 while str1[0] != '\0' and str2[0] != '\0' and i < n: if str1[0] != str2[0]: return int(str1[0]) - int(str2[0]) str1 += 1 str2 += 1 i += 1 if i < n: return int(str1[0]) - int(str2[0]) return 0 # Memory compare function def memcmp(ptr1: t.CVoid | t.CPtr, ptr2: t.CVoid | t.CPtr, n: t.CSizeT) -> int: p1: BYTEPTR = BYTEPTR(ptr1) p2: BYTEPTR = BYTEPTR(ptr2) i: t.CSizeT = 0 while i < n: if p1[i] != p2[i]: return int(p1[i]) - int(p2[i]) i += 1 return 0 # String find function def strchr(s: str, cr: int) -> str: while s[0] != '\0': if s[0] == t.CChar(cr): return str(s) s += 1 if cr == '\0': return str(s) return None # String reverse find function (find last occurrence of character) def strrchr(s: str, cr: int) -> str: last: str = None while s[0] != '\0': if s[0] == t.CChar(cr): last = s s += 1 if cr == '\0': return s return last # Substring search function (find first occurrence of needle in s, return pointer to that position, or None if not found) def strstr(s: str, needle: str) -> str: if needle[0] == 0: return s needle_len: t.CSizeT = strlen(needle) if needle_len == 0: return s i: t.CSizeT = 0 s_len: t.CSizeT = strlen(s) while i + needle_len <= s_len: if strncmp(s + i, needle, needle_len) == 0: return s + i i += 1 return None # String skip function def strspn(s: str, skip: str = " ") -> int: si: int = 0 while s[si] != 0: found: int = 0 sj: int = 0 while skip[sj] != 0: if s[si] == skip[sj]: found = 1 break sj += 1 if found == 0: break si += 1 return si # Memory set function export def memset(ptr: t.CPtr, value: int, num: t.CSizeT) -> t.CPtr: # Original implementation: # p: BYTEPTR = BYTEPTR(ptr) # i: t.CSizeT # for i in range(num): # p[i] = t.CUnsignedChar(value) if num == 0: return ptr c.Asm(f"""mov rdi, {c.AsmInp(ptr, t.ASM_DESCR.REG_ANY)} mov eax, {c.AsmInp(value, t.ASM_DESCR.REG_ANY)} mov rcx, {c.AsmInp(num, t.ASM_DESCR.REG_ANY)} rep stosb""", op=[t.ASM_DESCR.CLOBBER_MEMORY, t.ASM_DESCR.CLOBBER_RAX, t.ASM_DESCR.CLOBBER_RCX, t.ASM_DESCR.CLOBBER_RDI]) return ptr def memset32(ptr: t.CVoid | t.CPtr, value: t.CUInt32T, count: t.CSizeT) -> t.CVoid | t.CPtr: # Original implementation: # p: UINT32PTR = UINT32PTR(ptr) # i: t.CSizeT # for i in range(count): # p[i] = value if count == 0: return ptr c.Asm(f"""mov rdi, {c.AsmInp(ptr, t.ASM_DESCR.REG_ANY)} mov eax, {c.AsmInp(value, t.ASM_DESCR.REG_ANY)} mov rcx, {c.AsmInp(count, t.ASM_DESCR.REG_ANY)} rep stosd""", op=[t.ASM_DESCR.CLOBBER_MEMORY, t.ASM_DESCR.CLOBBER_RAX, t.ASM_DESCR.CLOBBER_RCX, t.ASM_DESCR.CLOBBER_RDI]) return ptr # Memory copy function export def memcpy(dest: t.CVoid | t.CPtr, src: t.CVoid | t.CPtr, num: t.CSizeT) -> t.CPtr: # Original implementation: # d: BYTEPTR = BYTEPTR(dest) # s: BYTEPTR = BYTEPTR(src) # i: t.CSizeT # for i in range(num): # d[i] = s[i] if num == 0: return dest c.Asm(f"""mov rdi, {c.AsmInp(dest, t.ASM_DESCR.REG_ANY)} mov rsi, {c.AsmInp(src, t.ASM_DESCR.REG_ANY)} mov rcx, {c.AsmInp(num, t.ASM_DESCR.REG_ANY)} rep movsb""", op=[t.ASM_DESCR.CLOBBER_MEMORY, t.ASM_DESCR.CLOBBER_RCX, t.ASM_DESCR.CLOBBER_RDI, t.ASM_DESCR.CLOBBER_RSI]) return dest # 内存移动函数 def memmove(dest: t.CVoid | t.CPtr, src: t.CVoid | t.CPtr, num: t.CSizeT) -> t.CVoid | t.CPtr: # 原始实现: # d: BYTEPTR = BYTEPTR(dest) # s: BYTEPTR = BYTEPTR(src) # i: t.CSizeT # if d < s: # for i in range(num): # d[i] = s[i] # elif d > s: # for i in range(num, 0, -1): # d[i - 1] = s[i - 1] if num == 0: return dest c.Asm(f"""mov rdi, {c.AsmInp(dest, t.ASM_DESCR.REG_ANY)} mov rsi, {c.AsmInp(src, t.ASM_DESCR.REG_ANY)} mov rcx, {c.AsmInp(num, t.ASM_DESCR.REG_ANY)} cmp rdi, rsi jb 2f std add rdi, rcx dec rdi add rsi, rcx dec rsi rep movsb cld jmp 3f 2: rep movsb 3:""", op=[t.ASM_DESCR.CLOBBER_MEMORY, t.ASM_DESCR.CLOBBER_RCX, t.ASM_DESCR.CLOBBER_RDI, t.ASM_DESCR.CLOBBER_RSI]) return dest def atoi(src: str) -> int: num: int = 0 sign: int = 1 s: str = src if s == None: return 0 # 跳过空白 while s[0] == ' ' or s[0] == '\t' or s[0] == '\n' or s[0] == '\r': s += 1 # 符号 if s[0] == '-': sign = -1 s += 1 elif s[0] == '+': s += 1 for ch in s: if ch < '0' or ch > '9': break digit: int = ch - '0' num = num * 10 + digit return num * sign def atoll(src: str) -> t.CInt64T: num: t.CInt64T = 0 sign: t.CInt64T = 1 s: str = src if s == None: return 0 while s[0] == ' ' or s[0] == '\t' or s[0] == '\n' or s[0] == '\r': s += 1 if s[0] == '-': sign = -1 s += 1 elif s[0] == '+': s += 1 # 十六进制前缀 0x / 0X is_hex: int = 0 if s[0] == '0' and (s[1] == 'x' or s[1] == 'X'): is_hex = 1 s += 2 if is_hex: for ch in s: d: int = 0 if ch >= '0' and ch <= '9': d = ch - '0' elif ch >= 'a' and ch <= 'f': d = ch - 'a' + 10 elif ch >= 'A' and ch <= 'F': d = ch - 'A' + 10 else: break digit: t.CInt64T = t.CInt64T(d) num = num * 16 + digit else: for ch in s: if ch < '0' or ch > '9': break d: int = ch - '0' digit: t.CInt64T = t.CInt64T(d) num = num * 10 + digit return num * sign # ============================================================ # 十进制字面量 → double 的正确舍入转换(N4) # # 旧实现用"逐位累加 + 反复乘/除 10":小数位超过 16 位后每步都舍入 # (e 偏 +1 ULP、ln2 偏 −1 ULP),指数按 while exp>0: result*=10.0 累乘 # 308 次(DBL_MAX 偏 −6 ULP)。 # 新实现:尾数装进 u64(≤19 位;第 20 位做一次舍入),用 10 的**精确幂** # 在**双 double(hi+lo,约 106 位)**下做一次缩放,最后一次性舍入。 # 算法先在 Python 里 1:1 对拍 float()(正确舍入)通过:20 万随机样例 + # 边界样例在**正规数范围**内 bit-exact;次正规/溢出仍走旧逐步缩放兜底 # (语义与旧实现一致,无回归)。 # 约定:不用全局表——10^0..10^22 由循环乘 10 得到(该区间每一步都可精确 # 表示);p<0 时在正规区算 10^p×2^600 再精确缩回,避免双 double 低位在 # ~1e-292 以下掉进次正规而丢有效位。 # ============================================================ # _dd_split_hi - Dekker 分裂的上半(hi = 取高 26 位) # # 含量级缩尺:|a| > 6.7e292 时先乘 2^-28 再算(否则 a*(2^27+1) 溢出为 inf); # |a| 极小(< 1e-292)时先乘 2^28(否则 lo = a-hi 掉进次正规丢位)。 # 缩尺因子均为 2 的幂 ⇒ 对正规数**无损**;调用方用 lo = a - hi 取下半部分。 def _dd_split_hi(a: double) -> double: aa: double = a big: int = 0 small: int = 0 if a > 6.7e292 or a < -6.7e292: aa = a * 3.725290298461914e-09 big = 1 elif (a > 0.0 and a < 1.0e-292) or (a < 0.0 and a > -1.0e-292): aa = a * 268435456.0 small = 1 tt: double = aa * 134217729.0 hi: double = tt - (tt - aa) if big != 0: return hi * 268435456.0 if small != 0: return hi * 3.725290298461914e-09 return hi # _dd_mul - 双 double 乘法:out = a × b(out[0]=hi, out[1]=lo) def _dd_mul(ah: double, al: double, bh: double, bl: double, out: t.CArray[double, 2]): p: double = ah * bh a_hi: double = _dd_split_hi(ah) a_lo: double = ah - a_hi b_hi: double = _dd_split_hi(bh) b_lo: double = bh - b_hi e: double = ((a_hi * b_hi - p) + a_hi * b_lo + a_lo * b_hi) + a_lo * b_lo e = e + (ah * bl + al * bh) s: double = p + e out[0] = s out[1] = e - (s - p) # _dd_add - 双 double 加法:out = a + b def _dd_add(ah: double, al: double, bh: double, bl: double, out: t.CArray[double, 2]): s: double = ah + bh bb: double = s - ah e: double = (ah - (s - bb)) + (bh - bb) e = e + (al + bl) r0: double = s + e out[0] = r0 out[1] = e - (r0 - s) # _dd_div - 双 double 除法:out = a / b(q0 + 一步残差修正) def _dd_div(ah: double, al: double, bh: double, bl: double, out: t.CArray[double, 2], tmp: t.CArray[double, 2]): q0: double = ah / bh _dd_mul(bh, bl, q0, 0.0, tmp) _dd_add(ah, al, -tmp[0], -tmp[1], tmp) q1: double = tmp[0] / bh _dd_add(q0, 0.0, q1, 0.0, out) # _dd_from_u64 - u64 → 双 double(精确:hi 为四舍五入值,lo 为精确残差) def _dd_from_u64(m: t.CUInt64T, out: t.CArray[double, 2]): hi: double = double(m) lo: double = 0.0 if m >= t.CUInt64T(9007199254740992): lo = double(m - t.CUInt64T(hi)) s: double = hi + lo bb: double = s - hi out[0] = s out[1] = (hi - (s - bb)) + (lo - bb) # _dd_pow10 - 10^e 的双 double(e >= 0;按 ≤22 分块,每块可精确表示) def _dd_pow10(e: int, out: t.CArray[double, 2], tmp: t.CArray[double, 2]): out[0] = 1.0 out[1] = 0.0 k: int = e while k > 0: step: int = 22 if k < 22: step = k p10: double = 1.0 i: int = 0 while i < step: p10 = p10 * 10.0 i += 1 _dd_mul(out[0], out[1], p10, 0.0, tmp) out[0] = tmp[0] out[1] = tmp[1] k -= step # _pow2 - 2^n(|n| <= 1000):循环乘 2/0.5,每步精确 def _pow2(n: int) -> double: r: double = 1.0 i: int = n if i >= 0: while i > 0: r = r * 2.0 i -= 1 else: while i < 0: r = r * 0.5 i += 1 return r # _atof_scale_stepwise - 旧的逐步 ×/÷10 缩放(次正规/溢出场景的兜底) def _atof_scale_stepwise(x: double, p: int) -> double: r: double = x e: int = p while e > 0: r = r * 10.0 e -= 1 while e < 0: r = r / 10.0 e += 1 return r def atof(src: str) -> double: s: str = src if s == None: return 0.0 # 跳过空白 while s[0] == ' ' or s[0] == '\t' or s[0] == '\n' or s[0] == '\r': s += 1 # 符号 sign: double = 1.0 if s[0] == '-': sign = -1.0 s += 1 elif s[0] == '+': s += 1 # 尾数:有效数字装进 u64(≤19 位),同时维护十进制指数 mant: t.CUInt64T = 0 nd: int = 0 dexp: int = 0 seen_dot: int = 0 started: int = 0 rounded: int = 0 while s[0] != '\0': ch: t.CChar = s[0] if ch >= '0' and ch <= '9': d: int = ch - '0' if started == 0: # 前导零不进尾数;小数部分的前导零要占十进制位 if d != 0: started = 1 mant = t.CUInt64T(d) nd = 1 if seen_dot != 0: dexp -= 1 elif seen_dot != 0: dexp -= 1 elif nd < 19: mant = mant * t.CUInt64T(10) + t.CUInt64T(d) nd += 1 if seen_dot != 0: dexp -= 1 else: # 第 20 位起:整数部分丢弃的位让指数 +1;小数部分丢弃的位不影响 # 指数。只用第 20 位做一次舍入(丢弃量 <= 10^-19 相对误差)。 if seen_dot == 0: dexp += 1 elif rounded == 0: if d >= 5: mant += t.CUInt64T(1) rounded = 1 elif ch == '.': seen_dot = 1 else: break s += 1 if started == 0: return sign * 0.0 # 进位:舍入可能使 19 位变 20 位 if mant >= t.CUInt64T(10000000000000000000): mant = mant // t.CUInt64T(10) dexp += 1 # 指数部分 exp: int = 0 if s[0] == 'e' or s[0] == 'E': s += 1 exp_sign: int = 1 if s[0] == '-': exp_sign = -1 s += 1 elif s[0] == '+': s += 1 while s[0] >= '0' and s[0] <= '9': exp = exp * 10 + (s[0] - '0') s += 1 exp = exp * exp_sign p: int = dexp + exp if p == 0: return sign * double(mant) # 双 double 缩放:mant × 10^p,最后一次舍入 ta: t.CArray[double, 2] tb: t.CArray[double, 2] tc: t.CArray[double, 2] tr: t.CArray[double, 2] _dd_from_u64(mant, ta) v: double = 0.0 if p > 0: _dd_pow10(p, tb, tr) _dd_mul(ta[0], ta[1], tb[0], tb[1], tr) v = tr[0] + tr[1] else: # p < 0:在正规区算「2^600 / 10^(-p)」= 10^p × 2^600,最后精确缩回。 # 不能直接算 10^p(|p| 大时 ~1e-308,双 double 低位掉次正规丢有效位); # 分母按 ≤308 分块累除(10^313 会先溢出成 inf 使结果变 NaN)。 tb[0] = _pow2(600) tb[1] = 0.0 q: int = -p while q > 0: step2: int = 308 if q < 308: step2 = q _dd_pow10(step2, tc, tr) _dd_div(tb[0], tb[1], tc[0], tc[1], tr, tc) tb[0] = tr[0] tb[1] = tr[1] q -= step2 _dd_mul(ta[0], ta[1], tb[0], tb[1], tr) v = (tr[0] + tr[1]) * _pow2(-600) # 正规数范围(非 NaN / 非 inf / 非次正规)→ 已正确舍入的结果 if v == v and v <= 1.7976931348623157e308 and v >= -1.7976931348623157e308 \ and (v == 0.0 or v >= 2.2250738585072014e-308 or v <= -2.2250738585072014e-308): return sign * v # 溢出 / 次正规 / NaN → 回退旧逐步缩放(与旧实现语义一致) return sign * _atof_scale_stepwise(double(mant), p) def atof_out(src: str, out: double | t.CPtr) -> int: """atof 结果写入 out[0](输出参数方式,避免跨模块 double 返回值传递 bug) 返回值仅表示成功与否(1=成功,0=失败),结果值通过 out 指针传递, 不依赖 double 返回值的跨模块传递。 """ if out is None: return 0 v: double = atof(src) out[0] = v return 1 def split(s: str, delim: str, result: t.CArray[str], cap: int) -> int: """按单字符分隔符切分 s,token 指针写入 result[0..],尾部写 None 哨兵。 cap: result 数组的**声明容量**(元素个数)。此前无容量参数 → 写 result[count] 与 result[count]=None 均无上界;token 数超过调用方数组 容量时越界写(devfs 用 t.CArray[str, 256],256 个 token 即写穿 2048 字节)。 现限制 token 数 ≤ cap-1(留一格给结尾哨兵)。 """ count: int = 0 start: str = s if not s or not delim or not result: return 0 if cap <= 0: return 0 d: t.CChar = delim[0] # 单分隔符 while start[0]: # 跳过分隔符 while start[0] == d: start += 1 if not start[0]: break # 容量保护:留最后一格放结尾哨兵 if count >= cap - 1: break # 记录token起始 result[count] = start count += 1 # 找到下一个分隔符,截断 while start[0] and start[0] != d: start += 1 if start[0]: start[0] = '\0' start += 1 result[count] = None # 结尾标记 return count ascii_lowercase: str = "abcdefghijklmnopqrstuvwxyz" ascii_uppercase: str = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" ascii_letters: str = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ" digits: str = "0123456789" hexdigits: str = "0123456789abcdefABCDEF" octdigits: str = "01234567" punctuation: str = "!\"#$%&'()*+,-./:;<=>?@[]^_`{|}~" whitespace: str = " \t\n\r\f\v" printable: str = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ!\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~ \t\n\r\f\v"