Commit graph

82 commits

Author SHA1 Message Date
Christophe de Dinechin
4331d7a623 Implement xroot operation
The `xroot` operation is equivalent to raising to the inverse power.

Fixes: #276

Signed-off-by: Christophe de Dinechin <christophe@dinechin.org>
2023-08-07 23:58:27 +02:00
Christophe de Dinechin
486f425dde Implement directories
Implement `crdir`, `updir`, `pgdir`, as well as per-directory lookup

Fixes: #298

Signed-off-by: Christophe de Dinechin <christophe@dinechin.org>
2023-08-07 23:58:27 +02:00
Christophe de Dinechin
59c4ef6057 Implement the disp command
Implement the `disp` command, with variants for font changes, etc.

Fixes: #296

Signed-off-by: Christophe de Dinechin <christophe@dinechin.org>
2023-08-07 23:58:27 +02:00
Christophe de Dinechin
32da9114ae font: Restore missing glyphs for hypot and atan2
The `hypot` and `atan2` operators have dedicated glyphs.
Somehow, these glyphs were lost in the last font update.
Restored from eariler version.

Fixes: #295

Signed-off-by: Christophe de Dinechin <christophe@dinechin.org>
2023-08-07 23:58:27 +02:00
Christophe de Dinechin
06b4ac3020 font: Add the glyph for the ⇄ sign
Add missing glyph for the `⇄` sign, which is to be used for
a few upcoming functions.

Signed-off-by: Christophe de Dinechin <christophe@dinechin.org>
Suggested-by: Jeff Roetman
2023-08-07 23:58:27 +02:00
Christophe de Dinechin
078563d278 Implement if-then-else and iferr
Implement `if` `then` `else` blocks, as well as the `iferr` variants.

Being able to test `iferr` also required implementing several
secondary error-management commands, like `errm`, `errn` and `doerr`.

Fixes: #290
Fixes: #291

Signed-off-by: Christophe de Dinechin <christophe@dinechin.org>
2023-08-07 23:58:27 +02:00
Christophe de Dinechin
64141d4701 Implement type and typename commands
Implement the `type` command that returns the type of an object as an
integer. No attempt is made to match the return value of `TYPE` on the
HP48. Maybe someday if this has any value.

Add the `typename` which is a portable version of the above, returning
the type name as text.

Fixes: #285

Signed-off-by: Christophe de Dinechin <christophe@dinechin.org>
2023-08-07 23:58:27 +02:00
Christophe de Dinechin
f36dda69dc Implement the bytes command
The `bytes` command on HP calculators returns the size of the object
in the first level of the stack, and the CRC32 (hash) of the object
in the second level fo the stack.

The implememntation here returns the _complete_ representation of the
object in level 2. Also, the size is always an integral number of
bytes (the Saturn-based calculators were 4-bit, so byte sizes could be
half integer)

The lowest part of the number matches the result of the `type` command.

Fixes: #284

Signed-off-by: Christophe de Dinechin <christophe@dinechin.org>
2023-08-07 23:58:27 +02:00
Christophe de Dinechin
57c273b531 Implement →Num and →Q
Following several requests from various users, implement `→Num`
(converting numbers to decimal representation) and its counterpart,
`→Q` (converting numbers to fractions), including the special cases
for pi and i.

Fixes: #255
Fixes: #282

Signed-off-by: Christophe de Dinechin <christophe@dinechin.org>
2023-08-07 23:58:27 +02:00
Christophe de Dinechin
de08b3060a Remove the fixed-base base numbers
The fixed-base based numbers are not that useful in practice, so
putting that under `CONFIG_FIXED_BASED_OBJECTS`. This can be
reactivated easily if we need it.

Fixes: #274

Signed-off-by: Christophe de Dinechin <christophe@dinechin.org>
2023-08-01 14:02:03 +02:00
Christophe de Dinechin
9a47650ca9 Add expand, collect and simplify functions
Add the basic rules for `expand`, `collect` and `simplify`.

And to be honest, I am quite proud of the fact that the core code looks
_exactly_ like this (this is actual code):

```c++
    return rewrite((x+y)*z,     x*z+y*z,
                   x*(y+z),     x*y+x*z,
                   (x-y)*z,     x*z-y*z,
                   x*(y-z),     x*y-x*z);
```

