Commit graph

2134 commits

Author SHA1 Message Date
Christophe de Dinechin
709476169e Release 0.7.5 "Perfect Joy" - Polynomials and symbolic rewrites
This release contains a lot of groundwork in preparation for future work on
symbolic expressions, symbolic solving and symbolic integration, as well as to
improve compatibility with HP calculators. In particular, `rewrite` has been
replaced with the HP equivalents, `↑Match` and `↓Match`, allowing top-down and
bottom-up replacement, as well as support for conditions. Also, these commands
return the number of replacements performed instead of just `0` or `1`.

THe other major user-visible new feature is the addition of a polynomials data
type, which does not exist on HP calculators, exposing polynomial features in a
way that is more consistent with the spirit of RPL. For example, Euclidean
division of polynomials can be achieved using the regular `/` operation on
polynomials instead of requiring a dedicated `DIV2` command.

**New features**

* Support for polynomials as a data type, including Euclidean division
* Arithmetic operations on polynomials, including `sq` and `cubed`
* Conversion functions `→Poly` and `Poly→` to convert to and from polynomials
* Optional case-sensitive symbol matching
* Algebra configuration directory (like `CASDIR` on HP calculators)
* rewrites: Replace `rewrite` command with HP-compatible `↑Match` and `↓Match`
* rewrites: Add `ExplicitWildcards` option to match HP syntax (`&A`)
* rewrites: Add rules to expand powers
* rewrites: Add support for conditions when matching patterns
* rewrites: Add support for step-by-step rewrites
* rewrites: Add support for bottom-up rewrites
* flags: `Purge` now resets system flags to default value

**Bug fixes**

* editor: Fix unresponsive keys after using `EXIT` key while searching
* complex: Avoid emitting syntax errors while parsing
* rewrites: Avoid potential garbage collection corruption problem
* rewrites: Disable auto-simplification during rewrites
* rewrites: Factor out rewrite loop
* expressions: Encode expressions with type ID >= 128 correctly
* arithmetic: Add space around `mod` and `rem` in rendering
* graph: Do not add parentheses for `X*(Y/Z)`
* functions: Make percentage operations binary functions
* functions: Turn `min` and `max` into algebraic functions
* cycle: For expressions, cycle graphic/text rendering correctly
* menus: Replace `EquationsMenu` with `ExpressionMenu` in other menus
* ui: Insert space when inserting array inside function

**Improvements**

* menus: Updates to `PolynomialMenu` to enter polynomials and for conversions
* menus: Add product and sum to symbolic and algebra menus
* menus: Make `ToolsMenu` select `SymbolicMenu` for symbols
* expressions: Reorganize the code for rewrites
* rewrites: Add recorders for rewrites that are actually done
* tests: Some adjustments on color images
* rewrites: Convert algebraics into expression as needed
* complex: Parse `3i` and `i3` in addition to `i`
* tests: Add support for more characters
* simulator: Separator color and dm32 support
* graph: Add space when rendering simple function
* keyboard: Updated SVG files with latest menu labeling changes

Signed-off-by: Christophe de Dinechin <christophe@dinechin.org>
2024-05-04 23:25:58 +02:00
Christophe de Dinechin
1b28f6d67d symbols: Support case-sensitive symbol matching
Since HP calculators are case-sensitive for symbols, add a setting
`DistinguishSymbolCase` to make symbol-matching case-sensitive.

The default DB48X behaviour is to ignore symbol case, and can be
activated using `IgnoreSymbolCase`

Fixes: #918

Signed-off-by: Christophe de Dinechin <christophe@dinechin.org>
2024-05-04 17:24:23 +02:00
Christophe de Dinechin
b79b40eb8a menu: Add algebra variable operations to AlgebraMenu
Add operations on algebra variables and configuration to `AlgebraMenu`

Also add the corresponding characters to the menus for testing purpose

Signed-off-by: Christophe de Dinechin <christophe@dinechin.org>
2024-05-04 12:11:01 +02:00
Christophe de Dinechin
ca7a180984 polynomials: Add tests for Euclidean division
Add a couple of tests for Euclidean division and remainder.
2024-05-04 01:27:36 +02:00
Christophe de Dinechin
160cfbe2d1 polynomials: Special case of empty polynomials
When subtracting a polynomial from another one with same value, we end
up with an empty polynomial, and we need to special-case this.

Signed-off-by: Christophe de Dinechin <christophe@dinechin.org>
2024-05-04 01:16:02 +02:00
Christophe de Dinechin
ef600c485c polynomials: Add basic tests
Add some basic testing for polynomials

Signed-off-by: Christophe de Dinechin <christophe@dinechin.org>
2024-05-04 00:33:24 +02:00
Christophe de Dinechin
6439d25a56 polynomials: Avoid type errors converting to polynomial
The calls to `is_one` were using the implicit argument `true` that
caused them to emit incorrect type errors.

