"""
Does the logarithmic-number-system (LNS) argument survive 2026 arithmetic?

The transcript's hardware claim: LNS turns multiplies into adds, so an AI chip
built on (sign, log|x|) replaces big multiplier arrays with small adders and wins.

That argument was formulated when the multiplier was the expensive thing. Test it
against (a) Horowitz ISSCC-2014 per-op energies at 45nm (the canonical table; the
RATIOS are what matter and they are stable across nodes), and (b) this repo's own
calibrated H100 constants from photonics/photonic/costmodel/baseline_gpu.py.

No new constants are invented here.
"""

# --- Horowitz, "Computing's Energy Problem (and what we can do about it)",
#     ISSCC 2014, 45 nm. Energies in pJ. -------------------------------------
E = {
    "int8_add": 0.03, "int8_mult": 0.2,
    "int32_add": 0.1, "int32_mult": 3.1,
    "fp16_add": 0.4,  "fp16_mult": 1.1,
    "fp32_add": 0.9,  "fp32_mult": 3.7,
    "sram_8kb_read_32b": 5.0,     # a LUT lookup lives here at best
    "dram_read_32b": 640.0,
}

# --- This repo's calibrated H100 numbers (baseline_gpu.py H100_SXM) ----------
J_PER_FLOP = 7.1e-13          # board-amortized, i.e. an UPPER bound on compute
J_PER_BYTE_HBM = 2.0e-11
PJ = 1e12

print("=" * 74)
print("1. THE MAC IS A MULTIPLY *AND* AN ACCUMULATE. LNS TRADES ONE FOR THE OTHER.")
print("=" * 74)
for dt in ("int8", "fp16", "fp32"):
    mul, add = E[f"{dt}_mult"], E[f"{dt}_add"]
    linear_mac = mul + add
    # LNS: multiply -> add (cheap). accumulate -> log-sum-exp.
    # LSE(a,b) = max(a,b) + f(|a-b|); f() is a LUT read + an add. Optimistically
    # price the LUT at a *dedicated small* table, 1/10th of an 8KB SRAM access.
    lut_optimistic = E["sram_8kb_read_32b"] / 10
    lut_realistic = E["sram_8kb_read_32b"]
    lns_mac_opt = add + (add + lut_optimistic + add)   # mult->add ; LSE = cmp/sub + LUT + add
    lns_mac_real = add + (add + lut_realistic + add)
    print(f"\n  {dt:>5}:  linear MAC = {mul:.2f} (mult) + {add:.2f} (add) = {linear_mac:.2f} pJ")
    print(f"          LNS MAC   = {add:.2f} (add) + LSE[{add:.2f}+LUT+{add:.2f}]")
    print(f"            optimistic LUT ({lut_optimistic:.2f} pJ): {lns_mac_opt:.2f} pJ "
          f"-> {lns_mac_opt/linear_mac:.2f}x linear  "
          f"({'WORSE' if lns_mac_opt > linear_mac else 'better'})")
    print(f"            realistic  LUT ({lut_realistic:.2f} pJ): {lns_mac_real:.2f} pJ "
          f"-> {lns_mac_real/linear_mac:.2f}x linear  "
          f"({'WORSE' if lns_mac_real > linear_mac else 'better'})")

print()
print("=" * 74)
print("2. EVEN A FREE MULTIPLIER BARELY MOVES DECODE, WHICH IS MEMORY-BOUND.")
print("=" * 74)
# One bf16 weight fetched from HBM enables exactly 2 FLOPs (one MAC).
bytes_per_weight = 2
flops_enabled = 2
e_move = bytes_per_weight * J_PER_BYTE_HBM * PJ
e_compute = flops_enabled * J_PER_FLOP * PJ
print(f"\n  move 1 bf16 weight from HBM : {e_move:8.2f} pJ")
print(f"  the 2 FLOPs it enables      : {e_compute:8.2f} pJ   ({e_compute/e_move*100:.1f}% of the move)")
print(f"  ratio                       : {e_move/e_compute:8.1f}x  <- data movement dominates")
print()
best_case = 1 - e_compute / (e_move + e_compute)
print(f"  Upper bound on ANY compute-side arithmetic trick in weight-bound decode:")
print(f"    even making arithmetic FREE saves {e_compute/(e_move+e_compute)*100:.2f}% of the energy.")
print(f"    LNS captures at most a fraction of that fraction.")

print()
print("=" * 74)
print("3. WHAT THE INDUSTRY ACTUALLY DID WITH THE LOG IDEA")
print("=" * 74)
print("""
  IEEE-754 is already (sign, exponent, mantissa) = a piecewise-linear log
  representation. The exponent field IS log2|x|, stored exactly.

  The 2026 frontier low-precision formats -- MXFP4/MXFP8 (OCP Microscaling),
  NVFP4 -- go further: a block of values SHARES one power-of-two scale. That is
  a logarithmic representation of the block magnitude with a linear mantissa.

  So the log idea was adopted precisely where it pays (the exponent / block
  scale, which is about DYNAMIC RANGE PER BIT) and rejected where it does not
  (the mantissa, because accumulation dominates).

  Note also what LNS-Madam (NVIDIA, IEEE Trans. Computers 2022) does: it
  multiplies in log domain and converts BACK to a linear fixed-point domain to
  accumulate. That is the exact opposite of the transcript's "stay in log
  coordinates through many operations" -- and for the reason computed in (1).
""")
