Hello Richard, On Thu, Sep 15, 2011 at 6:31 AM, Michael Kerrisk <mtk.manpages@xxxxxxxxx> wrote: > Hello Richard, > > On Fri, Aug 5, 2011 at 11:34 PM, Richard B. Kreckel <kreckel@xxxxxxxx> wrote: >> Hi everybody, >> >> On 11/27/2010 08:37 AM, Michael Kerrisk wrote: >>> >>> Hi Andries, >>> >>> Since you are the mathematician, can you comment? >>> >>> Thanks, >>> >>> Michael >>> >>> On Fri, Nov 26, 2010 at 9:57 AM, Richard B. Kreckel<kreckel@xxxxxxxx> >>> wrote: >>>> >>>> Hi! >>>> >>>> The man pages for cacos, cacosf, cacosl, catan, catanf, catanl, cacosh, >>>> cacoshf, cacoshl, catanh, catanhf, and catanhl contain wrong maths. >>>> >>>> cacos, cacosf, cacosl: >>>> The formula given in the man page >>>> cacos(z) = -i clog(z + csqrt(z * z - 1)) >>>> gives wrong results in second and fourth quadrant of complex plain. >>>> The formula >>>> cacos(z) = -i clog(z + I*csqrt(1 - z * z)) >>>> gives correct results. >>>> >>>> catan, catanf, catanl: >>>> The formula given in the man page >>>> catan(z) = 1 / 2i clog((1 + iz) / (1 - iz)) >>>> gives wrong results on the negative imaginary axis beginning at -I >>>> (along one of the two branch cuts). Besides, the formula is written >>>> in an ambiguous way. >>>> The formula >>>> catan(z) = (clog(1 + iz) - clog(1 - iz)) / 2i >>>> gives correct results. >>>> >>>> cacosh, cacoshf, cacoshl: >>>> The formula given in the man page >>>> cacosh(z) = (0.5) * clog((1 + z) / (1 - z)) >>>> gives wrong results everywhere in the complex plain. (The formula >>>> seems to be copied from the one for catanh, where it is sometimes >>>> correct.) >>>> The formula >>>> cacosh(z) = 2 * clog(csqrt((z + 1)/2) + csqrt((z - 1)/2)) >>>> gives correct results. >>>> >>>> catanh, catanhf, catanhl: >>>> The formula given in the man page >>>> catanh(z) = 0.5 * clog((1 + z) / (1 - z)) >>>> gives wrong results on the positive real axis beginning at 1 (along >>>> one of the two branch cuts). >>>> The formula >>>> catanh(z) = 0.5 * (clog(1 + z) - clog(1 - z)) >>>> gives correct results. >>>> >>>> I've also checked casin, casinf, casinl, casinh, casinhf, and casinhl and >>>> the formulae given there >>>> casin(z) = -i clog(iz + csqrt(1 - z * z)) >>>> casinh(z) = clog(z + csqrt(z * z + 1)) >>>> are actually correct. >>>> >>>> I suspect that some of these errors are due to somebody trying to >>>> "simplify" >>>> these formulae. Since this can ruin the behavior, I recommend to add a >>>> comment to the upstream sources that warns against attempt of >>>> simplification. >>>> >>>> For the sake of reference, I am looking at manpages-dev 3.25-1 on >>>> Debian/squeeze. >>>> >>>> Bye! >>>> -richy. >>>> -- >>>> Richard B. Kreckel >>>> <http://www.ginac.de/~kreckel/> >> >> This doesn't have seem to have been fixed in the Linux man pages, does it? > > Sorry -- no, not yet. > >> May I suggest a non-mathematical approach to moving forward? >> >> Just write a little C program and compare the complex results of >> a) the library implementation of catan, cacos, etc., >> b) the formula written in the man page, and >> c) the formula I proposed above. >> If you include a couple of values from all four quadrants, you'll see that >> my formula always agrees with the implementation while the one from the man >> page doesn't. > > Now there's a good idea ;-). It would have been even better if you'd > sent me a program--I don't mess round with complex numbers every day > of the week... > >> Is there anything else I can do to convince you that this should be fixed? >> If yes, pretty please, let me know! I would really appreciate getting this >> fixed. > > So, I eventually ironed out my complex math problems and came up with the below: > > === > /* Link with "-lm" */ > > #include <complex.h> > #include <stdlib.h> > #include <unistd.h> > #include <stdio.h> > > > > int > main(int argc, char *argv[]) > { > double complex z, c, f1, f2; > double complex i = I; > > if (argc != 3) { > fprintf(stderr, "Usage: %s <real> <imag>\n"); > exit(EXIT_FAILURE); > } > > z = atof(argv[1]) + atof(argv[2]) * I; > > c = cacos(z); > > printf("cacos() = %6.3f %6.3f*i\n", creal(c), cimag(c)); > > f1 = -i * clog(z + csqrt(z * z - 1)); > f2 = -i * clog(z + i * csqrt(1 - z * z)); > > printf("f1 = %6.3f %6.3f*i\n", creal(f1), cimag(f1)); > printf("f2 = %6.3f %6.3f*i\n", creal(f2), cimag(f2)); > > exit(EXIT_SUCCESS); > } > === > > Some sample runs certainly seem to prove your point for that function at least: > > $ ./cacos 1 1 > cacos() = 0.905 -1.061*i > f1 = 0.905 -1.061*i > f2 = 0.905 -1.061*i > $ ./cacos -1 -1 > cacos() = 2.237 1.061*i > f1 = 2.237 1.061*i > f2 = 2.237 1.061*i > $ ./cacos -1 1 > cacos() = 2.237 -1.061*i > f1 = -2.237 1.061*i > f2 = 2.237 -1.061*i > $ ./cacos 1 -1 > cacos() = 0.905 1.061*i > f1 = -0.905 -1.061*i > f2 = 0.905 1.061*i > > The above is what you meant, right? > > Thanks, > > Michael For man-pages-3.33, I have applied the changes below. They should be consistent with what you proposed (and Andries confirmed). Could you please carefully check... I think it's not so necessary to add a warning to the page source. Nowadays we have version control and logs, so the reasoning should be easy to find. Thanks, Michael diff --git a/man3/cacos.3 b/man3/cacos.3 index b483a0c..1ae6ff5 100644 --- a/man3/cacos.3 +++ b/man3/cacos.3 @@ -27,7 +27,7 @@ is chosen in the interval [0,pi]. One has: .nf - cacos(z) = \-i clog(z + csqrt(z * z \- 1)) + cacos(z) = \-i * clog(z + i * csqrt(1 \- z * z)) .fi .SH VERSIONS These functions first appeared in glibc in version 2.1. diff --git a/man3/cacosh.3 b/man3/cacosh.3 index 7bf60c9..bf3d99b 100644 --- a/man3/cacosh.3 +++ b/man3/cacosh.3 @@ -30,7 +30,7 @@ is chosen nonnegative. One has: .nf - cacosh(z) = (0.5) * clog((1 + z) / (1 \- z)) + cacosh(z) = 2 * clog(csqrt((z + 1) / 2) + csqrt((z \- 1) / 2)) .fi .SH VERSIONS These functions first appeared in glibc in version 2.1. diff --git a/man3/catan.3 b/man3/catan.3 index 30692bb..fe8c39e 100644 --- a/man3/catan.3 +++ b/man3/catan.3 @@ -25,7 +25,7 @@ The real part of y is chosen in the interval [\-pi/2,pi/2]. One has: .nf - catan(z) = 1 / 2i clog((1 + iz) / (1 \- iz)) + catan(z) = (clog(1 + i * z) \- clog(1 \- i * z)) / (2 * i) .fi .SH VERSIONS These functions first appeared in glibc in version 2.1. diff --git a/man3/catanh.3 b/man3/catanh.3 index e396021..4f2f230 100644 --- a/man3/catanh.3 +++ b/man3/catanh.3 @@ -27,7 +27,7 @@ is chosen in the interval [\-pi/2,pi/2]. One has: .nf - catanh(z) = 0.5 * clog((1 + z) / (1 \- z)) + catanh(z) = 0.5 * (clog(1 + z) \- clog(1 \- z)) .fi .SH VERSIONS These functions first appeared in glibc in version 2.1. -- Michael Kerrisk Linux man-pages maintainer; http://www.kernel.org/doc/man-pages/ Author of "The Linux Programming Interface"; http://man7.org/tlpi/ -- To unsubscribe from this list: send the line "unsubscribe linux-man" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html