class design question (inner classes)

Regan Heath regan at netmail.co.nz
Tue Sep 11 06:55:30 PDT 2007


coxalan wrote:
> Hello,
> 
> I come from mathematics and I want to create some classes for _fast_ computations in certain algebraic structures (groups, fields, rings, ...).
> 
> My hope is that specialization at compile time will give me an advantage over universal computer algebra systems.
> 
> I want to have:
> 1) Objects for the algebraic base structures
> 2) Some type (class, struct, whatever) for the elements of this structure
> 
> For example:
> 1) a class SymmetricGroup and 2) a class Permutation.
> 
> Each instance of type 2) "belongs" to exactly one object of class 1).
> But this link should not be stored for each instance of 2). Instead, It should be given statically by the type.
> 
> Furthermore, for convenience I really want to have overloaded operators for the objects of 2).
> 
> 
> Up to now I tried these two examples:
> 
> *** 1 ***
> import std.stdio;
> 
> class SymmetricGroup {
>     const uint degree;
> 
>     this(int degreeIn) {
>         degree = degreeIn;
>     }
> 
>     struct Permutation {
>         uint data[];
>     }
> 
>     Permutation createPermutation(uint[] dataIn) {
>         Permutation result;
>         result.data = dataIn;
>         return result;
>     }
> 
>     Permutation mul(Permutation a, Permutation b) {
>         Permutation result;
>         result.data.length = degree;
>         foreach(int i, uint val; b.data) {
>             result.data[i] = a.data[val];
>         }
>         return result;
>     }
> }
> 
> void main() {
>     SymmetricGroup s = new SymmetricGroup(3);
>     s.Permutation a = s.createPermutation([0,2,1]);
>     s.Permutation b = s.createPermutation([1,2,0]);
>     s.Permutation c = s.mul(a,b);
>     writefln("%d",c.data);
> }
> ********
> 
> The problem with this is that I don't know how to overload the *-Operator such that I can write
> s.Permutation c = a * b;
> instead of
> s.Permutation c = s.mul(a,b);
> 
> I cannot add a method "opMul" within the struct "Permutation", because to call the method "mul" I would need a pointer to the outer class "SymmetricGroup", which I don't have.
> 
> [Comment: Yes, I could write
> 
>         Permutation opMul(Permutation x) {
>             Permutation result;
>             result.data.length = data.length;
>             foreach(int i, uint val; x.data) {
>                 result.data[i] = data[val];
>             }
>             return result;
>         }
> 
> in this particular example, but in general I need information stored in the outer class 1).]
> 
> 
> *** 2 ***
> import std.stdio;
> 
> class SymmetricGroup {
>     const uint degree;
> 
>     this(int degreeIn) {
>         degree = degreeIn;
>     }
> 
>     class Permutation {
>         uint data[];
> 
>         this() {
>             data.length = degree;
>         }
> 
>         this(uint[] dataIn) {
>             data = dataIn;
>         }
> 
>         Permutation opMul(Permutation x) {
>             return mul(this, x);
>         }
>     }
> 
>     Permutation mul(Permutation a, Permutation b) {
>         Permutation result = new Permutation();
>         foreach(int i, uint val; b.data) {
>             result.data[i] = a.data[val];
>         }
>         return result;
>     }
> }
> 
> void main() {
>     SymmetricGroup s = new SymmetricGroup(3);
>     s.Permutation a = s.new Permutation([0,2,1]);
>     s.Permutation b = s.new Permutation([1,2,0]);
>     s.Permutation c = a * b;
>     writefln("%d",c.data);
> }
> ********
> 
> This is definitely more elegant than the first example. But here, every object of type "s.Permutation" stores a reference to the object "s", which I want to avoid.
> 
> If it was possible to instantiate the object "s" at compile time
> (something like
> static const SymmetricGroup s = new SymmetricGroup(3);
> ),
> the above mentioned references would not be needed. But unfortunately, It is not possible to instantiate objects at compile time (what's actually the reason for this?).
> 
> [A final comment:
> I know that I could go without the class SymmetricGroup, and have only objects of type Permutation. But I really want these outer classes, to do constructions like direct products of groups, etc.]
> 
> 
> I believe that within the D template toolkit, there must be a solution for my problem, which I simply don't see.
> I will appreciate any hint or suggestion.

Maybe template bolt-ins?  (I'm not 100% sure I know what you want to 
achieve so this may be waaaay off base)

class SymmetricGroup
{
      uint degree;

      this(int degreeIn) {
          degree = degreeIn;
      }
}

class Permutation(T, int D) : T
{
          uint data[];

          this() {
              super(D);
              data.length = degree;
          }

          this(uint[] dataIn) {
              super(D);
              data = dataIn;
          }

          Permutation opMul(Permutation b) {
		auto result = new Permutation;
		foreach(int i, uint val; b.data) {
		    result.data[i] = data[val] * b.data[val];
		}
		return result;
         }
}

alias Permutation!(SymmetricGroup, 3) SGP;

void main()
{
	SGP a = new SGP();
	SGP b = new SGP();
	SGP c = a * b;
}

In the above you don't actually need SymmetricGroup at all, your 
template could just take "int D" and use that for degree, however I 
suspect you want to add more to SymmetricGroup?

Regan



More information about the Digitalmars-d mailing list