# RPN Virtual Calculator A browser-friendly RPN calculator built around a small, generic JavaScript API. ## Overview This project provides: - a reusable JavaScript RPN engine in `src/rpn-calculator.js` - browser demos in `samples/dev/` and `samples/calc-02/` - a command system centralized in a single operation dictionary - a small public API focused on stack operations and generic command dispatch The main class is `RpnCalculator`. ## Project structure - `src/rpn-calculator.js`: calculator engine - `samples/dev/index.html`: active browser demo entry point - `samples/dev/index.css`: demo styles - `samples/dev/index.js`: demo UI and keyboard logic - `samples/calc-01/index.html`: active browser demo entry point - `samples/calc-01/index.css`: demo styles - `samples/calc-01/index.js`: demo UI and keyboard logic - `samples/calc-02/index.html`: new responsive HP48GX-style demo entry point - `samples/calc-02/index.css`: new responsive demo styles - `samples/calc-02/index.js`: responsive HP48GX-style demo UI and keyboard logic - `samples/calc-XX/`: placeholder name for future demo variants ## Public API The calculator API is centered on these methods: - `push(value)` - `pop()` - `clear()` - `swap(index1, index2)` - `remove(index)` - `edit(index)` - `isValidIndex(index)` - `input(command)` - `command(name, ...args)` Instance helpers also available: - `getOperationsByCategory()` - `getConstants()` Static helpers also available: - `RpnCalculator.getOperationCategories()` - `RpnCalculator.getOperationsByCategory()` State exposed on instances: - `inputValue` as a string - `isEditing` as a boolean - `stack` as the current internal stack array used by the demo - `angleMode` - `base` - `maxSize` ## Constructor options ```js README.md const calc = new RpnCalculator({ maxSize: 2048, base: 10, angleMode: 'deg', enabledCommands: ['add', 'sub', 'mul', 'div'] }); ``` Supported options: - `maxSize`: maximum stack size, default `2048` - `base`: numeric base, default `10`, accepted range `2..16` - `angleMode`: `deg`, `rad`, or `grad`, default `deg` - `enabledCommands`: optional whitelist of enabled commands and aliases ## Constants Available constants: - `pi` - `e` They can be used through `command(...)`: ```js README.md calc.command('pi'); calc.command('e'); ``` ## Supported commands ### Stack - `enter` - `dup` - `drop` - `swap` - `clear` ### Arithmetic - `add` alias: `+` - `sub` alias: `-` - `mul` alias: `*` - `div` alias: `/` - `mod` alias: `%` - `pow` aliases: `^`, `y^x` - `root` aliases: `y√x`, `yroot`, `nroot` - `sqr` - `neg` - `sqrt` alias: `sqrt(x)` - `recip` alias: `1/x` - `log` - `ln` ### Trigonometry - `sin` - `cos` - `tan` - `asin` - `acos` - `atan` ## Behavior notes - `mod` is a percentage operator: - `a b % => (a * b) / 100` - `pow` accepts aliases `^` and `y^x` - `sqrt` accepts alias `sqrt(x)` - `recip` accepts alias `1/x` - `div` and `recip` throw `Division by zero` when needed - `root` computes the y-th root as `x^(1/y)` and throws `Invalid input for root` for invalid inputs - `sqrt` throws `Invalid input for sqrt` for negative values - `asin` and `acos` throw explicit domain errors outside `[-1, 1]` - `log` throws `Invalid input for log` for values `<= 0` - `ln` throws `Invalid input for ln` for values `<= 0` - `log` uses `Math.log10` - `ln` uses `Math.log` - direct trigonometric functions convert input using `toRadians(...)` - inverse trigonometric functions convert results back using the current angle mode - `angleMode` supports `deg`, `rad`, and `grad` - formatted numeric values are rounded to 12 decimal places - `-0` is normalized to `0` - `inputValue` remains a string to preserve future non-decimal input support - base 10 input is parsed with `Number(...)` - non-decimal input currently uses `parseInt(..., base)` ## Input handling `input(command)` supports two modes: - single-character editing input - command dispatch Accepted single-character editing input currently includes: - `0-9` - `A-F` - `a-f` - `+` - `-` - `.` Everything else is forwarded to `command(...)`. ## Basic usage ### CommonJS ```js README.md const RpnCalculator = require('./src/rpn-calculator'); const calc = new RpnCalculator(); calc.push(2); calc.push(3); calc.command('add'); console.log(calc.pop()); // 5 ``` ### Browser ```html README.md ``` ### Editing values through `input(...)` ```js README.md const calc = new RpnCalculator(); calc.input('1'); calc.input('2'); calc.input('.'); calc.input('5'); calc.command('enter'); console.log(calc.pop()); // 12.5 ``` ### Aliases ```js README.md const calc = new RpnCalculator(); calc.push(6); calc.push(7); calc.command('+'); console.log(calc.pop()); // 13 ``` ### Constants and trigonometry ```js README.md const calc = new RpnCalculator({ angleMode: 'deg' }); calc.command('pi'); console.log(calc.pop()); calc.push(30); calc.command('sin'); console.log(calc.pop()); // 0.5 ``` ## Demo The active demo lives in `samples/dev/`. Main UI features: - four visible stack lines - main display/status area - visible angle mode indicator - angle mode selector for `deg`, `rad`, and `grad` - status pills for `inputValue` and `isEditing` - grouped panels for `Stack`, `Arithmetic`, `Trigonometry`, and `Constants` - error display area The demo loads the engine from: ```html README.md ``` ### Demo keyboard support The current demo supports: - digits and decimal point - numpad digits and numpad arithmetic keys - `Enter` - `Backspace` - `Delete` - `Escape` - `ArrowUp`, `ArrowDown`, `ArrowRight` - `+`, `-`, `*`, `/`, `%`, `^` - `q`, `n`, `r`, `i`, `g`, `l`, `s`, `c`, `S`, `C` - `x`, `y`, `z`, `t` The demo also implements stack selection and stack-item move mode in its UI layer using the public calculator methods. It keeps the calculator screen focused and updates the visible stack window as the selection moves. ## Calc 02 demo `samples/calc-02/` is a responsive HP48GX-inspired demo. It adapts its layout to the browser window, supports portrait and landscape arrangements, and includes the `y√x` root operation. ## Exports `RpnCalculator` is exposed in both environments: - browser: `window.RpnCalculator` - CommonJS: `module.exports = RpnCalculator`