A lot of template metaprogramming to turn that into transparent
building of _compile-time constants_ representing the RPL objects for
the equations, and passing that to the `rewrite` function that was
implemented earlier.

What is really neet about this is that the generated equations:

* Are automatically _shared_ if used multiple times, because they are
  represented by the same template. So the equations used in `collect`
  and those used in `expand` (which are the same in reverse) share the
  same memory.

* Automatically go into QSPI, not consuming precious flash space,
  because they are represented as initialized data arrays, and I
  requested that all C++ .rodata go in QSPI.

I intentionally did not support the historical names
(`expan` and `colct`). Our level of compatibility with the HP48 is
never going to be that good anyway.

The code as is works with `clang`, but runs into unsatisfied symbols
with g++ 10.3 due to what I believe is a g++ bug (that's what living
on the edge of template metaprogramming gives you):

```
/opt/homebrew/Cellar/arm-none-eabi-gcc/10.3-2021.07/gcc/bin/../lib/gcc/arm-none-eabi/10.3.1/../../../../arm-none-eabi/bin/ld: build/release/equation.o: in function `equation::collect() const':
equation.cc:(.text._ZNK8equation7collectEv+0xd0): undefined reference to `eq<(unsigned char)10, (unsigned char)1, (unsigned char)120, (unsigned char)10, (unsigned char)1, (unsigned char)122, (unsigned char)57, (unsigned char)10, (unsigned char)1, (unsigned char)121, (unsigned char)10, (unsigned char)1, (unsigned char)122, (unsigned char)57, (unsigned char)55>::object_data'
```

Fixes: #231

Signed-off-by: Christophe de Dinechin <christophe@dinechin.org>
2023-07-29 20:59:28 +02:00
Christophe de Dinechin
4cd7dc9ab7 Add limits for size of numbers and number of rewrites
Add explicit limits for the number of rewrites and the maximum size
for big numbers.

Fixes: #214

Signed-off-by: Christophe de Dinechin <christophe@dinechin.org>
2023-07-27 16:49:50 +02:00
Christophe de Dinechin
e082e2140b equations: Implement equation rewrite engine
Implement a general equation rewrite engine that we can use
to implement a variety of computer-algebra features.

Fixes: #203

Signed-off-by: Christophe de Dinechin <christophe@dinechin.org>
2023-07-26 09:03:19 +02:00
Christophe de Dinechin
488bec73a6 arithmetic: Simplifications in basic operations
In order to accelerate processing, it is desirable to simplify
symbolic expressions as we build them. This will minimize memory usage
and processing time, notably for symbolic matrices.

Note that the implementation carefully avoids non-numeric values,
for example to make sure that `{ 1 2 3 } 0 +` is not "simplified".

Fixes #197

Signed-off-by: Christophe de Dinechin <christophe@dinechin.org>
2023-07-25 19:18:57 +02:00
Christophe de Dinechin
16b8d99a13 det: Implement determinant on square matrices
General algorithm to compute the determinant

Compute the determinant by diagonalizing the matrix.
All computations are done in a way that will be conducive to getting
the correct result with integers or fractions. This is a step towards
implementing matrix invert and division.

The algorithm used is somewhat inspired from [this source][det], but
adapted for the RPL implementation in DB48X. Specifically, the matrix
is "exploded" to the stack by the `is_matrix()` function, which
returns the size of the matrix and puts all elements on the stack if
successful. The stack is then used as an array of value during the
various manipulations. Note that in the case of `det`, we can use a
single array, but that this technique can be extended to have multiple
arrays, which will be necessary for the division.

[det]:v https://www.geeksforgeeks.org/determinant-of-a-matrix

Fixes: #187

Signed-off-by: Christophe de Dinechin <christophe@dinechin.org>
2023-07-25 18:37:38 +02:00
Christophe de Dinechin
976b04caf1 Implement GET function
Implement the `GET` function on list, arrays and text.

Getting a character from a text value is a DB48X extension, which I
thought was in newRPL based on documentation, but experiments show
that does not work at the moment.

