GithubHelp home page GithubHelp logo

gavinhoward / bc Goto Github PK

View Code? Open in Web Editor NEW
141.0 9.0 29.0 11.73 MB

An implementation of the POSIX bc calculator with GNU extensions and dc, moved away from GitHub. Finished, but well-maintained.

Home Page: https://git.gavinhoward.com/gavin/bc

License: Other

Makefile 0.84% C 37.04% Shell 9.45% Python 2.19% Roff 50.39% sed 0.01% Batchfile 0.08%
bc posix dc

bc's Introduction

bc

WARNING: New user registration for https://git.gavinhoward.com/ is disabled because of spam. If you need to report a bug with bc, email gavin at this site minus the git. part for an account, and I will create one for you. Or you can report an issue at GitHub.

WARNING: This project has moved to https://git.gavinhoward.com/ for these reasons, though GitHub will remain a mirror.

This is an implementation of the POSIX bc calculator that implements GNU bc extensions, as well as the period (.) extension for the BSD flavor of bc.

For more information, see this bc's full manual.

This bc also includes an implementation of dc in the same binary, accessible via a symbolic link, which implements all FreeBSD and GNU extensions. (If a standalone dc binary is desired, bc can be copied and renamed to dc.) The ! command is omitted; I believe this poses security concerns and that such functionality is unnecessary.

For more information, see the dc's full manual.

This bc also provides bc's math as a library with C bindings, called bcl.

For more information, see the full manual for bcl.

License

This bc is Free and Open Source Software (FOSS). It is offered under the BSD 2-clause License. Full license text may be found in the LICENSE.md file.

Prerequisites

This bc only requires either:

  1. Windows 10 or later, or
  2. A C99-compatible compiler and a (mostly) POSIX 2008-compatible system with the XSI (X/Open System Interfaces) option group.

Since POSIX 2008 with XSI requires the existence of a C99 compiler as c99, any POSIX and XSI-compatible system will have everything needed.

POSIX-compatible systems that are known to work:

  • Linux
  • FreeBSD
  • OpenBSD
  • NetBSD
  • macOS
  • Solaris* (as long as the Solaris version supports POSIX 2008)
  • AIX
  • HP-UX* (except for history)

In addition, there is compatibility code to make this bc work on Windows.

Please submit bug reports if this bc does not build out of the box on any system.

Build

This bc should build unmodified on any POSIX-compliant system or on Windows starting with Windows 10 (though earlier versions may work).

For more complex build requirements than the ones below, see the build manual.

Windows

There is no guarantee that this bc will work on any version of Windows earlier than Windows 10 (I cannot test on earlier versions), but it is guaranteed to work on Windows 10 at least.

Also, if building with MSBuild, the MSBuild bundled with Visual Studio is required.

Note: Unlike the POSIX-compatible platforms, only one build configuration is supported on Windows: extra math and history enabled, NLS (locale support) disabled, with both calculators built.

bc

To build bc, you can open the vs/bc.sln file in Visual Studio, select the configuration, and build.

You can also build using MSBuild with the following from the root directory:

msbuild -property:Configuration=<config> vs/bc.sln

where <config> is either one of Debug or Release.

On Windows, the calculators are built as vs/bin/<platform>/<config>/bc.exe and vs/bin/<Platform>/<Config>/dc.exe, where <platform> can be either Win32 or x64, and <config> can be Debug or Release.

Note: On Windows, dc.exe is just copied from bc.exe; it is not linked. Patches are welcome for a way to do that.

bcl (Library)

To build the library, you can open the vs/bcl.sln file in Visual Studio, select the configuration, and build.

You can also build using MSBuild with the following from the root directory:

msbuild -property:Configuration=<config> vs/bcl.sln

where <config> is either one of Debug, ReleaseMD, or ReleaseMT.

On Windows, the library is built as vs/lib/<platform>/<config>/bcl.lib, where <platform> can be either Win32 or x64, and <config> can be Debug, ReleaseMD, or ReleaseMT.

POSIX-Compatible Systems

On POSIX-compatible systems, bc is built as bin/bc and dc is built as bin/dc by default.

Default

For the default build with optimization, use the following commands in the root directory:

./configure.sh -O3
make

One Calculator

To only build bc, use the following commands:

./configure.sh --disable-dc
make

To only build dc, use the following commands:

./configure.sh --disable-bc
make

Debug

For debug builds, use the following commands in the root directory:

./configure.sh -g
make

Install

To install, use the following command:

make install

By default, bc and dc will be installed in /usr/local. For installing in other locations, use the PREFIX environment variable when running configure.sh or pass the --prefix=<prefix> option to configure.sh. See the build manual, or run ./configure.sh --help, for more details.

Library

To build the math library, pass the -a or --library options to configure.sh:

./configure.sh -a

When building the library, the executables are not built. For more information, see the build manual.

The library API can be found in manuals/bcl.3.md or man bcl once the library is installed.

Package and Distro Maintainers

This section is for package and distro maintainers.

Out-of-Source Builds

Out-of-source builds are supported; just call configure.sh from the directory where the actual build will happen.

For example, if the source is in bc, the build should happen in build, then call configure.sh and make like so:

../bc/configure.sh
make

WARNING: The path to configure.sh from the build directory must not have spaces because make does not support target names with spaces.

Recommended Compiler

When I ran benchmarks with my bc compiled under clang, it performed much better than when compiled under gcc. I recommend compiling this bc with clang.

I also recommend building this bc with C11 if you can because bc will detect a C11 compiler and add _Noreturn to any relevant function(s).

Recommended Optimizations

I wrote this bc with Separation of Concerns, which means that there are many small functions that could be inlined. However, they are often called across file boundaries, and the default optimizer can only look at the current file, which means that they are not inlined.