Signed-off-by: Christophe de Dinechin <christophe@dinechin.org>
2024-05-03 23:50:49 +02:00
Christophe de Dinechin
593e6a41e6 menu: Update PolynomialMenu
Add `ToPolynomial` to the menu
Replace `sqrt` and `cbrt` with `sq` and `cubed`

Signed-off-by: Christophe de Dinechin <christophe@dinechin.org>
2024-05-03 23:49:49 +02:00
Christophe de Dinechin
791c814cf3 editor: Fix problem with EXIT key while searching
We were not correctly clearing the `searching` flag in `clear_error`,
and as a result we were stuck in search mode even when the editor was
not active.

Fixes: #917

Signed-off-by: Christophe de Dinechin <christophe@dinechin.org>
2024-05-03 23:12:39 +02:00
Christophe de Dinechin
3bf64805e3 complex: Avoid emitting syntax errors while parsing
While parsing complex numbers, we were emitting actual syntax errors
instead of deferring them by returning `WARN`.

Signed-off-by: Christophe de Dinechin <christophe@dinechin.org>
2024-05-03 22:52:22 +02:00
Christophe de Dinechin
7eaafbf683 polynomial: Put polynomial-specific rendering in final form
We were temporarily using an inverted form to identify polynomials.
Replace it with final version, which is to not display anything by
default, unless either editing or setting the `PrefixPolynomialRender`
setting, which causes a `[poly]` to show up before polynomials on the
stack as well.

Signed-off-by: Christophe de Dinechin <christophe@dinechin.org>
2024-05-03 22:50:24 +02:00
Christophe de Dinechin
e7c29190e2 menu: Add a way to enter polynomials on the command line
Add menu entry to be able to edit polynomials directly

Signed-off-by: Christophe de Dinechin <christophe@dinechin.org>
2024-05-02 17:42:59 +02:00
Christophe de Dinechin
5326fc0a4e polynomial: Add rendering and editing
Add rendering and editing of polynomials.

On the command line, a polynommial is identified by a prefix `Ⓟ`
(which displays as `[poly]` inverted).

Signed-off-by: Christophe de Dinechin <christophe@dinechin.org>
2024-05-02 17:39:57 +02:00
Christophe de Dinechin
a4062a4cd6 polynomial: Deal with squares and cubes correctly
Deal with square and cubes of polynomials, as well as when converting
from expression to polynomial.

Signed-off-by: Christophe de Dinechin <christophe@dinechin.org>
2024-05-02 13:55:10 +02:00
Christophe de Dinechin
2988adc531 polynomial: Add dedicated error for invalid polynomial
Use a dedicated error rather than return a type error
(which it is not)

Signed-off-by: Christophe de Dinechin <christophe@dinechin.org>
2024-05-02 13:54:14 +02:00
Christophe de Dinechin
453ca38437 polynomial: Render X^3-1 correctly
We optimize `1` away in general, but we should not if all exponents
are 0, meaning we have a constant 1 we need to show.

Signed-off-by: Christophe de Dinechin <christophe@dinechin.org>
2024-05-02 01:30:16 +02:00
Christophe de Dinechin
2e246e34cb polynomial: Add polynomial division
Implement polynomial euclidean division, which gives a meaning to
divide and remainder for polynomials.

Polynomial division is only well-defined with a single variable.
On HP calculators, this is configured by the `VX` variable in the
`CASDIR` directory. A similar mechanism is provided allowing the
creation of an algebraic configuration directory.

Signed-off-by: Christophe de Dinechin <christophe@dinechin.org>
2024-05-02 01:30:16 +02:00
Christophe de Dinechin
bf6516aa5a polynomials: Optimize cross terms
When multiplying `(A-B)` by `(A+B)` polynomials, the cross-terms
cancel out and should be correctly accounted for.

Signed-off-by: Christophe de Dinechin <christophe@dinechin.org>
2024-05-01 19:17:07 +02:00
Christophe de Dinechin
9e3c356d0f menus: Add product and sum to symbolic and algebra menus
Add the `sum` and `product` functions to relevant menu entries, now
that they are implemented.

Signed-off-by: Christophe de Dinechin <christophe@dinechin.org>
2024-05-01 19:17:06 +02:00
Christophe de Dinechin
b09a6444b2 polynomials: Fix one case where we incorrectly return nullptr
There was one scenario where we would incorrectly return a nullptr,
which manifested as the polynomial rendering as text (or as an error
when using `Show`).
2024-05-01 19:17:06 +02:00
Christophe de Dinechin
d290f88736 polynomial: Render negative factors with a - sign
Instead of rendering as `A+-3*X`, render as `A-3*X`.