Getting an element from a two-dimensional array is not going to work
the same as for RPL, and I wonder if I _want_ to make it work the
same. In traditional RPL, `[ [1 2 3] [4 5 6] ] 1 GET` gives you
`1`. In the DB48X implementation, it gives `[1 2 3]`. I think that
being able to extract vectors from a matrix is useful, and the ability
to extract an individual element using a list index should address
that problem.

Not yet implemented:
- `GET` with a list index for matrices
- `GET` with a name (dereferencing the name)

Fixes: #173

Signed-off-by: Christophe de Dinechin <christophe@dinechin.org>
2023-07-22 18:23:51 +02:00
Christophe de Dinechin
a75042eada menus: Implement the LastMenu feature
The `LastMenu` feature makes it possible to go back one menu

Fixes: #165

Signed-off-by: Christophe de Dinechin <christophe@dinechin.org>
2023-07-22 01:22:14 +02:00
Christophe de Dinechin
a091db6d39 Implement contextual Tool menu and contextual help
Implement a context-sensitive `ToolsMenu`, bound to the `Σ+` key.
This menu looks at the stack to attempt to figure out the relevant menu.

Implement a context-sensitive `Help` function on the same principle.

Also fixes a bug in the way the help file was closed.

Fixes: #127 (Tools key)
Fixes: #162 (Help command)

Signed-off-by: Christophe de Dinechin <christophe@dinechin.org>
2023-07-21 18:20:38 +02:00
Christophe de Dinechin
1444a8adb6 complex: Render polar argument with explicit angle unit
Add an explicit unit to rendering of polar complex number argument,
e.g. show `1∡90°` instead of just `1∡90`.

Fixes: #161

Signed-off-by: Christophe de Dinechin <christophe@dinechin.org>
2023-07-21 13:42:58 +02:00
Christophe de Dinechin
b23abb0fac Respect angle settings in trigonometric functions
Functions `sin`, `cos`, `tan`, `asin`, `acos`, `atan` and `atan2`
respect angle settings.

Parsing and rendering of polar angles respects that setting, but
that makes the internally-stored angle component setting dependent
(and it is not correctly updated when changing settings)

Fixes: #119

Signed-off-by: Christophe de Dinechin <christophe@dinechin.org>
2023-07-18 13:50:21 +02:00
Christophe de Dinechin
aac1bf89f5 Add command for pi
Add a command for pi. This inserts itself in equations for the moment.
Until we have a setting for numerical approximations, we will remain
with a symbolic value.

Fixes: #143

Signed-off-by: Christophe de Dinechin <christophe@dinechin.org>
2023-07-18 12:56:34 +02:00
Christophe de Dinechin
df4de41012 complex: Add ancilary functions
Add various ancilary functions for complex management, like conversions
from real to complex, extraction of real and imaginary part, etc.

Also add the factorial function

Fixes: #134
Fixes: #135

Signed-off-by: Christophe de Dinechin <christophe@dinechin.org>
2023-07-18 00:48:10 +02:00
Christophe de Dinechin
f9e4e726a8 Add the sign function
This is necessary to correctly express the complex square root

Signed-off-by: Christophe de Dinechin <christophe@dinechin.org>
2023-07-16 16:25:06 +02:00
Christophe de Dinechin
5d862b1ae5 Represent hypot and atan2 using special characters
This makes symbolic expressions that use them more readable, notably
as a result of symbolic evaluation for complex numbers

