Last active
June 29, 2016 14:34
-
-
Save wilzbach/ddc216a90c7a86964c637d676f17a32c to your computer and use it in GitHub Desktop.
Tricky enum bug with ranges
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
iv: -0x1p+0, -0x1.ccccccccccccdp-1 | |
iv: -0x1p+0, -0x1.ccccccccccccdp-1 | |
Interval!real(-1, -0.9, 2, 0, -nan, 0.118267, 2.00562, LinearFun!real(nan, nan, nan), LinearFun!real(nan, nan, nan)) | |
--- | |
iv.lx -1.0000000000 (-0x8p-3) | |
hat.a 0.1182672100 (0xf.23614391d01ffb5p-7) | |
hat.slope 1.1826721000 (0x9.761cca3b2214947p-3) | |
hat.y -0.9000000000 (-0xe.6666666666668p-4) | |
hat(p1) 0.0000000000 (0x0p+0) | |
hat(p2) 0.1182672100 (0xf.23614391d01ffb5p-7) | |
------ | |
with 'real' real | |
------ | |
iv1: -0x8p-3, -0xe.666666666666666p-4 | |
iv2: -0x1p+0, -0x1.ccccccccccccdp-1 | |
Interval!real(-1, -0.9, 2, 0, -nan, 0.118267, 2.00562, LinearFun!real(nan, nan, nan), LinearFun!real(nan, nan, nan)) | |
Interval!real(-1, -0.9, 2, 0, -nan, 0.118267, 2.00562, LinearFun!real(nan, nan, nan), LinearFun!real(nan, nan, nan)) | |
--- | |
iv.lx -1.0000000000 (-0x8p-3) | |
hat.a 0.1182672100 (0xf.23614391d021968p-7) | |
hat.slope 1.1826721000 (0x9.761cca3b2214fdfp-3) | |
hat.y -0.9000000000 (-0xe.666666666666666p-4) | |
hat(p1) -0.0000000000 (-0x8p-70) | |
hat(p2) 0.1182672100 (0xf.23614391d021968p-7) | |
--- | |
iv.lx -1.0000000000 (-0x8p-3) | |
hat.a 0.1182672100 (0xf.23614391d021968p-7) | |
hat.slope 1.1826721000 (0x9.761cca3b2214fdfp-3) | |
hat.y -0.9000000000 (-0xe.666666666666666p-4) | |
hat(p1) -0.0000000000 (-0x8p-70) | |
hat(p2) 0.1182672100 (0xf.23614391d021968p-7) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
void transform(S)(S c, S f0, S f1, ref S t0, ref S t1) | |
{ | |
import std.math: pow, exp, copysign; | |
// for c=0 no transformations are applied | |
t0 = (c == 0) ? f0 : copysign(S(1), c) * exp(c * f0); | |
t1 = (c == 0) ? f1 : c * t0 * f1; | |
} | |
Interval!S transformToInterval(S)(in S l, in S r, in S c, | |
in S lf0, in S lf1, | |
in S rf0, in S rf1) | |
{ | |
S lt0 = void, lt1 = void, rt0 = void, rt1 = void; | |
transform(c, lf0, lf1, lt0, lt1); | |
transform(c, rf0, rf1, rt0, rt1); | |
return Interval!S(l, r, c, lt0, lt1, rt0, rt1); | |
} | |
LinearFun!S secant(S)(in S xl, in S xr, in S yl, in S yr) | |
{ | |
auto slope = (yr - yl) / (xr - xl); | |
// y (aka x0) is defined to be the maximal point of the boundary | |
if (yl >= yr) | |
return LinearFun!S(slope, xl, yl); | |
else | |
return LinearFun!S(slope, xr, yr); | |
} | |
void determineSqueezeAndHat(S)(ref Interval!S iv) | |
{ | |
auto sec = secant(iv.lx, iv.rx, iv.ltx, iv.rtx); | |
auto t_l = LinearFun!S(iv.lx, iv.ltx, iv.lt1x); | |
auto t_r = LinearFun!S(iv.rx, iv.rtx, iv.rt1x); | |
iv.squeeze = iv.ltx < iv.rtx ? t_l : t_r; | |
iv.hat = sec; | |
} | |
struct LinearFun(S) | |
{ | |
/// direction and steepness | |
S slope; // aka beta | |
S _y; | |
S _a; | |
S a() @property const | |
{ | |
return _a; | |
} | |
this(in S slope, in S _y, in S _a) | |
{ | |
this.slope = slope; | |
this._y = _y; | |
this._a = _a; | |
} | |
/// call the linear function with x | |
S opCall(in S x) const | |
{ | |
return _a + slope * (x - _y); | |
} | |
} | |
struct Interval(S) | |
{ | |
/// positions of the interval | |
immutable S lx; | |
S rx; | |
/// T_c family of the interval | |
immutable S c; | |
/// transformed values | |
immutable S ltx, lt1x; | |
S rtx, rt1x; | |
LinearFun!S hat; | |
LinearFun!S squeeze; | |
/// only supported constructor | |
this (S lx, S rx, S c, | |
S ltx, S lt1x, | |
S rtx, S rt1x) | |
{ | |
this.lx = lx; | |
this.rx = rx; | |
this.c = c; | |
this.ltx = ltx; | |
this.lt1x = lt1x; | |
this.rtx = rtx; | |
this.rt1x = rt1x; | |
} | |
} | |
void main(string[] args) | |
{ | |
import std.stdio; | |
import std.math : log; | |
import std.range : lockstep; | |
import std.range : dropOne, save; | |
alias S = real; | |
auto f0 = (S x) => log(1 - x^^4); | |
auto f1 = (S x) => -4 * x^^3 / (1 - x^^4); | |
auto it = (S l, S r, S c) => transformToInterval!S(l, r, c, f0(l), f1(l), | |
f0(r), f1(r)); | |
enum lr = [-1.0, -0.9]; // -0x8p-3, -0xe.666666666666666p-4; | |
enum c2 = 2.0; | |
writefln("iv: %a, %a", lr[0], lr[1]); | |
// this is 'wrong' | |
foreach (j, p1, p2; lr.lockstep(lr.save.dropOne)) | |
{ | |
writefln("iv: %a, %a", p1, p2); | |
auto iv = it(p1, p2, c2); | |
writeln(iv); | |
determineSqueezeAndHat!S(iv); | |
writeln("---"); | |
writefln("iv.lx %.10f (%1$a)", iv.lx); | |
writefln("hat.a %.10f (%1$a)", iv.hat.a); | |
writefln("hat.slope %.10f (%1$a)", iv.hat.slope); | |
writefln("hat.y %.10f (%1$a)", iv.hat._y); | |
writefln("hat(p1) %.10f (%1$a)", iv.hat(iv.lx)); // bum!! | |
writefln("hat(p2) %.10f (%1$a)", iv.hat(iv.rx)); | |
} | |
writeln("------"); | |
writeln("with 'real' real"); | |
writeln("------"); | |
S p1 = -1.0; // -0x1p+0; | |
S p2 = -0.9; // -0x1.ccccccccccccdp-1; | |
writefln("iv1: %a, %a", p1, p2); | |
writefln("iv2: %a, %a", lr[0], lr[1]); | |
S c = 2; | |
auto iv1 = it(p1, p2, c); | |
auto iv2 = it(lr[0], lr[1], c2); | |
writeln(iv1); | |
writeln(iv2); | |
determineSqueezeAndHat!S(iv1); | |
determineSqueezeAndHat!S(iv2); | |
auto ivs = [iv1, iv2]; | |
foreach (i, ref iv; ivs) | |
{ | |
writeln("---"); | |
writefln("iv.lx %.10f (%1$a)", iv.lx); | |
writefln("hat.a %.10f (%1$a)", iv.hat.a); | |
writefln("hat.slope %.10f (%1$a)", iv.hat.slope); | |
writefln("hat.y %.10f (%1$a)", iv.hat._y); | |
writefln("hat(p1) %.10f (%1$a)", iv.hat(iv.lx)); | |
writefln("hat(p2) %.10f (%1$a)", iv.hat(iv.rx)); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment