33 with open(path,
"rb")
as f:
34 hdr = np.fromfile(f, dtype=np.int64, count=3)
36 raise ValueError(f
"{path}: bad magic {hdr[0]:x}")
37 rows, cols = int(hdr[1]), int(hdr[2])
38 a = np.fromfile(f, dtype=np.float64, count=rows * cols)
39 return a.reshape(rows, cols)
43 """Unpivoted LDL^T pivots of a symmetric matrix (the WO-H instrument, reproduced)."""
45 A = S.astype(np.float64).copy()
49 d[j] = A[j, j] - (L[j, :j] ** 2 * d[:j]).sum()
50 if abs(d[j]) < 1e-300:
52 for i
in range(j + 1, n):
53 L[i, j] = (A[i, j] - (L[i, :j] * L[j, :j] * d[:j]).sum()) / d[j]
58 """kappa(A) of the FINE operator on the mean-free subspace, and the attainable-accuracy floor it
59 implies. Classical result (Greenbaum; Higham NLA ch.19): a CG-type iteration cannot drive the
60 TRUE relative residual below O(eps * kappa(A)) whatever the preconditioner, because round-off in
61 the recurrence enters at that level. So this column says what a solve on this operator could
62 ever reach in each storage precision — the ceiling any precision policy is measured against, and
63 the reason a fixed rtol of 1e-8 stops being meaningful once kappa exceeds ~1e8 in fp64."""
67 one = np.ones(n) / np.sqrt(n)
71 nw = np.linalg.norm(w)
72 H = np.eye(n) - 2.0 * np.outer(w, w) / (nw * nw)
if nw > 1e-14
else np.eye(n)
74 ev = np.abs(np.linalg.eigvalsh(Q.T @ S @ Q))
75 kappa = float(ev.max() / max(ev.min(), 1e-300))
76 return dict(kappa=kappa, floor_f32=2.0 ** -24 * kappa, floor_f64=2.0 ** -53 * kappa)
83 fnorm = np.linalg.norm(M)
84 skew = np.linalg.norm(M - M.T) / (fnorm + 1e-300)
86 d =
ldl_pivots(S)
if n <= 1024
else np.array([np.nan])
87 scale = np.max(np.abs(d))
89 real_neg = np.sum((d < 0) & (np.abs(d) > 1e-10 * scale))
90 any_neg = int(np.sum(d < 0))
91 min_piv = float(d.min())
97 one = np.ones(n) / np.sqrt(n)
101 nw = np.linalg.norm(w)
102 H = np.eye(n) - 2.0 * np.outer(w, w) / (nw * nw)
if nw > 1e-14
else np.eye(n)
104 ev = np.linalg.eigvalsh(Q.T @ S @ Q)
106 neg_ev = int(np.sum(ev < -1e-10 * lmax))
111 real_neg=int(real_neg),
113 lmin=float(ev.min()),
122 files += sorted(glob.glob(os.path.join(d,
"M_*.bin")))
124 print(
"no M_*.bin found")
128 m = re.match(
r"M_(\w+)_(\w+)_n(\d+)_L(\d+)_r([0-9e+.]+)\.bin", os.path.basename(p))
131 prec, geom, nn, lv, ratio = m.groups()
133 ap = os.path.join(os.path.dirname(p),
"A" + os.path.basename(p)[1:])
135 dict(kappa=float(
"nan"), floor_f32=float(
"nan"), floor_f64=float(
"nan")))
136 r.update(prec=prec, geom=geom, grid=int(nn), levels=int(lv), ratio=float(ratio))
139 rows.sort(key=
lambda r: (r[
"geom"], r[
"ratio"], r[
"prec"]))
142 f
"{'geom':<9}{'ratio':>8} {'prec':<7}{'skew':>10}"
143 f
"{'LDL neg':>9}{'(raw)':>7}{'min pivot':>12}"
144 f
"{'lambda_min':>13}{'lambda_max':>12}{'neg eig':>9}"
145 f
"{'kappa(A)':>11}{'floor f32':>11}{'floor f64':>11}"
150 f
"{r['geom']:<9}{r['ratio']:>8.0e} {r['prec']:<7}{r['skew']:>10.2e}"
151 f
"{r['real_neg']:>9}{r['any_neg']:>7}{r['min_piv']:>12.2e}"
152 f
"{r['lmin']:>13.3e}{r['lmax']:>12.3e}{r['neg_ev']:>9}"
153 f
"{r['kappa']:>11.2e}{r['floor_f32']:>11.2e}{r['floor_f64']:>11.2e}"
156 print(
"LDL neg = pivots below -1e-10*max|pivot| (real indefiniteness);")
157 print(
"(raw) = every negative pivot including the round-off/null-direction sign noise;")
158 print(
"neg eig = negative eigenvalues of sym(M) on the mean-free subspace (the verdict column);")
159 print(
"kappa(A), floor = the FINE operator's condition number on the mean-free subspace and the")
160 print(
" O(eps*kappa) attainable relative residual it implies in each storage precision.")