simon-git: spigot (master): Simon Tatham
Commits to Tartarus hosted VCS
tartarus-commits at lists.tartarus.org
Thu Aug 15 23:23:43 BST 2019
TL;DR:
6ca2926 Refactor dgreet() to automate class-name printing.
78d972d Permit --debug to take a class name as an argument.
7d04900 Replace pi/tau implementation with Chudnovsky's formula.
Repository: https://git.tartarus.org/simon/spigot.git
On the web: https://git.tartarus.org/?p=simon/spigot.git
Branch updated: master
Committer: Simon Tatham <anakin at pobox.com>
Date: 2019-08-15 23:23:43
commit 6ca292639edcb4042e1904f600d995706b01fd22
web diff https://git.tartarus.org/?p=simon/spigot.git;a=commitdiff;h=6ca292639edcb4042e1904f600d995706b01fd22;hp=34f87c27cd20e509e7ba0f145d933c443faaf1d3
Author: Simon Tatham <anakin at pobox.com>
Date: Thu Aug 15 23:15:05 2019 +0100
Refactor dgreet() to automate class-name printing.
Now debuggable objects' initial calls to dgreet() don't have to start
with the boilerplate "hello" and the classname. That's generated
automatically, so all you have to write is
dgreet(); // if no further information (conveniently) available
dgreet("foo=", foo, " bar=", bar); // if params can usefully be printed
where previously you'd have had to write those as
dgreet("hello SomeClassName");
dgreet("hello SomeOtherClassName foo=", foo, " bar=", bar);
The mechanism for this is that there's a macro MAKE_CLASS_GREETER,
which defines a function that takes a pointer to a given class as a
parameter, ignores it, and (via cpp stringification) returns an object
containing a string representation of the same class name. So you
write MAKE_CLASS_GREETER(SomeClassName) at file scope somewhere it'll
be available to the class's constructor, and then the expansion of the
dgreet() macro includes a function call passing 'this' to that
function, which will select the right overload of the macro-generated
function even if more than one is present in a given translation unit.
Hence, the class names in debug greetings are generated automatically,
which means no typos and less boilerplate. (And if you try to use
dgreet() in the absence of one of those class-name retrieval
functions, you'll get a compile error to remind you.)
Partly the aim of this is to reduce the amount of boring typing I have
to do. But mostly, it's to make the names of debuggable class types
available to spigot at run time, which I'm about to use for extra
--debug functionality.
Notes on the diff for this commit: _most_ of the changes are a
completely boring and mechanical translation of every dgreet() call
into the new format, and adding MAKE_CLASS_GREETER invocations all
over the place. The interesting parts are in spigot.h, where I add a
mechanism for Debuggable to store a class name, implement the
MAKE_CLASS_GREETER macro, and rewrite the dprint() and dgreet() macros
and their system of variadically templated underlying inline
functions.
algebraic.cpp | 9 ++++++---
arithmetic.cpp | 6 ++++--
baseout.cpp | 4 +++-
cfracout.cpp | 4 +++-
consts.cpp | 24 ++++++++++++++++++------
enforce.cpp | 4 +++-
erf.cpp | 4 +++-
exp.cpp | 13 +++++++++----
expint.cpp | 20 +++++++++++++++-----
gamma.cpp | 16 ++++++++++++----
holefiller.cpp | 4 +++-
hypergeom.cpp | 21 +++++++++++++++------
io.cpp | 9 ++++++---
monotone.cpp | 8 ++++++--
spigot.cpp | 34 ++++++++++++++++++++++++++-------
spigot.h | 59 ++++++++++++++++++++++++++++++++++++++++++++--------------
sqrt.cpp | 12 +++++++++---
trig.cpp | 16 ++++++++++++----
trigint.cpp | 5 +++--
unary.cpp | 8 ++++++--
zeta.cpp | 4 +++-
21 files changed, 211 insertions(+), 73 deletions(-)
commit 78d972dd53caebf904d5c99c1f6b70167b219301
web diff https://git.tartarus.org/?p=simon/spigot.git;a=commitdiff;h=78d972dd53caebf904d5c99c1f6b70167b219301;hp=6ca292639edcb4042e1904f600d995706b01fd22
Author: Simon Tatham <anakin at pobox.com>
Date: Thu Aug 15 23:15:05 2019 +0100
Permit --debug to take a class name as an argument.
Now if I know which class I want to examine the progress of, I can
write things like 'spigot --debug=AlgebraicPrep', or 'spigot
--debug=Core2', which is easier than the previous approach of starting
with '--debug=greetings', grepping out the numeric debug id of the
class instance I was interested in, and then re-running with that id.
This is achieved by adapting the previous commit so that the
MAKE_CLASS_GREETER function returns a special Debuggable::ClassName
object in place of a string. All those objects are declared at file
scope to ensure they're constructed at startup, and the constructor
automatically registers each object in a centralised list, similarly
to the registration system in expr.cpp introduced by commit 3c9df5aa7.
So the option-parsing code in main() knows what's a legal class name
and what isn't, and it can even print a list of all of them if you
need it to (via the option --debug=help).
At the moment, the new --debug=ClassName syntax will print all debug
messages from all instances of that class. So if there are lots (e.g.
it's a class used by the operand to MonotoneHelper), they may all be
interleaved. I'm undecided about whether that's the best thing; I may
yet introduce further refinements like --debug=ClassName:greetings
(equivalent to --debug=greetings | grep ClassName), or
--debug=ClassName:first, or --debug=ClassName:12 (for the 12th
instance)...
main.cpp | 28 +++++++++++++++++++++++++++-
spigot.cpp | 53 +++++++++++++++++++++++++++++++++++++++++++++++++++--
spigot.h | 24 ++++++++++++++++++++++--
3 files changed, 100 insertions(+), 5 deletions(-)
commit 7d049000e69c16f0fcff91ecf2c4af8de39c0569
web diff https://git.tartarus.org/?p=simon/spigot.git;a=commitdiff;h=7d049000e69c16f0fcff91ecf2c4af8de39c0569;hp=78d972dd53caebf904d5c99c1f6b70167b219301
Author: Simon Tatham <anakin at pobox.com>
Date: Thu Aug 15 23:15:06 2019 +0100
Replace pi/tau implementation with Chudnovsky's formula.
I found out about this quite recently. It consists of a very silly-
looking infinite series, which converges linearly but with a very good
constant of proportionality: the terms decrease by a factor of about
1.5e14 each time, i.e. you get 14 extra decimal digits of precision
per term!
The downside is that once you've summed the series, you have to take
the reciprocal and multiply by sqrt(10005) to get to a rational
multiple of pi. But the fast convergence more than makes up for that:
in a speed test over 100,000 digits, I found this implementation wins
by nearly a factor of two over spigot's previous strategy of using
Machin's formula. So it's definitely worth switching.
The series is actually expressible as an instance of the generalised
hypergeometric function. You can implement this pi-evaluation strategy
manually in spigot's existing expression language by writing
let chudnovsky_pi = 426880/13591409 sqrt(10005) /
Hg(1/6, 1/2, 5/6, 558731543/545140134;
1, 1, 13591409/545140134;
-1/53360^3)
and even that is pretty fast. But for the official implementation of
the built-in constant 'pi', I've handwritten a custom spigot class for
the series component, which can get away with being more streamlined
than the existing generalised-hypergeometric machinery, and squeezes
out a bit of extra speed.
It's natural to wonder if this might also be faster at computing the
internal constant pi^2/6, because if you square the Chudnovsky formula
for pi, the sqrt(10005) factor becomes rational, so you end up with a
pure rational multiple of 1/(sum of series)^2. But I tried it, and the
existing pi^2/6 implementation is still quite a lot faster, so I've
left that one as it is. I imagine the Core2 / spigot_square()
mechanism is probably losing everything that the fast implementation
of pi gains.
consts.cpp | 146 +++++++++++++++++++++++++++++++++++++++++++++++--------------
manual.but | 4 +-
2 files changed, 114 insertions(+), 36 deletions(-)
More information about the tartarus-commits
mailing list