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