Boost logo

Boost :

From: Douglas Gregor (gregod_at_[hidden])
Date: 2002-01-23 17:31:44


Hello,
  Please find below a patch to boost/math/quaternion.hpp that allows it to
compile and run properly on GCC 2.95.3. I also verified that the changes do
not affect a more conforming platform (GCC 3.0.3). I'll summarize the changes
I made to get this working:
  - Include <boost/config.hpp> to figure out what we're running on
  - Only include <locale> if BOOST_NO_STD_LOCALE is not defined
  - include <sstream> always - it's used internally for I/O, and we can't do
without it.
  - include <boost/limits.hpp> instead of <limits>
  - Added the BOOST_GET_VALARRAY macro. GCC 2.95.x's standard library uses
expression templates for valarray computation, so an expression like
abs(some_valarray_variable).max() will fail because max() isn't defined
within the expression template. BOOST_GET_VALARRAY is a simple workaround for
this that will evaluate the expression template to a temporary that max() can
be executed on.
  - GCC 2.95.x's standard library has ostream and istream, but not
basic_ostream<...> and basic_istream<...>, so the input and output operators
have been changed to use ostream and istream (only for GCC 2.95.x, of course)
and to assume we are dealing with characters. ctype<charT>::narrow calls are
eliminated when compiling with GCC 2.95.x.
  - When there is no locale support, don't imbue() the stringstreams with the
incoming istream's locale.
  - GCC 2.95.x doesn't have a class ios_base, but instead has a class ios
that is very similar; use ios instead of ios_base for GCC 2.95.x.

  If the above workarounds are acceptable, I can commit them to CVS.
Octonions will require similar modifications -- I'll write those up and post
them later.

        Doug

Index: quaternion.hpp
===================================================================
RCS file: /cvsroot/boost/boost/boost/math/quaternion.hpp,v
retrieving revision 1.4
diff -c -3 -p -r1.4 quaternion.hpp
*** quaternion.hpp 2002/01/12 13:29:30 1.4
--- quaternion.hpp 2002/01/23 22:18:02
***************
*** 10,18 ****
--- 10,23 ----
  #ifndef BOOST_QUATERNION_HPP
  #define BOOST_QUATERNION_HPP
  
+ #include <boost/config.hpp>
  #include <complex>
  #include <iosfwd> // for the "<<" and ">>"
operators
+ #include <sstream>
+ #ifndef BOOST_NO_STD_LOCALE
  #include <locale> // for the "<<" operator
+ #endif // ndef BOOST_NO_STD_LOCALE
+
  #include <valarray>
  
  #include <boost/math/special_functions/sinc.hpp> // for the Sinus