Signed-off-by: Christophe de Dinechin <christophe@dinechin.org>
2024-05-01 19:17:06 +02:00
Christophe de Dinechin
375d220580 polynomial: Correctly return nullptr from graph when oversized
When we have an oversized graphic rendering, this was incorrectly
interpreted as the beginning of a sum, so we were only doing a partial
render instead of falling back to text-only rendering.

Signed-off-by: Christophe de Dinechin <christophe@dinechin.org>
2024-05-01 19:17:06 +02:00
Christophe de Dinechin
3a473ab64d polynomial: Small optimization for exponentiation
Exponentiation with a constant arithmetic does not need to go through
arithmetic.

Signed-off-by: Christophe de Dinechin <christophe@dinechin.org>
2024-05-01 19:17:06 +02:00
Christophe de Dinechin
7395eb8ac2 polynomial: Render inverted if InvertedPolynomialRender is set
This is an easy way to detect if a portion of an equation is a
polynomial.

Signed-off-by: Christophe de Dinechin <christophe@dinechin.org>
2024-05-01 19:17:06 +02:00
Christophe de Dinechin
1c38881e21 polynomial: Fix order of argument in binary operations
Binary operations had arguments swapped

Signed-off-by: Christophe de Dinechin <christophe@dinechin.org>
2024-05-01 19:17:06 +02:00
Christophe de Dinechin
6340ee70a4 polynomial: Do not render a factor of 1
When rendering `1·X`, render it as just `X`

Signed-off-by: Christophe de Dinechin <christophe@dinechin.org>
2024-05-01 19:17:06 +02:00
Christophe de Dinechin
184909c1e0 arithmetic: Connect arithmetic operations to polynomials
Connect the basic four operations to arithmetic.

Signed-off-by: Christophe de Dinechin <christophe@dinechin.org>
2024-05-01 19:17:06 +02:00
Christophe de Dinechin
2ac90faca7 polynomial: Keep existing polynomials in polynomial::make
No need to do any kind of expensive work if we already have what we
want.

Signed-off-by: Christophe de Dinechin <christophe@dinechin.org>
2024-04-29 20:42:39 +02:00
Christophe de Dinechin
89c3addb7a menu: Make ToolsMenu select SymbolicMenu for symbols
When parsing, we never generate naked symbols, they are always wrapped
in expressions. However, it's legitimate to have one on the stack, and
in that case, we should use the `SymbolicMenu`.

Signed-off-by: Christophe de Dinechin <christophe@dinechin.org>
2024-04-29 20:42:38 +02:00
Christophe de Dinechin
19bef01b06 polynomials: Add polynomials to symbolic items
This allows functions to take polynomials as arguments

Signed-off-by: Christophe de Dinechin <christophe@dinechin.org>
2024-04-29 20:42:38 +02:00
Christophe de Dinechin
d8c448a11b polynomial: Factor out the code converting algebraics to polynomials
Move the code in `ToPolynomial` into `polynomial::make`.

Signed-off-by: Christophe de Dinechin <christophe@dinechin.org>
2024-04-29 20:42:38 +02:00
Christophe de Dinechin
93ed90fad3 polynomials: Add FromPolynomials
Add conversion from polynomials to expression.

Signed-off-by: Christophe de Dinechin <christophe@dinechin.org>
2024-04-29 20:42:38 +02:00
Christophe de Dinechin
a8d6edc07e polynomials: Add code to identify numerical constants
In polynomials, we only want complex values with real arguments.

Signed-off-by: Christophe de Dinechin <christophe@dinechin.org>
2024-04-29 20:42:38 +02:00
Christophe de Dinechin
4f3dc0794b polynomials: Add ToPolynomial function
Add a function to convert an expression to a polynomial

Signed-off-by: Christophe de Dinechin <christophe@dinechin.org>
2024-04-29 20:42:38 +02:00
Christophe de Dinechin
fc1b2ea75c polynomials: Implement add, sub, mul, and skeleton for div/mod
Basic, and yet untested operations on polynomials.

Signed-off-by: Christophe de Dinechin <christophe@dinechin.org>
2024-04-29 20:42:38 +02:00
Christophe de Dinechin
b05453ad25 polynomials: Add support for polynomials as a separate type
Enough algorithms need a separate notion of polynomials.
Devise a space-efficient representation for them.

Signed-off-by: Christophe de Dinechin <christophe@dinechin.org>
2024-04-29 20:42:38 +02:00
Christophe de Dinechin
86a2d5ae18 expressions: Reorganize the code for rewrites
Add new types for wildcards, including testing for names,
zero vs. non-zero integers, etc.

The rewritten expand and collect are not better than before,
we need to connect them to polynomials first.

