Thread overview | |||||||||
---|---|---|---|---|---|---|---|---|---|
|
October 10, 2004 type promotion (on overloaded operators) | ||||
---|---|---|---|---|
| ||||
Hi there, I've just read the spec - great D, but can I somehow do the "type promotion" e.g. for matrices class CMatrix(T, int M, int N) { T data[M][N]; } CMatrix!(float,3,3) mf; CMatrix!(double,3,3) md; mf + md; // float matrix + double matrix = double matrix // or CMatrix!(float,1,3) v3; CMatrix!(float,3,3) m33; v3 * m33; // and this is really necessary to me ----------- In C++ I did something like this: template <class X, class Y> TAdd {}; template <> TAdd<float,double> { typedef double RET; }; // float + double = double template <class X, class Y, int M, int N> CMatrix<typename TAdd<X,Y>::RET,M,N> operator + (CMatrix<T,M,N> const &a, CMatrix<T,M,N> const &b) { /*...*/ } thanks Juraj Onderik (as I understand templates in D now - it's not really superset of C++ templates, or is it? :) Juraj Onderik |
October 10, 2004 Re: type promotion (on overloaded operators) | ||||
---|---|---|---|---|
| ||||
Posted in reply to wondermail | wondermail@szm.sk wrote:
> Hi there,
> I've just read the spec - great D, but can I somehow do the "type promotion"
> e.g. for matrices
>
> class CMatrix(T, int M, int N)
> {
> T data[M][N];
> }
>
> CMatrix!(float,3,3) mf;
> CMatrix!(double,3,3) md;
>
> mf + md; // float matrix + double matrix = double matrix
>
> // or
>
> CMatrix!(float,1,3) v3;
> CMatrix!(float,3,3) m33;
>
> v3 * m33; // and this is really necessary to me
>
>
> Juraj Onderik
use a bare template to perform bold action. Example:
class Matrix(T, int M, int N)
{
T data[M][N];
}
// bare template
template MatrixWorker(Ta, Tb, int Dx, int Dy, To) {
Matrix!(To, Dx, Dy) dotProduct(
in Matrix!(Ta, Dx, Dy) first,
in Matrix!(Tb, Dx, Dy) second) {
Matrix!(To, Dx, Dy) result = new Matrix!(To, Dx, Dy);
for(uint i; i < Dx; i++) {
for(uint j; j < Dy; j++) {
result.data[i][j] =
cast(To)first.data[i][j] *
cast(To)second.data[i][j];
}
}
return result;
}
Matrix!(To, Dx, Dy) sum(
in Matrix!(Ta, Dx, Dy) first,
in Matrix!(Tb, Dx, Dy) second) {
Matrix!(To, Dx, Dy) result = new Matrix!(To, Dx, Dy);
for(uint i; i < Dx; i++) {
for(uint j; j < Dy; j++) {
result.data[i][j] =
cast(To)first.data[i][j] +
cast(To)second.data[i][j];
}
}
return result;
}
}
int main(char[][] args) {
Matrix!(float,3,3) mf = new Matrix!(float,3,3)(/*Matrix init!*/);
Matrix!(double,3,3) md = new Matrix!(double,3,3)(/*Matrix init!*/);
Matrix!(double,3,3) mo;
mo = MatrixWorker!(float, double, 3, 3, double).dotProduct(mf, md);
// or
mo = MatrixWorker!(float, double, 3, 3, double).sum(mf, md);
return 0;
}
I think this should help. Of course, you can now write specific operators to perform it less painful ;-) But this should give you a kickstart.
Regards,
Sjoerd
N.B. This is D, not MFC, so leave out the C prefix, it's unwanted by the community and especially the big boss.
|
October 10, 2004 Type promotion Again | ||||
---|---|---|---|---|
| ||||
Posted in reply to Sjoerd van Leent | sure I know this :) Ok I meant it little bit different. Can I do "template function" : C++ : template <class X, class Y> void foo(X x, Y y) {} // general code // specializations - ... foo(1.2,3); foo("one", "two"); // D: template Foo(X,Y) { void foo(X x, Y y) {} } // a,b - some objects , you have specialized Foo for them Foo!(typeof(a),typeof(b)).foo(a,b); // OK foo(a,b); // bad - you must provide "template scope" So the "problem" is that compiler can't deduce template parameters from the function parameters - what c++ actually does. Sure it's not wrong, cause templates in D are new scopes. Anyway, sorry, but I still can't see, how to do it with operators, bacause I cannot parametrize it's argument's: template TM(X, int M, int N) { class Matrix { template NewScope(Y) { void opAdd(TM!(Y,M,N).Matrix m) { /*..*/ } } void opAdd(Matrix m) { /*...*/ } // m is TM!(T,M,N).Matrix } } void main () { TM!(float,3,3).Matrix a; TM!(double,3,3).Matrix b; a.opAdd(b); // this (float,3,3) + (float,3,3) a.NewScope!(double).opAdd(b); // this is NOT + operator } >use a bare template to perform bold action. Example: > mo = MatrixWorker!(float, double, 3, 3, double).dotProduct(mf, md); dot(a,b) = scalar - not a matrix :) Ok just for fun. >I think this should help. Of course, you can now write specific operators to perform it less painful ;-) But this should give you a kickstart. > >N.B. This is D, not MFC, so leave out the C prefix, it's unwanted by the community and especially the big boss. well I dont use MFC at all, but the C prefix means: class CFoo {} struct SFoo {} enum EFoo {} union UFoo {} but if the BIG boss is against I dont mind :) |
October 10, 2004 Re: type promotion (on overloaded operators) | ||||
---|---|---|---|---|
| ||||
Posted in reply to wondermail | wondermail@szm.sk wrote: > Hi there, > I've just read the spec - great D, but can I somehow do the "type > promotion" e.g. for matrices > > class CMatrix(T, int M, int N) > { > T data[M][N]; > } > > CMatrix!(float,3,3) mf; > CMatrix!(double,3,3) md; > > mf + md; // float matrix + double matrix = double matrix > > // or > > CMatrix!(float,1,3) v3; > CMatrix!(float,3,3) m33; > > v3 * m33; // and this is really necessary to me > You could try something like template GenericMatrixOps(Matrix,int M, int N) { Matrix opAdd(Matrix y) { // define addition Matrix+Matrix } } class Matrix(T:double, int M, int N) { T[M][N] data; mixin GenericMatrixOps!(Matrix,M,N) genericOps; alias genericOps.opAdd opAdd; // for overloading, maybe Matrix opAdd(Matrix!(float,M,N) y) { // define what to do with double+float matrices } } I haven't actually tried writing something out and compiling it but the general idea is to use mixins to share code and template specialization to define the special cases for mixed type arithmetic. > ----------- > In C++ I did something like this: > > template <class X, class Y> TAdd {}; > > template <> TAdd<float,double> { typedef double RET; }; // float + double = double > > template <class X, class Y, int M, int N> CMatrix<typename TAdd<X,Y>::RET,M,N> operator + (CMatrix<T,M,N> const &a, CMatrix<T,M,N> const &b) { /*...*/ } > > thanks Juraj Onderik > (as I understand templates in D now - it's not really superset of C++ > templates, or is it? :) > > Juraj Onderik D doesn't have implicit template instantiation so using "pure templates" will probably end up being more verbose than in C++. If you use member functions then you don't have to worry about instantiating the templates. -Ben |
October 11, 2004 Re: Type promotion Again | ||||
---|---|---|---|---|
| ||||
Posted in reply to Juraj Onderik | The following should help illustrate my earlier post. It probably wouldn't be hard to share more code than I do below but you get the idea. import std.stdio; template GenericVectorOps(Vector,T,int N) { // arithmetic with the same underlying data types Vector opAdd(Vector y) { Vector res; for(int k=0;k<N;k++) { res.data[k] = data[k]+y.data[k]; } return res; } // print out a Vector void print() { foreach(T val; data) writef(val," "); writefln(); } } struct Vector(T,int N) { T[N] data; mixin GenericVectorOps!(Vector,T,N) gops; alias gops.opAdd opAdd; } struct Vector(T:double,int N) { T[N] data; mixin GenericVectorOps!(Vector,T,N) gops; alias gops.opAdd opAdd; // now define mixed type arithmetic with double and float Vector opAdd(.Vector!(float,N) y) { Vector res; for(int k=0;k<N;k++) { res.data[k] = data[k]+y.data[k]; } return res; } } int main() { Vector!(double,3) x; x.data[0] = 1; x.data[1] = 2; x.data[2] = 3; Vector!(float,3) y; y.data[0] = 10; y.data[1] = 20; y.data[2] = 30; Vector!(double,3) z = x+y; Vector!(double,3) w = z+x; x.print(); y.print(); z.print(); w.print(); return 0; } |
Copyright © 1999-2021 by the D Language Foundation