From: Robert D. <rob...@gm...> - 2023-08-15 21:46:16
|
On Tue, Aug 15, 2023 at 2:22 PM Jamie Jones via Maxima-discuss <max...@li...> wrote: > I am trying to write a cbrt function that behaves like built-in maxima > functions, but with one difference. By cbrt I mean the cube root of an > expression. The function should be the same as raising an expression > to the (1/3) power, except with the difference that if the argument is > a negative real value, cbrt(x) should return -1 * (-1 * x)^(1/3) , > even with domain:complex and m1pbranch:true This is neatly implemented by simplification rules. I'll write the rules using tellsimpafter -- this means the new rules are applied after existing ones. /* most narrow special case: cbrt of negative real */ matchdeclare (xx, lambda ([e], numberp(e) and sign(e) = 'neg)); tellsimpafter (cbrt (xx), -1 * (-1 * xx)^(1/3)); /* broader special case */ matchdeclare (yy, numberp); /* could also say matchdeclare (yy, all) to catch everything */ tellsimpafter (cbrt (yy), yy^(1/3)); [cbrt(-8), cbrt(8), cbrt(1/8), cbrt(-1/8)]; => [ -2, 2, 1/2, -1/2 ]; cbrt(x^3); => cbrt(x^3) subst (x = -2, %); => -2 tellsimpafter rules are processed in the order in which they're defined, so declare the rules in order of increasing generality, i.e., more narrow cases before more general cases. (tellsimp rules go in the opposite order, from most general to most specific.) For the two rules defined above, only literal numbers (including rationals) are matched -- anything else isn't simplified. Of course, if you want to change the scope of a rule or define additional cases, that's all possible too. Hope this helps, Robert |