Patch: Numeric#divmod documentation error corrected and didactically improved

"Dirk Traulsen" <[email protected]> Tue, 18 Sep 2007 21:48:58 +0200
Newsgroups gmane.comp.lang.ruby.documentation
Message-ID <[email protected]>
Hi all!

I submitted the following to 
http://rubyforge.org/tracker/index.php?func=detail&aid=14051
&group_id=426&atid=1700

Numeric#divmod  (numeric.c line 264-302)
========================================

  1. There is an error in the table in column a/b:  13/-4 is -4, not -3!

       C:\Dokume~1\All Users\Dokume~1>irb
       irb(main):001:0> RUBY_VERSION    #=> "1.8.6"
       irb(main):002:0> 13/-4           #=> -4      <=!


  2. The divmod formula
    a. is given in C and not Ruby terms,
    b. should use the same parameter names as the table and
    c. is wrong: Numeric does not convert a and b to floats. The division
                 with "/" is handled by the respective subclasses and they
                 do it differently depending on the class of num.

       So, it would be correct and Ruby-esk to write:

 *  Returns an array containing the quotient and modulus obtained by
 *  dividing <i>num</i> by <i>aNumeric</i>.
 *  If 
 *          q, r = a.divmod(b)
 *  then
 *             q = (a/b).floor
 *             r = a.modulo(b) = a - q*b


  3. For didactical reasons I would also propose to change 
     the table layout:

 *                         |        a.divmod(b)        | 
 *      a   |  b  |  a/b   | (a/b).floor,  a.modulo(b) | a.remainder(b)
 *    ------+-----+--------+---------------------------+---------------
 *     13   |  4  |  3     |      3     ,    1         |     1
 *    ------+-----+--------+---------------------------+---------------
 *     13   | -4  | -4     |     -4     ,   -3         |     1
 *    ------+-----+--------+---------------------------+---------------

instead of

 *     a    |  b  |  a.divmod(b)  |   a/b   | a.modulo(b) | a.remainder(b)
 *    ------+-----+---------------+---------+-------------+---------------
 *     13   |  4  |   3,    1     |   3     |    1        |     1
 *    ------+-----+---------------+---------+-------------+---------------
 *     13   | -4  |  -4,   -3     |  -3     |   -3        |     1
 *    ------+-----+---------------+---------+-------------+---------------


Altogether my corrections and proposals sum up to:
--------------------------------------------------------------------------
/*
 *  call-seq:
 *     num.divmod( aNumeric )   => anArray
 *
 *  Returns an array containing the quotient and modulus obtained by
 *  dividing <i>num</i> by <i>aNumeric</i>.
 *  If 
 *          q, r = a.divmod(b)
 *  then
 *             q = (a/b).floor
 *             r = a.modulo(b) = a - q*b
 *     
 *  The quotient is rounded toward -infinity, as shown in the following 
table:
 *
 *                         |        a.divmod(b)        | 
 *      a   |  b  |  a/b   | (a/b).floor,  a.modulo(b) | a.remainder(b)
 *    ------+-----+--------+---------------------------+---------------
 *     13   |  4  |  3     |      3     ,    1         |     1
 *    ------+-----+--------+---------------------------+---------------
 *     13   | -4  | -4     |     -4     ,   -3         |     1
 *    ------+-----+--------+---------------------------+---------------
 *    -13   |  4  | -4     |     -4     ,    3         |    -1         
 *    ------+-----+--------+---------------------------+---------------
 *    -13   | -4  |  3     |      3     ,   -1         |    -1         
 *    ------+-----+--------+---------------------------+---------------
 *     11.5 |  4  |  2.875 |      2     ,    3.5       |     3.5       
 *    ------+-----+--------+---------------------------+---------------
 *     11.5 | -4  | -2.875 |     -3     ,   -0.5       |     3.5       
 *    ------+-----+--------+---------------------------+---------------
 *    -11.5 |  4  | -2.875 |     -3     ,    0.5       |    -3.5       
 *    ------+-----+--------+---------------------------+---------------
 *    -11.5 | -4  |  2.875 |      2     ,   -3.5       |    -3.5
 *
 *
 *  Examples
 *     11.divmod(3)                        #=> [3, 2]
 *     11.divmod(-3)                       #=> [-4, -1]
 *     11.divmod(3.5)                      #=> [3, 0.5]
 *     (-11.5).divmod(3.5)                 #=> [-4, 2.5]
 *     Rational(7,4).divmod Rational(1,2)  #=> [3, Rational(1,4)]
 */
--------------------------------------------------------------------------