Thus, because of the way this bc is built, it will automatically be slower than other bc implementations when running scripts with no math. (My bc's math is much faster, so any non-trivial script should run faster in my bc.)

Some, or all, of the difference can be made up with the right optimizations. The optimizations I recommend are:

  1. -O3
  2. -flto (link-time optimization)

in that order.

Link-time optimization, in particular, speeds up the bc a lot. This is because when link-time optimization is turned on, the optimizer can look across files and inline much more heavily.

However, I recommend NOT using -march=native. Doing so will reduce this bc's performance, at least when building with link-time optimization. See the benchmarks for more details.

Stripping Binaries

By default, non-debug binaries are stripped, but stripping can be disabled with the -T option to configure.sh.

Using This bc as an Alternative

If this bc is packaged as an alternative to an already existing bc package, it is possible to rename it in the build to prevent name collision. To prepend to the name, just run the following:

EXECPREFIX=<some_prefix> ./configure.sh

To append to the name, just run the following:

EXECSUFFIX=<some_suffix> ./configure.sh

If a package maintainer wishes to add both a prefix and a suffix, that is allowed.

Note: The suggested name (and package name) when bc is not available is bc-gh.

Karatsuba Number

Package and distro maintainers have one tool at their disposal to build this bc in the optimal configuration: scripts/karatsuba.py.

This script is not a compile-time or runtime prerequisite; it is for package and distro maintainers to run once when a package is being created. It finds the optimal Karatsuba number (see the algorithms manual for more information) for the machine that it is running on.

The easiest way to run this script is with make karatsuba.

If desired, maintainers can also skip running this script because there is a sane default for the Karatsuba number.

Status

This bc is robust.

It is well-tested, fuzzed, and fully standards-compliant (though not certified) with POSIX bc. The math has been tested with 40+ million random problems, so it is as correct as I can make it.

This bc can be used as a drop-in replacement for any existing bc. This bc is also compatible with MinGW toolchains.

In addition, this bc is considered complete; i.e., there will be no more releases with additional features. However, it is actively maintained, so if any bugs are found, they will be fixed in new releases. Also, additional translations will also be added as they are provided.

Development

If I (Gavin D. Howard) get hit by a bus and future programmers need to handle work themselves, the best place to start is the Development manual.

Vim Syntax

I have developed (using other people's code to start) vim syntax files for this bc and dc, including the extensions.

bc Libs

I have gathered some excellent bc and dc libraries. These libraries may prove useful to any serious users.

Comparison to GNU bc

This bc compares favorably to GNU bc.

  • This bc builds natively on Windows.
  • It has more extensions, which make this bc more useful for scripting. (See Extensions.)
  • This bc is a bit more POSIX compliant.
  • It has a much less buggy parser. The GNU bc will give parse errors for what is actually valid bc code, or should be. For example, putting an else on a new line after a brace can cause GNU bc to give a parse error.
  • This bc has fewer crashes.
  • GNU bc calculates the wrong number of significant digits for length(x).
  • GNU bc will sometimes print numbers incorrectly. For example, when running it on the file tests/bc/power.txt in this repo, GNU bc gets all the right answers, but it fails to wrap the numbers at the proper place when outputting to a file.
  • This bc is faster. (See Performance.)

Performance

Because this bc packs more than 1 decimal digit per hardware integer, this bc is faster than GNU bc and can be much faster. Full benchmarks can be found at manuals/benchmarks.md.

There is one instance where this bc is slower: if scripts are light on math. This is because this bc's intepreter is slightly slower than GNU bc, but that is because it is more robust. See the benchmarks.

Extensions

Below is a non-comprehensive list of extensions that this bc and dc have that all others do not.

  • The ! operator has higher precedence than the ! operator in other bc implementations.
  • An extended math library. (See here for more information.)
  • A command-line prompt.
  • Turning on and off digit clamping. (Digit clamping is about how to treat "invalid" digits for a particular base. GNU bc uses it, and the BSD bc does not. Mine does both.)
  • A pseudo-random number generator. This includes the ability to set the seed and get reproducible streams of random numbers.
  • The ability to use stacks for the globals scale, ibase, and obase instead of needing to restore them in every function.
  • The ability to not use non-standard keywords. For example, abs is a keyword (a built-in function), but if some script actually defines a function called that, it's possible to tell my bc to not treat it as a keyword, which will make the script parses correctly.
  • The ability to turn on and off printing leading zeroes on numbers greater than -1 and less than 1.
  • Outputting in scientific and engineering notation.
  • Accepting input in scientific and engineering notation.
  • Passing strings and arrays to the length() built-in function. (In dc, the Y command will do this for arrays, and the Z command will do this for both numbers and strings.)
  • The abs() built-in function. (This is the b command in dc.)
  • The is_number() and is_string() built-in functions. (These tell whether a variable is holding a string or a number, for runtime type checking. The commands are u and t in dc.)
  • For bc only, the divmod() built-in function for computing a quotient and remainder at the same time.
  • For bc only, the asciify() built-in function for converting an array to a string.
  • The $ truncation operator. (It's the same in bc and dc.)
  • The @ "set scale" operator. (It's the same in bc and dc.)
  • The decimal shift operators. (<< and >> in bc, H and h in dc.)
  • Built-in functions or commands to get the max of scale, ibase, and obase.
  • The ability to put strings into variables in bc. (This always existed in dc.)
  • The ' command in dc for the depth of the execution stack.
  • The y command in dc for the depth of register stacks.
  • Built-in functions or commands to get the value of certain environment variables that might affect execution.
  • The stream keyword to do the same thing as the P command in dc.
  • Defined order of evaluation.
  • Defined exit statuses.
  • All environment variables other than POSIXLY_CORRECT, BC_ENV_ARGS, and BC_LINE_LENGTH.
  • The ability for users to define their own defaults for various options during build. (See here for more information.)

Algorithms

To see what algorithms this bc uses, see the algorithms manual.

Locales

Currently, there is no locale support on Windows.

Additionally, this bc only has support for English (and US English), French, German, Portuguese, Dutch, Polish, Russian, Japanese, and Chinese locales. Patches are welcome for translations; use the existing *.msg files in locales/ as a starting point.

In addition, patches for improvements are welcome; the last two messages in Portuguese were made with Google Translate, and the Dutch, Polish, Russian, Japanese, and Chinese locales were all generated with DeepL.

The message files provided assume that locales apply to all regions where a language is used, but this might not be true for, e.g., fr_CA and fr_CH. Any corrections or a confirmation that the current texts are acceptable for those regions would be appreciated, too.

Other Projects

Other projects based on this bc are:

  • busybox bc. The busybox maintainers have made their own changes, so any bugs in the busybox bc should be reported to them.
  • toybox bc. The maintainer has also made his own changes, so bugs in the toybox bc should be reported there.
  • FreeBSD bc. While the bc in FreeBSD is kept up-to-date, it is better to report bugs there, as well as submit patches, and the maintainers of the package will contact me if necessary.
  • macOS bc. Any bugs in that bc should be reported to me, but do expect bugs because the version is old.
  • Android Open Source bc. Any bugs in that bc can be reported here.

This is a non-comprehensive list of Linux distros that use this bc as the system bc:

Other Linux distros package it as a second-class alternative, usually as bc-gh or howard-bc.

Language

This bc is written in pure ISO C99, using POSIX 2008 APIs with custom Windows compatibility code.

Commit Messages

This bc uses the commit message guidelines laid out in this blog post.

Semantic Versioning

This bc uses semantic versioning.

AI-Free

This repository is 100% AI-Free code.

Contents

Items labeled with (maintainer use only) are not included in release source tarballs.

Files:

.gitignore           The git ignore file (maintainer use only).
.gitattributes       The git attributes file (maintainer use only).
bcl.pc.in            A template pkg-config file for bcl.
configure            A symlink to configure.sh to make packaging easier.
configure.sh         The configure script.
LICENSE.md           A Markdown form of the BSD 2-clause License.
Makefile.in          The Makefile template.
NEWS.md              The changelog.
NOTICE.md            List of contributors and copyright owners.

Folders:

benchmarks  A folder of benchmarks for various aspects of bc performance.
gen         The bc math library, help texts, and code to generate C source.
include     All header files.
locales     Locale files, in .msg format. Patches welcome for translations.
manuals     Manuals for both programs.
src         All source code.
scripts     A bunch of shell scripts to help with development and building.
tests       All tests.
vs          Files needed for the build on Windows.

bc's People

Contributors

brooksdavis avatar bsdimp avatar bugcrazy avatar depler avatar dorjechang avatar e5ten avatar eg15 avatar firasuke avatar gavinhoward avatar henke9600 avatar ibara avatar josuah avatar jprjr avatar michaelforney avatar naggamura avatar pacordova avatar pstef avatar rofl0r avatar stesser avatar xry111 avatar yzenallc avatar zv-io avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

bc's Issues

Array - Multiple values

Hi, @gavinhoward,

I read the documentation file and it seems that arrays can only old a single value per each index (a number or a string). Is there any workaround to be able to store more than one single value in an array?

# This works
bc_example[0] = 1;

# This doesn't
bc_example[1] = [1, 2, 3];
bc_example[2] = [1, "Random", 3, "Another"];

print bc_example[2][1] # Random

As I already stated before in another issue, I'm using your amazing tool to keep track of my expenses and it would be amazing to be able to create a "matrix" or an "array of arrays" as people often call it. Although I know that my use case isn't the general one and that the type of feature that I'm requesting doesn't make much sense considering the main goal/purpose of this tool, I'm opening this issue to know if what I want is somehow possible using any syntax workaround not documented in the above file.

test failures on Android

i haven't been able to update for some time (5.0.1 was our last update!) because the tests fail in a weird way without much useful information. i've included the current failures for 6.2.2 below, for example.

my guess is that this is something to do with Android using mksh as its /bin/sh. the interleaved output makes it appear like there might be some disagreement about job handling between bash and mksh?

are the current bc tests known to work on shells other than bash (and in particular mksh)? any ideas where i should look (or some kind of parallelism i can just disable)?

~/aosp-master-with-phones/external/bc$ ./run-bc-tests-on-android.sh 
tests/: 413 files pushed, 0 skipped. 0.8 MB/s (1191155 bytes in 1.372s)
scripts/functions.sh: 1 file pushed, 0 skipped. 75.4 MB/s (12065 bytes in 0.000s)
***********************************************************************

Running bc tests...

Skipping bc lib2
Skipping bc shift
Skipping bc trunc
Skipping bc places
Skipping bc print test
SkRunning bc decimal...Running bc print2...ipping bc parse test
Running bc scale...Skipping bc scientific
Running bc length...Running bc sqrt...Running bc modulus...RuRunning bc add...nning bc divide...Running bc subtract...Skipping bc engineering
Running bc multiply...Running bc power...Running bc abs...Running bc functions...pass
Running bc boolean...Running bc comp...Running bc assignments...Running bc vars...pass
Skipping bc rand
pass
SRunning bc globals...kipping bc bitfuncs
pass
Running bc strings...pass
Running bc cosine...pass
Skipping bc strings2 test
Skipping bc bessel test
pass
Running bc sine...Running bc misc2...RRunning bc exponent...pRunning bc log...Running bc misc8...Running bc misc...Running bc misc4...Running bc pi...upass
Skipping bc leadingzero
nning bc misc1...ppasRunning bc arrays...asss

ass
Running bc arctangent...Running bc misc6...Running bc modexp...Running bc void...Running bc misc3...Running bc letters...pass
pass
pRunning bc misc7...ass
pass
pass
Running bc divmod...Running bc recursive_arrays...Running bc misc5...pass
pass
pass
pass
pass
pass
pass
ppass
ass
Running bc is_number...pass
pass
pass
pass
Running bc asciify_array...Running bc line_loop_quit1...pass
ppass
pass
pass
pass
pass
ass
Running bc is_string...Running bc line_by_line1...Running bc line_by_line2...Running bc line_loop_quit2...Running bc command-line error tests...Running bc stdin tests...pass
Running bc error file 01.txt with clamping...pass
pass
pass
Running bc read...Running bc error file 02.txt with clamping...Running bc error file 03.txt with clamping...pass
pass
pass
pass
pass
pass
pass
pass
Running bc error file 01.txt without clamping...Running bc error file 04.txt with clamping...ppass
Skipping bc script multiply.bc
pass
ass
Running bc error file 02.txt without clamping...pass
Running bc error file 05.txt with clamping...Skipping bc script divide.bc
Running bc error file 03.txt without clamping...Skipping bc script subtract.bc
pass
Running bc errors...Running bc read errors...pass
Skipping bc script add.bc
Running bc error file 06.txt with clamping...Running bc error file 04.txt without clamping...pRunning bc error file 07.txt with clamping...ass
Running bc error file 01.txt through cat with clamping...pass
Running bc error file 08.txt with clamping...pass
Skipping bc script print.bc
Running bc error file 02.txt through cat with clamping...Running bc error file 03.txt through cat with clamping...pass
pass
pass
Running bc error file 05.txt without clamping...pass
pass
Running bc error file 09.txt with clamping...pass
Running bc error file 07.txt without clamping...pass
Skipping bc script parse.bc
RunRunning bc error file 04.txt through cat wnith clamping...ing bc error file 06.txt without clamping...pass
Running bc error file 10.txt with clamping...RRunning bc empty read...Running bc error file 01.txt through cat without clamping...unning bc script array.bc...RRunning bc error file 03.txt through cat without clamping...pass
paRunning bc error file 08.txt without clamping...Running bc error file 11.txt with clamping...pss
unning bc script array2.bc...ass
pass
pass
Running bc error file 02.txt through cat without clamping...pass
pass
Running bc script atan.bc...Running bc error file 09.txt without clamping...Running bc error file 05.txt through cat with clamping...pass
pass
Running bc error file 10.txt without clamping...Running bc error file 06.txt through cat with clamping...Running bc error file 12.txt with clamping...RunRunning bc error file 04.txt through cat without clamping...pass
Skipping bc script bessel.bc
pass
ning bc error file 07.txt through cat with clamping...Running bc script functions.bc...pass
Running bc error file 11.txt without clamping...Running bc error file 13.txt with clamping...pass
pass
Running bc error file 08.txt through cat with clamping...pass
pass
Running bc error file 14.txt with clamping...pass
Running bc read EOF...pass
Running bc error file 09.txt through cat with clamping...pass
pass
pass
Running bc error file 05.txt through cat without clamping...pass
pRunning bc script globals.bc...pass
ass
Running bc error file 15.txt with clamping...Skipping bc script: rand.bc
RRunning Rbc error ufninlien g10.txt  through cbca ts cwriitpht  len.bc...clamping...pass
unning bc error file 07.txt through cat without clamping...pass
RRunning bc error file 06.txt through cat without clamping...pass
Running bc error file 11.txt through cat with clamping...unning bc error file 12.txt without clamping...pass
Running bc error file 08.txt through cat without clamping...pass
Running bc error file 16.txt with clamping...pass
Running bc error file 14.txt without clamping...pass
Running bc error file 13.txt without clamping...pass
Running bc script references.bc...Running bc error file 17.txt with clamping...Running bc error file 09.txt through cat without clamping...pass
pass
pass
pass
pass
pass
RuRunning bc error file 15.txt without clamping...nning bc error file 18.txt with clamping...Running bc script screen.bc...pass
Rpass
papass
unning bc error file 12.txt through cat with clamping...ss
Running bc error file 11.txt through cat without clamping...Rpass
unning bc error file 10.txt through cat without clamping...Running bc error file 19.txt with clamping...Skipping bc script strings2.bc
pass
Running bc error file 13.txt through cat with clamping...pass
Running bc error file 16.txt without clamping...pass
Running bc error file 14.txt through cat with clamping...Running bc error file 20.txt with clamping...pass
Running bc error file 17.txt without clamping...pass
pass
Running bc error file 21.txt with clamping...paspass
Running bc script ifs.bc...s
Running bc error file 18.txt without clamping...pass
Running bc error file 15.txt through cat with clamping...pass
Running bc script ifs2.bc...Rpass
pass
Running bc error file 12.txt through cat without clamping...pass
unning bc error file 19.txt without clamping...Running bc erpass
ror file 22.txt with clamping...Running bc error file 13.txt through cat without clamping...Rpass
pRunning bc error file 20.txt without clamping...pass
ass
RuRRuunning bc error file 14.txt through cat without clamping...nnning bc script afl1.bc...unning bc error file 23.txt with clning bcamp einrrg..or. file 16.txt through cat with clamping...pass
pass
Running bc error file 17.txt through cat with clamping...Running bc error filepass
pass
pass
RunniRunning bc error file 15.txt through cat without clamping... 21.txtng bc error file 24.txt with clamping... without clamping...Running bc error file 18.txt through cat with clamping...pass
pass
pass
pass
pass
Running bc error file 25.txt with clamping...pass
Running bc error file 22.txt without clamping...Running bc error file 19.txt through cat with clamping...pass
Running bc error file 16.txt through cat without clamping...Running bc error file 23.txt without clamping...pass
pass
pass
Running bc error file 20.txt through cat with clamping...pass
Running bc error file 26.txt with clamping...Running bc error file 17.txt through cat without clamping...Running bc error file 24.txt without clamping...Running bc error file 27.txt with clamping...pass
Running bc error file 18.txt through cat without clamping...pass
pass
pass
Running bc error file 21.txt through cat with clamping...pass
Running bc error file 19.txt through cat without clamping...pass
Running bc error file 22.txt through cat with clamping...pass
Running bc error file 25.txt without clamping...Running bc error file 28.txt with clamping...pass
pass
pass
pass
pass
Running bc error file 23.txt through cat with clamping...Running bc error file 20.txt through cat without clamping...RuRunning bc error file 29.txt with clamping...Running bc error file 24.txt through cat with clamping...pass
nning bc error file 26.txt without clamping...pass
Running bc error file 27.txt without clamping...pass
pass
pass
pass
Running bc error file 22.txt through cat without clamping...Running bc error file 30.txt with clamping...Running bc error file 21.txt through cat without clamping...Running bc error file 31.txt with clamping...pass
pass
Running bc error file 25.txt through cat with clamping...Running bc error file 28.txt without clamping...pass
Running bc error file 23.txt through cat without clamping...pass
Running bc error file 27.txt through cat with clamping...pass
Running bc error file 32.txt with clamping...Running bc error file 24.txt through cat without clamping...Skipping problematic bc error file 33.txt...
Running bc error file 26.txt through cat with clamping...pass
pass
pass
pass
paRunning bc error file 29.txt withss
pout clamping...ass
pass
RuRupass
A test failed!
Running bc error file 25.txt through cat without clamping...Running bc error file 30.txt without clamping...passnning bc error file 28.txt through nning bc error file 31.txt without clamping...
cat with clamping...pass
Running bc error file 27.txt through cat without clamping...pass
pass
A test failed!
Running bc error file 34.txt with clamping...Running bc error file 32.txt without clamping...pass
pass
A test failed!
Running bc error file 26.txt through cat without clampiRunning bc error file 29.txt through cat with clamping...pass
ng...pRunning bc error file 35.txt with clamping...pass
Running bc error file 31.txt through cat with clamping...A Running bc error file 36.txt with clamping...pass
Running bc error file 30.txt through cat with clamping...
Running bc quit test...test failed!
ass
pass
A test failed!
pass
Running bc error file 32.txt through cat with clamping...Running bc error file 28.txt through cat without clamping...Running bc error file 34.txt without clamping...pass
pass
pass
pass
RA pass
test failed!
unning bc error file 29.txt through cat without clamping...Running bcpass
 error file 35.txt without clamping...Running bc error file 30.txt through cat without clamping...pass
Running bc error file 31.txt through cat without clamping...Running bc error file 36.txt without clamping...A pass
test failed!
pass
Running bc error file 34.txt through cat with clamping...pA Running bc error file 32.txt through cat without clamping...ass
test failed!
pass
pass
pass
pass
A test failed!
RuRunning bc error file 35.txt through cat with clamping...nning bc error file 36.txt through cat with clamping...Rupass
nning bc environment var tests...pass
A test failed!
Running bc error file 34.txt through cat without clamping...A pass
test failed!
pass
Running bc error file 36.txt through cat without clamping...A test failed!pass
Running bc error file 35.txt through cat witpass

hout clamping...Running keyword redefinition test...paA test failed!
ss
pass
A test failed!
A test failed!
A test failed!
A test failed!
A test failed!
pass
A test failed!
Running multiline comment expression file test...A test failed!
A test failed!
A test failed!
A test failed!
pass
A test failed!
A test failed!
A Rtest ufnaniilnegd !m
ultiline comment expression file error test...A test failed!
A test failed!
A test failed!
pass
A test failed!
A test failed!
Running multiline string expression file test...A test failed!
A test failed!
A test failed!
A test failed!
pass
Running multiline string expression file error test...A test failed!
A test failed!
pass
A test failed!
Running bc line length tests...A test failed!
A test failed!
A test failed!
A test failed!
A test failed!
A test failed!
A test failed!
A test failed!
A test failed!
A test failed!
A test failed!
A test failed!
pass
A test failed!
A test failed!
Running bc arg tests...pass
Running bc builtin variable arg tests...pass
Running bc directory test...pass
Running bc binary file test...pass
Running bc binary stdin test...pass
Running bc limits tests...pass
pass
Running bc posix_errors...pass
~/aosp-master-with-phones/external/bc$ 

[TODO] MinGW compilers no longer supported (regression).

Using i686-w64-mingw32 and x86_64-w64-mingw32, the following error is produced, as the -H flag is "not yet implemented" by configure.sh and History support depends on termios.h, which is unavailable in MinGW.

This change occurred between 6bae85d (2018-12-14) and fb14efc (2018-12-22).

Testing C compilers...

CC (gcc) is not compatible with gcc/clang options

usage: ./configure.sh [-b|-d|-c] [-ghHSR] [-O OPT_LEVEL] [-k KARATSUBA_LEN]
...

The previous linenoise-based implementation worked well on Win32 save for a bug where a fresh line (returning from history) could not be reached, as first noted in IRC.

Specifying `--prefix` when cross-compiling

Hey there,

I've encountered an error recently where attempting to cross-compile bc while using CC as the cross compiler and HOSTCC as the compiler and when passing --prefix=/usr as a configuration flag.

It appears that bc is searching for header files in $PREFIX/include, although the help message mentions that these options control the installation directories of bc files and not the directories header/library files are searched for.

The error disappears when I remove the --prefix=/usr flag and the installation defaults to /usr/local as there's no way to change it because --prefix causes an error.

The error is:

     /usr/include/bits/types/time_t.h:8:9: error: unknown type name '__time64_t'
    8 | typedef __time64_t time_t;
      |         ^~~~~~~~~~

I don't recall changing the configuration flags I use for bc since version 4.0, did the behavior of these flags change?

Thanks in advance!

Incorrect behavior in Windows console

Steps to reproduce:

  1. Run bc.exe
  2. Type any test
  3. Click any arrow button

The result (text is mixed with random chars):
image

The problem is gone if compiled with BC_ENABLE_HISTORY=0

Command switch for scale?

Is there any command line switch to set scale at start, like bc.exe --scale 100? If not, could you please implement?

Build errors after ./configure -a

Hi, just want to make sure I'm not missing something glaringly obvious...

I'm trying to build just the library on macOS, so:

% ./configure -a
Testing for FreeBSD...
Not on FreeBSD. Using _POSIX_C_SOURCE and _XOPEN_SOURCE.

Testing for Mac OSX...
On Mac OSX. Using _DARWIN_C_SOURCE.

Testing for OpenBSD...
Not on OpenBSD.

Version: 6.7.2
Building bc
Building dc

BC_ENABLE_LIBRARY=1

BC_ENABLE_HISTORY=0
BC_ENABLE_EXTRA_MATH=1
BC_ENABLE_NLS=0

BC_ENABLE_AFL=0

BC_NUM_KARATSUBA_LEN=32

CC=c99
CFLAGS= -DBC_ENABLE_EDITLINE=0 -DBC_ENABLE_READLINE=0
HOSTCC=c99
HOSTCFLAGS=
CPPFLAGS=-DNDEBUG  -D_POSIX_C_SOURCE=200809L -D_XOPEN_SOURCE=700
LDFLAGS=-s 
PREFIX=/usr/local
BINDIR=/usr/local/bin
INCLUDEDIR=/usr/local/include
LIBDIR=/usr/local/lib
DATAROOTDIR=/usr/local/share
DATADIR=/usr/local/share
MANDIR=/usr/local/share/man
MAN1DIR=/usr/local/share/man/man1
MAN3DIR=/usr/local/share/man/man3
NLSPATH=
PC_PATH=/opt/homebrew/lib/pkgconfig
EXECSUFFIX=
EXECPREFIX=
DESTDIR=
LONG_BIT=
GEN_HOST=1
GEN_EMU=

Setting Defaults
================
bc.banner=0
bc.sigint_reset=1
dc.sigint_reset=1
bc.tty_mode=1
dc.tty_mode=0
bc.prompt=1
dc.prompt=0
bc.expr_exit=1
dc.expr_exit=1
bc.digit_clamp=0
dc.digit_clamp=0

seems to be happy, but it doesn't actually build:

% make
mkdir -p bin
c99 -DBC_ENABLED=1 -DDC_ENABLED=1 -I./include/ -DBUILD_TYPE=HN  -DEXECPREFIX= -DMAINEXEC=bc  -D_DARWIN_C_SOURCE -DBC_NUM_KARATSUBA_LEN=32 -DBC_ENABLE_NLS=0 -DBC_ENABLE_EXTRA_MATH=1 -DBC_ENABLE_HISTORY=0 -DBC_ENABLE_LIBRARY=1 -DBC_ENABLE_MEMCHECK=0 -DBC_ENABLE_AFL=0 -DBC_DEFAULT_BANNER=0 -DBC_DEFAULT_SIGINT_RESET=1 -DBC_DEFAULT_TTY_MODE=1 -DBC_DEFAULT_PROMPT=1 -DBC_DEFAULT_EXPR_EXIT=1 -DBC_DEFAULT_DIGIT_CLAMP=0 -DDC_DEFAULT_SIGINT_RESET=1 -DDC_DEFAULT_TTY_MODE=0 -DDC_DEFAULT_PROMPT=0 -DDC_DEFAULT_EXPR_EXIT=1 -DDC_DEFAULT_DIGIT_CLAMP=0 -DNDEBUG  -D_POSIX_C_SOURCE=200809L -D_XOPEN_SOURCE=700  -DBC_ENABLE_EDITLINE=0 -DBC_ENABLE_READLINE=0 -o src/args.o -c ./src//args.c
./src//args.c:62:6: error: use of undeclared identifier 'vm'
        if (vm->exprs.v == NULL)
            ^
./src//args.c:64:16: error: use of undeclared identifier 'vm'
                bc_vec_init(&vm->exprs, sizeof(uchar), BC_DTOR_NONE);
                             ^
...lots more...

vm appears to be defined in src/vm.c but inside a #if !BC_ENABLE_LIBRARY, while a lot of code in src/args.c are not correspondingly enclosed. I tried to sprinkle in some #if !BC_ENABLE_LIBRARY directives but that just exposed more code that needed to be #ifdefed out.

Building the executables (i.e., just plain ./configure) compiles and runs fine.

Would you mind clarifying if there's more needed than ./configure -a? I couldn't find anything that helps in the build manual, and I get the sense that args.c should not have been in the Makefile at all...

Thanks!

mac build broken by #define of strcpy (conflicts with Apple's fortify implementation)

seems like the attempt to use strcpy_s() on Windows broke the macOS build. it conflicts with the mac's _FORTIFY_SOURCE implementation (which [TIL] appears to be on by default), which has a #define of strcpy to __builtin_strcpy_chk.

here's the easiest option... i went with a new name because i assume you do want fortify where available rather than, say, strncpy() or strlcpy() --- certainly fortify seems closest to strcpy_s():

diff --git a/include/vector.h b/include/vector.h
index 8f7cbbcc..948e4751 100644
--- a/include/vector.h
+++ b/include/vector.h
@@ -441,7 +441,7 @@ void bc_slabvec_print(BcVec *v, const char *func);
  *           contain @a s.
  * @param s  The source string.
  */
-#define strcpy(d, l, s) strcpy(d, s)
+#define lstrcpy(d, l, s) strcpy(d, s)
 
 #else // _WIN32
 
@@ -452,7 +452,7 @@ void bc_slabvec_print(BcVec *v, const char *func);
  *           contain @a s.
  * @param s  The source string.
  */
-#define strcpy(d, l, s) strcpy_s(d, l, s)
+#define lstrcpy(d, l, s) strcpy_s(d, l, s)
 
 #endif // _WIN32
 
diff --git a/src/vector.c b/src/vector.c
index 1cd90f72..022a8548 100644
--- a/src/vector.c
+++ b/src/vector.c
@@ -461,7 +461,7 @@ static char* bc_slab_add(BcSlab *s, const char *str, size_t len) {
 
        ptr = (char*) (s->s + s->len);
 
-       strcpy(ptr, len, str);
+       lstrcpy(ptr, len, str);
 
        s->len += len;
 

(we don't have mac presubmit, so i didn't notice this until i submitted the upgrade this morning.)

Rename configure.sh

Would it be possible to rename the "configure.sh" script to the standard "configure" form?

This change would avoid specific code when packaging it into distributions that use standard templates.

Thank you

Additional arguments

Can you please implement some new command line arguments?

  1. Ability to print equation result without line breaks, i.e. just a solid text.
  2. Ability to force prepending zero in equation result, i.e. 0.123 instead of current .123

--prefix=... is partially ignored?

Testing on Debian11...

After configuring with --prefix=/tmp/bctmpdir and a successful build, make install fails:

/tmp/bc $ make install
./scripts/locale_install.sh /usr/share/locale/%L/%N bc 
mkdir: cannot create directory ‘//usr/share/locale/de_DE.utf8’: Permission denied
mkdir: cannot create directory ‘//usr/share/locale/de_DE.UTF-8’: Permission denied
ln: failed to create symbolic link '//usr/share/locale/de_DE.utf8/bc': No such file or directory
mkdir: cannot create directory ‘//usr/share/locale/en_GB.utf8’: Permission denied
ln: failed to create symbolic link '//usr/share/locale/en_GB.utf8/bc': No such file or directory
mkdir: cannot create directory ‘//usr/share/locale/en_US.utf8’: Permission denied
ln: failed to create symbolic link '//usr/share/locale/en_US.utf8/bc': No such file or directory
./scripts/safe-install.sh -Dm644 manuals/bc.1 /tmp/bctmpdir/share/man/man1/bc.1
./scripts/safe-install.sh -Dm644 manuals/dc.1 /tmp/bctmpdir/share/man/man1/dc.1
./scripts/exec-install.sh /tmp/bctmpdir/bin "" "/tmp/bc/bin"

Some paths aren't adapted to fit the --prefix=... setting, some others fit the desired prefix setting.

Build fails on macOS

platform: MacOS Ventura 13.2.1 (m1 max)
compiler: c99 from Xcode 14.2.0
version: https://git.gavinhoward.com/gavin/bc.git 55a6c05

Build fails:

$ ./configure -O3
<success>
$ make
c99 -DBC_ENABLED=1 -DDC_ENABLED=1 -I./include/ -DBUILD_TYPE=A  -DEXECPREFIX= -DMAINEXEC=bc  -DBC_NUM_KARATSUBA_LEN=32 -DBC_ENABLE_NLS=1 -DBC_ENABLE_EXTRA_MATH=1 -DBC_ENABLE_HISTORY=1 -DBC_ENABLE_LIBRARY=0 -DBC_ENABLE_MEMCHECK=0 -DBC_ENABLE_AFL=0 -DBC_DEFAULT_BANNER=0 -DBC_DEFAULT_SIGINT_RESET=1 -DBC_DEFAULT_TTY_MODE=1 -DBC_DEFAULT_PROMPT=1 -DBC_DEFAULT_EXPR_EXIT=1 -DBC_DEFAULT_DIGIT_CLAMP=0 -DDC_DEFAULT_SIGINT_RESET=1 -DDC_DEFAULT_TTY_MODE=0 -DDC_DEFAULT_PROMPT=0 -DDC_DEFAULT_EXPR_EXIT=1 -DDC_DEFAULT_DIGIT_CLAMP=0 -DNDEBUG  -D_POSIX_C_SOURCE=200809L -D_XOPEN_SOURCE=700 -O3  -DBC_ENABLE_EDITLINE=0 -DBC_ENABLE_READLINE=0 -o src/program.o -c ./src//program.c
./src//program.c:2994:6: error: use of undeclared identifier 'SIGWINCH'
        if (BC_SIG_INTERRUPT(vm))
            ^
./include/status.h:698:45: note: expanded from macro 'BC_SIG_INTERRUPT'
        BC_UNLIKELY((vm)->sig != 0 && (vm)->sig != SIGWINCH)
                                                   ^
./src//program.c:3724:6: error: use of undeclared identifier 'SIGWINCH'
        if (BC_SIG_INTERRUPT(vm))
            ^
./include/status.h:698:45: note: expanded from macro 'BC_SIG_INTERRUPT'
        BC_UNLIKELY((vm)->sig != 0 && (vm)->sig != SIGWINCH)
                                                   ^
2 errors generated.
make: *** [src/program.o] Error 1

I think ideally, configure.sh would detect this, and apply an appropriate set of flags, or the source would be changed appropriately.

As a workaround, this allows a successful build:

CFLAGS=-D_DARWIN_C_SOURCE ./configure -O3

New release

Hi! When are you going to release new version with recent changes?

another mksh/bash difference?

trying to update AOSP to 6.2.4 (https://android-review.googlesource.com/c/platform/external/bc/+/2433072) i hit:

tests/: 413 files pushed, 0 skipped. 6.5 MB/s (1197549 bytes in 0.175s)
scripts/functions.sh: 1 file pushed, 0 skipped. 60.6 MB/s (14190 bytes in 0.000s)
***********************************************************************

Running bc tests...

Running bc decimal...pass
Skipping bc print test
Skipping bc parse test
Skipping bc lib2
Running bc print2...pass
Running bc length...pass
Running bc scale...pass
Skipping bc shift
Running bc add...pass
Running bc subtract...pass
Running bc multiply...pass
Running bc divide...pass
Running bc modulus...pass
Running bc power...pass
Running bc sqrt...pass
Skipping bc trunc
Skipping bc places
Running bc vars...pass
Running bc boolean...pass
Running bc comp...pass
Running bc abs...pass
Running bc assignments...pass
Running bc functions...pass
Skipping bc scientific
Skipping bc engineering
Running bc globals...pass
Running bc strings...pass
Skipping bc strings2 test
Running bc letters...pass
Running bc exponent...pass
Running bc log...pass
Running bc pi...pass
Running bc arctangent...pass
Running bc sine...pass
Running bc cosine...pass
Skipping bc bessel test
Running bc arrays...pass
Running bc misc...pass
Running bc misc1...pass
Running bc misc2...pass
Running bc misc3...pass
Running bc misc4...pass
Running bc misc5...pass
Running bc misc6...pass
Running bc misc7...pass
Running bc misc8...pass
Running bc void...pass
Skipping bc rand
Running bc recursive_arrays...pass
Running bc divmod...pass
Running bc modexp...pass
Skipping bc bitfuncs
Skipping bc leadingzero
Running bc is_number...pass
Running bc is_string...pass
Running bc asciify_array...pass
Running bc line_by_line1...pass
Running bc line_by_line2...pass
Running bc line_loop_quit1...pass
Running bc line_loop_quit2...pass
Running bc stdin tests...pass
/data/local/tmp/bc-tests/tests/scripts.sh[66]: check_d_arg: inaccessible or not found

Exit Code: 127

looking at scripts.sh, it doesn't source functions.sh where the preceding scripts do. i'm not sure why that works with bash? i didn't think bash exported functions by default, but maybe it's doing so?

anyway, i tested the obvious fix (https://android-review.googlesource.com/c/platform/external/bc/+/2433072/2/tests/scripts.sh).

A few issues noted by Void

In Void Linux's issue tracker they have noted a few deficiencies in this bc:

  • The manual pages do not look good in man-db / mandoc.

  • Tests are not passing, but I think this is an issue with their build recipe.

  • Cross-compilation is difficult.

If I rewrote the manpages in mdoc (example from Adélie) would that be acceptable? It would look much better in normal man viewers, and could probably be converted to Markdown for viewing.

I'm not sure what they find difficult about crossing but I will try to cross it a few times and see what I find.

bc attempts to first calculate gigantic obase before erroring out

Dear Mr. Howard,

For gigantic obases, like those below the line, even though they're clearly beyond the hard-coded obase max of 2,147,483,647,bc appears to calculate the expression to full precision before erroring out, thus undermining any early exit criteria that ensure built-in named variables are within designated limits. I haven't tested against ibase but I suspect something similar would plague it, i.e. the right hand side expression is being calculated to full precision before any attempts to check them against caps.

The full zsh-based testing code and output are attached below.

Yours Sincerely
Jason K

ps : I've noticed the same issue plagues both gnu-bc I've installed via Homebrew as well as the macOS built-in bc.

 2 ^ 8 ^  1 := 2 ^          8
 2 ^ 8 ^  2 := 2 ^         64
 2 ^ 8 ^  3 := 2 ^        512
 2 ^ 8 ^  4 := 2 ^       4096
 2 ^ 8 ^  5 := 2 ^      32768
 2 ^ 8 ^  6 := 2 ^     262144
 2 ^ 8 ^  7 := 2 ^    2097152
----------------------------
 2 ^ 8 ^  8 := 2 ^   16777216
 2 ^ 8 ^  9 := 2 ^  134217728
 2 ^ 8 ^ 10 := 2 ^ 1073741824
bc 1.07.1
Copyright 1991-1994, 1997, 1998, 2000, 2004, 2006, 2008, 2012-2017 Free Software Foundation, Inc.

Darwin m1mx4CT 22.3.0 Darwin Kernel Version 22.3.0: Mon Jan 30 20:38:37 PST 2023; root:xnu-8792.81.3~2/RELEASE_ARM64_T6000 arm64

gbc is /usr/local/bin/gbc

BC_BASE_MAX     = 2147483647
BC_DIM_MAX      = 16777215
BC_SCALE_MAX    = 2147483647
BC_STRING_MAX   = 2147483647
MAX Exponent    = 9223372036854775807
Number of vars  = 32767

for __ in $( jot 10 ); do ( time ( printf 'obase=2^8^%d\0' "$__" | xargs -0 -n 1 -P 24 timeout -v --preserve-status --foreground 8 dash -c 'for __; do echo "$__" | gbc; done' _ ) ); echo "\f ----------\n\t finished 2^8^$__ with exit status $? ... \n --------"; done

( printf 'obase=2^8^%d\0' "$__" | xargs -0 -n 1 -P 24 timeout -v  --foregroun)  0.00s user 0.01s system 86% cpu 0.008 total

 ----------
	 finished 2^8^1 with exit status 0 ... 
 --------
Runtime warning (func=(main), adr=13): obase too large, set to 2147483647
( printf 'obase=2^8^%d\0' "$__" | xargs -0 -n 1 -P 24 timeout -v  --foregroun)  0.00s user 0.01s system 58% cpu 0.012 total

 ----------
	 finished 2^8^2 with exit status 0 ... 
 --------
Runtime warning (func=(main), adr=13): obase too large, set to 2147483647
( printf 'obase=2^8^%d\0' "$__" | xargs -0 -n 1 -P 24 timeout -v  --foregroun)  0.00s user 0.00s system 82% cpu 0.007 total

 ----------
	 finished 2^8^3 with exit status 0 ... 
 --------
Runtime warning (func=(main), adr=13): obase too large, set to 2147483647
( printf 'obase=2^8^%d\0' "$__" | xargs -0 -n 1 -P 24 timeout -v  --foregroun)  0.00s user 0.00s system 84% cpu 0.008 total

 ----------
	 finished 2^8^4 with exit status 0 ... 
 --------
Runtime warning (func=(main), adr=13): obase too large, set to 2147483647
( printf 'obase=2^8^%d\0' "$__" | xargs -0 -n 1 -P 24 timeout -v  --foregroun)  0.01s user 0.00s system 90% cpu 0.012 total

 ----------
	 finished 2^8^5 with exit status 0 ... 
 --------
Runtime warning (func=(main), adr=13): obase too large, set to 2147483647
( printf 'obase=2^8^%d\0' "$__" | xargs -0 -n 1 -P 24 timeout -v  --foregroun)  0.14s user 0.01s system 98% cpu 0.143 total

 ----------
	 finished 2^8^6 with exit status 0 ... 
 --------
Runtime warning (func=(main), adr=13): obase too large, set to 2147483647
( printf 'obase=2^8^%d\0' "$__" | xargs -0 -n 1 -P 24 timeout -v  --foregroun)  3.64s user 0.01s system 99% cpu 3.654 total

 ----------
	 finished 2^8^7 with exit status 0 ... 
 --------
timeout: sending signal TERM to command ‘dash’
( printf 'obase=2^8^%d\0' "$__" | xargs -0 -n 1 -P 24 timeout -v  --foregroun)  0.00s user 0.00s system 0% cpu 8.009 total

 ----------
	 finished 2^8^8 with exit status 0 ... 
 --------
timeout: sending signal TERM to command ‘dash’
( printf 'obase=2^8^%d\0' "$__" | xargs -0 -n 1 -P 24 timeout -v  --foregroun)  0.00s user 0.00s system 0% cpu 8.008 total

 ----------
	 finished 2^8^9 with exit status 0 ... 
 --------
Runtime warning (func=(main), adr=13): obase too large, set to 2147483647
timeout: sending signal TERM to command ‘dash’
( printf 'obase=2^8^%d\0' "$__" | xargs -0 -n 1 -P 24 timeout -v  --foregroun)  0.00s user 0.01s system 0% cpu 8.011 total

 ----------
	 finished 2^8^10 with exit status 0 ... 
 --------

Scale argument is ignored

Hi! Here is my command line: bc.exe --mathlib --leading-zeroes --no-line-length --scale=100.

Last argument is ignored by some reason. As I see it --mathlib is overriding scale value

[QUESTION] Bypass Math Overflow for Large Computations

Hi, there,

I love your command line tool and your blog (I read all your posts). You're an amazing developer. I hope one day I can be like you.
I'm opening this issue to ask you if there is any way to bypass the Math error: overflow: number cannot fit error on your calculator. I would like to test it for benchmark purposes against Julia REPL (for example), but your bc gives me this error when the number has too many digits.

Example Calculation: ((169287^137)^920)^13256118217109.

Regards,
STSM

bc freezes evaluating cbrt(0.01)

bin/bc enters an infinite loop while evaluating the cube-root of 0.01

bin/bc -l -e 'cbrt(0.1)'
returns .46415888336127788924 (which is expected)

bin/bc -l -e 'cbrt(0.01)'
freezes

Looking at the definition of root(x,n) in lib2.bc the following loop never exits

while(r!=q){
	r=q
	q=(p*r+x/r^p)/n
}

A simple hack makes the cbrt function working.

while(abs(r-q)>0.000001){
	r=q
	q=(p*r+x/r^p)/n
}

Incoherent rambling followed by a suggestion for an improvement.

Greetings,

I am going to start with some pleasantries and BS and work from there.

Hello. I also like bc. I have some bc-related repos: https://github.com/TediusTimmy/GNU_bc_with_GMP and https://github.com/TediusTimmy/OpenBSD_bc_with_GMP . The first one is an example of how fast bc can be, if we just use GMP. I also fixed as many of the crashes as I was aware of (admittedly, by fixing the back-end to be more robust rather than fixing the garbage generated by the front-end; if you find a crash, please let me know). In the second repo, I have a comparison of the speed of several implementations of bc (based on my own benchmark), including yours. I found it to be roughly comparable to, but still slightly slower than, OpenBSD's bc (except on one specific task, where it even beat GMP). I also wrote a spreadsheet program to use bc-like numbers: https://github.com/TediusTimmy/BC-DeciCalc (which I really need to work on the documentation for).

As for those bug-fixes in GNU bc: I really haven't been able to get ahold of Phil, or Ken. Thankfully, there were some really helpful people at Debian, and maybe one day, either https://salsa.debian.org/debian/bc/-/merge_requests/4 will be merged in, or they will just use a better bc implementation, like yours.

Finally, are you aware of this: https://www.php.net/manual/en/book.bc.php ? They have forked the GNU bc code for number.c and include it in their builds. Maybe they could use the library version of your code? (My only concern would be https://bugs.php.net/bug.php?id=66364 )

On to the issue: I'm not a big fan of your p(x,y) function. Let me explain by way of a contrived example: p(1024,32.1). Now 1024 is 2^10, so this SHOULD give us 2^10^32.1 which is 2^(10*32.1) or 2^321. And that's an integer, so it should be exact. But, when we do this we find that only the first 18 digits are correct with the default scale of 20. As you manipulate the scale variable, you find a correlation between the scale variable and the number of correct digits. So, in order to compute this result to 20 digits of scale, you would need to compute the log and exponential to around 117 digits of scale. I don't think that I'm out of line to expect that when you increase the scale of a computation that maybe the last three digits change and you then get extra new good digits. With this implementation of p(x,y), a good chunk of the number changes.

As I was thinking about this, four cases came up:

  1. If we are raising a number greater than one to a positive power, then we want to bump the scale by the length of the integer part.
  2. If we are raising a number greater than one to a negative power, then we can probably use e(y*l(x)) as that result goes to zero.
  3. Conversely, if we are raising a number less than one to a positive power, then we can probably use e(y*l(x)) as the result goes to zero.
  4. Finally, if if we are raising a number less than one to a negative power, then we need to be extra careful. We need to use the reciprocal to find the integer part, but want the reciprocal to the increased scale to have an accurate result (in my testing, it removed a problem in the unit in the last place).

So, my final function to improve p(x,y), then commentary:

define pow(x,y){
	auto a,i,s,z
	if(0==y)return 1@scale
	if(0==x){
		if(y>0)return 0
		return 1/0
	}
	a=y$
	if(y==a)return(x^a)@scale
	z=0
	if(x<1){
		y=-y
		a=-a
		z=x
		x=1/x
	}
	if(y<0){
		return e(y*l(x))
	}
	i=x^a
	s=scale
	scale+=length(i)
	if(z){
		x=1/z
		i=x^a
	}
	i*=e((y-a)*l(x))
	scale=s
	return i@scale
}

I started with your p(x,y) function and then added code. We begin with some special case handling for zeros, because people will complain (I didn't realize that bc already defines 0^0==1). Next is the detection for the easy case of an integer exponent that you already had. We then handle if x is between zero and one: we save x and proceed with the reciprocal, while negating the exponent. Remember that l(x)==-l(1/x). I specifically ignore if x is negative, because we will eventually call l(x), which will return an erroneous value if x is negative. If the exponent is now negative, we fall back on e(y*l(x)): that number is going to zero anyway. Next, we compute the integral portion of the exponent and use it to get the working scale for the fractional part of the exponent. After that, if we took the reciprocal of x, recompute the reciprocal and the integral part of the exponent at this higher scale to ensure that both are accurate. Penultimately, compute the fractional part of the exponent and multiply it by the integral part to get the complete exponent. Finally, return a result at the desired scale.

build failure without explicit -DBC_ENABLE_LIBRARY=0

this might be WAI as an unsupported configuration, but i accidentally ran into this because i have to maintain a parallel build for Android's build system...

with Android's existing Android.bp file:

FAILED: out/soong/.intermediates/external/bc/bc/android_x86_64_silvermont/obj/external/bc/src/data.o
PWD=/proc/self/cwd prebuilts/clang/host/linux-x86/clang-r428724/bin/clang -c  -Werror=implicit-function-declaration -DANDROID -fmessage-length=0 -W -Wall -Wno-unused -Winit-self -Wpointer-arith -Wunreachable-code-loop-increment -no-canonical-prefixes -DNDEBUG -UDEBUG -fno-exceptions -Wno-multichar -O2 -g -fdebug-info-for-profiling -fno-strict-aliasing -Werror=date-time -Werror=pragma-pack -Werror=pragma-pack-suspicious-include -Werror=string-plus-int -Werror=unreachable-code-loop-increment -D__compiler_offsetof=__builtin_offsetof -faddrsig -fcommon -Werror=int-conversion -fexperimental-new-pass-manager -Wno-reserved-id-macro -Wno-unused-command-line-argument -fcolor-diagnostics -Wno-sign-compare -Wno-defaulted-function-deleted -Wno-inconsistent-missing-override -Wno-c99-designator -Wno-gnu-folding-constant -Wunguarded-availability -D__ANDROID_UNAVAILABLE_SYMBOLS_ARE_WEAK__ -fdebug-prefix-map=/proc/self/cwd= -ftrivial-auto-var-init=zero -enable-trivial-auto-var-init-zero-knowing-it-will-be-removed-from-clang -ffunction-sections -fdata-sections -fno-short-enums -funwind-tables -fstack-protector-strong -Wa,--noexecstack -D_FORTIFY_SOURCE=2 -Wstrict-aliasing=2 -Werror=return-type -Werror=non-virtual-dtor -Werror=address -Werror=sequence-point -Werror=format-security -nostdlibinc -Wno-enum-compare -Wno-enum-compare-switch -Wno-null-pointer-arithmetic -Wno-null-dereference -Wno-pointer-compare -Wno-xor-used-as-pow -Wno-final-dtor-non-final-class -Wno-psabi -m64 -march=slm -mssse3 -msse4 -msse4.1 -msse4.2 -maes -mpopcnt -target x86_64-linux-android10000 -Bprebuilts/gcc/linux-x86/x86/x86_64-linux-android-4.9/x86_64-linux-android/bin -fPIE  -Iexternal/bc/include -Iexternal/bc -D__LIBC_API__=10000 -D__LIBM_API__=10000 -D__LIBDL_API__=10000 -Ibionic/libc/async_safe/include -Isystem/logging/liblog/include -Ibionic/libc/system_properties/include -Isystem/core/property_service/libpropertyinfoparser/include -Iout/soong/.intermediates/external/bc/bc-version.h/gen -isystem bionic/libc/include -isystem bionic/libc/kernel/uapi/asm-x86 -isystem bionic/libc/kernel/uapi -isystem bionic/libc/kernel/android/scsi -isystem bionic/libc/kernel/android/uapi -Wall -Werror -include bc-version.h -DBC_ENABLED=1 -DDC_ENABLED=0 -DBC_ENABLE_EXTRA_MATH=0 -DBC_ENABLE_HISTORY=0 -DBC_ENABLE_LONG_OPTIONS=1 -DBC_ENABLE_NLS=0 -DBC_ENABLE_SIGNALS=1 -Os -std=gnu99 -Isystem/core/include -Isystem/logging/liblog/include -Isystem/media/audio/include -Ihardware/libhardware/include -Ihardware/libhardware_legacy/include -Ihardware/ril/include -Iframeworks/native/include -Iframeworks/native/opengl/include -Iframeworks/av/include  -Werror=bool-operation -Werror=implicit-int-float-conversion -Werror=int-in-bool-context -Werror=int
In file included from external/bc/src/data.c:39:
In file included from external/bc/include/args.h:41:
external/bc/include/vm.h:401:2: error: unknown type name 'BcRNG'
        BcRNG rng;
        ^
1 error generated.

i needed to manually fix this:

diff --git a/Android.bp b/Android.bp
index c0a66126..7160fee1 100644
--- a/Android.bp
+++ b/Android.bp
@@ -24,6 +24,7 @@ cc_defaults {
     "-DDC_ENABLED=0",
     "-DBC_ENABLE_EXTRA_MATH=0",
     "-DBC_ENABLE_HISTORY=0",
+    "-DBC_ENABLE_LIBRARY=0",
     "-DBC_ENABLE_LONG_OPTIONS=1",
     "-DBC_ENABLE_NLS=0",
     "-DBC_ENABLE_SIGNALS=1",
@@ -88,7 +89,7 @@ sh_test {
   host_supported: true,
   device_supported: false,
   data: [
-    "functions.sh",
+    "scripts/functions.sh",
     "tests/**/*",
   ],
 }

the default Makefile hides this because of the CPPFLAGS8 line that ensures BC_ENABLE_LIBRARY is always set.

like i said, maybe WAI and fixed by making my build a bit more like yours, but i thought i'd mention it anyway in case you considered this an accident...

Test failure on aarch64 Alpine Linux


All bc tests passed.

***********************************************************************
Killed

dc crashed (137) on test:

    tests/dc/errors/33.txt
make: *** [Makefile:337: test_dc_errors] Error 137

The referred file tests/dc/errors/33.txt contains a binary file

Windows MSVC compilation problem

Hi,
I'm trying to compile the project using Visual Studio 19, and I get the following error: error C2065: 'SIGWINCH': undeclared identifier. I cannot find such definition in MSVC. MSYS64 version compiles without problems.
Thank you!

Divergence from grammar defined by POSIX

Observe:

$ bc -s <<x
define a(){
}define b(){
}
x

Parse error: bad token
    <stdin>:2

$ bc -s <<x
define a(){
};define b(){
}
x
$

As per POSIX, the first one should work fine, and the second should fail as a newline is required after a semicolon_list production. No other bc implementation exhibits this behavior except busybox bc, which is a fork of this one if I recall correctly.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.