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;


// std.numeric.gcd doesn't work with BigInt.
T gcd(T)(/*in*/ T a, /*in*/ T b) /*pure nothrow*/ {
T gcd(T)(in T a, in T b) pure /*nothrow*/ {
// std.numeric.gcd doesn't work with BigInt.
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)(/*in*/ T a, /*in*/ T b) {
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) {
/*const*/ private T num, den; // Numerator & denominator.
private T num, den; // Numerator & denominator.


private enum Type { NegINF = -2,
private enum Type { NegINF = -2,
Line 398: Line 398:
}
}


this(U, V)(/*in*/ U n, /*in*/ V d) /*pure nothrow*/ {
this(U, V)(in U n, in V d) pure /*nothrow*/ {
num = toT(n);
num = toT(n);
den = toT(d);
den = toT(d);
/*const*/ T common = gcd(num, den);
const common = gcd(num, den);
if (common != 0) {
if (common != 0) {
num /= common;
num /= common;
Line 415: Line 415:
}
}


static T toT(U)(/*in*/ ref U n) pure nothrow if (is(U == T)) {
static T toT(U)(in ref U n) pure nothrow if (is(U == T)) {
return n;
return n;
}
}
Line 424: Line 424:
}
}


T nomerator() /*const*/ pure nothrow @property {
T nomerator() const pure nothrow @property {
return num;
return num;
}
}


T denominator() /*const*/ pure nothrow @property {
T denominator() const pure nothrow @property {
return den;
return den;
}
}


string toString() /*pure const*/ {
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)(/*in*/ RationalT r)
RationalT opBinary(string op)(in RationalT r)
/*const pure nothrow*/ if (op == "+" || op == "-") {
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)(/*in*/ RationalT r)
RationalT opBinary(string op)(in RationalT r)
/*const pure nothrow*/ if (op == "*") {
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)(/*in*/ RationalT r)
RationalT opBinary(string op)(in RationalT r)
/*const pure nothrow*/ if (op == "/") {
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 == "+" ||
const pure /*nothrow*/ if (isIntegral!U && (op == "+" ||
op == "-" || op == "*" || 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 == "^^") {
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) {
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)(/*in*/ U l)
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 == "-") {
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)(/*in*/ U r) /*const pure nothrow*/ {
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)(/*in*/ U r) /*const pure nothrow*/ {
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() /*const pure nothrow*/ {
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;