Compare commits

...

2 Commits

5 changed files with 32 additions and 8 deletions
+2
View File
@@ -4,3 +4,5 @@
- Read `.memory/state.md` for current state.
- Keep names and commands in English.
- Update memory files based on events: engine, demo, API, commands, exports, docs, or tasks.
- Core arithmetic now includes `root` for y-th roots, and `samples/calc-02/` uses it for `y√x`.
- `samples/calc-02/` in portrait mode remains the active responsive demo.
+2 -2
View File
@@ -1,9 +1,9 @@
# State
- Core engine: `src/rpn-calculator.js`
- Active demo: `samples/calc-02/` responsive HP48GX layout with HP48-like X-line editing; display-adjacent button row stays in 4 columns
- Active demo: `samples/calc-02/` responsive HP48GX layout with portrait/landscape support; display-adjacent button row stays in 4 columns
- Mode button shows the current angle mode only; selecting a mode uses a popup menu
- Public API: `push`, `pop`, `clear`, `swap`, `remove`, `edit`, `isValidIndex`, `input`, `command`, `getOperationsByCategory`, `getConstants`
- Config: `maxSize`, `base`, `angleMode`, `enabledCommands`
- Commands: arithmetic, stack, trigonometry, constants `pi` and `e`
- Commands: arithmetic, stack, trigonometry, constants `pi` and `e`; arithmetic now includes `root` for y-th roots
- Demo actions: keyboard focus is kept on the hidden input on desktop so typing keeps working; the keypad layout places Enter in the bottom-left, ± in the former Enter position, and Esc before Clear for safety; paste parses clipboard text as a number before pushing it to the stack; Ctrl+V is supported via the hidden input paste event; backspace is ignored when the stack is empty; operation errors are shown as an overlay bar on top of the calculator with a shorter timeout and darker red
- Exports: browser `window.RpnCalculator`, CommonJS `module.exports`
+6 -4
View File
@@ -7,7 +7,7 @@ A browser-friendly RPN calculator built around a small, generic JavaScript API.
This project provides:
- a reusable JavaScript RPN engine in `src/rpn-calculator.js`
- a browser demo in `samples/dev/`
- 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
@@ -24,7 +24,7 @@ The main class is `RpnCalculator`.
- `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`: new demo UI and keyboard logic
- `samples/calc-02/index.js`: responsive HP48GX-style demo UI and keyboard logic
- `samples/calc-XX/`: placeholder name for future demo variants
## Public API
@@ -110,6 +110,7 @@ calc.command('e');
- `div` alias: `/`
- `mod` alias: `%`
- `pow` aliases: `^`, `y^x`
- `root` aliases: `y√x`, `yroot`, `nroot`
- `sqr`
- `neg`
- `sqrt` alias: `sqrt(x)`
@@ -134,6 +135,7 @@ calc.command('e');
- `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`
@@ -270,8 +272,8 @@ It keeps the calculator screen focused and updates the visible stack window as t
## Calc 02 demo
`samples/calc-02/` is a new responsive HP48GX-inspired demo.
It adapts its layout to the browser window and switches between the supplied portrait and landscape arrangements.
`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
+7 -1
View File
@@ -58,7 +58,7 @@ const functionKeys = [
{ label: '1/x', action: 'recip', className: 'key-default' },
{ label: '%', action: 'mod', className: 'key-default' },
{ label: '√x', action: 'sqrt', className: 'key-default' },
{ label: 'y√x', action: 'pow', className: 'key-default' },
{ label: 'y√x', action: 'root', className: 'key-default' },
{ label: '10ˣ', action: 'pow10', className: 'key-default' },
{ label: '', spacer: true },
{ label: 'log', action: 'log', className: 'key-default' },
@@ -243,11 +243,17 @@ function execute(name) {
}
} else if (name === 'pow10') {
pushEditingValueIfNeeded();
const exponent = calc.stack[0];
calc.remove(0);
calc.push(10);
calc.push(exponent);
calc.command('pow');
} else if (name === 'exp') {
pushEditingValueIfNeeded();
const exponent = calc.stack[0];
calc.remove(0);
calc.push(Math.E);
calc.push(exponent);
calc.command('pow');
} else {
pushEditingValueIfNeeded();
+15 -1
View File
@@ -46,6 +46,20 @@ class RpnCalculator {
aliases: ['^', 'y^x'],
execute: (calc, a, b) => Math.pow(a, b),
},
root: {
category: 'Arithmetic',
argCount: 2,
aliases: ['y√x', 'yroot', 'nroot'],
execute: (calc, a, b) => {
if (b === 0) {
throw new Error('Invalid input for root');
}
if (a < 0 && b % 2 === 0) {
throw new Error('Invalid input for root');
}
return Math.pow(a, 1 / b);
},
},
sqr: {
category: 'Arithmetic',
argCount: 1,
@@ -178,7 +192,7 @@ class RpnCalculator {
static getOperationsByCategory() {
return {
Stack: ['dup', 'drop', 'swap', 'clear', 'enter'],
Arithmetic: ['add', 'sub', 'mul', 'div', 'mod', 'pow', 'sqr', 'neg', 'sqrt', 'recip', 'log', 'ln'],
Arithmetic: ['add', 'sub', 'mul', 'div', 'mod', 'pow', 'root', 'sqr', 'neg', 'sqrt', 'recip', 'log', 'ln'],
Trigonometry: ['sin', 'cos', 'tan', 'asin', 'acos', 'atan'],
};
}