Subject: Re: replacement for bc(1), dc(1), diff(1), and diff(3)
To: None <tech-userlevel@netbsd.org>
From: Otto Moerbeek <otto@drijf.net>
List: tech-userlevel
Date: 03/27/2005 13:25:02
As the author of OpenBSD's dc(1) and bc(1), I have some remarks.

> d) Although not mentioned in the original post, for me the real
> technical issue is how does the product perform in use. The following
> are time tests on a variety of operations.  It is targetting the most
> expensive operations in bc(1).  First, it checks out the math library
> and then looks at things like multiplication, division, raising and
> square root.  As you will see, GNU bc outperforms OpenBSD in many of
> the tests and some cases, OpenBSD can't even do what GNU bc does.  In
> 2 cases below, I killed OpenBSD dc after it ran for 10 or more minutes
>of CPU time. (time reports ' Command terminated abnormally.' in these
> cases.)

My first goal was the create an easy maintainable bc(1) and dc(1),
without reimplementing the big number routines.

OpenBSD's bc(1) and dc(1) might have bugs, bu probably amny program has. 
GNU dc(1) has some problems too. Try '[lax]sa lax' in GNU dc(1), for 
example.

See below for some comments on the specific issues you found.

>
> Each of the tests listed below are quite simple.  For example, the "exp.b"
> test is:
>     for (a=0; a<180; a+=.4) x=e(a)
>     x
>     quit

Very likely you are hit by a bug in the big number routines of OpenSSL 
which I discovered when starting the work on dc(1), which is fixed by 
this: 
http://www.openbsd.org/cgi-bin/cvsweb/src/lib/libssl/src/crypto/bn/bn_word.c.diff?r1=1.5&r2=1.7

> The one for fact.b is:
>    define f (x) {
>
>      if (x<=1) return(1)
>      return (f(x-1)*x)
>    }
>
>    for (a=1; a<600; a++) b=f(a)
>    "
>    "
>    "b=";b
>    quit

The call stack has a fixed recusion limit of 100. I never got around to 
making that dynamic.

> We haven't even begun to talk about POSIX compliance.  The above tests
> show that OpenBSD doesn't comply with the POSIX output requirement
> that the \ in continuation numbers is also to be counted in the line
> length.  So a line of a maximum of 70 characters, the default output
> line size, should have 69 digits and one \.  OpenBSD bc has 70 digits
> and the \.

IMO Posix is ambiguous:

"Very large numbers shall be split across lines with 70 characters per
line in the POSIX locale; other locales may split at different
character boundaries. Lines that are continued shall end with a
backslash ( '\' )."

I copied the behaviour from the original (4.2 iirc) BSD dc(1). Although 
dc(1) and bc(1) are completly new implementations, I tried to stay close 
to these originals. But if I'm wrong in this, I'm happy to change that.

    -Otto