cardinal
*************** namespace boost
*** 24,29 ****
--- 29,38 ----
      namespace math
      {
  #if defined(__GNUC__) && (__GNUC__ < 3)
+ // gcc 2.95.x uses expression templates for valarray calculations,
but
+ // the result is not conforming. We need BOOST_GET_VALARRAY to get
an
+ // actual valarray result when we need to call a member function
+ # define BOOST_GET_VALARRAY(T, x) valarray<T>(x)
          // gcc 2.x ignores function scope using declarations,
          // put them in the scope of the enclosing namespace instead:
          using ::std::valarray;
*************** namespace boost
*** 32,39 ****
          using ::std::sin;
          using ::std::exp;
          using ::std::cosh;
  #endif
!
      #define BOOST_QUATERNION_ACCESSOR_GENERATOR(type) \
              type real() const \
              { \
--- 41,50 ----
          using ::std::sin;
          using ::std::exp;
          using ::std::cosh;
+ #else
+ # define BOOST_GET_VALARRAY(T, x) x
  #endif
!
      #define BOOST_QUATERNION_ACCESSOR_GENERATOR(type) \
              type real() const \
              { \
*************** namespace boost
*** 123,130 ****
              type b; \
              type c; \
              type d;
-
          
          template<typename T>
          class quaternion
          {
--- 134,143 ----
              type b; \
              type c; \
              type d;
          
+
+ template<typename T> class quaternion;
+
          template<typename T>
          class quaternion
          {
*************** namespace boost
*** 572,578 ****
                  tr[0] = rhs.real();
         \
                  tr[1] = rhs.imag();
         \
                                                                              
         \
! type mixam = static_cast<type>(1)/abs(tr).max();
         \
                                                                              
         \
                  tr *= mixam;
         \
                                                                              
         \
--- 585,591 ----
                  tr[0] = rhs.real();
         \
                  tr[1] = rhs.imag();
         \
                                                                              
         \
! type mixam =
static_cast<type>(1)/BOOST_GET_VALARRAY(type, abs(tr)).max(); \
                                                                              
         \
                  tr *= mixam;
         \
                                                                              
         \
*************** namespace boost
*** 608,614 ****
                  tr[2] = static_cast<type>(rhs.R_component_3());
  \
                  tr[3] = static_cast<type>(rhs.R_component_4());
  \
                                                                              
  \
! type mixam = static_cast<type>(1)/abs(tr).max();
  \
                                                                              
  \
                  tr *= mixam;
  \
                                                                              
  \
--- 621,627 ----
                  tr[2] = static_cast<type>(rhs.R_component_3());
  \
                  tr[3] = static_cast<type>(rhs.R_component_4());
  \
                                                                              
  \
! type mixam =
static_cast<type>(1)/BOOST_GET_VALARRAY(type, abs(tr)).max(); \
                                                                              
  \
                  tr *= mixam;
  \
                                                                              
  \
*************** namespace boost
*** 1055,1288 ****
          // a
          // (a), (a,b), (a,b,c), (a,b,c,d)
          // (a,(c)), (a,(c,d)), ((a)), ((a),c), ((a),(c)),
((a),(c,d)), ((a,b)), ((a,b),c), ((a,b),(c)), ((a,b),(c,d))
!
          template<typename T, typename charT, class traits>
          ::std::basic_istream<charT,traits> & operator >> (
::std::basic_istream<charT,traits> & is,
                                                                  
quaternion<T> & q)
          {
! const ::std::ctype<charT> & ct = ::std::use_facet<
::std::ctype<charT> >(is.getloc());
!
! T a = T();
! T b = T();
! T c = T();
! T d = T();
!
! ::std::complex<T> u = ::std::complex<T>();
! ::std::complex<T> v = ::std::complex<T>();
!
! charT ch = charT();
! char cc;
!
! is >> ch; // get the
first lexeme
!
! if (!is.good()) goto finish;
!
! cc = ct.narrow(ch, char());
!
! if (cc == '(') // read "(",
possible: (a), (a,b), (a,b,c), (a,b,c,d), (a,(c)), (a,(c,d)), ((a)), ((a),c),
((a),(c)), ((a),(c,d)), ((a,b)), ((a,b),c), ((a,b),(c)), ((a,b,),(c,d,))
! {
! is >> ch; // get the
second lexeme
!
! if (!is.good()) goto finish;
!
! cc = ct.narrow(ch, char());
!
! if (cc == '(') // read "((",
possible: ((a)), ((a),c), ((a),(c)), ((a),(c,d)), ((a,b)), ((a,b),c),
((a,b),(c)), ((a,b,),(c,d,))
                  {
! is.putback(ch);
!
! is >> u; // we extract
the first and second components
! a = u.real();
! b = u.imag();
                      
! if (!is.good()) goto finish;
                      
! is >> ch; // get the
next lexeme
                      
! if (!is.good()) goto finish;
                      
! cc = ct.narrow(ch, char());
!
! if (cc == ')') // format:
((a)) or ((a,b))
                      {
! q = quaternion<T>(a,b);
                      }
! else if (cc == ',') // read "((a),"
or "((a,b),", possible: ((a),c), ((a),(c)), ((a),(c,d)), ((a,b),c),
((a,b),(c)), ((a,b,),(c,d,))
                      {
! is >> v; // we extract
the third and fourth components
! c = v.real();
! d = v.imag();
!
! if (!is.good()) goto finish;
!
! is >> ch; // get the
last lexeme
                          
! if (!is.good()) goto finish;
                          
! cc = ct.narrow(ch, char());
                          
! if (cc == ')') // format:
((a),c), ((a),(c)), ((a),(c,d)), ((a,b),c), ((a,b),(c)) or ((a,b,),(c,d,))
                          {
! q = quaternion<T>(a,b,c,d);
                          }
! else // error
                          {
! is.setstate(::std::ios_base::failbit);
                          }
                      }
! else // error
                      {
! is.setstate(::std::ios_base::failbit);
                      }
                  }
! else // read "(a", possible:
(a), (a,b), (a,b,c), (a,b,c,d), (a,(c)), (a,(c,d))
                  {
! is.putback(ch);
!
! is >> a; // we extract
the first component
                      
! if (!is.good()) goto finish;
                      
! is >> ch; // get the
third lexeme
                      
! if (!is.good()) goto finish;
                      
! cc = ct.narrow(ch, char());
                      
! if (cc == ')') // format: (a)
                      {
! q = quaternion<T>(a);
                      }
! else if (cc == ',') // read "(a,",
possible: (a,b), (a,b,c), (a,b,c,d), (a,(c)), (a,(c,d))
                      {
! is >> ch; // get the
fourth lexeme
                          
! if (!is.good()) goto finish;
                          
! cc = ct.narrow(ch, char());
!
! if (cc == '(') // read "(a,(",
possible: (a,(c)), (a,(c,d))
                          {
! is.putback(ch);
                              
! is >> v; // we extract
the third and fourth component
                              
! c = v.real();
! d = v.imag();
                              
! if (!is.good()) goto finish;
                              
! is >> ch; // get the
ninth lexeme
                              
! if (!is.good()) goto finish;
                              
! cc = ct.narrow(ch, char());
                              
! if (cc == ')') // format:
(a,(c)) or (a,(c,d))
                              {
! q = quaternion<T>(a,b,c,d);
                              }
! else // error
                              {
! is.setstate(::std::ios_base::failbit);
                              }
                          }
! else // read "(a,b",
possible: (a,b), (a,b,c), (a,b,c,d)
                          {
! is.putback(ch);
                              
! is >> b; // we extract
the second component
                              
! if (!is.good()) goto finish;
                              
! is >> ch; // get the
fifth lexeme
                              
! if (!is.good()) goto finish;
                              
! cc = ct.narrow(ch, char());
!
! if (cc == ')') // format:
(a,b)
                              {
! q = quaternion<T>(a,b);
                              }
! else if (cc == ',') // read "(a,b,",
possible: (a,b,c), (a,b,c,d)
                              {
! is >> c; // we extract
the third component
!
! if (!is.good()) goto finish;
!
! is >> ch; // get the
seventh lexeme
                                  
! if (!is.good()) goto finish;
                                  
! cc = ct.narrow(ch, char());
                                  
! if (cc == ')') // format:
(a,b,c)
                                  {
! q = quaternion<T>(a,b,c);
                                  }
! else if (cc == ',') // read
"(a,b,c,", possible: (a,b,c,d)
                                  {
! is >> d; // we extract
the fourth component
!
! if (!is.good()) goto finish;
                                      
! is >> ch; // get the
ninth lexeme
                                      
! if (!is.good()) goto finish;
                                      
! cc = ct.narrow(ch, char());
!
! if (cc == ')') // format:
(a,b,c,d)
                                      {
! q = quaternion<T>(a,b,c,d);
                                      }
! else // error
                                      {
!
is.setstate(::std::ios_base::failbit);
                                      }
                                  }
! else // error
                                  {
! is.setstate(::std::ios_base::failbit);
                                  }
                              }
! else // error
                              {
! is.setstate(::std::ios_base::failbit);
                              }
                          }
                      }
! else // error
                      {
! is.setstate(::std::ios_base::failbit);
                      }
                  }
              }
! else // format: a
              {
! is.putback(ch);
                  
! is >> a; // we extract
the first component
                  
! if (!is.good()) goto finish;
                  
! q = quaternion<T>(a);
              }
              
! finish:
! return(is);
          }
          
!
          template<typename T, typename charT, class traits>
          ::std::basic_ostream<charT,traits> & operator << (
::std::basic_ostream<charT,traits> & os,
                                                                  
quaternion<T> const & q)
          {
              ::std::basic_ostringstream<charT,traits> s;
!
              s.flags(os.flags());
              s.imbue(os.getloc());
              s.precision(os.precision());
              
              s << '(' << q.R_component_1() << ','
--- 1068,1382 ----
          // a
          // (a), (a,b), (a,b,c), (a,b,c,d)
          // (a,(c)), (a,(c,d)), ((a)), ((a),c), ((a),(c)),
((a),(c,d)), ((a,b)), ((a,b),c), ((a,b),(c)), ((a,b),(c,d))
! #if defined(__GNUC__) && __GNUC__ < 3
! template<typename T>
! std::istream& operator>>(std::istream& is, quaternion<T>& q)
! #else
          template<typename T, typename charT, class traits>
          ::std::basic_istream<charT,traits> & operator >> (
::std::basic_istream<charT,traits> & is,
                                                                  
quaternion<T> & q)
+ #endif
          {
! #ifndef BOOST_NO_STD_LOCALE
! const ::std::ctype<charT> & ct = ::std::use_facet<
::std::ctype<charT> >(is.getloc());
! #endif
!
! #if defined(__GNUC__) && __GNUC__ < 3
! typedef char charT;
! #endif
!
! T a = T();
! T b = T();
! T c = T();
! T d = T();
!
! ::std::complex<T> u = ::std::complex<T>();
! ::std::complex<T> v = ::std::complex<T>();
!
! charT ch = charT();
! char cc;
!
! is >> ch; // get the first
lexeme
!
! if (!is.good()) goto finish;
! #if defined(__GNUC__) && __GNUC__ < 3
! cc = ch;
! #else
! cc = ct.narrow(ch, char());
! #endif
! if (cc == '(') // read "(",
possible: (a), (a,b), (a,b,c), (a,b,c,d), (a,(c)), (a,(c,d)), ((a)), ((a),c),
((a),(c)), ((a),(c,d)), ((a,b)), ((a,b),c), ((a,b),(c)), ((a,b,),(c,d,))
! {
! is >> ch; // get the
second lexeme
!
! if (!is.good()) goto finish;
! #if defined(__GNUC__) && __GNUC__ < 3
! cc = ch;
! #else
! cc = ct.narrow(ch, char());
! #endif
! if (cc == '(') // read "((",
possible: ((a)), ((a),c), ((a),(c)), ((a),(c,d)), ((a,b)), ((a,b),c),
((a,b),(c)), ((a,b,),(c,d,))
                  {
! is.putback(ch);
                      
! is >> u; // we extract the
first and second components
! a = u.real();
! b = u.imag();
                      
! if (!is.good()) goto finish;
                      
! is >> ch; // get the next
lexeme
                      
! if (!is.good()) goto finish;
!
! #if defined(__GNUC__) && __GNUC__ < 3
! cc = ch;
! #else
! cc = ct.narrow(ch, char());
! #endif
!
! if (cc == ')') // format: ((a))
or ((a,b))
                      {
! q = quaternion<T>(a,b);
                      }
! else if (cc == ',') // read "((a)," or
"((a,b),", possible: ((a),c), ((a),(c)), ((a),(c,d)), ((a,b),c), ((a,b),(c)),
((a,b,),(c,d,))
                      {
! is >> v; // we extract the
third and fourth components
! c = v.real();
! d = v.imag();
                          
! if (!is.good()) goto finish;
                          
! is >> ch; // get the
last lexeme
                          
! if (!is.good()) goto finish;
! #if defined(__GNUC__) && __GNUC__ < 3
! cc = ch;
! #else
! cc = ct.narrow(ch, char());
! #endif
!
! if (cc == ')') // format:
((a),c), ((a),(c)), ((a),(c,d)), ((a,b),c), ((a,b),(c)) or ((a,b,),(c,d,))
                          {
! q = quaternion<T>(a,b,c,d);
                          }
! else // error
                          {
! #if defined(__GNUC__) && __GNUC__ < 3
! is.setstate(std::ios::failbit);
! #else
! is.setstate(::std::ios_base::failbit);
! #endif
                          }
                      }
! else // error
                      {
! #if defined(__GNUC__) && __GNUC__ < 3
! is.setstate(std::ios::failbit);
! #else
! is.setstate(::std::ios_base::failbit);
! #endif
                      }
                  }
! else // read "(a", possible:
(a), (a,b), (a,b,c), (a,b,c,d), (a,(c)), (a,(c,d))
                  {
! is.putback(ch);
                      
! is >> a; // we extract the
first component
                      
! if (!is.good()) goto finish;
                      
! is >> ch; // get the third
lexeme
                      
! if (!is.good()) goto finish;
                      
! #if defined(__GNUC__) && __GNUC__ < 3
! cc = ch;
! #else
! cc = ct.narrow(ch, char());
! #endif
! if (cc == ')') // format: (a)
                      {
! q = quaternion<T>(a);
                      }
! else if (cc == ',') // read "(a,",
possible: (a,b), (a,b,c), (a,b,c,d), (a,(c)), (a,(c,d))
                      {
! is >> ch; // get the
fourth lexeme
                          
! if (!is.good()) goto finish;
                          
! #if defined(__GNUC__) && __GNUC__ < 3
! cc = ch;
! #else
! cc = ct.narrow(ch, char());
! #endif
! if (cc == '(') // read "(a,(",
possible: (a,(c)), (a,(c,d))
                          {
! is.putback(ch);
                              
! is >> v; // we extract the
third and fourth component
                              
! c = v.real();
! d = v.imag();
                              
! if (!is.good()) goto finish;
                              
! is >> ch; // get the ninth
lexeme
                              
! if (!is.good()) goto finish;
                              
! #if defined(__GNUC__) && __GNUC__ < 3
! cc = ch;
! #else
! cc = ct.narrow(ch, char());
! #endif
                              
! if (cc == ')') // format:
(a,(c)) or (a,(c,d))
                              {
! q = quaternion<T>(a,b,c,d);
                              }
! else // error
                              {
! #if defined(__GNUC__) && __GNUC__ < 3
! is.setstate(std::ios::failbit);
! #else
! is.setstate(::std::ios_base::failbit);
! #endif
                              }
                          }
! else // read "(a,b", possible:
(a,b), (a,b,c), (a,b,c,d)
                          {
! is.putback(ch);
                              
! is >> b; // we extract the
second component
                              
! if (!is.good()) goto finish;
                              
! is >> ch; // get the fifth
lexeme
                              
! if (!is.good()) goto finish;
                              
! #if defined(__GNUC__) && __GNUC__ < 3
! cc = ch;
! #else
! cc = ct.narrow(ch, char());
! #endif
!
! if (cc == ')') // format: (a,b)
                              {
! q = quaternion<T>(a,b);
                              }
! else if (cc == ',') // read "(a,b,",
possible: (a,b,c), (a,b,c,d)
                              {
! is >> c; // we extract the
third component
                                  
! if (!is.good()) goto finish;
                                  
! is >> ch; // get the
seventh lexeme
                                  
! if (!is.good()) goto finish;
!
! #if defined(__GNUC__) && __GNUC__ < 3
! cc = ch;
! #else
! cc = ct.narrow(ch, char());
! #endif
!
! if (cc == ')') // format:
(a,b,c)
                                  {
! q = quaternion<T>(a,b,c);
                                  }
! else if (cc == ',') // read "(a,b,c,",
possible: (a,b,c,d)
                                  {
! is >> d; // we extract the
fourth component
                                      
! if (!is.good()) goto finish;
                                      
! is >> ch; // get the ninth
lexeme
                                      
! if (!is.good()) goto finish;
!
! #if defined(__GNUC__) && __GNUC__ < 3
! cc = ch;
! #else
! cc = ct.narrow(ch, char());
! #endif
!
! if (cc == ')') // format:
(a,b,c,d)
                                      {
! q = quaternion<T>(a,b,c,d);
                                      }
! else // error
                                      {
! #if defined(__GNUC__) && __GNUC__ < 3
! is.setstate(std::ios::failbit);
! #else
! is.setstate(::std::ios_base::failbit);
! #endif
                                      }
                                  }
! else // error
                                  {
! #if defined(__GNUC__) && __GNUC__ < 3
! is.setstate(std::ios::failbit);
! #else
! is.setstate(::std::ios_base::failbit);
! #endif
                                  }
                              }
! else // error
                              {
! #if defined(__GNUC__) && __GNUC__ < 3
! is.setstate(std::ios::failbit);
! #else
! is.setstate(::std::ios_base::failbit);
! #endif
                              }
                          }
                      }
! else // error
                      {
! #if defined(__GNUC__) && __GNUC__ < 3
! is.setstate(std::ios::failbit);
! #else
! is.setstate(::std::ios_base::failbit);
! #endif
                      }
                  }
              }
! else // format: a
              {
! is.putback(ch);
                  
! is >> a; // we extract the
first component
                  
! if (!is.good()) goto finish;
                  
! q = quaternion<T>(a);
              }
              
! finish:
! return(is);
          }
          
!
! #if defined(__GNUC__) && __GNUC__ < 3
! template<typename T>
! ::std::ostream& operator<<(::std::ostream& os, quaternion<T> const
& q)
! #else
          template<typename T, typename charT, class traits>
          ::std::basic_ostream<charT,traits> & operator << (
::std::basic_ostream<charT,traits> & os,
                                                                  
quaternion<T> const & q)
+ #endif
          {
+ #if defined(__GNUC__) && __GNUC__ < 3
+ ::std::ostringstream s;
+ #else
              ::std::basic_ostringstream<charT,traits> s;
! #endif
              s.flags(os.flags());
+ #ifndef BOOST_NO_STD_LOCALE
              s.imbue(os.getloc());
+ #endif
              s.precision(os.precision());
              
              s << '(' << q.R_component_1() << ','
*************** namespace boost
*** 1326,1332 ****
          {
              BOOST_QUATERNION_VALARRAY_LOADER
              
! return(abs(temp).max());
          }
          
          
--- 1420,1426 ----
          {
              BOOST_QUATERNION_VALARRAY_LOADER
              
! return(BOOST_GET_VALARRAY(T, abs(temp)).max());
          }
          
          
*************** namespace boost
*** 1335,1341 ****
          {
              BOOST_QUATERNION_VALARRAY_LOADER
              
! return(abs(temp).sum());
          }
          
          
--- 1429,1435 ----
          {
              BOOST_QUATERNION_VALARRAY_LOADER
              
! return(BOOST_GET_VALARRAY(T, abs(temp)).sum());
          }
          
          
*************** namespace boost
*** 1346,1352 ****
              
              BOOST_QUATERNION_VALARRAY_LOADER
              
! T maxim = abs(temp).max(); // overflow protection
              
              if (maxim == static_cast<T>(0))
              {
--- 1440,1446 ----
              
              BOOST_QUATERNION_VALARRAY_LOADER
              
! T maxim = BOOST_GET_VALARRAY(T, abs(temp)).max();
// overflow protection
              
              if (maxim == static_cast<T>(0))
              {
*************** namespace boost
*** 1615,1620 ****
          }
      }
  }
!
  
  #endif /* BOOST_QUATERNION_HPP */
--- 1709,1714 ----
          }
      }
  }
! #undef BOOST_GET_VALARRAY
  
  #endif /* BOOST_QUATERNION_HPP */


Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk