Skip to content

Instantly share code, notes, and snippets.

@Laeeth
Created July 2, 2015 21:02
Show Gist options
  • Save Laeeth/6251fa731e4cee84bcdc to your computer and use it in GitHub Desktop.
Save Laeeth/6251fa731e4cee84bcdc to your computer and use it in GitHub Desktop.
surprise - hacked up attempt at fixedpoint causes some difficulties...
// idea here was to have a dummy type as a placeholder so I could work on other features of library and could later implement properly.
// I do think this is one prominent feature missing in D
module kprop.math.fixeddecimal;
import std.stdio;
import std.conv;
import std.traits;
// should implement rounding behaviour
U kpRoundAndScale(U,int dp, T)(T value)
{
enum double Scale=10^^dp;
enum double roundBump=0.5*(10.0^^(-dp));
enum double HalfScale=Scale/2.0;
static if(isFloatingPoint!(T))
{
auto remainder=(value*Scale)%Scale;
if(remainder>HalfScale)
return cast(U)(Scale*(value+roundBump));
else
return cast(U)(value*Scale);
}
else
return cast(U)(value*Scale);
}
struct FixedDecimal(Type, int dp)
if (isIntegral!(Type))
{
pragma(msg,dp);
enum double Scale=10^^dp;
enum double HalfScale=Scale/2.0;
Type price;
alias price this;
this(T)(T value)
if (isNumeric!(T))
{
//writefln("constructor called arg=%s",value);
price=kpRoundAndScale!(Type,dp,T)(value);
//writefln("turned into %s",price.to!double/Scale);
}
int opCmp(T)(T value) // not going to work properly for floating point - need to fix
{
auto lhs=price.to!double/Scale;
auto rhs=value.to!double;
if (lhs>rhs)
return 1;
if (lhs==rhs)
return 0;
if (lhs<rhs)
return -1;
assert(0);
}
bool opEquals(T)(T value) // not going to work properly for floating point - need to fix
{
auto lhs=price.to!double/Scale;
auto rhs=value.to!double;
return(lhs==rhs);
}
void opAssign(T)(T value)
if (isNumeric!(T))
{
price=kpRoundAndScale!(Type,dp,T)(value);
}
void opOpAssign(string s,T)(T value)
if (isNumeric!(T))
{
price=mixin("price"~s~"(cast("~Type.stringof~")(value*Scale))");
}
FixedDecimal opUnary(string s)()
{
return kpRoundAndScale!(FixedDecimal,dp,double)(mixin(s~"(price.to!double/Scale)"));
}
FixedDecimal opBinary(string s,T)(T rhs)
if (isNumeric!(T))
{
//static if (!is Type== BigInt)
//{
return kpRoundAndScale!(FixedDecimal,dp,double)(mixin("(price.to!double/Scale"~s~"rhs.to!double)/Scale"));
//}
/**
else
{
return kpRoundAndScale!(typeof(this),dp,BigInt)(
}
*/
}
T opCast(T)()
if (isNumeric!(T))
{
return cast(T)(price.to!double/Scale);
}
string toString()
{
return (price.to!double/Scale).to!string;
}
}
version(None)
{
void main(string[] args)
{
FixedDecimal!(int,2) i;
i=FixedDecimal!(int,2)(100.02);
auto k=FixedDecimal!(long,2)(100.12345);
double j=0.3352;
writefln("i>j: %s",i>j);
writefln("i>j: %s",i<j);
writefln("i==j: %s",i==j);
i+=j;
auto hybrid=i+j;
writefln("hybrid=%s, %s,%s",hybrid,typeid(hybrid),hybrid.price);
writefln("%s",j);
writefln("%s",i);
writefln("%s",i.sizeof);
//writefln("%s",int.max);
//writefln("%s",long.max);
double dd=cast(double)(i+j);
writefln("dd=%s",dd);
auto z=i+j;
writefln("z=%s",z.price);
double l=cast(double)(z);
writefln("%s",l);
writefln("%s",typeid(l));
//auto bigFixedDecimal=FixedDecimal!(BigInt,10);
//import std.math;
//bigFixedDecimal=math.pi;
//writefln("%s",bigFixedDecimal);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment