At Tue, 6 Mar 2012 17:12:02 +0000,
Stuart Henderson wrote:
> 
> On 2012/03/07 01:00, AIDA Shinra wrote:
> > Hi,
> > 
> > I found the e() and l() in the bc(1) math library are not
> > precise. Their scaling algorithms are wrong.
> > 
> > In addition, BSD bc evaluates length(0.000) to 1 instead of 3.
> > Such a behaviour will surprise people who expect that
> > length(x) >= scale(x). While POSIX is silent, the GNU bc returns 3.
> > 
> > The attached patches fix them. They also enable the editline in the
> > intaractive "bc -d".
> > 
> > See also:
> > http://www.FreeBSD.org/cgi/query-pr.cgi?pr=bin/159227
> > 
> > Regards,
> > shinra
> > 
> > [demime 1.01d removed an attachment of type application/octet-stream]
> > 
> > [demime 1.01d removed an attachment of type application/octet-stream]
> > 
> 
> Please send your diffs inline in the email body (diff -u format).
> Thanks!
 
Sorry, the patches follow:
Index: bc.library
===================================================================
RCS file: /cvs/src/usr.bin/bc/bc.library,v
retrieving revision 1.3
diff -u -r1.3 bc.library
--- bc.library  3 Feb 2007 21:15:06 -0000       1.3
+++ bc.library  6 Mar 2012 14:20:40 -0000
@@ -45,7 +45,9 @@
        r = ibase
        ibase = A
        t = scale
-       scale = t + .434*x + 1
+       scale = 0
+       if (x > 0) scale = (0.435*x)/1
+       scale = scale + t + 1
 
        w = 0
        if (x < 0) {
@@ -94,26 +96,33 @@
        t = scale
 
        f = 1
-       scale = scale + scale(x) - length(x) + 1
-       s = scale
+       if (x < 1) {
+               s = scale(x)
+       } else {
+               s = length(x)-scale(x)
+       }
+       scale = 0
+       a = (2.31*s)/1 /* estimated integer part of the answer */
+       s = t + length(a) + 2 /* estimated length of the answer */
        while (x > 2) {
-               s = s + (length(x) - scale(x))/2 + 1
-               if (s > 0) scale = s
+               scale=0
+               scale = (length(x) + scale(x))/2 + 1
+               if (scale < s) scale = s
                x = sqrt(x)
                f = f*2
        }
        while (x < .5) {
-               s = s + (length(x) - scale(x))/2 + 1
-               if (s > 0) scale = s
+               scale = 0
+               scale = scale(x)/2 + 1
+               if (scale < s) scale = s
                x = sqrt(x)
                f = f*2
        }
 
-       scale = t + length(f) - scale(f) + 1
+       scale = t + length(f) + length(t + length(f)) + 1
        u = (x - 1)/(x + 1)
-
-       scale = scale + 1.1*length(t) - 1.1*scale(t)
        s = u*u
+       scale = t + 2
        b = 2*f
        c = b
        d = 1
Index: bc.y
===================================================================
RCS file: /cvs/src/usr.bin/bc/bc.y,v
retrieving revision 1.40
diff -u -r1.40 bc.y
--- bc.y        6 Oct 2011 14:37:56 -0000       1.40
+++ bc.y        6 Mar 2012 14:20:40 -0000
@@ -45,6 +45,7 @@
 #include <string.h>
 #include <termios.h>
 #include <unistd.h>
+#include <stdlib.h>
 
 #include "extern.h"
 #include "pathnames.h"
@@ -1144,19 +1145,6 @@
                        dup(p[1]);
                        close(p[0]);
                        close(p[1]);
-                       if (interactive) {
-                               gettty(&ttysaved);
-                               el = el_init("bc", stdin, stderr, stderr);
-                               hist = history_init();
-                               history(hist, &he, H_SETSIZE, 100);
-                               el_set(el, EL_HIST, history, hist);
-                               el_set(el, EL_EDITOR, "emacs");
-                               el_set(el, EL_SIGNAL, 0);
-                               el_set(el, EL_PROMPT, dummy_prompt);
-                               el_set(el, EL_ADDFN, "bc_eof", "", bc_eof);
-                               el_set(el, EL_BIND, "^D", "bc_eof", NULL);
-                               el_source(el, NULL);
-                       }
                } else {
                        close(STDIN_FILENO);
                        dup(p[0]);
@@ -1165,6 +1153,19 @@
                        execl(_PATH_DC, "dc", "-x", (char *)NULL);
                        err(1, "cannot find dc");
                }
+       }
+       if (interactive) {
+               gettty(&ttysaved);
+               el = el_init("bc", stdin, stderr, stderr);
+               hist = history_init();
+               history(hist, &he, H_SETSIZE, 100);
+               el_set(el, EL_HIST, history, hist);
+               el_set(el, EL_EDITOR, "emacs");
+               el_set(el, EL_SIGNAL, 0);
+               el_set(el, EL_PROMPT, dummy_prompt);
+               el_set(el, EL_ADDFN, "bc_eof", "", bc_eof);
+               el_set(el, EL_BIND, "^D", "bc_eof", NULL);
+               el_source(el, NULL);
        }
        yywrap();
        return yyparse();
Index: bcode.c
===================================================================
RCS file: /cvs/src/usr.bin/dc/bcode.c,v
retrieving revision 1.41
diff -u -r1.41 bcode.c
--- bcode.c     15 May 2010 10:59:29 -0000      1.41
+++ bcode.c     6 Mar 2012 14:25:38 -0000
@@ -682,7 +682,7 @@
        u_int           i;
 
        if (BN_is_zero(n->number))
-               return 1;
+               return n->scale ? n->scale : 1;
 
        int_part = new_number();
        fract_part = new_number();

Reply via email to