Skip to content
Prev 35319 / 63424 Next

RFC: lchoose() vs lfactorial() etc

On Tue, Dec 15, 2009 at 09:49:28AM +0100, Martin Maechler wrote:
I do not have a strong opinion, whether lchoose() should be log(choose(.,.))
or log(abs(choose(.,.))), although i would slightly prefere the latter (with abs()).
One of the reasons is that this would simplify the code of the function
lchoose() in src/nmath/choose.c. It produces the NA by explicit testing
the sign, so this test could be simply removed.

Let me also point out that the current implementation seems to contain
a bug, which causes that it is neither log(choose(.,.)) nor log(abs(choose(.,.))).

  x <- choose(1/2, 1:10)
  y <- lchoose(1/2, 1:10)
  cbind(choose=x, lchoose=y, log.choose=log(abs(x)))
            choose    lchoose log.choose
  #  [1,]  0.500000000 -0.6931472 -0.6931472
  #  [2,] -0.125000000 -2.0794415 -2.0794415
  #  [3,]  0.062500000        NaN -2.7725887
  #  [4,] -0.039062500 -3.2425924 -3.2425924
  #  [5,]  0.027343750        NaN -3.5992673
  #  [6,] -0.020507812 -3.8869494 -3.8869494
  #  [7,]  0.016113281        NaN -4.1281114
  #  [8,] -0.013092041 -4.3357508 -4.3357508
  #  [9,]  0.010910034        NaN -4.5180723
  # [10,] -0.009273529 -4.6805913 -4.6805913

So, besides x[1], we get NA for those cases, when choose() is positive.
The reason seems to be the test at line 89 of src/nmath/choose.c, which is

    if (fmod(floor(n-k+1), 2.) == 0) /* choose() < 0 */
        return ML_NAN;

but it should be negated. I tested it using

    if (fmod(floor(n-k+1), 2.) != 0) /* choose() < 0 */
        return ML_NAN;

when we get

            choose    lchoose log.choose
   [1,]  0.500000000 -0.6931472 -0.6931472
   [2,] -0.125000000        NaN -2.0794415
   [3,]  0.062500000 -2.7725887 -2.7725887
   [4,] -0.039062500        NaN -3.2425924
   [5,]  0.027343750 -3.5992673 -3.5992673
   [6,] -0.020507812        NaN -3.8869494
   [7,]  0.016113281 -4.1281114 -4.1281114
   [8,] -0.013092041        NaN -4.3357508
   [9,]  0.010910034 -4.5180723 -4.5180723
  [10,] -0.009273529        NaN -4.6805913

Petr Savicky.