mirror of
https://gitlab.com/c3d/db48x.git
synced 2024-09-29 05:36:58 +02:00
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>
This commit is contained in:
parent
7451edfccc
commit
9a47650ca9
9 changed files with 139 additions and 8 deletions
|
@ -7,7 +7,7 @@ extern const unsigned char EditorFont_sparse_font_data[];
|
|||
const unsigned char EditorFont_sparse_font_data[74100] FONT_QSPI =
|
||||
{
|
||||
|
||||
0x81, 0x02, 0xEF, 0xC2, 0x04, 0x36, 0x00, 0x01, 0x00, 0x2C, 0x01, 0x01, 0x00, 0x00, 0x0D, 0x01,
|
||||
0x84, 0x02, 0xEF, 0xC2, 0x04, 0x36, 0x00, 0x01, 0x00, 0x2C, 0x01, 0x01, 0x00, 0x00, 0x0D, 0x01,
|
||||
0x00, 0x2C, 0x01, 0x01, 0x08, 0x00, 0x20, 0x5F, 0x00, 0x2C, 0x01, 0x01, 0x08, 0x00, 0x02, 0x0B,
|
||||
0x05, 0x21, 0x09, 0xEF, 0xBD, 0xF7, 0xDE, 0x7B, 0xEF, 0xBD, 0xF7, 0xDE, 0x7B, 0xEF, 0xBD, 0xF7,
|
||||
0x1E, 0x00, 0x00, 0xB8, 0xFF, 0xFF, 0xFF, 0x0E, 0x03, 0x0B, 0x0B, 0x0F, 0x11, 0x8F, 0x7F, 0xFC,
|
||||
|
|
|
@ -7,7 +7,7 @@ extern const unsigned char HelpFont_sparse_font_data[];
|
|||
const unsigned char HelpFont_sparse_font_data[15113] FONT_QSPI =
|
||||
{
|
||||
|
||||
0x81, 0x02, 0x85, 0x76, 0x14, 0x00, 0x01, 0x00, 0x11, 0x01, 0x01, 0x00, 0x00, 0x0D, 0x01, 0x00,
|
||||
0x84, 0x02, 0x85, 0x76, 0x14, 0x00, 0x01, 0x00, 0x11, 0x01, 0x01, 0x00, 0x00, 0x0D, 0x01, 0x00,
|
||||
0x11, 0x01, 0x01, 0x03, 0x00, 0x20, 0x5F, 0x00, 0x11, 0x01, 0x01, 0x03, 0x00, 0x01, 0x04, 0x02,
|
||||
0x0D, 0x04, 0xFF, 0xFF, 0xF3, 0x03, 0x01, 0x04, 0x04, 0x05, 0x06, 0xFF, 0xFF, 0x0F, 0x01, 0x04,
|
||||
0x08, 0x0D, 0x0A, 0x12, 0x12, 0x14, 0x7F, 0x7F, 0x24, 0x24, 0x24, 0xFE, 0xFE, 0x28, 0x48, 0x48,
|
||||
|
|
|
@ -7,7 +7,7 @@ extern const unsigned char StackFont_sparse_font_data[];
|
|||
const unsigned char StackFont_sparse_font_data[36629] FONT_QSPI =
|
||||
{
|
||||
|
||||
0x81, 0x02, 0x90, 0x9E, 0x02, 0x24, 0x00, 0x01, 0x00, 0x1C, 0x01, 0x01, 0x00, 0x00, 0x0D, 0x01,
|
||||
0x84, 0x02, 0x90, 0x9E, 0x02, 0x24, 0x00, 0x01, 0x00, 0x1C, 0x01, 0x01, 0x00, 0x00, 0x0D, 0x01,
|
||||
0x00, 0x1C, 0x01, 0x01, 0x06, 0x00, 0x20, 0x5F, 0x00, 0x1C, 0x01, 0x01, 0x06, 0x00, 0x02, 0x05,
|
||||
0x03, 0x17, 0x06, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x1F, 0xC0, 0xFF, 0x1F, 0x02, 0x05, 0x08, 0x0A,
|
||||
0x0C, 0xE7, 0xE7, 0xE7, 0xE7, 0xE7, 0xE7, 0xE7, 0xE7, 0xE7, 0xE7, 0x01, 0x05, 0x0E, 0x17, 0x10,
|
||||
|
|
|
@ -701,3 +701,54 @@ COMMAND_BODY(Rewrite)
|
|||
|
||||
return OK;
|
||||
}
|
||||
|
||||
static eq_symbol<'x'> x;
|
||||
static eq_symbol<'y'> y;
|
||||
static eq_symbol<'z'> z;
|
||||
static eq_integer<0> zero;
|
||||
static eq_integer<1> one;
|
||||
static eq_integer<2> two;
|
||||
|
||||
equation_p equation::expand() const
|
||||
// ----------------------------------------------------------------------------
|
||||
// Run various rewrites to expand equation
|
||||
// ----------------------------------------------------------------------------
|
||||
{
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
equation_p equation::collect() const
|
||||
// ----------------------------------------------------------------------------
|
||||
// Run various rewrites to collect terms / factor equation
|
||||
// ----------------------------------------------------------------------------
|
||||
{
|
||||
return rewrite(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, x*(y-z));
|
||||
}
|
||||
|
||||
|
||||
equation_p equation::simplify() const
|
||||
// ----------------------------------------------------------------------------
|
||||
// Run various rewrites to simplify equation
|
||||
// ----------------------------------------------------------------------------
|
||||
{
|
||||
return rewrite(x + zero, x,
|
||||
zero + x, x,
|
||||
x - zero, x,
|
||||
zero - x, x,
|
||||
x * zero, zero,
|
||||
zero * x, zero,
|
||||
x * one, x,
|
||||
one * x, x,
|
||||
x / one, x,
|
||||
x / x, one,
|
||||
one / x, inv(x),
|
||||
x * x * x, cubed(x),
|
||||
x * x, sq(x));
|
||||
}
|
||||
|
|
|
@ -88,11 +88,34 @@ struct equation : program
|
|||
}
|
||||
|
||||
equation_p rewrite(equation_r from, equation_r to) const;
|
||||
equation_p rewrite(equation_p from, equation_p to) const
|
||||
{
|
||||
return rewrite(equation_g(from), equation_g(to));
|
||||
}
|
||||
|
||||
static equation_p rewrite(equation_r eq, equation_r from, equation_r to)
|
||||
{
|
||||
return eq->rewrite(from, to);
|
||||
}
|
||||
|
||||
template<typename from_eq, typename to_eq>
|
||||
equation_p rewrite(from_eq from, to_eq to) const
|
||||
{
|
||||
return rewrite(from.as_equation(), to.as_equation());
|
||||
}
|
||||
|
||||
template <typename from_eq, typename to_eq, typename ...args>
|
||||
equation_p rewrite(from_eq from, to_eq to, args... rest) const
|
||||
{
|
||||
if (equation_p eq = rewrite(from, to))
|
||||
return eq->rewrite(rest...);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
equation_p expand() const;
|
||||
equation_p collect() const;
|
||||
equation_p simplify() const;
|
||||
|
||||
protected:
|
||||
static symbol_g render(uint depth, int &precedence, bool edit);
|
||||
static symbol_g parentheses(symbol_g what);
|
||||
|
|
|
@ -514,3 +514,51 @@ INSERT_BODY(fact)
|
|||
// We need to pass "x!' because ui.edit() strips the x
|
||||
return ui.edit(utf8("x!"), 2, ui.POSTFIX);
|
||||
}
|
||||
|
||||
|
||||
FUNCTION_BODY(Expand)
|
||||
// ----------------------------------------------------------------------------
|
||||
// Expand equations
|
||||
// ----------------------------------------------------------------------------
|
||||
{
|
||||
if (!x.Safe())
|
||||
return nullptr;
|
||||
if (equation_p eq = x->as<equation>())
|
||||
return algebraic_p(eq->expand());
|
||||
if (x->is_algebraic())
|
||||
return x;
|
||||
rt.type_error();
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
||||
FUNCTION_BODY(Collect)
|
||||
// ----------------------------------------------------------------------------
|
||||
// Collect equations
|
||||
// ----------------------------------------------------------------------------
|
||||
{
|
||||
if (!x.Safe())
|
||||
return nullptr;
|
||||
if (equation_p eq = x->as<equation>())
|
||||
return algebraic_p(eq->collect());
|
||||
if (x->is_algebraic())
|
||||
return x;
|
||||
rt.type_error();
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
||||
FUNCTION_BODY(Simplify)
|
||||
// ----------------------------------------------------------------------------
|
||||
// Simplify equations
|
||||
// ----------------------------------------------------------------------------
|
||||
{
|
||||
if (!x.Safe())
|
||||
return nullptr;
|
||||
if (equation_p eq = x->as<equation>())
|
||||
return algebraic_p(eq->simplify());
|
||||
if (x->is_algebraic())
|
||||
return x;
|
||||
rt.type_error();
|
||||
return nullptr;
|
||||
}
|
||||
|
|
|
@ -194,4 +194,8 @@ FUNCTION(im);
|
|||
FUNCTION(arg);
|
||||
FUNCTION(conj);
|
||||
|
||||
FUNCTION(Expand);
|
||||
FUNCTION(Collect);
|
||||
FUNCTION(Simplify);
|
||||
|
||||
#endif // FUNCTIONS_H
|
||||
|
|
|
@ -236,7 +236,7 @@ CMD(re)
|
|||
CMD(im)
|
||||
CMD(arg)
|
||||
CMD(conj)
|
||||
NAMED(det, "Determinant")
|
||||
NAMED(det, "Determinant") // Last algebraic
|
||||
|
||||
|
||||
|
||||
|
@ -265,6 +265,9 @@ NAMED(ToList, "→List")
|
|||
CMD(Get)
|
||||
|
||||
CMD(Rewrite)
|
||||
CMD(Expand)
|
||||
CMD(Collect)
|
||||
CMD(Simplify)
|
||||
|
||||
NAMED(RealToComplex, "ℝ→ℂ")
|
||||
ALIAS(RealToComplex, "R→C")
|
||||
|
|
10
src/menu.cc
10
src/menu.cc
|
@ -536,12 +536,13 @@ MENU(SymbolicMenu,
|
|||
// ----------------------------------------------------------------------------
|
||||
// Symbolic operations
|
||||
// ----------------------------------------------------------------------------
|
||||
ID_Rewrite,
|
||||
"Collect", ID_Unimplemented,
|
||||
"Expand", ID_Unimplemented,
|
||||
ID_Rewrite,
|
||||
ID_Collect,
|
||||
ID_Expand,
|
||||
ID_Simplify,
|
||||
|
||||
"Isolate", ID_Unimplemented,
|
||||
"Apply", ID_Unimplemented,
|
||||
"Taylor", ID_Unimplemented,
|
||||
|
||||
"Ex/Co", ID_Unimplemented,
|
||||
"→Q", ID_Unimplemented,
|
||||
|
@ -554,6 +555,7 @@ MENU(SymbolicMenu,
|
|||
"∑", ID_Unimplemented,
|
||||
"∏", ID_Unimplemented,
|
||||
"∆", ID_Unimplemented,
|
||||
"Taylor", ID_Unimplemented,
|
||||
|
||||
"Show", ID_Unimplemented,
|
||||
"Quote", ID_Unimplemented,
|
||||
|
|
Loading…
Reference in a new issue