Advertisement
Guest User

Untitled

a guest
Aug 23rd, 2015
73
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
D 7.72 KB | None | 0 0
  1. import std.stdio;
  2. import std.traits;
  3. import std.range;
  4. import std.conv;
  5. import std.math;
  6. import std.algorithm;
  7.  
  8. template mostPrecise(T, U) {
  9.     static if(!isNumeric!T || !isNumeric!U) {
  10.         static assert(0, "Arguments must be numeric.");
  11.     }
  12.     static if(isFloatingPoint!T && isFloatingPoint!U) {
  13.         static if(T.sizeof > U.sizeof) {
  14.             alias mostPrecise = T;
  15.         } else {
  16.             alias mostPrecise = U;
  17.         }
  18.     } else static if(!isFloatingPoint!T && isFloatingPoint!U) {
  19.         static if(T.sizeof <= 32) {
  20.             alias mostPrecise = mostPrecise!(float, U);
  21.         } else static if(T.sizeof <= 64) {
  22.             alias mostPrecise = mostPrecise!(double, U);
  23.         } else {
  24.             alias mostPrecise = real;
  25.         }
  26.     } else static if(!isFloatingPoint!U && isFloatingPoint!T) {
  27.         alias mostPrecise = mostPrecise!(U, T);
  28.     } else { // !isFloatingPoint!T && !isFloatingPoint!U
  29.         static if(T.sizeof > U.sizeof) {
  30.             alias mostPrecise = T;
  31.         } else {
  32.             alias mostPrecise = U;
  33.         }
  34.     }
  35. }
  36.  
  37. template Dimension(T, long[7] _powers) {
  38.     static long[] addPowers(string op)(long[] a, long[] b) {
  39.         long[] c;
  40.         for(uint i = 0; i < 7; i++) {
  41.             mixin("c[i] = a[i] " ~ op ~ " b[i];");
  42.         }
  43.     }
  44.  
  45.     static long minPower(long[] powers) {
  46.         long m = long.max;
  47.         for(uint i = 0; i < 7; i++) {
  48.             m = min(m, powers[i]);
  49.         }
  50.         return m;
  51.     }
  52.  
  53.     static ubyte numPowers(string op)(long[] powers) {
  54.         ubyte n;
  55.         for(uint i = 0; i < 7; i++) {
  56.             if(mixin("powers[i] " ~ op ~ " 0")) {
  57.                 n++;
  58.             }
  59.         }
  60.         return n;
  61.     }
  62.  
  63.     pragma(msg, numPowers!("==")(_powers).to!string);
  64.  
  65.     static if(!isNumeric!T) {
  66.         static assert(0, "Dimension cannot be instantiated with non-numeric type.");
  67.     } else static if(numPowers!("==")(_powers)) {
  68.         alias Dimension = T;
  69.     } else {
  70.         struct Dimension {
  71.             public static const long[7] powers = _powers.dup;
  72.             private static const string unitNames = [ "m", "kg", "s", "A", "K", "mol", "cd" ];
  73.  
  74.             public T value;
  75.  
  76.             this(T value) {
  77.                 this.value = value;
  78.             }
  79.  
  80.             void opAssign(T value) {
  81.                 this.value = value;
  82.             }
  83.  
  84.             auto opBinary(string op, V)(V rhs) {
  85.                 static if(op == "+") {
  86.                     static if(!is(typeof(this) == V)) {
  87.                         static assert(0, "Cannot add unlike dimensions " ~ stringof ~ " and " ~ V.stringof ~ ".");
  88.                     }
  89.                     alias D = Dimension!(mostPrecise!(T, typeof(V.value)), V.powers);
  90.                     return D(this.value + rhs.value);
  91.                 } else static if(op == "-") {
  92.                     static if(!is(typeof(this) == V)) {
  93.                         static assert(0, "Cannot subtract unlike dimensions " ~ stringof ~ " and " ~ V.stringof ~ ".");
  94.                     }
  95.                     alias D = Dimension!(mostPrecise!(T, typeof(V.value)), V.powers);
  96.                     return D(this.value - rhs.value);
  97.                 } else static if(op == "*") {
  98.  
  99.                     alias D = Dimension!(mostPrecise!(T, typeof(V.value)), addPowers!("+")(powers, V.powers));
  100.                     return D(this.value * rhs.value);
  101.                 } else static if(op == "/") {
  102.                     alias D = Dimension!(mostPrecise!(T, typeof(V.value)), addPowers!("-")(powers, V.powers));
  103.                     return D(this.value / rhs.value);
  104.                 } else {
  105.                     static assert(0, "Unsupported operator " ~ op ~ " for dimension type.");
  106.                 }
  107.             }
  108.  
  109.             template getUnit() {
  110.                 static const string getUnit = (() {
  111.                     char[] ret;
  112.                     bool hasNeg = minPower(powers) < 0;
  113.                     ubyte numTop = numPowers!(">")(powers);
  114.                     ubyte numBottom = numPowers!("<")(powers);
  115.                     numTop    = (lpower > 0) + (mpower > 0) + (tpower > 0);
  116.                     numBottom = (lpower < 0) + (mpower < 0) + (tpower < 0);
  117.                     bool mul = false;
  118.                     if(numTop > 1 && numTop > 1) {
  119.                         ret ~= "(";
  120.                     }
  121.                     if(powers[i] > 0) {
  122.                         ret ~= unitNames[0];
  123.                         if(powers[i] > 1) {
  124.                             ret ~= "^" ~ powers[i].to!string;
  125.                         }
  126.                         mul = true;
  127.                     }
  128.                     for(uint i = 1; i < powers.length; i++) {
  129.                         if(powers[i] > 0) {
  130.                             ret ~= (mul ? "*" : "") ~ unitNames[i];
  131.                             if(powers[i] > 1) {
  132.                                 ret ~= "^" ~ powers[i].to!string;
  133.                             }
  134.                             mul = true;
  135.                         }
  136.                     }
  137.                     if(numTop > 1 && numTop > 1) {
  138.                         ret ~= ")";
  139.                     }
  140.                     if(numBottom > 0) {
  141.                         ret ~= "/";
  142.                         mul = false;
  143.                         if(numTop > 1 && numTop > 1) {
  144.                             ret ~= "(";
  145.                         }
  146.                         if(powers[0] < 0) {
  147.                             ret ~= lstr;
  148.                             if(powers[0] < -1) {
  149.                                 ret ~= "^" ~ (-powers[0]).to!string;
  150.                             }
  151.                             mul = true;
  152.                         }
  153.                         for(uint i = 0; i < powers.length; i++) {
  154.                             if(powers[i] < 0) {
  155.                                 ret ~= (mul ? "*" : "") ~ unitNames[i];
  156.                                 if(powers[i] < -1) {
  157.                                     ret ~= "^" ~ (-powers[i]).to!string;
  158.                                 }
  159.                                 mul = true;
  160.                             }
  161.                         }
  162.                         if(numTop > 1 && numTop > 1) {
  163.                             ret ~= ")";
  164.                         }
  165.                     }
  166.                     return ret;
  167.                 })();
  168.             }
  169.  
  170.             public static const string stringof = getUnit!();
  171.  
  172.             string toString() {
  173.                 return value.to!string ~ stringof;
  174.             }
  175.         }
  176.     }
  177. }
  178.  
  179. template Compose(alias e) {
  180.     auto Compose(T)(T value = 0) {
  181.         alias D = Dimension!(T, e.powers.dup);
  182.         return D(value);
  183.     }
  184. }
  185.  
  186. auto Length(T)(T value = 0) {
  187.     return Dimension!(T, [ 1, 0, 0, 0, 0, 0, 0 ])(value);
  188. }
  189.  
  190. auto Mass(T)(T value = 0) {
  191.     return Dimension!(T, [ 0, 1, 0, 0, 0, 0, 0 ])(value);
  192. }
  193.  
  194. auto Time(T)(T value = 0) {
  195.     return Dimension!(T, [ 0, 0, 1, 0, 0, 0, 0 ])(value);
  196. }
  197.  
  198. void main() {
  199.     pragma(msg, typeof(Length(20)));
  200.     alias V = typeof(Length(1) * Length(1));
  201.     pragma(msg, V.stringof);
  202.     alias Area          = Compose!(Length * Length);
  203.     alias Volume        = Compose!(Area * Length);
  204.     alias Velocity      = Compose!(Length / Time(1));
  205.     alias Acceleration  = Compose!(Velocity / Time(1));
  206.     alias Force         = Compose!(Mass * Acceleration);
  207.     alias Work          = Compose!(Force * Length);
  208.     alias Power         = Compose!(Work / Time(1));
  209.  
  210.     auto mass = Mass(63.5);
  211.     auto g = Acceleration(9.8);
  212.     auto f = mass * g;
  213.  
  214.     writeln("My mass is " ~ mass.to!string ~ ".");
  215.     writeln("The acceleration due to gravity on Earth is " ~ g.to!string ~ ".");
  216.     writeln("I exert a force of " ~ f.to!string ~ "on the ground.");
  217. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement