fork(1) download
  1. import std.stdio
  2. , std.typecons
  3. , std.traits
  4. , std.algorithm
  5. , std.range
  6. , std.container
  7. , conv = std.conv
  8. , std.format;
  9.  
  10.  
  11. // This could also be done with bare templates instead of a struct
  12. // and with mixin-ed free functions, allowing natural overloading
  13. // without the awkward `A.stuff` all over the place
  14.  
  15. // I'm tired, though.
  16.  
  17.  
  18. void main() {
  19. with(Reals)
  20. to_str(add(one, one)).writeln();
  21.  
  22. with(Complex)
  23. to_str(add(one, one)).writeln();
  24.  
  25. with(Quaternion)
  26. to_str(add(one, one)).writeln();
  27.  
  28.  
  29. }
  30.  
  31.  
  32. /// "sig"
  33. template isDivAlgebra(alias Testant) {
  34. alias e = Testant;
  35.  
  36. enum bool isDivAlgebra = __traits(compiles, {
  37. alias K = e.kind;
  38. K r;
  39. K function(K) _conj = e.conj;
  40. K function() _zero = &e.zero;
  41. K function() _one = &e.one;
  42. bool function(K) _zero_chk = e.zero_chk;
  43. K function(K, K) _add = e.add;
  44. K function(K, K) _sub = e.sub;
  45. K function(K, K) _mul = e.mul;
  46. K function(K) _inv = e.inv;
  47. string function(K) _to_str = e.to_str;
  48. });
  49. }
  50.  
  51.  
  52. /// BareReals struct
  53. //template BareReals() {
  54. struct BareReals {
  55.  
  56. /*template sig(Testant) {
  57. enum bool sig = isDivAlgebra!Testant;
  58. }*/
  59.  
  60.  
  61. public:
  62. alias kind = float;
  63.  
  64. static:
  65. enum conj = (float x) pure => x;
  66.  
  67. float zero() @property pure { return 0.0f; }
  68.  
  69. float one() @property pure { return 1.0f; }
  70.  
  71. enum zero_chk = (float x) pure => x == 0.0f;
  72.  
  73. enum add = (float x, float y) pure => x + y;
  74.  
  75. enum sub = (float x, float y) pure => x - y;
  76.  
  77. enum mul = (float x, float y) pure => x * y;
  78.  
  79. enum inv = (float x) pure => 1.0f / x;
  80.  
  81. enum to_str = (float x) => std.format.format("%g", x);
  82. }
  83.  
  84. static if(isDivAlgebra!(BareReals))
  85. alias BareReals Reals;
  86. //mixin BareReals!() Reals;
  87.  
  88. //static assert( is( typeof(Reals.one) == Reals.kind function() ) );
  89. //static assert( is( Complex.NewKind == Quaternion.NewKind ) );
  90. /// functor "G"
  91. template G(alias Alg)
  92. if(isDivAlgebra!Alg) {
  93.  
  94. //template G() {
  95. struct G {
  96. public:
  97.  
  98. alias A = Alg;
  99.  
  100. // Using templates here isn't working T-T I don't get all the semantics yet
  101. /*enum newKind = "NewKind_" ~ Alg.kind.stringof;
  102. mixin(`struct ` ~ newKind ~ ` {
  103. A.kind r;
  104. A.kind i;
  105. }`);
  106.  
  107. alias kind = id!(mixin(newKind));/**/
  108.  
  109. struct NewKind {
  110. A.kind r;
  111. A.kind i;
  112. }
  113. alias kind = NewKind;
  114.  
  115. static:
  116. enum conj = (kind x) pure => kind(A.conj(x.r), A.sub(A.zero(), x.i));
  117.  
  118. auto zero() @property pure { return kind(A.zero, A.zero); }
  119.  
  120. auto one() @property pure { return kind(A.one, A.zero); }
  121.  
  122. enum zero_chk = (kind x) => A.zero_chk(x.r) && A.zero_chk(x.r);
  123.  
  124. enum add = (kind x, kind y) pure => kind( A.add(x.r, y.r), A.add(x.i, y.i) );
  125. enum sub = (kind x, kind y) pure => kind( A.sub(x.r, y.r), A.sub(x.i, y.i) );
  126.  
  127. enum mul = (kind x, kind y) pure {
  128. return kind(
  129. A.sub( A.mul( x.r, y.r ), A.mul( A.conj(x.i), y.i ) )
  130. , A.add( A.mul(x.r, y.i), A.mul(x.i, y.r) )
  131. );
  132. };
  133.  
  134. enum inv = (kind x) pure {
  135. auto d = A.inv( A.add( A.mul(A.conj(x.i), x.i), A.mul(A.conj(x.r), x.r) ) );
  136. return kind( A.mul(d, A.conj(x.r)), A.sub(A.zero(), A.mul(d, x.i)) );
  137. };
  138.  
  139. enum to_str = (kind x) => (A.to_str(x.r) ~ ", " ~ A.to_str(x.i));
  140. }
  141.  
  142. //static assert(isDivAlgebra!( G!() ) );
  143. }
  144.  
  145. /**/alias Complex = G!Reals;
  146. alias Quaternion = G!Complex;/**/
  147.  
  148. /*mixin G!Reals Complex;
  149. alias G!Reals Complex_;
  150. mixin G!(G!(BareReals!())) Quaternion;/**/
  151.  
  152. alias id(alias token) = token;
  153.  
  154.  
  155.  
  156.  
  157.  
  158.  
  159.  
  160.  
  161.  
  162.  
  163.  
  164.  
  165.  
  166.  
  167.  
  168.  
  169.  
  170.  
  171.  
  172.  
  173.  
  174.  
  175.  
  176.  
  177.  
Success #stdin #stdout 0s 16424KB
stdin
Standard input is empty
stdout
2
2, 0
2, 0, 0, 0