Skip to content

Instantly share code, notes, and snippets.

@majiang
Created November 10, 2013 01:12
Show Gist options
  • Select an option

  • Save majiang/7392313 to your computer and use it in GitHub Desktop.

Select an option

Save majiang/7392313 to your computer and use it in GitHub Desktop.
Fixed point arithmetic
module fixed;
import std.traits : isSigned;
struct Fixed(BaseSigned, size_t digitsFraction)
if (isSigned!BaseSigned)
{
BaseSigned x;
Fixed opBinary(string op)(Fixed!(BaseSigned, digitsFraction) rhs) pure
if (op == "+" || op == "-" || op == "*" || op == "/")
{
auto lhs = this;
mixin ("lhs "~op~"= rhs;");
return lhs;
}
Fixed opOpAssign(string op)(Fixed!(BaseSigned, digitsFraction) rhs)
if (op == "+" || op == "-" || op == "*" || op == "/")
{
auto y = rhs.x;
static if (op == "*" || op == "/")
{
immutable bool sign = (x < 0) != (y < 0);
if (x < 0) x = -x;
if (y < 0) y = -y;
}
static if (op == "*")
{
// right shift x and y, by total of digitsFraction.
auto r = digitsFraction;
while (r)
{
(x < y ? y : x) >>= 1;
r -= 1;
}
}
static if (op == "/")
{
// left shift x and right shift y, by total of digitsFraction.
auto r = digitsFraction;
while (r && (x << 1 >> 1 == x))
{
x <<= 1;
r -= 1;
}
while (r)
{
y >>= 1;
r -= 1;
}
}
mixin ("x "~op~"= y;");
return this;
}
string toString()
{
import std.conv : to;
import std.math;
return (x / (2.0 ^^ digitsFraction)).to!string();
}
}
unittest
{
import std.stdio;
alias Fixed!(long, 16) myfloat;
auto x = myfloat(31415926);
auto y = myfloat(27182818);
"%s + %s = %s".writefln(x.toString(), y.toString(), (x + y).toString());
"%s - %s = %s".writefln(x.toString(), y.toString(), (x - y).toString());
"%s * %s = %s".writefln(x.toString(), y.toString(), (x * y).toString());
"%s / %s = %s".writefln(x.toString(), y.toString(), (x / y).toString());
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment