L
ling-wallet
↓ 0 downloadsLing Wallet: a post-quantum privacy-coin wallet, full node and HyperTorus miner for LNG
Keywords wallet, cryptocurrency, lng, node, miner, ling
lingfu install ling-walletCode / Files (116)
ling/ui/torus.ling
# torus.ling — HyperTorus visualizer. The miner's 4-torus walk samples are
# placed on a Clifford torus in S3, rotated in the xw and yz planes, projected
# 4D -> 3D -> 2D and drawn as glowing points with a trail, over a faint torus
# grid and the TETRA tetrahedron. Several visualizers can coexist by name.
bind TZ_CAP = 640
bind TZ_U32 = 4294967296
bind TZ_R = 0.7071067811865476
fn twist_color(twist, w) {
return roygbiv(((twist % 4) * 2 + sel(w >= 2147483648, 1, 0)) % 7)
}
fn tz_clear(n) {
st_lclear(n + "_x")
st_lclear(n + "_y")
st_lclear(n + "_z")
st_lclear(n + "_w")
st_lclear(n + "_c")
st_lclear(n + "_b")
st_set(n + "_count", 0)
st_set(n + "_head", 0)
st_set(n + "_last", 0 - 1)
st_set(n + "_hp", [])
}
# Feed a trace (list of [x, y, z, w, twist]); keeps every 6th step and the head.
fn tz_feed(n, trace, t) {
bind tl = len(trace)
if tl == 0 { return () }
bind hp = list_get(trace, tl - 1)
if list_get(hp, 0) == st_get(n + "_last", 0 - 1) { return () }
st_set(n + "_last", list_get(hp, 0))
st_set(n + "_hp", hp)
bind i = 0
while i < tl {
if i % 6 == 0 || i == tl - 1 {
bind p = list_get(trace, i)
bind a1 = list_get(p, 0) / TZ_U32 * 6.283185307179586
bind a2 = list_get(p, 1) / TZ_U32 * 6.283185307179586
bind slot = st_get(n + "_head", 0)
st_lset(n + "_x", slot, cos(a1) * TZ_R)
st_lset(n + "_y", slot, sin(a1) * TZ_R)
st_lset(n + "_z", slot, cos(a2) * TZ_R)
st_lset(n + "_w", slot, sin(a2) * TZ_R)
st_lset(n + "_c", slot, twist_color(list_get(p, 4), list_get(p, 3)))
st_lset(n + "_b", slot, t)
st_set(n + "_head", (slot + 1) % TZ_CAP)
st_set(n + "_count", min(TZ_CAP, st_get(n + "_count", 0) + 1))
}
bind i = i + 1
}
}
fn tz_head(n) { return st_get(n + "_hp", []) }
# The per-frame view coefficients.
fn tz_view(t, cx, cy, scale) {
bind a = t * 0.23
bind b = t * 0.141
bind yaw = sin(t * 0.05) * 0.6
return [sin(a), cos(a), sin(b), cos(b), sin(yaw), cos(yaw), sin(0.42), cos(0.42), cx, cy, scale]
}
# Project a point; returns [sx, sy, depth] with depth 1 = near.
fn tz_project(v, x, y, z, w) {
bind sa = list_get(v, 0)
bind ca = list_get(v, 1)
bind sb = list_get(v, 2)
bind cb = list_get(v, 3)
bind x1 = x * ca - w * sa
bind w1 = x * sa + w * ca
bind y1 = y * cb - z * sb
bind z1 = y * sb + z * cb
bind k4 = 1 / (1.75 - w1)
bind x2 = x1 * k4
bind y2 = y1 * k4
bind z2 = z1 * k4
bind sy = list_get(v, 4)
bind cy = list_get(v, 5)
bind x3 = x2 * cy + z2 * sy
bind z3 = z2 * cy - x2 * sy
bind stl = list_get(v, 6)
bind ct = list_get(v, 7)
bind y4 = y2 * ct - z3 * stl
bind z4 = y2 * stl + z3 * ct
bind k3 = 2.6 / (2.6 + z4) * list_get(v, 10)
return [list_get(v, 8) + x3 * k3, list_get(v, 9) - y4 * k3, clampf((1 - z4) * 0.5, 0, 1)]
}
fn tz_draw(n, x, y, w, h, t, active, detail) {
clip_push(x, y, w, h)
bind cx = x + w / 2
bind cy = y + h / 2 + 6
bind mn = min(w, h)
bind v = tz_view(t, cx, cy, mn * 0.42)
# tz_project inlined for the grid and the walk samples (a call and a list
# per point was most of the frame); these are its coefficients.
bind sa = list_get(v, 0)
bind ca = list_get(v, 1)
bind sb = list_get(v, 2)
bind cb = list_get(v, 3)
bind ys = list_get(v, 4)
bind yc = list_get(v, 5)
bind ts = list_get(v, 6)
bind tc = list_get(v, 7)
bind sk = 2.6 * list_get(v, 10)
bind rr = mn * 0.46
px_ring(cx, cy, rr, C_LINE_FAINT, 1)
px_ring(cx, cy, rr * 0.5, C_LINE_FAINT, 0.7)
hline(x + 8, floor(cy), w - 16, C_LINE_FAINT, 0.8)
vline(floor(cx), y + 8, h - 16, C_LINE_FAINT, 0.8)
# 72 ticks; (ux, uy) steps round the circle by a fixed rotation
bind dc = cos(6.283185307179586 / 72)
bind ds = sin(6.283185307179586 / 72)
bind ux = 1
bind uy = 0
bind i = 0
while i < 72 {
bind l = 3
if i % 6 == 0 { bind l = 8 }
px_line(cx + ux * rr, cy + uy * rr, cx + ux * (rr - l), cy + uy * (rr - l), C_LINE_SOFT, 0.8)
bind nx = ux * dc - uy * ds
bind uy = ux * ds + uy * dc
bind ux = nx
bind i = i + 1
}
# torus grid: loops of constant theta1 and theta2
bind loops = sel(detail, 12, 8)
bind steps = sel(detail, 36, 24)
bind dc = cos(6.283185307179586 / steps)
bind ds = sin(6.283185307179586 / steps)
bind k = 0
while k < 2 {
bind gcol = sel(k == 0, C_INDIGO, C_BLUE)
bind li = 0
while li < loops {
bind fixed = li / loops * 6.283185307179586
bind fc = cos(fixed) * TZ_R
bind fs = sin(fixed) * TZ_R
bind vc = TZ_R
bind vs = 0
bind px = 0
bind py = 0
bind pd = 0
bind s = 0
while s <= steps {
bind gx = fc
bind gy = fs
bind gz = vc
bind gw = vs
if k > 0 {
bind gx = vc
bind gy = vs
bind gz = fc
bind gw = fs
}
bind k4 = 1 / (1.75 - gx * sa - gw * ca)
bind x1 = (gx * ca - gw * sa) * k4
bind y1 = (gy * cb - gz * sb) * k4
bind z1 = (gy * sb + gz * cb) * k4
bind z3 = z1 * yc - x1 * ys
bind z4 = y1 * ts + z3 * tc
bind k3 = sk / (2.6 + z4)
bind qx = cx + (x1 * yc + z1 * ys) * k3
bind qy = cy - (y1 * tc - z3 * ts) * k3
bind d = (1 - z4) * 0.5
if d < 0 { bind d = 0 }
if d > 1 { bind d = 1 }
if s > 0 { px_line(px, py, qx, qy, gcol, 0.06 + 0.08 * (pd + d)) }
bind px = qx
bind py = qy
bind pd = d
bind nv = vc * dc - vs * ds
bind vs = vc * ds + vs * dc
bind vc = nv
bind s = s + 1
}
bind li = li + 1
}
bind k = k + 1
}
# tetrahedron
bind tetra = [[1, 1, 1, 0 - 1], [1, 0 - 1, 0 - 1, 1], [0 - 1, 1, 0 - 1, 1], [0 - 1, 0 - 1, 1, 1]]
bind tv = []
bind j = 0
while j < 4 {
bind tp = list_get(tetra, j)
bind tv = list_push(tv, tz_project(v, list_get(tp, 0) * 0.5, list_get(tp, 1) * 0.5, list_get(tp, 2) * 0.5, list_get(tp, 3) * 0.5))
bind j = j + 1
}
bind ia = 0
while ia < 4 {
bind ib = ia + 1
while ib < 4 {
bind pa = list_get(tv, ia)
bind pb = list_get(tv, ib)
bind ax = list_get(pa, 0)
bind ay = list_get(pa, 1)
bind dx = (list_get(pb, 0) - ax) / 28
bind dy = (list_get(pb, 1) - ay) / 28
bind dd = 0
while dd < 28 {
px_line(ax + dx * dd, ay + dy * dd, ax + dx * (dd + 1), ay + dy * (dd + 1), C_VIOLET, 0.35)
bind dd = dd + 2
}
bind ib = ib + 1
}
bind ia = ia + 1
}
bind hp = tz_head(n)
bind hv = 0 - 1
if len(hp) > 3 { bind hv = floor(list_get(hp, 3) / 1073741824) }
bind vi = 0
while vi < 4 {
bind p = list_get(tv, vi)
bind hi = hv == vi && active
bind sz = sel(hi, 6, 4)
bind vc2 = sel(hi, lift(C_VIOLET, 0.4), C_VIOLET)
bind qx = list_get(p, 0)
bind qy = list_get(p, 1)
line(qx - sz, qy, qx, qy - sz, vc2, 0.9)
line(qx, qy - sz, qx + sz, qy, vc2, 0.9)
line(qx + sz, qy, qx, qy + sz, vc2, 0.9)
line(qx, qy + sz, qx - sz, qy, vc2, 0.9)
t_text(F_MONO, 16, qx + 9, qy + 4, "V" + num_str(vi), shade(vc2, 0.2))
bind vi = vi + 1
}
# walk samples, oldest first, then a trail through the newest
bind cnt = st_get(n + "_count", 0)
bind head = st_get(n + "_head", 0)
bind start = (head - cnt + TZ_CAP) % TZ_CAP
bind life = 2.6
bind tail_n = 40
bind lx = 0
bind ly = 0
bind lc = 0
# the sample lists fetched once (a shared reference, not a copy): one store call each, not one per sample
bind lxs = st_get(n + "_x", [])
bind lys = st_get(n + "_y", [])
bind lzs = st_get(n + "_z", [])
bind lws = st_get(n + "_w", [])
bind lcs = st_get(n + "_c", [])
bind lbs = st_get(n + "_b", [])
bind m = 0
while m < cnt {
bind slot = (start + m) % TZ_CAP
bind gx = list_get(lxs, slot)
bind gw = list_get(lws, slot)
bind gy = list_get(lys, slot)
bind gz = list_get(lzs, slot)
bind k4 = 1 / (1.75 - gx * sa - gw * ca)
bind x1 = (gx * ca - gw * sa) * k4
bind y1 = (gy * cb - gz * sb) * k4
bind z1 = (gy * sb + gz * cb) * k4
bind z3 = z1 * yc - x1 * ys
bind z4 = y1 * ts + z3 * tc
bind k3 = sk / (2.6 + z4)
bind qx = cx + (x1 * yc + z1 * ys) * k3
bind qy = cy - (y1 * tc - z3 * ts) * k3
bind d = (1 - z4) * 0.5
if d < 0 { bind d = 0 }
if d > 1 { bind d = 1 }
bind col = list_get(lcs, slot)
bind fade = 1 - (t - list_get(lbs, slot)) / life
if fade < 0.12 { bind fade = 0.12 }
if fade > 1 { bind fade = 1 }
bind al = fade * (0.25 + 0.75 * d)
px_disc(qx, qy, 1.6 + 1.4 * d, col, 0.45 * al)
px_rect(floor(qx), floor(qy), 1, 1, C_TEXT_STRONG, 0.4 * al)
if m > cnt - tail_n && m > 0 {
bind tk = (m - (cnt - tail_n)) / tail_n
px_line(lx, ly, qx, qy, col, 0.05 + 0.3 * tk * tk)
}
bind lx = qx
bind ly = qy
bind lc = col
bind m = m + 1
}
if cnt > 0 && active {
bind pulse = 0.6 + 0.4 * sin(t * 6)
glow(lx, ly, 9, lc, 0.6 * pulse)
ring(lx, ly, 7, C_TEXT_STRONG, 0.8)
if hv >= 0 {
bind pv = list_get(tv, hv)
line(lx, ly, list_get(pv, 0), list_get(pv, 1), lift(C_VIOLET, 0.3), 0.45)
}
}
clip_pop()
}