Signed-off-by: Christophe de Dinechin <christophe@dinechin.org>
2023-07-15 23:34:57 +02:00
Christophe de Dinechin
b1686374f8 fonts: Add some missing characters to the font
Add glyphs for ⅉ, ℎ (Planck's constant), ℏ (reduced Planck constant),
ℝ (will be useful for some menu entries), ℚ (same).

I'm still looking for the best place to take a k for quaternions.
The mathematical k is out of range (out of the 16-bit range I'd rather stay in)

Signed-off-by: Christophe de Dinechin <christophe@dinechin.org>
2023-07-15 16:06:04 +02:00
Christophe de Dinechin
25a970eee0 complex: Implement imaginary constant
Implement the complex unity as a standalone command.

Fixes: #130

Signed-off-by: Christophe de Dinechin <christophe@dinechin.org>
2023-07-13 23:57:29 +02:00
Christophe de Dinechin
4ae830002e complex: Implement parser for polar and rectangular
Implement a parser for polar and rectangular types.

Also added missing glyphs for ⅈ (used as complex number separator) and ℂ
(used already in some complex menus), and reorganize menus a bit to match
latest thinking in terms of layout.

Fixes: #15

Signed-off-by: Christophe de Dinechin <christophe@dinechin.org>
2023-07-13 23:49:36 +02:00
Christophe de Dinechin
4219575de3 Implement xshift-EXIT as state save
This makes it possible to quickly save the sate of the calculator.
This is the meaning of the 'SAVE' labeling on the proposed keyboard layout.

Fixes: #113

Signed-off-by: Christophe de Dinechin <christophe@dinechin.org>
2023-07-12 22:38:54 +02:00
Christophe de Dinechin
ae90444e08 Implement →List (ToList)
Implement the `→List` command, which will be helpful
to implement Unto

Signed-off-by: Christophe de Dinechin <christophe@dinechin.org>
2023-07-03 19:19:01 +02:00
Christophe de Dinechin
81e892a2de Implement the 'same' function
On the HP-48, `same` compares objects without evaluating names,
whereas `==` follows names. Note that DB48X adds `=` which tests
for equality rather than identity.

Signed-off-by: Christophe de Dinechin <christophe@dinechin.org>
2023-07-03 19:19:01 +02:00
Christophe de Dinechin
22befc1a3a Local variables
Block with local variables, e.g. `→ X Y « X Y - X Y + * »`

Local values reside above the stack. They are referenced by an index,
which makes them very efficient (there is no name lookup). Reading
or storing in a local variable is as efficient as accessing the stack.
This is much faster than global variables, which require a rather slow
linear name lookup and, when storing, moving the directory object.

Implements #54

Signed-off-by: Christophe de Dinechin <christophe@dinechin.org>
2023-07-03 19:19:01 +02:00
Christophe de Dinechin
47b9fe0281 Add Version command, built from git version
Fetch the version number directly from git.
Add the `Version` command with version information.

Signed-off-by: Christophe de Dinechin <christophe@dinechin.org>
2023-07-01 09:32:52 +02:00
Christophe de Dinechin
dbd9bd4738 Add PowerOff and SystemSetup commands
The `PowerOff` command shuts down the system.
The `SystemSetup` command displays the system setup menu

Signed-off-by: Christophe de Dinechin <christophe@dinechin.org>
2023-06-30 21:55:22 +02:00
Christophe de Dinechin
576b7adce2 Allow rendering of large numbers with spacing
Allow a multiplicity of spacing options:
* Using thin space, e.g. `1 000 000.000 00`
* Using a comma or a dot, opposite of decimal mark, e.g. `1.000.000,000.00`
* Using a tick mark, e.g. `1'000'000,000'00`
* Using an underscore, e.g. `1_000_000,000_00`

Also allows different spacing for normal and based numbers, and for
mantissa and fractional part.

Fixes #59

Signed-off-by: Christophe de Dinechin <christophe@dinechin.org>
2023-06-29 23:43:26 +02:00
Christophe de Dinechin
564b66ec2a Settings for font selection
Make it possible to select the font to display:

* The result (first level of the stack)
* The stack (higher levels of the stack)
* The editor (when editing one or two lines)
* THe multi-line editor (when editing more than two lines)

Signed-off-by: Christophe de Dinechin <christophe@dinechin.org>
2023-06-28 17:26:48 +02:00
Christophe de Dinechin
1ee7dbe10f Binary computations in arbitrary bases
When using the a specific suffix, e.g. `#1234Ah`, you force the base of the
object to be hexadecimal. It does not change even if you change it on display.

When not using a specific suffix, e.g. `#1234A`, the current base setting is
used, and the display changes when the `Base` setting is changed.

Fixes #18

Signed-off-by: Christophe de Dinechin <christophe@dinechin.org>
2023-06-28 07:50:00 +02:00
Christophe de Dinechin
9b0a36296e Reorganization of settings
Centralize the functions saving all the settings in a single
`Modes` function.

Add settings for word-size and base.

Signed-off-by: Christophe de Dinechin <christophe@dinechin.org>
2023-06-27 21:09:14 +02:00
Christophe de Dinechin
fc2391f0d4 Add NonSciRange command to control switch-over to sci mode
The NonSciRange command controls when the display switches from
standard to scientific notation.

Signed-off-by: Christophe de Dinechin <christophe@dinechin.org>
2023-06-27 18:09:47 +02:00
Christophe de Dinechin
5e2ccbc045 Change the glyph for mathematical power of 10
Change from something that looks like a E to something that looks
like a small x10.

Signed-off-by: Christophe de Dinechin <christophe@dinechin.org>
2023-06-27 18:08:39 +02:00
Christophe de Dinechin
96bcd3af32 Attempt to build a QSPI image that is compatible with DM42 program
The idea is to keep the same symbols that the DM42 software uses in
a compatible location, to make it possible to alternatively load the
DM42 and DB48X program.

This seems to work relatively well, but there is a strange behavior
from the DM42 program that complains about being unable to open
the STATE directory of the calculator. It is possible that it is
confused by the presence of .48S files there.

Signed-off-by: Christophe de Dinechin <christophe@dinechin.org>
2023-06-25 21:18:11 +02:00
Christophe de Dinechin
7444ed5467 Seriously reworked the rendering of decimal numbers
The existing code was really hard to read and maintain. I could not get FIX to
really work the way it's supposed to be, so restarted from the ground up.

While I was thinking about this, added the `SIG` mode for display, which
displays significant digits. I remember some other calculator having that, and
it's neat. It's like `STD`, but with a given precision.

Signed-off-by: Christophe de Dinechin <christophe@dinechin.org>
2023-06-25 19:52:12 +02:00
Christophe de Dinechin
bd22b47a30 Implement commands for various settings
Implement RPL commands to manipulate various settings:
- Display mode (STD, FIX, SCI, ENG)
- Angle mode (DEG, RAD, GRAD)
- Decimal separator (dot or comma)
- Command display (lowercase, uppercase, capitalized or long-form)

Signed-off-by: Christophe de Dinechin <christophe@dinechin.org>
2023-06-24 14:55:29 +02:00
Christophe de Dinechin
1831d93826 Directory parsing and rendering
This will allow us to export and parse a variable that contains directories and
subdirectories.

Signed-off-by: Christophe de Dinechin <christophe@dinechin.org>
2023-06-23 16:31:36 +02:00
Christophe de Dinechin
512e20e503 Move fonts to QSPI
This saves a bit of space for the more interesting parts of DB48X

Signed-off-by: Christophe de Dinechin <christophe@dinechin.org>
2023-06-22 16:00:53 +02:00
Christophe de Dinechin
9e8444e6c3 Implement a fraction type for both integer and bignum
Two representations for fractions, one for small value of numerator and
denominator, one when both values are larger.

Signed-off-by: Christophe de Dinechin <christophe@dinechin.org>
2023-06-20 19:06:56 +02:00
Christophe de Dinechin
77bc37c58a Reimplement bignum as a separate type
Having a sized type for bignum is more efficient both at runtime and in terms of
memory usage:

- At runtime, we don't need all the 7-bit masking and modulo-7 arithmetic
- In terms of memory, there is a cross-over at 63 bits, which is almost exactly
  where it becomes uninteresting to do in-CPU arithmetic

Signed-off-by: Christophe de Dinechin <christophe@dinechin.org>
2023-06-19 22:08:33 +02:00
Christophe de Dinechin
7cdf8828e7 Implement rendering of algebraic objects
Render objects like '1+X' as text for now (graphics will be later)

Signed-off-by: Christophe de Dinechin <christophe@dinechin.org>
2023-06-19 22:05:30 +02:00
Christophe de Dinechin
f569566ab4 Added ->Text functionality
... with some preparation to be able to render equations

Signed-off-by: Christophe de Dinechin <christophe@dinechin.org>
2023-06-19 22:05:30 +02:00
Christophe de Dinechin
094eafd126 Implement missing Stack functions
Signed-off-by: Christophe de Dinechin <christophe@dinechin.org>
2023-06-19 22:05:30 +02:00
Christophe de Dinechin
0b771b1993 Add comparison and logic operators
Also add the missing 'abs' function

Signed-off-by: Christophe de Dinechin <christophe@dinechin.org>
2023-06-19 22:05:30 +02:00