digitalmars.D - opBinary failes with templates
- Asger Dam Hoedt (36/37) Jul 27 2011 Hey
- Steven Schveighoffer (10/47) Jul 27 2011 It is a bug, someone just brought up almost exactly this problem in
- Asger Dam Hoedt (4/63) Jul 27 2011 Oh nice. I'll go with the clean solution then and disregard the bug for ...
- KennyTM~ (10/68) Jul 27 2011 Actually you shouldn't need to write a vector struct if "+" is all it
- simendsjo (4/96) Jul 27 2011 The last time I tried to use vector ops, they failed for all but the
- Peter Alexander (14/23) Jul 28 2011 For 3 floats, it will not be more efficient.
- Pelle (11/17) Jul 28 2011 It does not, for example:
Hey I've very recently started playing around with D, but I seem to have hit my head against a bug in dmd. I want to create a Vector class templated with its dimension. This works fine until I try to overload the + operator for my vector and use it. I then get the error Error: incompatible types for ((vec) + (vec)): 'Vector!(3)' and 'Vector!(3)' I've boiled it down to a small example struct Vector(int D) { float es[D]; public: this(immutable float x, immutable float y, immutable float z) { es[0] = x; es[1] = y; es[2] = z; } Vector!(D) opBinary(string s)(immutable Vector!(D) rhs) if (s == "+") { Vector!(D) ret; for(int i = 0; i < D; ++i) ret.es[i] = es[i] + rhs.es[i]; return ret; } } alias Vector!(3) Vector3; void main() { Vector3 vec = Vector3(0,1,2); vec = vec.opBinary!("+")(vec); // This works fine vec = vec + vec; // This line fails miserably } If I replace the template argument in for the argument rhs with 3, then everything works, but that's not really a nice solution :) Is it me trying to use templates in a way they aren't meant to be used or is this a bug in dmd? If it is a bug, does anyone have an idea how to solve this? I wouldn't mind fixing it in dmd myself, I just need some guidelines. /papaboo -- I confess ---From the desk of Dr. John Zoidberg, M.D.(\/)(',,,')(\/)
Jul 27 2011
On Wed, 27 Jul 2011 15:48:24 -0400, Asger Dam Hoedt <asgerhoedt gmail.com> wrote:Hey I've very recently started playing around with D, but I seem to have hit my head against a bug in dmd. I want to create a Vector class templated with its dimension. This works fine until I try to overload the + operator for my vector and use it. I then get the error Error: incompatible types for ((vec) + (vec)): 'Vector!(3)' and 'Vector!(3)' I've boiled it down to a small example struct Vector(int D) { float es[D]; public: this(immutable float x, immutable float y, immutable float z) { es[0] = x; es[1] = y; es[2] = z; } Vector!(D) opBinary(string s)(immutable Vector!(D) rhs) if (s == "+") { Vector!(D) ret; for(int i = 0; i < D; ++i) ret.es[i] = es[i] + rhs.es[i]; return ret; } } alias Vector!(3) Vector3; void main() { Vector3 vec = Vector3(0,1,2); vec = vec.opBinary!("+")(vec); // This works fine vec = vec + vec; // This line fails miserably } If I replace the template argument in for the argument rhs with 3, then everything works, but that's not really a nice solution :) Is it me trying to use templates in a way they aren't meant to be used or is this a bug in dmd? If it is a bug, does anyone have an idea how to solve this? I wouldn't mind fixing it in dmd myself, I just need some guidelines.It is a bug, someone just brought up almost exactly this problem in d.learn. http://www.digitalmars.com/webnews/newsgroups.php?art_group=digitalmars.D.learn&article_id=28455 The proper workaround (and actually, the cleaner solution) is to use Vector and not Vector!D. Inside a template, the name of the template is the same as if you invoked the template with the same template parameters. If you actually do need a different value for D, I'm not sure what works. -Steve
Jul 27 2011
2011/7/27 Steven Schveighoffer <schveiguy yahoo.com>On Wed, 27 Jul 2011 15:48:24 -0400, Asger Dam Hoedt <asgerhoedt gmail.com> wrote: HeyOh nice. I'll go with the clean solution then and disregard the bug for now. Thanks for the quick help. /asgerI've very recently started playing around with D, but I seem to have hit my head against a bug in dmd. I want to create a Vector class templated with its dimension. This works fine until I try to overload the + operator for my vector and use it. I then get the error Error: incompatible types for ((vec) + (vec)): 'Vector!(3)' and 'Vector!(3)' I've boiled it down to a small example struct Vector(int D) { float es[D]; public: this(immutable float x, immutable float y, immutable float z) { es[0] = x; es[1] = y; es[2] = z; } Vector!(D) opBinary(string s)(immutable Vector!(D) rhs) if (s == "+") { Vector!(D) ret; for(int i = 0; i < D; ++i) ret.es[i] = es[i] + rhs.es[i]; return ret; } } alias Vector!(3) Vector3; void main() { Vector3 vec = Vector3(0,1,2); vec = vec.opBinary!("+")(vec); // This works fine vec = vec + vec; // This line fails miserably } If I replace the template argument in for the argument rhs with 3, then everything works, but that's not really a nice solution :) Is it me trying to use templates in a way they aren't meant to be used or is this a bug in dmd? If it is a bug, does anyone have an idea how to solve this? I wouldn't mind fixing it in dmd myself, I just need some guidelines.It is a bug, someone just brought up almost exactly this problem in d.learn. http://www.digitalmars.com/**webnews/newsgroups.php?art_** group=digitalmars.D.learn&**article_id=28455<http://www.digitalmars.com/webnews/newsgroups.php?art_group=digitalmars.D.learn&article_id=28455> The proper workaround (and actually, the cleaner solution) is to use Vector and not Vector!D. Inside a template, the name of the template is the same as if you invoked the template with the same template parameters. If you actually do need a different value for D, I'm not sure what works. -Steve
Jul 27 2011
On Jul 28, 11 05:25, Asger Dam Hoedt wrote:2011/7/27 Steven Schveighoffer <schveiguy yahoo.com <mailto:schveiguy yahoo.com>> On Wed, 27 Jul 2011 15:48:24 -0400, Asger Dam Hoedt <asgerhoedt gmail.com <mailto:asgerhoedt gmail.com>> wrote: Hey I've very recently started playing around with D, but I seem to have hit my head against a bug in dmd. I want to create a Vector class templated with its dimension. This works fine until I try to overload the + operator for my vector and use it. I then get the error Error: incompatible types for ((vec) + (vec)): 'Vector!(3)' and 'Vector!(3)' I've boiled it down to a small example struct Vector(int D) { float es[D]; public: this(immutable float x, immutable float y, immutable float z) { es[0] = x; es[1] = y; es[2] = z; } Vector!(D) opBinary(string s)(immutable Vector!(D) rhs) if (s == "+") { Vector!(D) ret; for(int i = 0; i < D; ++i) ret.es <http://ret.es>[i] = es[i] + rhs.es <http://rhs.es>[i]; return ret; } } alias Vector!(3) Vector3; void main() { Vector3 vec = Vector3(0,1,2); vec = vec.opBinary!("+")(vec); // This works fine vec = vec + vec; // This line fails miserably } If I replace the template argument in for the argument rhs with 3, then everything works, but that's not really a nice solution :) Is it me trying to use templates in a way they aren't meant to be used or is this a bug in dmd? If it is a bug, does anyone have an idea how to solve this? I wouldn't mind fixing it in dmd myself, I just need some guidelines. It is a bug, someone just brought up almost exactly this problem in d.learn. http://www.digitalmars.com/__webnews/newsgroups.php?art___group=digitalmars.D.learn&__article_id=28455 <http://www.digitalmars.com/webnews/newsgroups.php?art_group=digitalmars.D.learn&article_id=28455> The proper workaround (and actually, the cleaner solution) is to use Vector and not Vector!D. Inside a template, the name of the template is the same as if you invoked the template with the same template parameters. If you actually do need a different value for D, I'm not sure what works. -Steve Oh nice. I'll go with the clean solution then and disregard the bug for now. Thanks for the quick help. /asgerActually you shouldn't need to write a vector struct if "+" is all it required, as D supports array operation already: void main() { float[3] x = [1, 3, 5], y = [5, -6, 2]; x[] = x[] + y[]; assert(x == [6, -3, 7]); } It is also more efficient than the for-loop since this could use SIMD operations in some cases.
Jul 27 2011
On 27.07.2011 23:39, KennyTM~ wrote:On Jul 28, 11 05:25, Asger Dam Hoedt wrote:The last time I tried to use vector ops, they failed for all but the most straight forward use-cases. I was told it wasn't fully implemented yet. Is this still the case, or are they ready for prime-time?2011/7/27 Steven Schveighoffer <schveiguy yahoo.com <mailto:schveiguy yahoo.com>> On Wed, 27 Jul 2011 15:48:24 -0400, Asger Dam Hoedt <asgerhoedt gmail.com <mailto:asgerhoedt gmail.com>> wrote: Hey I've very recently started playing around with D, but I seem to have hit my head against a bug in dmd. I want to create a Vector class templated with its dimension. This works fine until I try to overload the + operator for my vector and use it. I then get the error Error: incompatible types for ((vec) + (vec)): 'Vector!(3)' and 'Vector!(3)' I've boiled it down to a small example struct Vector(int D) { float es[D]; public: this(immutable float x, immutable float y, immutable float z) { es[0] = x; es[1] = y; es[2] = z; } Vector!(D) opBinary(string s)(immutable Vector!(D) rhs) if (s == "+") { Vector!(D) ret; for(int i = 0; i < D; ++i) ret.es <http://ret.es>[i] = es[i] + rhs.es <http://rhs.es>[i]; return ret; } } alias Vector!(3) Vector3; void main() { Vector3 vec = Vector3(0,1,2); vec = vec.opBinary!("+")(vec); // This works fine vec = vec + vec; // This line fails miserably } If I replace the template argument in for the argument rhs with 3, then everything works, but that's not really a nice solution :) Is it me trying to use templates in a way they aren't meant to be used or is this a bug in dmd? If it is a bug, does anyone have an idea how to solve this? I wouldn't mind fixing it in dmd myself, I just need some guidelines. It is a bug, someone just brought up almost exactly this problem in d.learn. http://www.digitalmars.com/__webnews/newsgroups.php?art___group=digitalmars.D.learn&__article_id=28455 <http://www.digitalmars.com/webnews/newsgroups.php?art_group=digitalmars.D.learn&article_id=28455> The proper workaround (and actually, the cleaner solution) is to use Vector and not Vector!D. Inside a template, the name of the template is the same as if you invoked the template with the same template parameters. If you actually do need a different value for D, I'm not sure what works. -Steve Oh nice. I'll go with the clean solution then and disregard the bug for now. Thanks for the quick help. /asgerActually you shouldn't need to write a vector struct if "+" is all it required, as D supports array operation already: void main() { float[3] x = [1, 3, 5], y = [5, -6, 2]; x[] = x[] + y[]; assert(x == [6, -3, 7]); } It is also more efficient than the for-loop since this could use SIMD operations in some cases.
Jul 27 2011
On 27/07/11 10:39 PM, KennyTM~ wrote:Actually you shouldn't need to write a vector struct if "+" is all it required, as D supports array operation already: void main() { float[3] x = [1, 3, 5], y = [5, -6, 2]; x[] = x[] + y[]; assert(x == [6, -3, 7]); } It is also more efficient than the for-loop since this could use SIMD operations in some cases.For 3 floats, it will not be more efficient. In my experiments, manually writing: x[0] += y[0]; x[1] += y[1]; x[2] += y[2]; Is about 6x faster than calling x[] = x[] + y[]; // or x[] += y[]; same result You only get the advantage of the SIMD arrays ops in large arrays. The overhead of the function call, loading the scalars into and out of vector registers, and looping through the array is way more than the work that needs to be done. DMD really shouldn't call those SIMD array ops for small statically sized arrays.
Jul 28 2011
On Wed, 27 Jul 2011 22:46:21 +0200, Steven Schveighoffer <schveiguy yahoo.com> wrote:The proper workaround (and actually, the cleaner solution) is to use Vector and not Vector!D. Inside a template, the name of the template is the same as if you invoked the template with the same template parameters. If you actually do need a different value for D, I'm not sure what works. -SteveIt does not, for example: struct matrix(uint m, uint n) { //... matrix!(n,m) transposed() { //... } } matrix(3,1) m; m = m.transposed().transposed(); // doesn't work
Jul 28 2011