On Sunday, 24 March 2024 at 22:16:06 UTC, Kdevel wrote:
> The term containing the pow
invocation computes the alternating sequence -1, 1, -1, ..., which can be replaced by e.g.
immutable int [2] sign = [-1, 1];
n += sign [i & 1] / (i * 2.0 - 1.0);
This saves the expensive call to the pow function.
I also used this code:
import std.stdio : writefln;
import std.datetime.stopwatch;
enum ITERATIONS = 1_000_000;
enum BENCHMARKS = 20;
auto leibniz(bool speed = true)(int iter) {
double n = 1.0;
static if(speed) const sign = [-1, 1];
for(int i = 2; i < iter; i++) {
static if(speed) {
const m = i << 1;
n += sign [i & 1] / (m - 1.0);
} else {
n += pow(-1, i - 1) / (i * 2.0 - 1.0);
}
}
return n * 4.0;
}
auto pow(F, G)(F x, G n) @nogc @trusted pure nothrow {
import std.traits : Unsigned, Unqual;
real p = 1.0, v = void;
Unsigned!(Unqual!G) m = n;
if(n < 0) {
if(n == -1) return 1 / x;
m = cast(typeof(m))(0 - n);
v = p / x;
} else {
switch(n) {
case 0: return 1.0;
case 1: return x;
case 2: return x * x;
default:
}
v = x;
}
while(true) {
if(m & 1) p *= v;
m >>= 1;
if(!m) break;
v *= v;
}
return p;
}
void main()
{
double result;
long total_time = 0;
for(int i = 0; i < BENCHMARKS; i++)
{
auto sw = StopWatch(AutoStart.no);
sw.start();
result = ITERATIONS.leibniz;//!false;
sw.stop();
total_time += sw.peek.total!"nsecs";
}
result.writefln!"%0.21f";
writefln("Avg execution time: %f\n", total_time / BENCHMARKS / 1e9);
}
and results:
> dmd -run "leibnizTest.d"
3.141594653593692054727
Avg execution time: 0.002005
If I compile with leibniz!false(ITERATIONS) the average execution time increases slightly:
> Avg execution time: 0.044435
However, if you pay attention, it is not connected to an external library and a power function that works with integers is used. Normally the following function of the library should be called:
> Unqual!(Largest!(F, G)) pow(F, G)(F x, G y) @nogc @trusted pure nothrow
if (isFloatingPoint!(F) && isFloatingPoint!(G))
...
Now, the person asking the question will ask why it is slow even though we use exactly the same codes in C; rightly. You may think that the more watermelon you carry in your arms, the slower you naturally become. I think the important thing is not to drop the watermelons :)
SDB@79