(function () { "use strict"; // ---- Data types & quantization ---- const dataTypes = [ { name: "float32", bits: 32, bytes: 4 }, { name: "float16", bits: 16, bytes: 2 }, { name: "bfloat16", bits: 16, bytes: 2 }, { name: "8-bit (INT8)", bits: 8, bytes: 1 }, { name: "6-bit (Q_6)", bits: 6, bytes: 0.75 }, { name: "4-bit (Q_4)", bits: 4, bytes: 0.5 }, { name: "3-bit (Q_3)", bits: 3, bytes: 0.375 }, { name: "2-bit (Q_2)", bits: 2, bytes: 0.25 } ]; // ---- DOM refs ---- const paramInput = document.getElementById('paramInput'); const calculateBtn = document.getElementById('calculateBtn'); const tableBody = document.getElementById('tableBody'); const paramDisplay = document.getElementById('paramDisplay'); const themeToggle = document.getElementById('themeToggle'); const themeIcon = document.getElementById('themeIcon'); // ---- Helper: parse "1.5B", "100M", "7B", "1,000,000", etc. ---- function parseParameters(rawInput) { let cleaned = String(rawInput).replace(/,/g, '').replace(/\s/g, '').trim(); if (cleaned === '') return NaN; const lower = cleaned.toLowerCase(); let multiplier = 1; let numStr = cleaned; if (lower.endsWith('b')) { multiplier = 1e9; numStr = cleaned.slice(0, -1); } else if (lower.endsWith('m')) { multiplier = 1e6; numStr = cleaned.slice(0, -1); } const num = parseFloat(numStr); if (isNaN(num) || num < 0) return NaN; return num * multiplier; } // ---- Helpers for formatting ---- function formatNumber(num, decimals = 2) { if (num === undefined || !isFinite(num)) return '—'; return num.toFixed(decimals).replace(/\B(?=(\d{3})+(?!\d))/g, ','); } function formatBytes(bytes) { if (bytes === undefined || !isFinite(bytes)) return '—'; if (Math.abs(bytes) >= 1e15) { return bytes.toExponential(2); } return formatNumber(bytes, 2); } function bytesToGB(bytes) { return bytes / 1e9; } function bytesToMiB(bytes) { return bytes / (1024 * 1024); } // ---- Map data type name to CSS class for color coding ---- function getDataTypeClass(name) { if (name.includes('float')) return 'float'; if (name.includes('8-bit')) return 'int8'; if (name.includes('6-bit')) return 'q6'; if (name.includes('4-bit')) return 'q4'; if (name.includes('3-bit')) return 'q3'; if (name.includes('2-bit')) return 'q2'; return ''; } // ---- Main calculation ---- function calculateAndRender(rawInput) { const numParams = parseParameters(rawInput); if (isNaN(numParams)) { tableBody.innerHTML = `Please enter a valid number (e.g., 7B, 1.5b, 100M).`; paramDisplay.textContent = 'Invalid input'; return; } // Update badge let displayText = formatNumber(numParams, 0) + ' parameters'; if (numParams >= 1e9) { displayText = (numParams / 1e9).toFixed(2) + 'B parameters'; } else if (numParams >= 1e6) { displayText = (numParams / 1e6).toFixed(2) + 'M parameters'; } paramDisplay.textContent = displayText; // Build rows let rowsHtml = ''; dataTypes.forEach(dt => { const bytes = numParams * dt.bytes; const gb = bytesToGB(bytes); const mib = bytesToMiB(bytes); const typeClass = getDataTypeClass(dt.name); rowsHtml += ` ${dt.name} ${dt.bits} ${formatNumber(gb, 2)} ${formatNumber(mib, 2)} ${formatBytes(bytes)} `; }); tableBody.innerHTML = rowsHtml; } // ---- Event listeners ---- calculateBtn.addEventListener('click', function () { calculateAndRender(paramInput.value); }); paramInput.addEventListener('keydown', function (e) { if (e.key === 'Enter') { e.preventDefault(); calculateAndRender(paramInput.value); } }); document.querySelectorAll('.btn-preset').forEach(btn => { btn.addEventListener('click', function () { const value = this.getAttribute('data-value'); paramInput.value = value; calculateAndRender(value); }); }); // Initial load (7B) calculateAndRender(paramInput.value); // ---- Dark / Light toggle (custom class, default = dark) ---- function setTheme(theme) { const html = document.documentElement; if (theme === 'dark') { html.classList.add('dark-mode'); themeIcon.textContent = '☀️'; // sun icon for switching to light } else { html.classList.remove('dark-mode'); themeIcon.textContent = '🌙'; // moon icon for switching to dark } localStorage.setItem('theme', theme); } themeToggle.addEventListener('click', function () { const current = document.documentElement.classList.contains('dark-mode') ? 'dark' : 'light'; setTheme(current === 'dark' ? 'light' : 'dark'); }); // Load saved theme, or default to dark function loadTheme() { const saved = localStorage.getItem('theme'); if (saved) { setTheme(saved); } else { setTheme('dark'); // default to dark } } loadTheme(); })();