T.Day@ucl-cs.UUCP (12/19/89)
From: Tim Day <T.Day@uk.ac.ucl.cs>
+-----------------------------------------------------------------------------+
Tim Day | Meet every second in life as challenge;
Department of Photogrammetry | Respond fully to whatever happens
UCL, Gower St., London WC1E 6BT | without anxiety, or complaint, or clinging
+-----------------------------------------------------------------------------+
// Hope you can handle this... I like it W I D E
//
// I recently got around to putting some consts in my Vector3 class
// .. which promply broke. This used to work fine before
// I added the consts. Am I using them right ? I get no errors from compiler
//
// Compiled with g++ (-v gcc version 1.36.1 (based on GCC 1.36)) on Sun3, OS4.something>0
// g++ -m68020 -m68881 -O -fdefault-inline -finline-functions -fstrength-reduce -fomit-frame-pointer vector.cc -o vector
// Problem described in main() at end
// g++ -m68020 -m68881 -g vector.cc -o vector works OK... some kinda optimisation bug
// Also works fine if you #define const /* */
#include <stream.h>
typedef void Void;
typedef char Char;
typedef short Short;
typedef int Int;
typedef long Long;
typedef float Float;
typedef double Double;
typedef unsigned char UnsignedChar;
typedef unsigned short UnsignedShort;
typedef unsigned int UnsignedInt;
typedef unsigned long UnsignedLong;
typedef Int Boolean;
typedef ostream Ostream;
typedef istream Istream;
class Vector3
{
Double component[3];
public:
Void x(Double x) {component[0]=x;}
Void y(Double y) {component[1]=y;}
Void z(Double z) {component[2]=z;}
Void c(Int c,Double m) {component[c]=m;}
Double x() const {return component[0];}
Double y() const {return component[1];}
Double z() const {return component[2];}
Double c(Int n) const {return component[n];}
Vector3(Double a=0.0,Double b=0.0,Double c=0.0) {x(a);y(b);z(c);}
Vector3(const Vector3 &p) {x(p.x());y(p.y());z(p.z());}
Void operator+=(const Vector3 &p) {x(x()+p.x());y(y()+p.y());z(z()+p.z());}
Void operator-=(const Vector3 &p) {x(x()-p.x());y(y()-p.y());z(z()-p.z());}
Void operator*=(Double a) {x(a*x());y(a*y());z(a*z());} // Problem in here
Void operator/=(Double a) {(*this)*=(1.0/a);}
Double magnitude2() const {return x()*x()+y()*y()+z()*z();}
Double magnitude() const {return sqrt(magnitude2());}
Void normalise() {(*this)*=(1.0/magnitude());}
Vector3 normalised() const;
};
inline Vector3 Vector3::normalised() const return r(*this);{r.normalise();}
inline Vector3 operator+(const Vector3 &p,const Vector3 &q) return r(p);{r+=q;}
inline Vector3 operator-(const Vector3 &p,const Vector3 &q) return r(p);{r-=q;}
inline Vector3 operator-(const Vector3 &p) {return Vector3(-p.x(),-p.y(),-p.z());}
inline Vector3 operator*(Double a,const Vector3 &p) return r(p);{r*=a;}
inline Vector3 operator*(const Vector3 &p,Double a) return r(p);{r*=a;}
inline Vector3 operator/(const Vector3 &p,Double a) return r(p);{r/=a;}
inline Boolean operator==(const Vector3 &p,const Vector3 &q) {return (p.x()==q.x() && p.y()==q.y() && p.z()==q.z());}
inline Boolean operator!=(const Vector3 &p,const Vector3 &q) {return (p.x()!=q.x() || p.y()!=q.y() || p.z()==q.z());}
inline Double operator&(const Vector3 &p,const Vector3 &q) {return p.x()*q.x()+p.y()*q.y()+p.z()*q.z();} /* Dot product */
inline Vector3 operator*(const Vector3 &p,const Vector3 &q) {return Vector3(p.y()*q.z()-p.z()*q.y(), /* Cross product */
p.z()*q.x()-p.x()*q.z(),
p.x()*q.y()-p.y()*q.x()
);
}
Istream& operator>>(Istream &i,Vector3 &v) {Double x,y,z;if (i>>x && i>>y && i>>z) v=Vector3(x,y,z);return i;}
Ostream& operator<<(Ostream &o,const Vector3 &v) {o << v.x() << " " << v.y() << " " << v.z();return o;}
Void foo(const Vector3 &t) {cout << t << "\n";}
main()
{ Vector3 t(1.0,1.0,1.0);
t*=10.0;
cout << t << "\n"; // Outputs 10 1 10 on Sun3, (OK on Sun4)
foo(t); // But foo output 10 10 10 !
exit(0);
}
// Looking at the assembler output reveals...
// That the first ``cout<<'' is all mixed up with the multiplies, whereas the call to foo
// operates on the finished result. I can't follow the inlined cout<< stuff enough to work out what's happening.
// The constructors are inline, but don't call inline versions of x(), y() (irrelevant to this problem)
// Putting some cerr<<s into operator*= seems to indicate that y() has the right value
// after y(a*y()), but then gets clobbered by z()... but something more subtle
// must be going on as it contains the right value for the call to foo.