instead of the old:
--------------------------------------------------------------------------
/*
 *  call-seq:
 *     num.divmod( aNumeric ) -> anArray
 *
 *  Returns an array containing the quotient and modulus obtained by
 *  dividing <i>num</i> by <i>aNumeric</i>. If <code>q, r =
 *  x.divmod(y)</code>, then
 *
 *      q = floor(float(x)/float(y))
 *      x = q*y + r
 *
 *  The quotient is rounded toward -infinity, as shown in the following 
table:
 *
 *     a    |  b  |  a.divmod(b)  |   a/b   | a.modulo(b) | a.remainder(b)
 *    ------+-----+---------------+---------+-------------+---------------
 *     13   |  4  |   3,    1     |   3     |    1        |     1
 *    ------+-----+---------------+---------+-------------+---------------
 *     13   | -4  |  -4,   -3     |  -3     |   -3        |     1
 *    ------+-----+---------------+---------+-------------+---------------
 *    -13   |  4  |  -4,    3     |  -4     |    3        |    -1
 *    ------+-----+---------------+---------+-------------+---------------
 *    -13   | -4  |   3,   -1     |   3     |   -1        |    -1
 *    ------+-----+---------------+---------+-------------+---------------
 *     11.5 |  4  |   2,    3.5   |   2.875 |    3.5      |     3.5
 *    ------+-----+---------------+---------+-------------+---------------
 *     11.5 | -4  |  -3,   -0.5   |  -2.875 |   -0.5      |     3.5
 *    ------+-----+---------------+---------+-------------+---------------
 *    -11.5 |  4  |  -3,    0.5   |  -2.875 |    0.5      |    -3.5
 *    ------+-----+---------------+---------+-------------+---------------
 *    -11.5 | -4  |   2,   -3.5   |   2.875 |   -3.5      |    -3.5
 *
 *
 *  Examples
 *     11.divmod(3)         #=> [3, 2]
 *     11.divmod(-3)        #=> [-4, -1]
 *     11.divmod(3.5)       #=> [3, 0.5]
 *     (-11).divmod(3.5)    #=> [-4, 3.0]
 *     (11.5).divmod(3.5)   #=> [3, 1.0]
 */
--------------------------------------------------------------------------
The patch to numeric.c is attached.

Regards,
Dirk
numeric.c.patch (application/octet-stream, 3.8 KB)
--- numeric.c	2007-09-04 14:27:12.406250000 +0200
+++ numeric_new.c	2007-09-18 21:16:35.375000000 +0200
@@ -263,42 +263,44 @@
 
 /*
  *  call-seq:
- *     num.divmod( aNumeric ) -> anArray
+ *     num.divmod( aNumeric )   => anArray
  *
  *  Returns an array containing the quotient and modulus obtained by
- *  dividing <i>num</i> by <i>aNumeric</i>. If <code>q, r =
- *  x.divmod(y)</code>, then
- *
- *      q = floor(float(x)/float(y))
- *      x = q*y + r
- *
+ *  dividing <i>num</i> by <i>aNumeric</i>.
+ *  If 
+ *          q, r = a.divmod(b)
+ *  then
+ *             q = (a/b).floor
+ *             r = a.modulo(b) = a - q*b
+ *     
  *  The quotient is rounded toward -infinity, as shown in the following table:
  *
- *     a    |  b  |  a.divmod(b)  |   a/b   | a.modulo(b) | a.remainder(b)
- *    ------+-----+---------------+---------+-------------+---------------
- *     13   |  4  |   3,    1     |   3     |    1        |     1
- *    ------+-----+---------------+---------+-------------+---------------
- *     13   | -4  |  -4,   -3     |  -3     |   -3        |     1
- *    ------+-----+---------------+---------+-------------+---------------
- *    -13   |  4  |  -4,    3     |  -4     |    3        |    -1
- *    ------+-----+---------------+---------+-------------+---------------
- *    -13   | -4  |   3,   -1     |   3     |   -1        |    -1
- *    ------+-----+---------------+---------+-------------+---------------
- *     11.5 |  4  |   2,    3.5   |   2.875 |    3.5      |     3.5
- *    ------+-----+---------------+---------+-------------+---------------
- *     11.5 | -4  |  -3,   -0.5   |  -2.875 |   -0.5      |     3.5
- *    ------+-----+---------------+---------+-------------+---------------
- *    -11.5 |  4  |  -3,    0.5   |  -2.875 |    0.5      |    -3.5
- *    ------+-----+---------------+---------+-------------+---------------
- *    -11.5 | -4  |   2,   -3.5   |   2.875 |   -3.5      |    -3.5
+ *                         |        a.divmod(b)        | 
+ *      a   |  b  |  a/b   | (a/b).floor,  a.modulo(b) | a.remainder(b)
+ *    ------+-----+--------+---------------------------+---------------
+ *     13   |  4  |  3     |      3     ,    1         |     1
+ *    ------+-----+--------+---------------------------+---------------
+ *     13   | -4  | -4     |     -4     ,   -3         |     1
+ *    ------+-----+--------+---------------------------+---------------
+ *    -13   |  4  | -4     |     -4     ,    3         |    -1         
+ *    ------+-----+--------+---------------------------+---------------
+ *    -13   | -4  |  3     |      3     ,   -1         |    -1         
+ *    ------+-----+--------+---------------------------+---------------
+ *     11.5 |  4  |  2.875 |      2     ,    3.5       |     3.5       
+ *    ------+-----+--------+---------------------------+---------------
+ *     11.5 | -4  | -2.875 |     -3     ,   -0.5       |     3.5       
+ *    ------+-----+--------+---------------------------+---------------
+ *    -11.5 |  4  | -2.875 |     -3     ,    0.5       |    -3.5       
+ *    ------+-----+--------+---------------------------+---------------
+ *    -11.5 | -4  |  2.875 |      2     ,   -3.5       |    -3.5
  *
  *
  *  Examples
- *     11.divmod(3)         #=> [3, 2]
- *     11.divmod(-3)        #=> [-4, -1]
- *     11.divmod(3.5)       #=> [3, 0.5]
- *     (-11).divmod(3.5)    #=> [-4, 3.0]
- *     (11.5).divmod(3.5)   #=> [3, 1.0]
+ *     11.divmod(3)                        #=> [3, 2]
+ *     11.divmod(-3)                       #=> [-4, -1]
+ *     11.divmod(3.5)                      #=> [3, 0.5]
+ *     (-11.5).divmod(3.5)                 #=> [-4, 2.5]
+ *     Rational(7,4).divmod Rational(1,2)  #=> [3, Rational(1,4)]
  */
 
 static VALUE