fredrikj.net / blog /

Calcium 0.1

September 8, 2020

This post will be is a short announcement of Calcium, a new project I've been working on since April. The code is still highly experimental, but I have tagged version 0.1 to solicit feedback sooner rather than later.

Briefly, Calcium is a C library for computing exactly with real and complex numbers. This means not only being being able to evaluate numbers to arbitrary precision, but being able to solve problems requiring exact comparisons. In Calcium, $(\pi + 1) - 1 = \pi$ exactly. You can think of it as a computer algebra system limited to constant values, or as something like Sage's exact field of algebraic numbers but faster (at least for certain things) and with support for transcendental numbers too.

Calcium builds on Arb (for arbitrary-precision ball arithmetic), Flint (for rational numbers and multivariate polynomial arithmetic) and Antic (for arithmetic in algebraic number fields). The basic idea behind Calcium is to represent numbers as elements of formal fields $\mathbb{Q}(a_1,\ldots,a_n)$ where the extension numbers $a_k$ can be algebraic or transcendental. Simplifications are handled through the field arithmetic together with ideal reduction. This is reasonably fast even for huge expressions thanks to Flint and Antic. Algebraic relations between extension numbers are discovered automatically using LLL and proved through symbolic tests and recursive field computations. The field constructions are managed automatically by the system so that numbers (the Calcium ca_t type) are very easy to use.

To get a better idea of what Calcium can do, the example programs are a good place to start. Here are some examples of expressions that Calcium automatically evaluates to a simple form:

$$\frac{\varphi^{100} - (1-\varphi)^{100}}{\sqrt{5}} \; \rightarrow \; 354224848179261915075$$ $$i^i - e^{-\pi/2} \; \rightarrow \; 0$$ $$\frac{\log(1 + \sqrt{2})}{\log(3 + 2 \sqrt{2})} \; \rightarrow \; \frac{1}{2}$$ $$12 \operatorname{atan}\left(\frac{1}{49}\right) + 32\operatorname{atan}\left(\frac{1}{57}\right) -5 \operatorname{atan}\left(\frac{1}{239}\right) + 12 \operatorname{atan}\left(\frac{1}{110443}\right) - \frac{\pi}{4} \; \rightarrow \; 0$$

Another nice example is constructing Swinnerton-Dyer polynomials $$S_n = \prod (x \pm \sqrt{2} \pm \sqrt{3} \pm \sqrt{5} \pm \ldots \pm \sqrt{p_n}),$$ for example $$S_3 = (x+\sqrt{2}+\sqrt{3}+\sqrt{5})(x+\sqrt{2}+\sqrt{3}-\sqrt{5})\cdots(x-\sqrt{2}-\sqrt{3}-\sqrt{5}) = x^8 - 40x^6 + 352x^4 - 960x^2 + 576.$$ With Calcium, you can just construct the list of roots and multiply out the polynomial. The $n = 10$ polynomial which has degree 1024 and 800-digit coefficients takes 10 seconds to compute. It can be done faster with Arb, but 10 seconds is not bad for a symbolic solution requiring no cleverness at all on the part of the user.

Yet another nice benchmark problem comes from a Sage help request posted recently, in which a user asked for a way to prove equality of two algebraic numbers defined by huge (7000 arithmetic operations) formulas. This takes forever with Sage's QQbar unless the user makes some manipulations to put the input in a better form. Calcium solves the problem in the original form in 8 minutes, and in only 25 seconds if one uses Calcium's internal algebraic number type (qqbar_t) instead of the general-purpose Calcium number type ca_t (it should be possible to fix this discrepancy: on this test problem, the ca_t type is slow partly for entirely stupid reasons).

Right now, Calcium's performance is all over the place. Some things are extremely fast, other things are absurdly slow. Many simplifications don't work, either because the algorithms are not implemented, or because they would be too expensive to apply automatically. Calcium is already reasonably good at determining whether expressions involving logarithms are equal; it knows much less about powers and exponentials and things like real and imaginary parts of numbers. Calcium can always decide equality of algebraic numbers, but merely evaluating an expression does not automatically produce a fully simplified form. For example, $$\sqrt{5 + 2 \sqrt{6}} - \sqrt{2} - \sqrt{3}$$ does not automatically evaluate to zero (but Calcium will prove that it equals zero when prompted through ca_check_is_zero). Should this expression evaluate to zero automatically? Arguably, yes, but then there will be a line to draw somewhere else. I'm going to explore the cost-benefit tradeoffs for expensive simplifications further in the future (hopefully, there will be tricks so that even "expensive" simplifications become practical).

Calcium is in some ways an outgrowth of the Python library for symbolic expressions which I started developing last year as part of Fungrim, though it is motivated by other applications as well. It turns out that much of the complexity when manipulating symbolic expressions over the complex numbers is in actually manipulating constant values, so it seemed like a good idea to write a library specifically for this. At first, I considered developing Calcium as a Python library or a Julia library, but after some thought I decided that it was going to be doable in plain C.

There is a long list of things left to do before Calcium can be considered production-ready. This will probably keep me occupied for several months. There will hopefully be time for other projects too :-)