|
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/
|