From: Patrick H. <pa...@13...> - 2004-09-16 21:20:22
|
On Thu, 2004-09-16 at 16:05 -0500, Allen Bierbaum wrote: > Patrick Hartling wrote: > > What is the fix for this: > >=20 > > gmtl/TriOps.h:60: error: no match for 'operator*' in 'gmtl::operator > > +(const > > gmtl::VecBase<T, SIZE, R1>&, const gmtl::VecBase<T, SIZE, R2>&) [wit= h > > T =3D > > double, unsigned int SIZE =3D 3, R1 =3D > > gmtl::meta::VecBinaryExpr<gmtl::VecBase<double, 3, > > gmtl::meta::DefaultVecTag>, gmtl::VecBase<double, 3, > > gmtl::meta::DefaultVecTag>, gmtl::meta::VecPlusBinary>, R2 =3D > > gmtl::meta::DefaultVecTag]((+(+tri)->gmtl::Tri<DATA_TYPE>::operator[= ] > > [with > > DATA_TYPE =3D double](2))) * one_third' > >=20 > > The code that is not compiling is this (from gmtl/TriOps.h modified to > > include gmtl/VecOps.h): > >=20 > > template< class DATA_TYPE > > > Point<DATA_TYPE, 3> center( const Tri<DATA_TYPE>& tri ) > > { > > const float one_third =3D (1.0f/3.0f); > > return (tri[0] + tri[1] + tri[2]) * one_third; > > } > >=20 > > It seems as though the operator* overload in gmtl/VecOps.h isn't > > matching the above for some reason, but I can't figure out why. I've > > tried calling the gmtl::Point<DATA_TYPE,3> constructor explicitly insid= e > > the parentheses performing the point addition, but that doesn't help. > > Based on what you say below, the above shouldn't be affected at all by > > the changes you just checked in, but I don't have a very good > > understanding of this stuff in general. >=20 > Strange, try using: >=20 > DATA_TYPE(one_third) and see what happens. Ah, that did it. I was hunting around through the gmtl::meta namespace for a hard-coded float type (there was no error with a gmtl::Tri<float>) and completely overlooked the one in the function in question. > Teh strange part of this is the operator* above seems to have two=20 > VecBase params. This should not be allowed. I'll take your word for it on this one. -Patrick > > On Thu, 2004-09-16 at 14:51 -0500, Allen Bierbaum wrote: > >=20 > >>I just merged my work on expression templates from the work branch into= =20 > >>the CVS head of GMTL. > >> > >>This is a *major* feature addition and re-working of the VecBase (Vec &= =20 > >>Point) classes and all operators that work on them. > >> > >>This change uses expression templates to remove temporary objects from=20 > >>expression evaluation and potentially allow compilers to better optimiz= e=20 > >>the code. > >> > >>For example, with the previous code: > >> > >>vec1 =3D vec2 + vec3 + (vec4 * 6) > >> > >>that would have created 3 temporary vectors. In the new code the=20 > >>expression templates output code that directly computes the final value= =20 > >>from the given operands. This has shown at least a 2x performance=20 > >>increase in my tests. > >> > >>The code is far from perfect though and could definitely be optimized=20 > >>much further. (especially by someone that knows intel assembly and has= =20 > >>some patience) > >> > >>There is one common compiler error to be aware of. It is not possible=20 > >>to pass expression templates where VecBase/Vec/Point objects are expect= ed. > >> > >>Details: > >> > >>GMTL makes extensive use of expression templates. These templates come= =20 > >>into play when evaluating statement such as: > >> > >>gmtl::Vec3f vec1, vec2, vec3; > >>vec1 =3D vec2 + (vec3 * 6.0); > >> > >>When evaluating the expression on the second line, GMTL creates an=20 > >>expression template tree to fully evaluate this expression when =3D is=20 > >>called. The details of this process are normally hidden from the user,= =20 > >>but can come to the forefront when a method expects a Vec or Point=20 > >>argument and is passed an expression. For example: > >> > >>void myMethod(gmtl::Vec3f vec) > >>{ ... } > >> > >>gmtl::Vec3f vec1, vec2; > >> > >>myMethod(vec1); // Works correctly > >>myMethod(vec1 + vec2); // Fails to compile > >> > >>The reason the second line fails to compile is that the type for "vec1 = +=20 > >>vec2" is not a Vec3f. It is an expression template that describes how=20 > >>to sum two Vec3f's. (You may expect an autoconversion to happen, but it= =20 > >>does not because of template argument deduction rules). > >> > >>There are two solutions to this, either explicitly construct a temporar= y > >>object to pass to the method (which is what an auto conversion would do= =20 > >>anyway) or write the method to handle expression templates. This secon= d=20 > >>option is not difficult, but does require a further understanding of=20 > >>GMTL then is documented here. > >> > >>Here is how the first option could be used: > >> > >>myMethod(gmtl::Vec3f(vec1 + vec2)); // Creates a temporary to pass = in > >> > >> > >> > >>In closing: Give the code and try and let me know what you think. :) > >> > >> > >>-Allen >=20 >=20 --=20 Patrick L. Hartling | Research Assistant, VRAC http://www.137.org/patrick/ | 2274 Howe Hall Room 2624 PGP: http://tinyurl.com/2oum9 | http://www.vrac.iastate.edu/ |