// BigInt Encoder Calculator // Converted from Scheme to JavaScript using BigInt for arbitrary precision // ENCODE ONE BIT // (n × 2) - 3, requires n > 3 function oneEncode(n) { if (typeof n === 'string') { n = BigInt(n); } else if (typeof n === 'number') { n = BigInt(n); } if (n > 3n) { return (n * 2n) - 3n; } else { throw new Error('Invalid input: n must be greater than 3'); } } // ENCODE ZERO BIT // (n × 2) - 2, requires n > 3 function zeroEncode(n) { if (typeof n === 'string') { n = BigInt(n); } else if (typeof n === 'number') { n = BigInt(n); } if (n > 3n) { return (n * 2n) - 2n; } else { throw new Error('Invalid input: n must be greater than 3'); } } // MAXED HELPER // Recursively finds the largest power of 2 <= num function maxedHelper(num, out) { if (out > num) { return out / 2n; } else if (out <= num) { return maxedHelper(num, out * 2n); } else { throw new Error('Unexpected error in maxedHelper'); } } // MAX OUT THE COMPONENT // Finds the largest power of 2 less than or equal to num function maxed(num) { if (typeof num === 'string') { num = BigInt(num); } else if (typeof num === 'number') { num = BigInt(num); } if (num > 0n) { return maxedHelper(num, 2n); } else { throw new Error('Invalid input: num must be greater than 0'); } } // CORE HELPER // Recursively compresses the data function coreHelper(maxedVal, num, out) { if (maxedVal < 1n) { return out; } else if (maxedVal > num) { return coreHelper(maxedVal / 2n, num, zeroEncode(out)); } else if (maxedVal <= num) { return coreHelper(maxedVal / 2n, num - maxedVal, oneEncode(out)); } else { throw new Error('Unexpected error in coreHelper'); } } // COMPRESS DATA // Main compression function - starts with 4, then subtracts 4 from result function core(num) { if (typeof num === 'string') { num = BigInt(num); } else if (typeof num === 'number') { num = BigInt(num); } if (num > 0n) { const maxedVal = maxed(num); const result = coreHelper(maxedVal, num, 4n); return result - 4n; } else { throw new Error('Invalid input: num must be greater than 0'); } } // Calculate bit length of a BigInt function getBitLength(bigIntValue) { if (bigIntValue === 0n) return 1; return bigIntValue.toString(2).length; } // Calculate alternate output: output + 2^(input_bit_length - 1) function calculateAlternateOutput(output, inputBitLength) { if (inputBitLength < 1) { return output; // Can't subtract 1 from bit length if it's less than 1 } const powerValue = 2n ** BigInt(inputBitLength - 1); return output + powerValue; } // Parse input - supports both decimal and binary (with 0b prefix) function parseInput(input) { input = input.trim(); if (!input) { throw new Error('Please enter a number'); } // Check if input is binary (starts with 0b or 0B) if (input.toLowerCase().startsWith('0b')) { const binaryPart = input.slice(2); // Validate binary string if (!/^[01]+$/.test(binaryPart)) { throw new Error('Invalid binary format. Use only 0 and 1 after 0b prefix'); } if (binaryPart.length === 0) { throw new Error('Binary string cannot be empty after 0b prefix'); } // Convert binary string to BigInt using parseInt with base 2 // For very large numbers, we need to use BigInt constructor with proper formatting return BigInt('0b' + binaryPart); } else { // Validate decimal string if (!/^\d+$/.test(input)) { throw new Error('Please enter a valid positive integer or binary with 0b prefix'); } return BigInt(input); } } // UI Functions function getInputValue() { const input = document.getElementById('numberInput').value; return parseInput(input); } function updateBitCounts(inputBits, outputBits) { const inputBitsEl = document.getElementById('inputBits'); const outputBitsEl = document.getElementById('outputBits'); if (inputBitsEl) { inputBitsEl.textContent = inputBits !== null ? `${inputBits} bits` : '-'; } if (outputBitsEl) { outputBitsEl.textContent = outputBits !== null ? `${outputBits} bits` : '-'; } } function displayInputBinary(value, isError = false) { const inputBinaryDiv = document.getElementById('inputBinary'); inputBinaryDiv.className = 'results-content'; if (isError) { inputBinaryDiv.innerHTML = `<span class="error">${value}</span>`; } else { inputBinaryDiv.textContent = value; } } function displayResult(value, isError = false) { const resultsDiv = document.getElementById('results'); resultsDiv.className = 'results-content'; if (isError) { resultsDiv.innerHTML = `<span class="error">${value}</span>`; } else { resultsDiv.textContent = value; } } function displayAlternateResult(value, isError = false) { const alternateResultsDiv = document.getElementById('alternateResults'); alternateResultsDiv.className = 'results-content'; if (isError) { alternateResultsDiv.innerHTML = `<span class="error">${value}</span>`; } else { alternateResultsDiv.textContent = value; } } function calculateCore() { try { const inputBigInt = getInputValue(); if (inputBigInt <= 0n) { throw new Error('Input must be greater than 0'); } const inputBitLength = getBitLength(inputBigInt); const inputBinary = inputBigInt.toString(2); const result = core(inputBigInt); const outputBitLength = getBitLength(result); const alternateResult = calculateAlternateOutput(result, inputBitLength); displayInputBinary(inputBinary); displayResult(result.toString()); displayAlternateResult(alternateResult.toString()); updateBitCounts(inputBitLength, outputBitLength); } catch (error) { displayInputBinary(error.message, true); displayResult(error.message, true); displayAlternateResult('', true); updateBitCounts(null, null); } } function clearAll() { document.getElementById('numberInput').value = ''; const inputBinaryDiv = document.getElementById('inputBinary'); const resultsDiv = document.getElementById('results'); const alternateResultsDiv = document.getElementById('alternateResults'); inputBinaryDiv.innerHTML = '<p class="placeholder">Binary representation will appear here...</p>'; resultsDiv.innerHTML = '<p class="placeholder">Results will appear here...</p>'; alternateResultsDiv.innerHTML = '<p class="placeholder">Alternate results will appear here...</p>'; updateBitCounts(null, null); } function copyOutput() { const resultsDiv = document.getElementById('results'); const text = resultsDiv.textContent.trim(); // Check if there's actual output to copy if (text === 'Results will appear here...' || text === '') { showNotification('No output to copy!', false); return; } // Check if it's an error message if (resultsDiv.querySelector('.error')) { showNotification('Cannot copy error message!', false); return; } // Copy to clipboard navigator.clipboard.writeText(text).then(() => { showNotification('Copied to clipboard!', true); }).catch(err => { showNotification('Failed to copy!', false); }); } function copyBinaryInput() { const inputBinaryDiv = document.getElementById('inputBinary'); const text = inputBinaryDiv.textContent.trim(); // Check if there's actual output to copy if (text === 'Binary representation will appear here...' || text === '') { showNotification('No binary input to copy!', false); return; } // Check if it's an error message if (inputBinaryDiv.querySelector('.error')) { showNotification('Cannot copy error message!', false); return; } // Copy to clipboard navigator.clipboard.writeText(text).then(() => { showNotification('Binary input copied!', true); }).catch(err => { showNotification('Failed to copy!', false); }); } function copyAlternateOutput() { const alternateResultsDiv = document.getElementById('alternateResults'); const text = alternateResultsDiv.textContent.trim(); // Check if there's actual output to copy if (text === 'Alternate results will appear here...' || text === '') { showNotification('No alternate output to copy!', false); return; } // Check if it's an error message if (alternateResultsDiv.querySelector('.error')) { showNotification('Cannot copy error message!', false); return; } // Copy to clipboard navigator.clipboard.writeText(text).then(() => { showNotification('Alternate output copied!', true); }).catch(err => { showNotification('Failed to copy!', false); }); } function showNotification(message, isSuccess) { // Remove any existing notification const existingNotification = document.querySelector('.copy-notification'); if (existingNotification) { existingNotification.remove(); } // Create new notification const notification = document.createElement('div'); notification.className = 'copy-notification'; notification.textContent = message; notification.style.background = isSuccess ? '#28a745' : '#dc3545'; document.body.appendChild(notification); // Remove after 2 seconds setTimeout(() => { notification.remove(); }, 2000); } // Wait for DOM to be ready document.addEventListener('DOMContentLoaded', function() { // Allow Enter key to trigger Core calculation const inputField = document.getElementById('numberInput'); if (inputField) { inputField.addEventListener('keypress', function(event) { if (event.key === 'Enter') { calculateCore(); } }); } });