sirunchained's picture
done.
3783386
Raw
History Blame Contribute Delete
5.82 kB
(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 = `<tr><td colspan="5" class="text-center text-danger">Please enter a valid number (e.g., 7B, 1.5b, 100M).</td></tr>`;
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 += `
<tr data-type="${typeClass}">
<td><strong>${dt.name}</strong></td>
<td>${dt.bits}</td>
<td>${formatNumber(gb, 2)}</td>
<td>${formatNumber(mib, 2)}</td>
<td>${formatBytes(bytes)}</td>
</tr>
`;
});
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();
})();