sinh(acoth(x))

9 views
Skip to first unread message

Qian Yun

unread,
Apr 18, 2026, 7:31:46 AM (4 days ago) Apr 18
to fricas-devel
(1) -> sinh(acoth(x))

1
(1) - ---------
+------+
| 2
\|x - 1

The result is wrong, the sign should be positive.

Same goes for csch(acoth(x)).

The fix is straight forward as bellow, (I'll commit it with
regression test after discussion).

This bug is valid and the fix is correct, right?

I have to say I'm a bit surprised when LLM tells me this is a bug.
I thought it was LLM hallucination. Also it finds the bug by
scanning the file, without invocation of fricas.

- Qian

diff --git a/src/algebra/elemntry.spad b/src/algebra/elemntry.spad
index 44e521c3..6033ed87 100644
--- a/src/algebra/elemntry.spad
+++ b/src/algebra/elemntry.spad
@@ -513,7 +513,7 @@
is?(x, opasinh) => y
is?(x, opacosh) => sqrt(y^2 - 1)
is?(x, opatanh) => y / sqrt(1 - y^2)
- is?(x, opacoth) => - inv sqrt(y^2 - 1)
+ is?(x, opacoth) => inv sqrt(y^2 - 1)
is?(x, opasech) => sqrt(1 - y^2) / y
is?(x, opacsch) => inv y
kernel(opsinh, x)
@@ -568,7 +568,7 @@
is?(x, opasinh) => inv y
is?(x, opacosh) => inv sqrt(y^2 - 1)
is?(x, opatanh) => sqrt(1 - y^2) / y
- is?(x, opacoth) => - sqrt(y^2 - 1)
+ is?(x, opacoth) => sqrt(y^2 - 1)
is?(x, opasech) => y / sqrt(1 - y^2)
is?(x, opacsch) => y
kernel(opcsch, x)

Qian Yun

unread,
Apr 18, 2026, 9:04:51 AM (4 days ago) Apr 18
to fricas-devel
Hmm, for x < -1, the value is negative,

so sinh(acoth(x)) = 1/x/sqrt(1-1/x^2) is more accurate.

But the choice for kernel is not unique then.

- Qian

Waldek Hebisch

unread,
Apr 18, 2026, 11:06:36 AM (4 days ago) Apr 18
to fricas...@googlegroups.com
On Sat, Apr 18, 2026 at 07:31:41PM +0800, Qian Yun wrote:
> (1) -> sinh(acoth(x))
>
> 1
> (1) - ---------
> +------+
> | 2
> \|x - 1
>
> The result is wrong, the sign should be positive.
>
> Same goes for csch(acoth(x)).
>
> The fix is straight forward as bellow, (I'll commit it with
> regression test after discussion).
>
> This bug is valid and the fix is correct, right?

This is clearly problematic. As you noted in next message, if
you consider square root to be positive, then this formula is
good for positive x, while current formula is good for negative
x. Symbolically, sign of square root should be considered as
essentially undetermined. So there are no really good fix.
We could keep current formula, as this allows some simplifications.
We could flip the sign as that also allows simplifications and
people are likely to look more at positive numbers. We could
drop this transformation, that would avoid wrong results, but
would mean that some simplifications are no longer possible.

In general, all similar transforms containing square root are
potentially suspect. That is sometimes composition of
functions really gives effect of square root. But sometimes
such formulas lead to different branching behaviour, maybe
subtly, like different values on branch cuts, maybe worse,
like different branch cuts/taking different branch.

Let me add that interesting symbolic functionality in FriCAS
depends on having differential fields. Strictly speaking,
expressins of this sort are equivalent to having zero
divisiors, which means that we should either refuse to
handle them or need to somehow resolve the problem.

BTW: I have the following patch in my queue "for deeper analysis":

diff --git a/src/algebra/elemntry.spad b/src/algebra/elemntry.spad
index f3ad2e01..fa0a1775 100644
--- a/src/algebra/elemntry.spad
+++ b/src/algebra/elemntry.spad
@@ -343,8 +343,8 @@ ElementaryFunction(R, F) : Exports == Implementation where
is?(x, opasin) => y
is?(x, opacos) => sqrt(1 - y^2)
is?(x, opatan) => y / sqrt(1 + y^2)
- is?(x, opacot) => inv sqrt(1 + y^2)
- is?(x, opasec) => sqrt(y^2 - 1) / y
+ is?(x, opacot) => 1/(y*sqrt(1 + 1/y^2))
+ is?(x, opasec) => sqrt(1 - 1/y^2)
is?(x, opacsc) => inv y
h := inv(2::F)
s2 := h * iisqrt2()


