CompressedGemma commited on
Commit
56eff0f
·
verified ·
1 Parent(s): e3887bb

Upload 13 files

Browse files
Files changed (5) hide show
  1. __init__.py +10 -0
  2. analog.py +213 -0
  3. config.py +3 -0
  4. factored.py +121 -5
  5. pipeline.py +15 -12
__init__.py CHANGED
@@ -6,6 +6,12 @@ Viterbi, spectral/DC shaping, local-safety floors) while replacing the
6
  original factored solver with a monotone, multi-start, fp16-exact version.
7
  """
8
 
 
 
 
 
 
 
9
  from .config import HPCConfig
10
  from .factored import (
11
  FactorResult,
@@ -26,6 +32,10 @@ __all__ = [
26
  "QuantizedTensor",
27
  "TensorStats",
28
  "QK_K",
 
 
 
 
29
  "dequantize_params",
30
  "factor_1d",
31
  "factor_candidates",
 
6
  original factored solver with a monotone, multi-start, fp16-exact version.
7
  """
8
 
9
+ from .analog import (
10
+ build_block_analogs,
11
+ subblock_isomoment_analog,
12
+ subscale_lattice_analog,
13
+ vesica_gram_analog,
14
+ )
15
  from .config import HPCConfig
16
  from .factored import (
17
  FactorResult,
 
32
  "QuantizedTensor",
33
  "TensorStats",
34
  "QK_K",
35
+ "build_block_analogs",
36
+ "subblock_isomoment_analog",
37
+ "subscale_lattice_analog",
38
+ "vesica_gram_analog",
39
  "dequantize_params",
40
  "factor_1d",
41
  "factor_candidates",
analog.py ADDED
@@ -0,0 +1,213 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """Geometry-preserving weight analogs for Q2_K bilinear factorization.
2
+
3
+ At 2 bits per weight (4 levels ``q in {0, 1, 2, 3}`` and 4-bit sub-block
4
+ scales ``Ls, Lm in {0..15}``), raw weight blocks suffer from two structural
5
+ bottlenecks:
6
+
7
+ 1. **Intra-sub-block outlier collapse**: a single heavy-tailed weight stretches
8
+ the sub-block span ``xmax - xmin``, forcing 13-15 of the 16 weights into
9
+ one or two quantization bins.
10
+ 2. **Inter-sub-block scale crushing**: a single high-variance sub-block inflates
11
+ the shared superblock scale ``d``, collapsing ``Ls_j`` of the remaining
12
+ 15 sub-blocks toward small integers with severe rounding loss.
13
+
14
+ Rather than factoring raw weights alone, V2 constructs a bank of
15
+ **geometry-preserving weight analogs** ``x_tilde`` of the eligible weights:
16
+
17
+ * :func:`subblock_isomoment_analog` maps each 16-weight sub-block through an
18
+ importance-weighted saturating transport blended with the optimal 4-level
19
+ quantile spacing, then orthogonally projects back onto the exact weighted
20
+ mean ``mu_j`` and weighted variance ``sigma_j^2`` of the original sub-block.
21
+ * :func:`vesica_gram_analog` operates in the D6 / Vesica fold basis
22
+ ``(x_p + x_{p+128}, x_p - x_{p+128})``, regularizing outliers in the whitened
23
+ eigen-basis and coloring back so the exact 2x2 weighted Gram matrix and means
24
+ of the two half-blocks are preserved.
25
+ * :func:`subscale_lattice_analog` tempers cross-sub-block dispersion toward the
26
+ 4-bit ``{0..15}`` scale lattice while preserving every sub-block's unit
27
+ direction, mean, and total block weighted energy.
28
+
29
+ The discrete Q2_K lattice coordinates ``(Ls, Lm, q)`` discovered on each analog
30
+ are then projected back onto the **true weights** ``x`` via coupled bilinear
31
+ least-squares, guaranteeing that the final emitted block is strictly optimal
32
+ under the true objective.
33
+ """
34
+
35
+ from __future__ import annotations
36
+
37
+ import numpy as np
38
+
39
+ from .q2k import NS, QK_K
40
+
41
+ _Q2_IDEAL_QUANTILES = np.linspace(-1.35, 1.35, 16, dtype=np.float64)
42
+
43
+
44
+ def subblock_isomoment_analog(
45
+ x: np.ndarray,
46
+ w: np.ndarray | None = None,
47
+ tau: float = 1.65,
48
+ beta: float = 0.25,
49
+ quantile_blend: float = 0.30,
50
+ enforce_nonpositive_min: bool = False,
51
+ ) -> np.ndarray:
52
+ """Create a sub-block iso-moment analog preserving weighted mean & variance.
53
+
54
+ Invariants per 16-weight sub-block ``j`` (when ``enforce_nonpositive_min``
55
+ is ``False``):
56
+ * ``sum_k w_{j,k} x_tilde_{j,k} == sum_k w_{j,k} x_{j,k}``
57
+ * ``sum_k w_{j,k} (x_tilde_{j,k} - mu_j)^2 == sum_k w_{j,k} (x_{j,k} - mu_j)^2``
58
+ * strict rank-order preservation with respect to ``x_{j,k}`` (when ``beta == 0``)
59
+ """
60
+ xb = np.asarray(x, dtype=np.float64).reshape(NS, 16)
61
+ wb = (
62
+ np.ones((NS, 16), dtype=np.float64)
63
+ if w is None
64
+ else np.asarray(w, dtype=np.float64).reshape(NS, 16)
65
+ )
66
+ wsum = np.maximum(np.sum(wb, axis=1, keepdims=True), 1.0e-30)
67
+ mu = np.sum(wb * xb, axis=1, keepdims=True) / wsum
68
+ centered = xb - mu
69
+ var = np.sum(wb * centered * centered, axis=1, keepdims=True) / wsum
70
+ sigma = np.sqrt(np.maximum(var, 1.0e-30))
71
+ active = (sigma[:, 0] >= 1.0e-15)
72
+
73
+ z = centered / sigma
74
+ w_mean = wsum / 16.0
75
+ w_rel = np.power(np.maximum(wb / w_mean, 1.0e-12), beta) if beta != 0.0 else 1.0
76
+ z_comp = tau * np.tanh((z * w_rel) / max(tau, 1.0e-6))
77
+
78
+ if quantile_blend > 0.0:
79
+ order = np.argsort(z, axis=1, kind="stable")
80
+ z_quant = np.empty_like(z)
81
+ rows = np.arange(NS)[:, None]
82
+ z_quant[rows, order] = _Q2_IDEAL_QUANTILES[None, :]
83
+ z_analog = (1.0 - quantile_blend) * z_comp + quantile_blend * z_quant
84
+ else:
85
+ z_analog = z_comp
86
+
87
+ mu_a = np.sum(wb * z_analog, axis=1, keepdims=True) / wsum
88
+ z_analog = z_analog - mu_a
89
+ var_a = np.sum(wb * z_analog * z_analog, axis=1, keepdims=True) / wsum
90
+ scale = np.where(var_a > 1.0e-30, np.sqrt(var / np.maximum(var_a, 1.0e-30)), 0.0)
91
+ out = np.where(active[:, None], mu + z_analog * scale, xb)
92
+
93
+ if enforce_nonpositive_min:
94
+ orig_min = np.min(xb, axis=1)
95
+ new_min = np.min(out, axis=1)
96
+ shift = np.where((orig_min <= 0.0) & (new_min > 0.0), new_min, 0.0)
97
+ out = out - shift[:, None]
98
+
99
+ return out.reshape(QK_K).astype(np.float32)
100
+
101
+
102
+ def vesica_gram_analog(
103
+ x: np.ndarray,
104
+ w: np.ndarray | None = None,
105
+ tau: float = 1.9,
106
+ ) -> np.ndarray:
107
+ """Create a D6 / Vesica fold analog preserving the 2x2 half-block Gram matrix.
108
+
109
+ Decomposes ``x`` into symmetric ``v = 0.5*(x[:128] + x[128:])`` and
110
+ antisymmetric ``u = 0.5*(x[:128] - x[128:])`` modes under pair weights
111
+ ``wp = 0.5*(w[:128] + w[128:])``. Whitens ``(v, u)``, applies smooth
112
+ hyperbolic saturation in the principal axes, and colors back with the exact
113
+ 2x2 covariance square-root so ``Gram(v_tilde, u_tilde) == Gram(v, u)``.
114
+ """
115
+ x_f64 = np.asarray(x, dtype=np.float64).reshape(QK_K)
116
+ w_f64 = (
117
+ np.ones(QK_K, dtype=np.float64)
118
+ if w is None
119
+ else np.asarray(w, dtype=np.float64).reshape(QK_K)
120
+ )
121
+ half = QK_K // 2
122
+ x0, x1 = x_f64[:half], x_f64[half:]
123
+ wp = np.maximum(0.5 * (w_f64[:half] + w_f64[half:]), 1.0e-30)
124
+ wsum = float(np.sum(wp))
125
+
126
+ v = 0.5 * (x0 + x1)
127
+ u = 0.5 * (x0 - x1)
128
+ mv = float(np.sum(wp * v) / wsum)
129
+ mu = float(np.sum(wp * u) / wsum)
130
+ Y = np.vstack([v - mv, u - mu]) # (2, 128)
131
+
132
+ G = (Y * wp[None, :]) @ Y.T / wsum # 2x2 weighted covariance
133
+ evals, evecs = np.linalg.eigh(G)
134
+ if float(np.max(evals)) < 1.0e-28:
135
+ return x_f64.astype(np.float32)
136
+
137
+ pos = evals > 1.0e-28
138
+ inv_sqrt = np.where(pos, 1.0 / np.sqrt(np.maximum(evals, 1.0e-30)), 0.0)
139
+ W_white = (evecs * inv_sqrt[None, :]) @ evecs.T
140
+ Z = W_white @ Y # whitened (2, 128)
141
+
142
+ Z_comp = tau * np.tanh(Z / max(tau, 1.0e-6))
143
+ Z_mean = np.sum(Z_comp * wp[None, :], axis=1, keepdims=True) / wsum
144
+ Z_comp = Z_comp - Z_mean
145
+
146
+ G_z = (Z_comp * wp[None, :]) @ Z_comp.T / wsum
147
+ ez, Vz = np.linalg.eigh(G_z)
148
+ pos_z = ez > 1.0e-28
149
+ if not np.all(pos_z):
150
+ return x_f64.astype(np.float32)
151
+ inv_sqrt_z = np.where(pos_z, 1.0 / np.sqrt(np.maximum(ez, 1.0e-30)), 0.0)
152
+ Z_orth = (Vz * inv_sqrt_z[None, :]) @ Vz.T @ Z_comp
153
+
154
+ sqrt_G = (evecs * np.sqrt(np.maximum(evals, 0.0))[None, :]) @ evecs.T
155
+ Y_tilde = sqrt_G @ Z_orth
156
+ v_new = mv + Y_tilde[0]
157
+ u_new = mu + Y_tilde[1]
158
+ return np.concatenate([v_new + u_new, v_new - u_new]).astype(np.float32)
159
+
160
+
161
+ def subscale_lattice_analog(
162
+ x: np.ndarray,
163
+ w: np.ndarray | None = None,
164
+ gamma: float = 0.65,
165
+ ) -> np.ndarray:
166
+ """Create a cross-sub-block analog whose sub-block dispersions fit 4-bit scales.
167
+
168
+ Preserves each sub-block's mean ``mu_j`` and unit direction
169
+ ``(x_j - mu_j) / sigma_j``, while tempering extreme sub-block standard
170
+ deviations ``sigma_j`` toward the superblock root-mean-square dispersion
171
+ and rescaling to preserve total centered weighted energy.
172
+ """
173
+ xb = np.asarray(x, dtype=np.float64).reshape(NS, 16)
174
+ wb = (
175
+ np.ones((NS, 16), dtype=np.float64)
176
+ if w is None
177
+ else np.asarray(w, dtype=np.float64).reshape(NS, 16)
178
+ )
179
+ wsum = np.maximum(np.sum(wb, axis=1, keepdims=True), 1.0e-30)
180
+ mu = np.sum(wb * xb, axis=1, keepdims=True) / wsum
181
+ centered = xb - mu
182
+ energy_j = np.sum(wb * centered * centered, axis=1, keepdims=True)
183
+ total_energy = float(np.sum(energy_j))
184
+ if total_energy <= 1.0e-30:
185
+ return xb.reshape(QK_K).astype(np.float32)
186
+
187
+ sigma = np.sqrt(np.maximum(energy_j / wsum, 1.0e-30))
188
+ sigma_ref = float(np.sqrt(total_energy / max(float(np.sum(wsum)), 1.0e-30)))
189
+ target_sigma = np.power(np.maximum(sigma, 1.0e-30), gamma) * (
190
+ sigma_ref ** (1.0 - gamma)
191
+ )
192
+ scaled = np.where(sigma > 1.0e-15, centered * (target_sigma / sigma), 0.0)
193
+ new_energy = float(np.sum(wb * scaled * scaled))
194
+ if new_energy > 1.0e-30:
195
+ scaled = scaled * np.sqrt(total_energy / new_energy)
196
+ out = mu + scaled
197
+ return out.reshape(QK_K).astype(np.float32)
198
+
199
+
200
+ def build_block_analogs(
201
+ x: np.ndarray,
202
+ w: np.ndarray | None = None,
203
+ ) -> list[np.ndarray]:
204
+ """Return the portfolio of geometry-preserving weight analogs for a block."""
205
+ a1 = subblock_isomoment_analog(
206
+ x, w, tau=1.60, beta=0.25, quantile_blend=0.30, enforce_nonpositive_min=True
207
+ )
208
+ a2 = subblock_isomoment_analog(
209
+ x, w, tau=2.15, beta=0.15, quantile_blend=0.15, enforce_nonpositive_min=True
210
+ )
211
+ a3 = vesica_gram_analog(x, w, tau=1.85)
212
+ a4 = subscale_lattice_analog(a1, w, gamma=0.70)
213
+ return [a1, a2, a3, a4]
config.py CHANGED
@@ -33,6 +33,9 @@ class HPCConfig:
33
  factor_portfolio: bool = True
34
  factor_spectral_refine: bool = True
35
  factor_exact_emit: bool = True
 
 
 
36
 
37
  # ---- objective ------------------------------------------------------
38
  use_spectral: bool = True
 
33
  factor_portfolio: bool = True
34
  factor_spectral_refine: bool = True
35
  factor_exact_emit: bool = True
36
+ use_weight_analogs: bool = True
37
+ factor_coupled_q2k: bool = True
38
+ factor_joint_subscales: bool = True
39
 
40
  # ---- objective ------------------------------------------------------
41
  use_spectral: bool = True
factored.py CHANGED
@@ -28,6 +28,7 @@ from dataclasses import dataclass
28
 
29
  import numpy as np
30
 
 
31
  from .config import HPCConfig
32
  from .fp16 import from_fp16_bits, fp16_ulp_neighbors, nearest_int, round_fp16, to_fp16_bits
33
  from .q2k import NS, QK_K, codes_from_params, derive_subscales
@@ -298,6 +299,83 @@ def _ls_init(x, w, cfg: HPCConfig, legacy_1d: bool = False):
298
  return d, m, ls, lm, codes
299
 
300
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
301
  def _sub_ls(x, w, codes):
302
  x = np.asarray(x, dtype=np.float64)
303
  w = np.asarray(w, dtype=np.float64)
@@ -350,14 +428,26 @@ def _solve(
350
  best = (obj, d, m, ls.copy(), lm.copy(), codes.copy())
351
  stall = 0
352
  iters = 0
 
 
 
 
 
 
353
  for it in range(max(1, max_iter)):
354
  iters = it + 1
355
  codes = codes_from_params(x, d, m, ls, lm)
356
  s, t = _sub_ls(x, w, codes)
357
  q = codes.astype(np.float64).reshape(NS, 16)
358
- wb = w.reshape(NS, 16)
359
- ws = np.sum(wb * q * q, axis=1)
360
- wt = np.sum(wb, axis=1)
 
 
 
 
 
 
361
 
362
  if pin & 1:
363
  if d > 1.0e-30:
@@ -368,16 +458,39 @@ def _solve(
368
  d_new, ls_new = _factor_1d_for(s, ws, 15, cfg, legacy_1d)
369
  d, ls = float(d_new), ls_new
370
 
 
 
 
 
 
 
371
  if pin & 2:
372
  if m > 1.0e-30:
373
- lm = np.clip(nearest_int(t / m), 0, 15).astype(np.uint8)
374
  else:
375
  lm = np.zeros(NS, dtype=np.uint8)
376
  else:
377
- m_new, lm_new = _factor_1d_for(t, wt, 15, cfg, legacy_1d)
378
  m, lm = float(m_new), lm_new
379
 
380
  codes = codes_from_params(x, d, m, ls, lm)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
381
  cur, _ = objective(x, w, d, m, ls, lm, codes, cfg, dc_carry)
382
  if cur < best[0] - 1.0e-15:
383
  best = (cur, d, m, ls.copy(), lm.copy(), codes.copy())
@@ -465,6 +578,9 @@ def factor_q2k_block(
465
  out.append((d, m, ls, lm, codes))
466
  if starts > 1:
467
  out.append(_ls_init(x, w, cfg, legacy_1d))
 
 
 
468
  return out
469
 
470
  best = None
 
28
 
29
  import numpy as np
30
 
31
+ from .analog import build_block_analogs
32
  from .config import HPCConfig
33
  from .fp16 import from_fp16_bits, fp16_ulp_neighbors, nearest_int, round_fp16, to_fp16_bits
34
  from .q2k import NS, QK_K, codes_from_params, derive_subscales
 
299
  return d, m, ls, lm, codes
300
 
301
 
302
+ def _analog_init(x, w, x_analog, cfg: HPCConfig):
303
+ """Extract discrete Q2_K lattice coordinates from a geometry-preserving analog
304
+ and project continuous scales onto the true weights ``x``."""
305
+ _, _, _, _, analog_codes = _range_init(x_analog, w, cfg, False)
306
+ s, t = _sub_ls(x, w, analog_codes)
307
+ q = analog_codes.astype(np.float64).reshape(NS, 16)
308
+ wb = np.asarray(w, dtype=np.float64).reshape(NS, 16)
309
+ xb = np.asarray(x, dtype=np.float64).reshape(NS, 16)
310
+ Sw = np.sum(wb, axis=1)
311
+ Swq = np.sum(wb * q, axis=1)
312
+ Sqq = np.sum(wb * q * q, axis=1)
313
+ Sx = np.sum(wb * xb, axis=1)
314
+ q_bar = np.where(Sw > 1.0e-30, Swq / np.maximum(Sw, 1e-30), 0.0)
315
+ Vqq = np.maximum(Sqq - Swq * q_bar, 1.0e-12 * Sw)
316
+ d, ls = _factor_1d_for(s, Vqq, 15, cfg, False)
317
+ t_coupled = np.maximum(
318
+ 0.0, (d * ls.astype(np.float64) * Swq - Sx) / np.maximum(Sw, 1e-30)
319
+ )
320
+ m, lm = _factor_1d_for(t_coupled, Sw, 15, cfg, False)
321
+ codes = codes_from_params(x, d, m, ls, lm)
322
+ return d, m, ls, lm, codes
323
+
324
+
325
+ def _joint_subscale_scan(x, w, d: float, m: float) -> tuple[np.ndarray, np.ndarray]:
326
+ """Vectorized exact (Ls_j, Lm_j) in {0..15}^2 minimizer per sub-block."""
327
+ xb = np.asarray(x, dtype=np.float32).reshape(NS, 16)
328
+ wb = np.asarray(w, dtype=np.float32).reshape(NS, 16)
329
+ ls_opts = np.arange(16, dtype=np.float32)[:, None]
330
+ lm_opts = np.arange(16, dtype=np.float32)[None, :]
331
+ d_sub = np.float32(d) * ls_opts
332
+ m_sub = np.float32(m) * lm_opts
333
+ safe = d_sub >= np.float32(1.0e-15)
334
+ safe_d = np.where(safe, d_sub, np.float32(1.0))
335
+ subs = xb[:, None, None, :]
336
+ raw = (subs + m_sub[None, :, :, None]) / safe_d[None, :, :, None]
337
+ q = np.clip(nearest_int(raw), 0, 3).astype(np.float32)
338
+ q = np.where(safe[None, :, :, None], q, 0.0)
339
+ deq = d_sub[None, :, :, None] * q - m_sub[None, :, :, None]
340
+ err = np.sum(wb[:, None, None, :] * (subs - deq) ** 2, axis=3).reshape(NS, 256)
341
+ best_idx = np.argmin(err, axis=1)
342
+ return (best_idx // 16).astype(np.uint8), (best_idx % 16).astype(np.uint8)
343
+
344
+
345
+ def _global_bilinear_dm_solve(
346
+ x, w, d: float, m: float, ls, lm, codes, cfg: HPCConfig, dc_carry: float, use_spectral: bool
347
+ ) -> tuple[float, float]:
348
+ """Exact 2x2 weighted least-squares solve for superblock (d, dmin)."""
349
+ x_f64 = np.asarray(x, dtype=np.float64).ravel()
350
+ w_f64 = np.asarray(w, dtype=np.float64).ravel()
351
+ A = np.repeat(np.asarray(ls, dtype=np.float64), 16) * np.asarray(codes, dtype=np.float64)
352
+ B = np.repeat(np.asarray(lm, dtype=np.float64), 16)
353
+ Saa = float(np.sum(w_f64 * A * A))
354
+ Sab = float(np.sum(w_f64 * A * B))
355
+ Sbb = float(np.sum(w_f64 * B * B))
356
+ Sxa = float(np.sum(w_f64 * x_f64 * A))
357
+ Sxb = float(np.sum(w_f64 * x_f64 * B))
358
+ if use_spectral and cfg.dc_lambda > 0.0:
359
+ rw = float(cfg.dc_lambda) / QK_K
360
+ rA = float(np.sum(A))
361
+ rB = float(np.sum(B))
362
+ rS = float(np.sum(x_f64)) + float(dc_carry)
363
+ Saa += rw * rA * rA
364
+ Sab += rw * rA * rB
365
+ Sbb += rw * rB * rB
366
+ Sxa += rw * rS * rA
367
+ Sxb += rw * rS * rB
368
+ det = Saa * Sbb - Sab * Sab
369
+ if det > 1.0e-30:
370
+ d_opt = (Sbb * Sxa - Sab * Sxb) / det
371
+ m_opt = (Sab * Sxa - Saa * Sxb) / det
372
+ if d_opt > 0.0 and np.isfinite(d_opt):
373
+ d = float(d_opt)
374
+ if m_opt >= 0.0 and np.isfinite(m_opt):
375
+ m = float(m_opt)
376
+ return d, m
377
+
378
+
379
  def _sub_ls(x, w, codes):
380
  x = np.asarray(x, dtype=np.float64)
381
  w = np.asarray(w, dtype=np.float64)
 
428
  best = (obj, d, m, ls.copy(), lm.copy(), codes.copy())
429
  stall = 0
430
  iters = 0
431
+ xb_f64 = x.astype(np.float64).reshape(NS, 16)
432
+ wb_f64 = w.astype(np.float64).reshape(NS, 16)
433
+ Sw = np.sum(wb_f64, axis=1)
434
+ Sx = np.sum(wb_f64 * xb_f64, axis=1)
435
+ coupled = (not legacy_1d) and cfg.factor_coupled_q2k
436
+
437
  for it in range(max(1, max_iter)):
438
  iters = it + 1
439
  codes = codes_from_params(x, d, m, ls, lm)
440
  s, t = _sub_ls(x, w, codes)
441
  q = codes.astype(np.float64).reshape(NS, 16)
442
+ Sqq = np.sum(wb_f64 * q * q, axis=1)
443
+ Swq = np.sum(wb_f64 * q, axis=1)
444
+
445
+ if coupled:
446
+ q_bar = np.where(Sw > 1.0e-30, Swq / np.maximum(Sw, 1.0e-30), 0.0)
447
+ ws = np.maximum(Sqq - Swq * q_bar, 1.0e-12 * Sw)
448
+ else:
449
+ ws = Sqq
450
+ wt = Sw
451
 
452
  if pin & 1:
453
  if d > 1.0e-30:
 
458
  d_new, ls_new = _factor_1d_for(s, ws, 15, cfg, legacy_1d)
459
  d, ls = float(d_new), ls_new
460
 
461
+ t_target = (
462
+ np.maximum(0.0, (d * ls.astype(np.float64) * Swq - Sx) / np.maximum(Sw, 1.0e-30))
463
+ if coupled
464
+ else t
465
+ )
466
+
467
  if pin & 2:
468
  if m > 1.0e-30:
469
+ lm = np.clip(nearest_int(t_target / m), 0, 15).astype(np.uint8)
470
  else:
471
  lm = np.zeros(NS, dtype=np.uint8)
472
  else:
473
+ m_new, lm_new = _factor_1d_for(t_target, wt, 15, cfg, legacy_1d)
474
  m, lm = float(m_new), lm_new
475
 
476
  codes = codes_from_params(x, d, m, ls, lm)
477
+ if coupled:
478
+ if pin == 0:
479
+ d, m = _global_bilinear_dm_solve(
480
+ x, w, d, m, ls, lm, codes, cfg, dc_carry, use_spectral
481
+ )
482
+ if cfg.factor_joint_subscales:
483
+ d_f16 = float(d) if (pin & 1) else float(round_fp16(np.float32(d)))
484
+ m_f16 = float(m) if (pin & 2) else float(round_fp16(np.float32(m)))
485
+ ls_j, lm_j = _joint_subscale_scan(x, w, d_f16, m_f16)
486
+ codes_j = codes_from_params(x, d_f16, m_f16, ls_j, lm_j)
487
+ obj_j, _ = objective(x, w, d_f16, m_f16, ls_j, lm_j, codes_j, cfg, dc_carry)
488
+ if obj_j < best[0] - 1.0e-15:
489
+ d, m, ls, lm, codes = d_f16, m_f16, ls_j, lm_j, codes_j
490
+ best = (obj_j, d, m, ls.copy(), lm.copy(), codes.copy())
491
+ stall = 0
492
+ continue
493
+
494
  cur, _ = objective(x, w, d, m, ls, lm, codes, cfg, dc_carry)
495
  if cur < best[0] - 1.0e-15:
496
  best = (cur, d, m, ls.copy(), lm.copy(), codes.copy())
 
578
  out.append((d, m, ls, lm, codes))
579
  if starts > 1:
580
  out.append(_ls_init(x, w, cfg, legacy_1d))
581
+ if (not legacy_1d) and cfg.use_weight_analogs and d_seed <= 1.0e-30 and m_seed <= 1.0e-30:
582
+ for x_analog in build_block_analogs(x, w):
583
+ out.append(_analog_init(x, w, x_analog, cfg))
584
  return out
585
 
586
  best = None
pipeline.py CHANGED
@@ -501,18 +501,21 @@ class Q2KQuantizer:
501
  candidate_floor_used += 1
502
 
503
  if cfg.use_factor_floor:
504
- fac = at_slot[i]
505
- fobj, fsse = objective(
506
- X[i], wi, fac.d, fac.dmin, fac.ls, fac.lm, fac.codes, cfg, float(carry[i])
507
- )
508
- if fobj < obj - 1.0e-15:
509
- d = float(fac.d)
510
- m = float(fac.dmin)
511
- ls = fac.ls.copy()
512
- lm = fac.lm.copy()
513
- codes = fac.codes.copy()
514
- obj, sse = fobj, fsse
515
- factor_floor_used += 1
 
 
 
516
 
517
  blocks.append(make_block(d, m, ls, lm, codes))
518
 
 
501
  candidate_floor_used += 1
502
 
503
  if cfg.use_factor_floor:
504
+ for fac in (at_slot[i], standalone[i]):
505
+ fcodes = refine_codes_hadamard(
506
+ X[i], wi, fac.d, fac.dmin, fac.ls, fac.lm, fac.codes, cfg, float(carry[i])
507
+ )
508
+ fobj, fsse = objective(
509
+ X[i], wi, fac.d, fac.dmin, fac.ls, fac.lm, fcodes, cfg, float(carry[i])
510
+ )
511
+ if fobj < obj - 1.0e-15:
512
+ d = float(fac.d)
513
+ m = float(fac.dmin)
514
+ ls = fac.ls.copy()
515
+ lm = fac.lm.copy()
516
+ codes = fcodes.copy()
517
+ obj, sse = fobj, fsse
518
+ factor_floor_used += 1
519
 
520
  blocks.append(make_block(d, m, ls, lm, codes))
521