mirror of
https://github.com/dlang/dmd.git
synced 2025-04-26 05:00:16 +03:00
166 lines
4.4 KiB
D
166 lines
4.4 KiB
D
// PERMUTE_ARGS:
|
|
// REQUIRED_ARGS:
|
|
|
|
// NOTE: the shootout is under a BSD license
|
|
// The Great Computer Language Shootout
|
|
// http://shootout.alioth.debian.org/
|
|
//
|
|
// contributed by Sebastien Loisel
|
|
|
|
import core.stdc.math;
|
|
|
|
alias fl F;
|
|
struct fl
|
|
{
|
|
double a;
|
|
|
|
static fl opCall() { fl f; f.a = 0; return f; }
|
|
static fl opCall(fl v) { fl f; f.a = v.a; return f; }
|
|
void set(double x)
|
|
{
|
|
if(x==0) { a=0; return; }
|
|
int k=cast(int)log(fabs(x));
|
|
a=round(x*exp(-k+6.0))*exp(k-6.0);
|
|
}
|
|
static fl opCall(int x) { fl f; f.set(x); return f; }
|
|
static fl opCall(double x) { fl f; f.set(x); return f; }
|
|
fl opBinary(string op : "+")(fl y) { return fl(a+y.a); }
|
|
fl opOpAssign(string op : "+")(fl y) { this=(this)+y; return this; }
|
|
fl opBinary(string op : "-")(fl y) { return fl(a-y.a); }
|
|
fl opOpAssign(string op : "+")(fl y) { this=(this)-y; return this; }
|
|
fl opBinary(string op : "*")(fl y) { return fl(a*y.a); }
|
|
fl opBinary(string op : "/")(fl y) { return fl(a/y.a); }
|
|
|
|
fl opBinary(string op : "+")(int y) { return fl(a+y); }
|
|
fl opBinary(string op : "-")(int y) { return fl(a-y); }
|
|
fl opBinary(string op : "*")(int y) { return fl(a*y); }
|
|
fl opBinary(string op : "/")(int y) { return fl(a/y); }
|
|
|
|
fl opBinary(string op : "+")(double y) { return fl(a+y); }
|
|
fl opBinary(string op : "-")(double y) { return fl(a-y); }
|
|
fl opBinary(string op : "*")(double y) { return fl(a*y); }
|
|
fl opBinary(string op : "/")(double y) { return fl(a/y); }
|
|
}
|
|
|
|
struct ad
|
|
{
|
|
F x, dx;
|
|
static ad opCall() { ad t; t.x = F(0); t.dx = F(0); return t; }
|
|
static ad opCall(int y) { ad t; t.x = F(y); t.dx = F(0); return t; }
|
|
static ad opCall(F y) { ad t; t.x = y; t.dx = F(0); return t; }
|
|
static ad opCall(F X, F DX) { ad t; t.x = X; t.dx = DX; return t; }
|
|
ad opBinary(string op : "+")(ad y) { return ad(x+y.x,dx+y.dx); }
|
|
ad opBinary(string op : "-")(ad y) { return ad(x-y.x,dx-y.dx); }
|
|
ad opBinary(string op : "*")(ad y) { return ad(x*y.x,dx*y.x+x*y.dx); }
|
|
ad opBinary(string op : "/")(ad y) { return ad(x/y.x,(dx*y.x-x*y.dx)/(y.x*y.x)); }
|
|
ad opBinary(string op : "*")(F v) { return ad(x*v,dx*v); }
|
|
ad opBinary(string op : "+")(F v) { return ad(x+v,dx); }
|
|
}
|
|
|
|
F sqr(F x) { return x * x; }
|
|
ad sqr(ad x) { return x * x; }
|
|
|
|
F pow(F x, int i)
|
|
{
|
|
if(i < 1) return F(1);
|
|
if(i & 1) if(i == 1) return x; else return x * pow(x,i-1);
|
|
return sqr(pow(x,i/2));
|
|
}
|
|
ad pow(ad x, int i)
|
|
{
|
|
if(i < 1) return ad(1);
|
|
if(i & 1) if(i == 1) return x; else return x * pow(x,i-1);
|
|
return sqr(pow(x,i/2));
|
|
}
|
|
|
|
F rat(F x)
|
|
{
|
|
F t = (x * F(2) + pow(x,2) * F(3) + pow(x,6) * F(7) + pow(x,11) * F(5) + F(1))
|
|
/ (x * F(5) - pow(x,3) * F(6) - pow(x,7) * F(3) + F(2));
|
|
return t;
|
|
}
|
|
ad rat(ad x)
|
|
{
|
|
ad t = (x * ad(2) + pow(x,2) * ad(3) + pow(x,6) * ad(7) + pow(x,11) * ad(5) + ad(1))
|
|
/ (x * ad(5) - pow(x,3) * ad(6) - pow(x,7) * ad(3) + ad(2));
|
|
return t;
|
|
}
|
|
|
|
F newton(F x0, int n, trapezoid_method_rooter g)
|
|
{
|
|
|
|
for(int i=0 ; i<n; i++)
|
|
{
|
|
ad val = g( ad(x0,F(1)) ); // ad = trapezoid_method_rooter(ad);
|
|
//**
|
|
x0 = x0 - val.x / val.dx;
|
|
/+
|
|
F t0 = val.x;
|
|
F t1 = val.dx;
|
|
x0 = x0 - t0 / t1;
|
|
+/
|
|
}
|
|
|
|
return x0;
|
|
}
|
|
|
|
struct trapezoid_method_rooter
|
|
{
|
|
sqrintegrand g;
|
|
ad g0;
|
|
F y0, t0, t1;
|
|
trapezoid_method_rooter opCall(sqrintegrand G, F Y0, F T0, F T1)
|
|
{
|
|
g = G;
|
|
y0 = Y0;
|
|
t0 = T0;
|
|
t1 = T1;
|
|
g0 = G(T0,Y0); // ad = sqr/ratintegrand(float,float);
|
|
return this;
|
|
}
|
|
ad opCall(ad y1)
|
|
{
|
|
return (g(ad(t1),y1) + g0) * ((t1-t0)/F(2)) + y0 - y1; // ad = sqr/ratintegrand(ad,ad);
|
|
}
|
|
}
|
|
|
|
F trapezoid_method(F t0, F dt, F y0, sqrintegrand g, int numsteps)
|
|
{
|
|
for(int i = 0; i < numsteps; i++)
|
|
{
|
|
trapezoid_method_rooter solver;
|
|
y0 = newton(y0,10,solver(g,y0,t0,t0+dt));
|
|
t0 = t0 + dt;
|
|
}
|
|
return y0;
|
|
}
|
|
|
|
struct sqrintegrand
|
|
{
|
|
ad opCall(F t, F y) { return ad(sqr(y)); }
|
|
ad opCall(ad t, ad y) { return sqr(y); }
|
|
}
|
|
|
|
struct ratintegrand
|
|
{
|
|
ad opCall(F t, F y) { return ad(rat(y) - t); }
|
|
ad opCall(ad t, ad y) { return rat(y) - t; }
|
|
}
|
|
|
|
auto integrate_functions(F x0, int n)
|
|
{
|
|
sqrintegrand i1;
|
|
return trapezoid_method(F(1), F(1) / F(n), x0, i1 ,n).a;
|
|
}
|
|
|
|
int main(string[] args)
|
|
{
|
|
int N = 50;
|
|
|
|
const res = integrate_functions(F(0.02),N);
|
|
|
|
assert(0.01999 < res);
|
|
assert(res < 0.02);
|
|
|
|
return 0;
|
|
}
|