> I have to say I'm a bit surprised when LLM tells me this is a bug.
> I thought it was LLM hallucination. Also it finds the bug by
> scanning the file, without invocation of fricas.

This is area of controversies in all CAS-es. There are traditional
formulas, used in hand calulation in pre-computer era. But
depending on desired branches (which person doing the calulation
was supposed to know) slightly different formula could be used.
And yes, changing sign counts as "slightly different". Such
formulas were used in CAS-es, but when applied blindly can lead
to wrong results. Some things of this sort were cleanded up in
FriCAS, but frankly several availalble functions are rather obscure.
For example, in my country everybody learns about sin, cos and tan
in the school. Math students (and possible earlier) learn about
sinh, cosh and tanh. But I think that it is possible to get math
degree without knowing about coth. And I suspect that vast majority
of math degree holders do not know about sec and asec. Due to
obscurity of those functions testing is limited and plainly wrong
formulas could survive quite long.

> - Qian
>
> diff --git a/src/algebra/elemntry.spad b/src/algebra/elemntry.spad
> index 44e521c3..6033ed87 100644
> --- a/src/algebra/elemntry.spad
> +++ b/src/algebra/elemntry.spad
> @@ -513,7 +513,7 @@
> is?(x, opasinh) => y
> is?(x, opacosh) => sqrt(y^2 - 1)
> is?(x, opatanh) => y / sqrt(1 - y^2)
> - is?(x, opacoth) => - inv sqrt(y^2 - 1)
> + is?(x, opacoth) => inv sqrt(y^2 - 1)
> is?(x, opasech) => sqrt(1 - y^2) / y
> is?(x, opacsch) => inv y
> kernel(opsinh, x)
> @@ -568,7 +568,7 @@
> is?(x, opasinh) => inv y
> is?(x, opacosh) => inv sqrt(y^2 - 1)
> is?(x, opatanh) => sqrt(1 - y^2) / y
> - is?(x, opacoth) => - sqrt(y^2 - 1)
> + is?(x, opacoth) => sqrt(y^2 - 1)
> is?(x, opasech) => y / sqrt(1 - y^2)
> is?(x, opacsch) => y
> kernel(opcsch, x)
>
> --
> You received this message because you are subscribed to the Google Groups "FriCAS - computer algebra system" group.
> To unsubscribe from this group and stop receiving emails from it, send an email to fricas-devel...@googlegroups.com.
> To view this discussion visit https://groups.google.com/d/msgid/fricas-devel/c8a8444c-c8bd-4a2e-b9dc-16f4184bbbf6%40gmail.com.

--
Waldek Hebisch

Qian Yun

unread,
Apr 18, 2026, 6:23:22 PM (4 days ago) Apr 18
to fricas...@googlegroups.com
On 4/18/26 11:06 PM, Waldek Hebisch wrote:
> On Sat, Apr 18, 2026 at 07:31:41PM +0800, Qian Yun wrote:
>> (1) -> sinh(acoth(x))
>>
>> 1
>> (1) - ---------
>> +------+
>> | 2
>> \|x - 1
>>
>> The result is wrong, the sign should be positive.
>>
>> Same goes for csch(acoth(x)).
>>
>> The fix is straight forward as bellow, (I'll commit it with
>> regression test after discussion).
>>
>> This bug is valid and the fix is correct, right?
>
> This is clearly problematic. As you noted in next message, if
> you consider square root to be positive, then this formula is
> good for positive x, while current formula is good for negative
> x. Symbolically, sign of square root should be considered as
> essentially undetermined. So there are no really good fix.
> We could keep current formula, as this allows some simplifications.
> We could flip the sign as that also allows simplifications and
> people are likely to look more at positive numbers. We could
> drop this transformation, that would avoid wrong results, but
> would mean that some simplifications are no longer possible.
>

Yes, simplifications should try to preserve branch cuts.

Current behavior causes numeric evaluation to contradiction
between integer and float,

(2) -> sinh(acoth 2)+0.0

(2) - 0.5773502691_8962576451


(3) -> sinh acoth 2.0

(3) 0.5773502691_8962576451

And furthermore, it affects "draw", as the expression is
simplified before passing to "draw".

If sinh(acoth(x)) = 1/x/sqrt(1-1/x^2) is not satisfying,
then this transformation should be moved to other simplifying
functions instead of happening automatically.

- Qian
Reply all
Reply to author
Forward
0 new messages