Arithmetic/Rational: Difference between revisions
Content added Content deleted
(Improved D entry) |
(Updated D entry) |
||
Line 370: | Line 370: | ||
<lang d>import std.bigint, std.traits, std.conv; |
<lang d>import std.bigint, std.traits, std.conv; |
||
⚫ | |||
T gcd(T)( |
T gcd(T)(in T a, in T b) pure /*nothrow*/ { |
||
⚫ | |||
return (b != 0) ? gcd(b, a % b) : (a < 0) ? -a : a; |
return (b != 0) ? gcd(b, a % b) : (a < 0) ? -a : a; |
||
} |
} |
||
T lcm(T)( |
T lcm(T)(in T a, in T b) pure /*nothrow*/ { |
||
return a / gcd(a, b) * b; |
return a / gcd(a, b) * b; |
||
} |
} |
||
struct RationalT(T) { |
struct RationalT(T) { |
||
private T num, den; // Numerator & denominator. |
|||
private enum Type { NegINF = -2, |
private enum Type { NegINF = -2, |
||
Line 398: | Line 398: | ||
} |
} |
||
this(U, V)( |
this(U, V)(in U n, in V d) pure /*nothrow*/ { |
||
num = toT(n); |
num = toT(n); |
||
den = toT(d); |
den = toT(d); |
||
const common = gcd(num, den); |
|||
if (common != 0) { |
if (common != 0) { |
||
num /= common; |
num /= common; |
||
Line 415: | Line 415: | ||
} |
} |
||
static T toT(U)( |
static T toT(U)(in ref U n) pure nothrow if (is(U == T)) { |
||
return n; |
return n; |
||
} |
} |
||
Line 424: | Line 424: | ||
} |
} |
||
T nomerator() |
T nomerator() const pure nothrow @property { |
||
return num; |
return num; |
||
} |
} |
||
T denominator() |
T denominator() const pure nothrow @property { |
||
return den; |
return den; |
||
} |
} |
||
string toString() /*pure |
string toString() const /*pure nothrow*/ { |
||
if (den != 0) |
if (den != 0) |
||
return num.text ~ (den == 1 ? "" : "/" ~ den.text); |
return num.text ~ (den == 1 ? "" : "/" ~ den.text); |
||
Line 441: | Line 441: | ||
} |
} |
||
real toReal() const { |
real toReal() pure const /*nothrow*/ { |
||
static if (is(T == BigInt)) |
|||
return num.toLong / cast(real)den.toLong; |
return num.toLong / cast(real)den.toLong; |
||
else |
|||
return num / cast(real)den; |
|||
} |
} |
||
RationalT opBinary(string op)( |
RationalT opBinary(string op)(in RationalT r) |
||
const pure /*nothrow*/ if (op == "+" || op == "-") { |
|||
T common = lcm(den, r.den); |
T common = lcm(den, r.den); |
||
T n = mixin("common / den * num" ~ op ~ |
T n = mixin("common / den * num" ~ op ~ |
||
Line 453: | Line 456: | ||
} |
} |
||
RationalT opBinary(string op)( |
RationalT opBinary(string op)(in RationalT r) |
||
const pure /*nothrow*/ if (op == "*") { |
|||
return RationalT(num * r.num, den * r.den); |
return RationalT(num * r.num, den * r.den); |
||
} |
} |
||
RationalT opBinary(string op)( |
RationalT opBinary(string op)(in RationalT r) |
||
const pure /*nothrow*/ if (op == "/") { |
|||
return RationalT(num * r.den, den * r.num); |
return RationalT(num * r.den, den * r.num); |
||
} |
} |
||
RationalT opBinary(string op, U)(in U r) |
RationalT opBinary(string op, U)(in U r) |
||
const pure /*nothrow*/ if (isIntegral!U && (op == "+" || |
|||
op == "-" || op == "*" || op == "/")) { |
|||
return opBinary!op(RationalT(r)); |
return opBinary!op(RationalT(r)); |
||
} |
} |
||
RationalT opBinary(string op)(in size_t p) |
RationalT opBinary(string op)(in size_t p) |
||
const pure /*nothrow*/ if (op == "^^") { |
|||
return RationalT(num ^^ p, den ^^ p); |
return RationalT(num ^^ p, den ^^ p); |
||
} |
} |
||
RationalT opBinaryRight(string op, U)(in U l) |
RationalT opBinaryRight(string op, U)(in U l) |
||
const pure /*nothrow*/ if (isIntegral!U) { |
|||
return RationalT(l).opBinary!op(RationalT(num, den)); |
return RationalT(l).opBinary!op(RationalT(num, den)); |
||
} |
} |
||
RationalT opOpAssign(string op, U)( |
RationalT opOpAssign(string op, U)(in U l) pure /*nothrow*/ { |
||
/*const pure nothrow*/ { |
|||
mixin("this = this " ~ op ~ "l;"); |
mixin("this = this " ~ op ~ "l;"); |
||
return this; |
return this; |
||
Line 486: | Line 488: | ||
RationalT opUnary(string op)() |
RationalT opUnary(string op)() |
||
const pure /*nothrow*/ if (op == "+" || op == "-") { |
|||
return RationalT(mixin(op ~ "num"), den); |
return RationalT(mixin(op ~ "num"), den); |
||
} |
} |
||
Line 494: | Line 496: | ||
} |
} |
||
int opEquals(U)( |
int opEquals(U)(in U r) const pure nothrow { |
||
RationalT rhs = RationalT(r); |
RationalT rhs = RationalT(r); |
||
if (type() == Type.NaRAT || rhs.type() == Type.NaRAT) |
if (type() == Type.NaRAT || rhs.type() == Type.NaRAT) |
||
Line 501: | Line 503: | ||
} |
} |
||
int opCmp(U)( |
int opCmp(U)(in U r) const pure nothrow { |
||
auto rhs = RationalT(r); |
auto rhs = RationalT(r); |
||
if (type() == Type.NaRAT || rhs.type() == Type.NaRAT) |
if (type() == Type.NaRAT || rhs.type() == Type.NaRAT) |
||
Line 513: | Line 515: | ||
} |
} |
||
Type type() |
Type type() const pure nothrow { |
||
if (den > 0) return Type.NORMAL; |
if (den > 0) return Type.NORMAL; |
||
if (den < 0) return Type.NegDEN; |
if (den < 0) return Type.NegDEN; |