Signed-off-by: Christophe de Dinechin <christophe@dinechin.org>
2024-04-29 20:42:38 +02:00
Christophe de Dinechin
a298599a53 rewrites: Avoid garbage collection problem
Use GC pointers inside `match` because garbage collection can be
triggered by evaluation of operations when `compute` is set.

Also enable `u`, `v`, `w` wildcards to sort non-names.

Signed-off-by: Christophe de Dinechin <christophe@dinechin.org>
2024-04-24 15:08:13 +02:00
Christophe de Dinechin
8f57103432 rewrites: Add recorders for rewrites that are actually done
By enabling `-trewrites_done`, you only see the rewrites that are
successful, which is much less noisy.

Signed-off-by: Christophe de Dinechin <christophe@dinechin.org>
2024-04-24 15:05:27 +02:00
Christophe de Dinechin
02ab72495c rewrites: Disable auto-simplification during rewrites
If we explicitly write a rule like `sq(x)` -> `x*x`, we don't want
auto-simplification to give us `sq(x)` back, otherwise we are going to
loop forever without making forward progress.

Signed-off-by: Christophe de Dinechin <christophe@dinechin.org>
2024-04-24 15:03:16 +02:00
Christophe de Dinechin
4b1d47fc89 rewrites: Make sure rewrites work with ExplicitWildcards
The internal rules do not have explicit wildcards.

Fixes: #913

Signed-off-by: Christophe de Dinechin <christophe@dinechin.org>
2024-04-24 00:37:40 +02:00
Christophe de Dinechin
9a0b051f7e rewrites: Add rules to expand powers
Add rules to expand `A^(B+C)` and (A*B)^C`.

Signed-off-by: Christophe de Dinechin <christophe@dinechin.org>
2024-04-24 00:37:08 +02:00
Christophe de Dinechin
8d2cf8272c rewrites: Factor out rewrite loop
Factor out the many variants of rewrite loop for multiple expressions,
in order to be able to introduce conditionals in rewrite sequences.

Signed-off-by: Christophe de Dinechin <christophe@dinechin.org>
2024-04-24 00:24:08 +02:00
Christophe de Dinechin
0811b471a7 expressions: Encode expressions with type ID >= 128 correctly
When we are building an equation that has a type that does not fit in
one byte, like `cbrt`, we now use `std::conditional` to automatically
select a two-byte encoding for the expression.

Fixes: #916

Signed-off-by: Christophe de Dinechin <christophe@dinechin.org>
2024-04-23 22:06:34 +02:00
Christophe de Dinechin
ffa6948022 tests: Some adjustments on color images
The color of the bar on the left was changed. Adjust test files.

Signed-off-by: Christophe de Dinechin <christophe@dinechin.org>
2024-04-23 20:40:40 +02:00
Christophe de Dinechin
3d6d470ea1 rewrites: Add ExplicitWildcards flag
The `ExplicitWildcards` flag requires a `&` sign at the beginning of
wilcards like on HP calculators. When the flag is clear, variable
names in patterns are wildcards by default.

Fixes: #913

Signed-off-by: Christophe de Dinechin <christophe@dinechin.org>
2024-04-22 23:31:54 +02:00
Christophe de Dinechin
31b867816b rewrites: Add support for conditions
Add support for conditions in rewrites (match)

Fixes: #914

Signed-off-by: Christophe de Dinechin <christophe@dinechin.org>
2024-04-22 22:48:14 +02:00
Christophe de Dinechin
caf5bfd46c flags: Purge should reset system flags
When purging a named flag, update its value instead of reading it.

Fixes: #915

Signed-off-by: Christophe de Dinechin <christophe@dinechin.org>
2024-04-22 20:59:49 +02:00
Christophe de Dinechin
48e3e3bb98 rewrites: Enhance ↓Match and ↑Match to return number of changes
The result of `↓Match` and `↑Match` on HP calculators is `0` for no
rewrites, or `1` if a replacement occured.

However, it's possible (rarely) for more than one rewrite to occur
even on HP (it's difficult because the algorithm appears to be
single-pass). DB48X can perform multiple rewrites on the same
expression, so it makes sense to enhance `↓Match` and `↑Match` to
return the number of replacements performed. This can still be used as
a test.

Also document the differences in terms of pattern.

Fixes: #912

Signed-off-by: Christophe de Dinechin <christophe@dinechin.org>
2024-04-22 19:06:10 +02:00
Christophe de Dinechin
e255f044fe rewrites: Convert algebraics into expression as needed
In order to be able to run the example page 3-142 of the HP50G
advanced reference manual, which applies `↓Match` to a decimal number,
we need to transparently convert all the non-expression algebraic
values to expressions.

Fixes: #910

Signed-off-by: Christophe de Dinechin <christophe@dinechin.org>
2024-04-22 00:51:30 +02:00