R14:rawptr[X] -> X*(41 文件 / 2037 行改动),X 含模块限定名与嵌套下标(rawptr[GSList[NameEntry]] -> GSList[NameEntry]*)。保留 6 处 rawptr[t.CPtr](规范例外:存纯裸指针);# 注释与字符串里的 rawptr[...] 属元语法描述,未动。 R16(保守子集):t.CConst | str/bytes -> const str/bytes,t.CConst | char | t.CPtr -> const str;typedef 右值位置豁免(const str 在该处无法注册,与 R1 同源)。 验证:TPC 自举三重重编 SUCCESS;TransPyV.exe 全量 77/77 顺序回归通过。
302 lines
9.8 KiB
Plaintext
302 lines
9.8 KiB
Plaintext
# vrandom - Hardware Random Number Generation Library
|
|
# Implemented using inline assembly based on x86 RDRAND / RDSEED instructions
|
|
import t, c
|
|
import math
|
|
|
|
|
|
# Retry limit (RDRAND usually doesn't need retries, RDSEED might)
|
|
define RDRAND_RETRY_LIMIT = 10
|
|
define RDSEED_RETRY_LIMIT = 100
|
|
|
|
|
|
# ============================================================
|
|
# RDRAND - Hardware random numbers (output from a pseudo-random number generator)
|
|
# ============================================================
|
|
def rdrand16() -> uint16:
|
|
val: uint32 = 0
|
|
__asm__(f"rdrand {c.AsmOut(val, t.ASM_DESCR.OUTPUT_REG)}",
|
|
out=[asmout(val, ASM_DESCR.OUTPUT_REG)],
|
|
op=[ASM_DESCR.CLOBBER_CC])
|
|
return uint16(val)
|
|
|
|
def rdrand32() -> uint32:
|
|
val: uint32 = 0
|
|
__asm__(f"rdrand {c.AsmOut(val, t.ASM_DESCR.OUTPUT_REG)}",
|
|
out=[asmout(val, ASM_DESCR.OUTPUT_REG)],
|
|
op=[ASM_DESCR.CLOBBER_CC])
|
|
return val
|
|
|
|
def rdrand64() -> uint64:
|
|
val: uint64 = 0
|
|
__asm__(f"rdrand {c.AsmOut(val, t.ASM_DESCR.OUTPUT_REG)}",
|
|
out=[asmout(val, ASM_DESCR.OUTPUT_REG)],
|
|
op=[ASM_DESCR.CLOBBER_CC])
|
|
return val
|
|
|
|
|
|
# ============================================================
|
|
# RDSEED - Hardware random seeds (direct output from entropy source)
|
|
# ============================================================
|
|
def rdseed16() -> uint16:
|
|
val: uint32 = 0
|
|
__asm__(f"rdseed {c.AsmOut(val, t.ASM_DESCR.OUTPUT_REG)}",
|
|
out=[asmout(val, ASM_DESCR.OUTPUT_REG)],
|
|
op=[ASM_DESCR.CLOBBER_CC])
|
|
return uint16(val)
|
|
|
|
def rdseed32() -> uint32:
|
|
val: uint32 = 0
|
|
__asm__(f"rdseed {c.AsmOut(val, t.ASM_DESCR.OUTPUT_REG)}",
|
|
out=[asmout(val, ASM_DESCR.OUTPUT_REG)],
|
|
op=[ASM_DESCR.CLOBBER_CC])
|
|
return val
|
|
|
|
def rdseed64() -> uint64:
|
|
val: uint64 = 0
|
|
__asm__(f"rdseed {c.AsmOut(val, t.ASM_DESCR.OUTPUT_REG)}",
|
|
out=[asmout(val, ASM_DESCR.OUTPUT_REG)],
|
|
op=[ASM_DESCR.CLOBBER_CC])
|
|
return val
|
|
|
|
|
|
# ============================================================
|
|
# Step version (with success flag, matching GCC builtin interface)
|
|
# Returns success flag: 1 on success, 0 on failure; random value written to *p
|
|
# ============================================================
|
|
def rdrand16_step(p: uint16*) -> int:
|
|
val: uint32 = 0
|
|
ok: uint32 = 0
|
|
c.Asm(f"""rdrand {c.AsmOut(val, t.ASM_DESCR.OUTPUT_REG)}
|
|
setc al
|
|
movzx {c.AsmOut(ok, t.ASM_DESCR.OUTPUT_REG)}, al""",
|
|
out=[asmout(val, ASM_DESCR.OUTPUT_REG), asmout(ok, ASM_DESCR.OUTPUT_REG)],
|
|
op=[ASM_DESCR.CLOBBER_CC, ASM_DESCR.CLOBBER_AL])
|
|
p[0] = uint16(val)
|
|
return int(ok)
|
|
|
|
def rdrand32_step(p: uint32*) -> int:
|
|
val: uint32 = 0
|
|
ok: uint32 = 0
|
|
c.Asm(f"""rdrand {c.AsmOut(val, t.ASM_DESCR.OUTPUT_REG)}
|
|
setc al
|
|
movzx {c.AsmOut(ok, t.ASM_DESCR.OUTPUT_REG)}, al""",
|
|
out=[asmout(val, ASM_DESCR.OUTPUT_REG), asmout(ok, ASM_DESCR.OUTPUT_REG)],
|
|
op=[ASM_DESCR.CLOBBER_CC, ASM_DESCR.CLOBBER_AL])
|
|
p[0] = val
|
|
return int(ok)
|
|
|
|
def rdrand64_step(p: uint64*) -> int:
|
|
val: uint64 = 0
|
|
ok: uint32 = 0
|
|
c.Asm(f"""rdrand {c.AsmOut(val, t.ASM_DESCR.OUTPUT_REG)}
|
|
setc al
|
|
movzx {c.AsmOut(ok, t.ASM_DESCR.OUTPUT_REG)}, al""",
|
|
out=[asmout(val, ASM_DESCR.OUTPUT_REG), asmout(ok, ASM_DESCR.OUTPUT_REG)],
|
|
op=[ASM_DESCR.CLOBBER_CC, ASM_DESCR.CLOBBER_AL])
|
|
p[0] = val
|
|
return int(ok)
|
|
|
|
def rdseed16_step(p: uint16*) -> int:
|
|
val: uint32 = 0
|
|
ok: uint32 = 0
|
|
c.Asm(f"""rdseed {c.AsmOut(val, t.ASM_DESCR.OUTPUT_REG)}
|
|
setc al
|
|
movzx {c.AsmOut(ok, t.ASM_DESCR.OUTPUT_REG)}, al""",
|
|
out=[asmout(val, ASM_DESCR.OUTPUT_REG), asmout(ok, ASM_DESCR.OUTPUT_REG)],
|
|
op=[ASM_DESCR.CLOBBER_CC, ASM_DESCR.CLOBBER_AL])
|
|
p[0] = uint16(val)
|
|
return int(ok)
|
|
|
|
def rdseed32_step(p: uint32*) -> int:
|
|
val: uint32 = 0
|
|
ok: uint32 = 0
|
|
c.Asm(f"""rdseed {c.AsmOut(val, t.ASM_DESCR.OUTPUT_REG)}
|
|
setc al
|
|
movzx {c.AsmOut(ok, t.ASM_DESCR.OUTPUT_REG)}, al""",
|
|
out=[asmout(val, ASM_DESCR.OUTPUT_REG), asmout(ok, ASM_DESCR.OUTPUT_REG)],
|
|
op=[ASM_DESCR.CLOBBER_CC, ASM_DESCR.CLOBBER_AL])
|
|
p[0] = val
|
|
return int(ok)
|
|
|
|
def rdseed64_step(p: uint64*) -> int:
|
|
val: uint64 = 0
|
|
ok: uint32 = 0
|
|
c.Asm(f"""rdseed {c.AsmOut(val, t.ASM_DESCR.OUTPUT_REG)}
|
|
setc al
|
|
movzx {c.AsmOut(ok, t.ASM_DESCR.OUTPUT_REG)}, al""",
|
|
out=[asmout(val, ASM_DESCR.OUTPUT_REG), asmout(ok, ASM_DESCR.OUTPUT_REG)],
|
|
op=[ASM_DESCR.CLOBBER_CC, ASM_DESCR.CLOBBER_AL])
|
|
p[0] = val
|
|
return int(ok)
|
|
|
|
|
|
# ============================================================
|
|
# Convenient interface with retry (automatically retries until it succeeds or reaches the limit)
|
|
# ============================================================
|
|
def random_u16() -> uint16:
|
|
r: uint16 = 0
|
|
for i in range(RDRAND_RETRY_LIMIT):
|
|
if rdrand16_step(&r) == 1: return r
|
|
return 0
|
|
|
|
def random_u32() -> uint32:
|
|
r: uint32 = 0
|
|
for i in range(RDRAND_RETRY_LIMIT):
|
|
if rdrand32_step(&r) == 1: return r
|
|
return 0
|
|
|
|
def random_u64() -> uint64:
|
|
r: uint64 = 0
|
|
for i in range(RDRAND_RETRY_LIMIT):
|
|
if rdrand64_step(&r) == 1: return r
|
|
return 0
|
|
|
|
def seed_u16() -> uint16:
|
|
r: uint16 = 0
|
|
for i in range(RDRAND_RETRY_LIMIT):
|
|
if rdseed16_step(&r) == 1: return r
|
|
return 0
|
|
|
|
def seed_u32() -> uint32:
|
|
r: uint32 = 0
|
|
for i in range(RDRAND_RETRY_LIMIT):
|
|
if rdseed32_step(&r) == 1: return r
|
|
return 0
|
|
|
|
def seed_u64() -> uint64:
|
|
r: uint64 = 0
|
|
for i in range(RDSEED_RETRY_LIMIT):
|
|
if rdseed64_step(&r) == 1: return r
|
|
return 0
|
|
|
|
|
|
# ============================================================
|
|
# Python random standard library function implementations
|
|
# Default types: uint64 (u64), double (f64), int (i32)
|
|
# ============================================================
|
|
# ---------- ONE, Random integers ----------
|
|
def randint(a: int, b: int) -> int:
|
|
return int(a + int(random_u64() % uint64(b - a + 1)))
|
|
|
|
def randrange(start: int, stop: int, step: int = 1) -> int:
|
|
width: int = 0
|
|
if step > 0: width = (stop - start + step - 1) // step
|
|
else: width = (start - stop - step - 1) // (-step)
|
|
return int(start + int(random_u64() % uint64(width)) * step)
|
|
|
|
def getrandbits(k: int) -> uint64:
|
|
r: uint64 = rdrand64()
|
|
if k >= 64: return r
|
|
mask: uint64 = (uint64(1) << k) - uint64(1)
|
|
return r & mask
|
|
|
|
# ---------- TWO, Random floating-point numbers ----------
|
|
def random() -> double:
|
|
return double(rdrand64() >> 11) * (1.0 / 9007199254740992.0)
|
|
|
|
def uniform(a: double, b: double) -> double:
|
|
return a + (b - a) * random()
|
|
|
|
def triangular(low: double, high: double, mode: double) -> double:
|
|
u: double = random()
|
|
c: double = (mode - low) / (high - low)
|
|
tmp: double = 0.0
|
|
if u > c:
|
|
u = 1.0 - u; c = 1.0 - c
|
|
tmp = low; low = high; high = tmp
|
|
return low + (high - low) * math.sqrt(u * c)
|
|
|
|
def betavariate(alpha: double, beta: double) -> double:
|
|
y: double = gammavariate(alpha, 1.0)
|
|
if y != 0.0: return y / (y + gammavariate(beta, 1.0))
|
|
return 0.0
|
|
|
|
def expovariate(lambd: double) -> double:
|
|
u: double = random()
|
|
if u < 1e-300: u = 1e-300
|
|
return -math.log(1.0 - u) / lambd
|
|
|
|
def gammavariate(alpha: double, beta: double) -> double:
|
|
u: double = 0.0
|
|
d: double = 0.0
|
|
c: double = 0.0
|
|
x: double = 0.0
|
|
v: double = 0.0
|
|
if alpha <= 0.0 or beta <= 0.0: return 0.0
|
|
if alpha < 1.0:
|
|
u = random()
|
|
if u < 1e-300: u = 1e-300
|
|
return gammavariate(alpha + 1.0, beta) * math.pow(u, 1.0 / alpha)
|
|
d = alpha - 1.0 / 3.0
|
|
c = 1.0 / math.sqrt(9.0 * d)
|
|
while True:
|
|
x = gauss(0.0, 1.0)
|
|
v = 1.0 + c * x
|
|
if v > 0.0:
|
|
v = v * v * v
|
|
u = random()
|
|
if u < 1.0 - 0.0331 * x * x * x * x: return d * v * beta
|
|
if math.log(u) < 0.5 * x * x + d * (1.0 - v + math.log(v)): return d * v * beta
|
|
|
|
def gauss(mu: double, sigma: double) -> double:
|
|
u1: double = random()
|
|
u2: double = random()
|
|
if u1 < 1e-300: u1 = 1e-300
|
|
z0: double = math.sqrt(-2.0 * math.log(u1)) * math.cos(2.0 * math.U_M_PI * u2)
|
|
return mu + sigma * z0
|
|
|
|
def normalvariate(mu: double, sigma: double) -> double:
|
|
NV_MAGICCONST: double = 1.7155277699214135
|
|
u1: double = 0.0
|
|
u2: double = 0.0
|
|
z: double = 0.0
|
|
zz: double = 0.0
|
|
while True:
|
|
u1 = random()
|
|
u2 = random()
|
|
if u2 < 1e-300: continue
|
|
z = NV_MAGICCONST * (u1 - 0.5) / u2
|
|
zz = z * z / 4.0
|
|
if zz <= 0.0 - math.log(u2): break
|
|
return mu + z * sigma
|
|
|
|
def lognormvariate(mu: double, sigma: double) -> double:
|
|
return math.exp(gauss(mu, sigma))
|
|
|
|
def vonmisesvariate(mu: double, kappa: double) -> double:
|
|
if kappa <= 1e-6: return math.U_M_PI * 2.0 * random()
|
|
s: double = 0.5 / kappa
|
|
r: double = s + math.sqrt(1.0 + s * s)
|
|
u1: double = 0.0
|
|
u2: double = 0.0
|
|
u3: double = 0.0
|
|
z: double = 0.0
|
|
d: double = 0.0
|
|
q: double = 0.0
|
|
f: double = 0.0
|
|
theta: double = 0.0
|
|
two_pi: double = math.U_M_PI * 2.0
|
|
while True:
|
|
u1 = random()
|
|
z = math.cos(math.U_M_PI * u1)
|
|
d = 1.0 / (r + z)
|
|
u2 = random()
|
|
if (u2 < 1.0 - d * d) or (u2 < (1.0 - z) * math.exp(kappa * (z - 1.0) - d * kappa * r)): break
|
|
q = 1.0 / r
|
|
f = (q + z) / (1.0 + q * z)
|
|
u3 = random()
|
|
theta = mu + (math.acos(f) if u3 > 0.5 else -math.acos(f))
|
|
while theta < 0.0: theta += two_pi
|
|
while theta >= two_pi: theta -= two_pi
|
|
return theta
|
|
|
|
def paretovariate(alpha: double) -> double:
|
|
u: double = random()
|
|
if u < 1e-300: u = 1e-300
|
|
return 1.0 / math.pow(1.0 - u, 1.0 / alpha)
|
|
|
|
def weibullvariate(alpha: double, beta: double) -> double:
|
|
u: double = random()
|
|
if u < 1e-300: u = 1e-300
|
|
return alpha * math.pow(-1.0 * math.log(1.0 - u), 1.0 / beta)
|