Browse Source

merge 0.9.5

Christophe Riccio 11 years ago
parent
commit
b5ffd74c3e
5 changed files with 780 additions and 764 deletions
  1. 162 172
      glm/gtx/io.hpp
  2. 584 565
      glm/gtx/io.inl
  3. 30 24
      glm/gtx/quaternion.inl
  4. 2 1
      readme.txt
  5. 2 2
      test/core/core_func_matrix.cpp

+ 162 - 172
glm/gtx/io.hpp

@@ -57,178 +57,168 @@
 
 namespace glm
 {
-  /// @addtogroup gtx_io
-  /// @{
-  
-  namespace io
-  {
-    
-    enum order_type { column_major, row_major, };
-    
-    template <typename CTy>
-    class format_punct : public std::locale::facet {
-
-      typedef CTy char_type;
-      
-    public:
-
-      static std::locale::id id;
-
-      bool       formatted;
-      unsigned   precision;
-      unsigned   width;
-      char_type  separator;
-      char_type  delim_left;
-      char_type  delim_right;
-      char_type  space;
-      char_type  newline;
-      order_type order;
-      
-      explicit format_punct(size_t a = 0);
-      explicit format_punct(format_punct const&);
-      
-    };
-
-    template <typename CTy, typename CTr = std::char_traits<CTy> >
-    class basic_state_saver {
-
-    public:
-
-      explicit basic_state_saver(std::basic_ios<CTy,CTr>&);
-              ~basic_state_saver();
-
-    private:
-
-      typedef ::std::basic_ios<CTy,CTr>      state_type;
-      typedef typename state_type::char_type char_type;
-      typedef ::std::ios_base::fmtflags      flags_type;
-      typedef ::std::streamsize              streamsize_type;
-      typedef ::std::locale const            locale_type;
-      
-      state_type&     state_;
-      flags_type      flags_;
-      streamsize_type precision_;
-      streamsize_type width_;
-      char_type       fill_;
-      locale_type     locale_;
-      
-      basic_state_saver& operator=(basic_state_saver const&);
-      
-    };
-
-    typedef basic_state_saver<char>     state_saver;
-    typedef basic_state_saver<wchar_t> wstate_saver;
-    
-    template <typename CTy, typename CTr = std::char_traits<CTy> >
-    class basic_format_saver {
-
-    public:
-
-      explicit basic_format_saver(std::basic_ios<CTy,CTr>&);
-              ~basic_format_saver();
-
-    private:
-
-      basic_state_saver<CTy> const bss_;
-
-      basic_format_saver& operator=(basic_format_saver const&);
-      
-    };
-
-    typedef basic_format_saver<char>     format_saver;
-    typedef basic_format_saver<wchar_t> wformat_saver;
-    
-    struct precision {
-
-      unsigned value;
-      
-      explicit precision(unsigned);
-      
-    };
-
-    struct width {
-
-      unsigned value;
-      
-      explicit width(unsigned);
-      
-    };
-
-    template <typename CTy>
-    struct delimeter {
-
-      CTy value[3];
-      
-      explicit delimeter(CTy /* left */, CTy /* right */, CTy /* separator */ = ',');
-      
-    };
-
-    struct order {
-
-      order_type value;
-      
-      explicit order(order_type);
-      
-    };
-    
-    // functions, inlined (inline)
-
-    template <typename FTy, typename CTy, typename CTr>
-    FTy const& get_facet(std::basic_ios<CTy,CTr>&);
-    template <typename FTy, typename CTy, typename CTr>
-    std::basic_ios<CTy,CTr>& formatted(std::basic_ios<CTy,CTr>&);
-    template <typename FTy, typename CTy, typename CTr>
-    std::basic_ios<CTy,CTr>& unformattet(std::basic_ios<CTy,CTr>&);
-    
-    template <typename CTy, typename CTr>
-    std::basic_ostream<CTy, CTr>& operator<<(std::basic_ostream<CTy, CTr>&, precision const&);
-    template <typename CTy, typename CTr>
-    std::basic_ostream<CTy, CTr>& operator<<(std::basic_ostream<CTy, CTr>&, width const&);
-    template <typename CTy, typename CTr>
-    std::basic_ostream<CTy, CTr>& operator<<(std::basic_ostream<CTy, CTr>&, delimeter<CTy> const&);
-    template <typename CTy, typename CTr>
-    std::basic_ostream<CTy, CTr>& operator<<(std::basic_ostream<CTy, CTr>&, order const&);
-    
-  }//namespace io
-
-  namespace detail
-  {
-
-    template <typename CTy, typename CTr, typename T, precision P>
-    GLM_FUNC_DECL std::basic_ostream<CTy,CTr>& operator<<(std::basic_ostream<CTy,CTr>&, tquat<T,P> const&);
-    template <typename CTy, typename CTr, typename T, precision P>
-    GLM_FUNC_DECL std::basic_ostream<CTy,CTr>& operator<<(std::basic_ostream<CTy,CTr>&, tvec2<T,P> const&);
-    template <typename CTy, typename CTr, typename T, precision P>
-    GLM_FUNC_DECL std::basic_ostream<CTy,CTr>& operator<<(std::basic_ostream<CTy,CTr>&, tvec3<T,P> const&);
-    template <typename CTy, typename CTr, typename T, precision P>
-    GLM_FUNC_DECL std::basic_ostream<CTy,CTr>& operator<<(std::basic_ostream<CTy,CTr>&, tvec4<T,P> const&);
-    template <typename CTy, typename CTr, typename T, precision P>
-    GLM_FUNC_DECL std::basic_ostream<CTy,CTr>& operator<<(std::basic_ostream<CTy,CTr>&, tmat2x2<T,P> const&);
-    template <typename CTy, typename CTr, typename T, precision P>
-    GLM_FUNC_DECL std::basic_ostream<CTy,CTr>& operator<<(std::basic_ostream<CTy,CTr>&, tmat2x3<T,P> const&);
-    template <typename CTy, typename CTr, typename T, precision P>
-    GLM_FUNC_DECL std::basic_ostream<CTy,CTr>& operator<<(std::basic_ostream<CTy,CTr>&, tmat2x4<T,P> const&);
-    template <typename CTy, typename CTr, typename T, precision P>
-    GLM_FUNC_DECL std::basic_ostream<CTy,CTr>& operator<<(std::basic_ostream<CTy,CTr>&, tmat3x2<T,P> const&);
-    template <typename CTy, typename CTr, typename T, precision P>
-    GLM_FUNC_DECL std::basic_ostream<CTy,CTr>& operator<<(std::basic_ostream<CTy,CTr>&, tmat3x3<T,P> const&);
-    template <typename CTy, typename CTr, typename T, precision P>
-    GLM_FUNC_DECL std::basic_ostream<CTy,CTr>& operator<<(std::basic_ostream<CTy,CTr>&, tmat3x4<T,P> const&);
-    template <typename CTy, typename CTr, typename T, precision P>
-    GLM_FUNC_DECL std::basic_ostream<CTy,CTr>& operator<<(std::basic_ostream<CTy,CTr>&, tmat4x2<T,P> const&);
-    template <typename CTy, typename CTr, typename T, precision P>
-    GLM_FUNC_DECL std::basic_ostream<CTy,CTr>& operator<<(std::basic_ostream<CTy,CTr>&, tmat4x3<T,P> const&);
-    template <typename CTy, typename CTr, typename T, precision P>
-    GLM_FUNC_DECL std::basic_ostream<CTy,CTr>& operator<<(std::basic_ostream<CTy,CTr>&, tmat4x4<T,P> const&);
-    
-    template <typename CTy, typename CTr, typename T, precision P>
-    GLM_FUNC_DECL std::basic_ostream<CTy,CTr>& operator<<(std::basic_ostream<CTy,CTr>&,
-                                                          std::pair<tmat4x4<T,P> const,
-                                                                    tmat4x4<T,P> const> const&);
-    
-  }//namespace detail
-  
-  /// @}
+	/// @addtogroup gtx_io
+	/// @{
+
+	namespace io
+	{
+		enum order_type { column_major, row_major};
+
+		template <typename CTy>
+		class format_punct : public std::locale::facet
+		{
+			typedef CTy char_type;
+
+		public:
+
+			static std::locale::id id;
+
+			bool       formatted;
+			unsigned   precision;
+			unsigned   width;
+			char_type  separator;
+			char_type  delim_left;
+			char_type  delim_right;
+			char_type  space;
+			char_type  newline;
+			order_type order;
+
+			explicit format_punct(size_t a = 0);
+			explicit format_punct(format_punct const&);
+		};
+
+		template <typename CTy, typename CTr = std::char_traits<CTy> >
+		class basic_state_saver {
+
+		public:
+
+			explicit basic_state_saver(std::basic_ios<CTy,CTr>&);
+					~basic_state_saver();
+
+		private:
+
+			typedef ::std::basic_ios<CTy,CTr>      state_type;
+			typedef typename state_type::char_type char_type;
+			typedef ::std::ios_base::fmtflags      flags_type;
+			typedef ::std::streamsize              streamsize_type;
+			typedef ::std::locale const            locale_type;
+
+			state_type&     state_;
+			flags_type      flags_;
+			streamsize_type precision_;
+			streamsize_type width_;
+			char_type       fill_;
+			locale_type     locale_;
+
+			basic_state_saver& operator=(basic_state_saver const&);
+		};
+
+		typedef basic_state_saver<char>     state_saver;
+		typedef basic_state_saver<wchar_t> wstate_saver;
+
+		template <typename CTy, typename CTr = std::char_traits<CTy> >
+		class basic_format_saver
+		{
+		public:
+
+			explicit basic_format_saver(std::basic_ios<CTy,CTr>&);
+					~basic_format_saver();
+
+		private:
+
+			basic_state_saver<CTy> const bss_;
+
+			basic_format_saver& operator=(basic_format_saver const&);
+		};
+
+		typedef basic_format_saver<char>     format_saver;
+		typedef basic_format_saver<wchar_t> wformat_saver;
+
+		struct precision
+		{
+			unsigned value;
+
+			explicit precision(unsigned);
+		};
+
+		struct width
+		{
+			unsigned value;
+
+			explicit width(unsigned);
+		};
+
+		template <typename CTy>
+		struct delimeter
+		{
+			CTy value[3];
+
+			explicit delimeter(CTy /* left */, CTy /* right */, CTy /* separator */ = ',');
+		};
+
+		struct order
+		{
+			order_type value;
+
+			explicit order(order_type);
+		};
+
+		// functions, inlined (inline)
+
+		template <typename FTy, typename CTy, typename CTr>
+		FTy const& get_facet(std::basic_ios<CTy,CTr>&);
+		template <typename FTy, typename CTy, typename CTr>
+		std::basic_ios<CTy,CTr>& formatted(std::basic_ios<CTy,CTr>&);
+		template <typename FTy, typename CTy, typename CTr>
+		std::basic_ios<CTy,CTr>& unformattet(std::basic_ios<CTy,CTr>&);
+
+		template <typename CTy, typename CTr>
+		std::basic_ostream<CTy, CTr>& operator<<(std::basic_ostream<CTy, CTr>&, precision const&);
+		template <typename CTy, typename CTr>
+		std::basic_ostream<CTy, CTr>& operator<<(std::basic_ostream<CTy, CTr>&, width const&);
+		template <typename CTy, typename CTr>
+		std::basic_ostream<CTy, CTr>& operator<<(std::basic_ostream<CTy, CTr>&, delimeter<CTy> const&);
+		template <typename CTy, typename CTr>
+		std::basic_ostream<CTy, CTr>& operator<<(std::basic_ostream<CTy, CTr>&, order const&);
+	}//namespace io
+
+	namespace detail
+	{
+		template <typename CTy, typename CTr, typename T, precision P>
+		GLM_FUNC_DECL std::basic_ostream<CTy,CTr>& operator<<(std::basic_ostream<CTy,CTr>&, tquat<T,P> const&);
+		template <typename CTy, typename CTr, typename T, precision P>
+		GLM_FUNC_DECL std::basic_ostream<CTy,CTr>& operator<<(std::basic_ostream<CTy,CTr>&, tvec2<T,P> const&);
+		template <typename CTy, typename CTr, typename T, precision P>
+		GLM_FUNC_DECL std::basic_ostream<CTy,CTr>& operator<<(std::basic_ostream<CTy,CTr>&, tvec3<T,P> const&);
+		template <typename CTy, typename CTr, typename T, precision P>
+		GLM_FUNC_DECL std::basic_ostream<CTy,CTr>& operator<<(std::basic_ostream<CTy,CTr>&, tvec4<T,P> const&);
+		template <typename CTy, typename CTr, typename T, precision P>
+		GLM_FUNC_DECL std::basic_ostream<CTy,CTr>& operator<<(std::basic_ostream<CTy,CTr>&, tmat2x2<T,P> const&);
+		template <typename CTy, typename CTr, typename T, precision P>
+		GLM_FUNC_DECL std::basic_ostream<CTy,CTr>& operator<<(std::basic_ostream<CTy,CTr>&, tmat2x3<T,P> const&);
+		template <typename CTy, typename CTr, typename T, precision P>
+		GLM_FUNC_DECL std::basic_ostream<CTy,CTr>& operator<<(std::basic_ostream<CTy,CTr>&, tmat2x4<T,P> const&);
+		template <typename CTy, typename CTr, typename T, precision P>
+		GLM_FUNC_DECL std::basic_ostream<CTy,CTr>& operator<<(std::basic_ostream<CTy,CTr>&, tmat3x2<T,P> const&);
+		template <typename CTy, typename CTr, typename T, precision P>
+		GLM_FUNC_DECL std::basic_ostream<CTy,CTr>& operator<<(std::basic_ostream<CTy,CTr>&, tmat3x3<T,P> const&);
+		template <typename CTy, typename CTr, typename T, precision P>
+		GLM_FUNC_DECL std::basic_ostream<CTy,CTr>& operator<<(std::basic_ostream<CTy,CTr>&, tmat3x4<T,P> const&);
+		template <typename CTy, typename CTr, typename T, precision P>
+		GLM_FUNC_DECL std::basic_ostream<CTy,CTr>& operator<<(std::basic_ostream<CTy,CTr>&, tmat4x2<T,P> const&);
+		template <typename CTy, typename CTr, typename T, precision P>
+		GLM_FUNC_DECL std::basic_ostream<CTy,CTr>& operator<<(std::basic_ostream<CTy,CTr>&, tmat4x3<T,P> const&);
+		template <typename CTy, typename CTr, typename T, precision P>
+		GLM_FUNC_DECL std::basic_ostream<CTy,CTr>& operator<<(std::basic_ostream<CTy,CTr>&, tmat4x4<T,P> const&);
+
+		template <typename CTy, typename CTr, typename T, precision P>
+		GLM_FUNC_DECL std::basic_ostream<CTy,CTr> & operator<<(
+			std::basic_ostream<CTy,CTr> &,
+			std::pair<tmat4x4<T,P> const,
+			tmat4x4<T,P> const> const &);
+	}//namespace detail
+
+	/// @}
 }//namespace glm
 
 #include "io.inl"

+ 584 - 565
glm/gtx/io.inl

@@ -10,570 +10,589 @@
 #include <iomanip> // std::setfill<>, std::fixed, std::setprecision, std::right, std::setw
 #include <ostream> // std::basic_ostream<>
 
-namespace glm
+namespace glm{
+namespace io
 {
-  namespace io
-  {
-  
-    template <typename CTy>
-    /* explicit */ GLM_FUNC_QUALIFIER
-    format_punct<CTy>::format_punct(size_t a)
-      : std::locale::facet(a),
-        formatted         (true),
-        precision         (3),
-        width             (1 + 4 + 1 + precision),
-        separator         (','),
-        delim_left        ('['),
-        delim_right       (']'),
-        space             (' '),
-        newline           ('\n'),
-        order             (row_major)
-    {}
-
-    template <typename CTy>
-    /* explicit */ GLM_FUNC_QUALIFIER
-    format_punct<CTy>::format_punct(format_punct const& a)
-      : std::locale::facet(0),
-        formatted         (a.formatted),
-        precision         (a.precision),
-        width             (a.width),
-        separator         (a.separator),
-        delim_left        (a.delim_left),
-        delim_right       (a.delim_right),
-        space             (a.space),
-        newline           (a.newline),
-        order             (a.order)
-    {}
-    
-    template <typename CTy> std::locale::id format_punct<CTy>::id;
-
-    template <typename CTy, typename CTr>
-    /* explicit */ GLM_FUNC_QUALIFIER
-    basic_state_saver<CTy,CTr>::basic_state_saver(std::basic_ios<CTy,CTr>& a)
-      : state_    (a),
-        flags_    (a.flags()),
-        precision_(a.precision()),
-        width_    (a.width()),
-        fill_     (a.fill()),
-        locale_   (a.getloc())
-    {}
-    
-    template <typename CTy, typename CTr>
-    GLM_FUNC_QUALIFIER
-    basic_state_saver<CTy,CTr>::~basic_state_saver()
-    {
-      state_.imbue(locale_);
-      state_.fill(fill_);
-      state_.width(width_);
-      state_.precision(precision_);
-      state_.flags(flags_);
-    }
-    
-    template <typename CTy, typename CTr>
-    /* explicit */ GLM_FUNC_QUALIFIER
-    basic_format_saver<CTy,CTr>::basic_format_saver(std::basic_ios<CTy,CTr>& a)
-      : bss_(a)
-    {
-      a.imbue(std::locale(a.getloc(), new format_punct<CTy>(get_facet<format_punct<CTy> >(a))));
-    }
-
-    template <typename CTy, typename CTr>
-    GLM_FUNC_QUALIFIER
-    basic_format_saver<CTy,CTr>::~basic_format_saver()
-    {}
-    
-    /* explicit */ GLM_FUNC_QUALIFIER
-    precision::precision(unsigned a)
-      : value(a)
-    {}
-
-    /* explicit */ GLM_FUNC_QUALIFIER
-    width::width(unsigned a)
-      : value(a)
-    {}
-
-    template <typename CTy>
-    /* explicit */ GLM_FUNC_QUALIFIER
-    delimeter<CTy>::delimeter(CTy a, CTy b, CTy c)
-      : value()
-    {
-      value[0] = a;
-      value[1] = b;
-      value[2] = c;
-    }
-
-    /* explicit */ GLM_FUNC_QUALIFIER
-    order::order(order_type a)
-      : value(a)
-    {}
-    
-    template <typename FTy, typename CTy, typename CTr>
-    GLM_FUNC_QUALIFIER FTy const&
-    get_facet(std::basic_ios<CTy,CTr>& ios)
-    {
-      if (!std::has_facet<FTy>(ios.getloc())) {
-        ios.imbue(std::locale(ios.getloc(), new FTy));
-      }
-
-      return std::use_facet<FTy>(ios.getloc());
-    }
-
-    template <typename CTy, typename CTr>
-    GLM_FUNC_QUALIFIER std::basic_ios<CTy,CTr>&
-    formatted(std::basic_ios<CTy,CTr>& ios)
-    {
-      const_cast<format_punct<CTy>&>(get_facet<format_punct<CTy> >(ios)).formatted = true;
-
-      return ios;
-    }
-    
-    template <typename CTy, typename CTr>
-    GLM_FUNC_QUALIFIER std::basic_ios<CTy,CTr>&
-    unformatted(std::basic_ios<CTy,CTr>& ios)
-    {
-      const_cast<format_punct<CTy>&>(get_facet<format_punct<CTy> >(ios)).formatted = false;
-
-      return ios;
-    }
-    
-    template <typename CTy, typename CTr>
-    GLM_FUNC_QUALIFIER std::basic_ostream<CTy, CTr>&
-    operator<<(std::basic_ostream<CTy, CTr>& os, precision const& a)
-    {
-      const_cast<format_punct<CTy>&>(get_facet<format_punct<CTy> >(os)).precision = a.value;
-
-      return os;
-    }
-
-    template <typename CTy, typename CTr>
-    GLM_FUNC_QUALIFIER std::basic_ostream<CTy, CTr>&
-    operator<<(std::basic_ostream<CTy, CTr>& os, width const& a)
-    {
-      const_cast<format_punct<CTy>&>(get_facet<format_punct<CTy> >(os)).width = a.value;
-
-      return os;
-    }
-
-    template <typename CTy, typename CTr>
-    std::basic_ostream<CTy, CTr>& operator<<(std::basic_ostream<CTy, CTr>& os,
-                                             delimeter<CTy> const& a)
-    {
-      format_punct<CTy>& fmt(const_cast<format_punct<CTy>&>(get_facet<format_punct<CTy> >(os)));
-
-      fmt.delim_left  = a.value[0];
-      fmt.delim_right = a.value[1];
-      fmt.separator   = a.value[2];
-      
-      return os;
-    }
-
-    template <typename CTy, typename CTr>
-    GLM_FUNC_QUALIFIER std::basic_ostream<CTy, CTr>&
-    operator<<(std::basic_ostream<CTy, CTr>& os, order const& a)
-    {
-      const_cast<format_punct<CTy>&>(get_facet<format_punct<CTy> >(os)).order = a.value;
-
-      return os;
-    }
-    
-  } // namespace io
-  
-  namespace detail {
-    
-    template <typename CTy, typename CTr, typename T, precision P>
-    GLM_FUNC_QUALIFIER std::basic_ostream<CTy,CTr>&
-    operator<<(std::basic_ostream<CTy,CTr>& os, tquat<T,P> const& a)
-    {
-      typename std::basic_ostream<CTy,CTr>::sentry const cerberus(os);
-
-      if (cerberus) {
-        io::format_punct<CTy> const& fmt(io::get_facet<io::format_punct<CTy> >(os));
-
-        if (fmt.formatted) {
-          io::basic_state_saver<CTy> const bss(os);
-        
-          os << std::fixed
-             << std::right
-             << std::setprecision(fmt.precision)
-             << std::setfill(fmt.space)
-             << fmt.delim_left
-             << std::setw(fmt.width) << a.w << fmt.separator
-             << std::setw(fmt.width) << a.x << fmt.separator
-             << std::setw(fmt.width) << a.y << fmt.separator
-             << std::setw(fmt.width) << a.z
-             << fmt.delim_right;
-        } else {
-          os << a.w << fmt.space << a.x << fmt.space << a.y << fmt.space << a.z;
-        }
-      }
-      
-      return os;
-    }
-    
-    template <typename CTy, typename CTr, typename T, precision P>
-    GLM_FUNC_QUALIFIER std::basic_ostream<CTy,CTr>&
-    operator<<(std::basic_ostream<CTy,CTr>& os, tvec2<T,P> const& a)
-    {
-      typename std::basic_ostream<CTy,CTr>::sentry const cerberus(os);
-
-      if (cerberus) {
-        io::format_punct<CTy> const& fmt(io::get_facet<io::format_punct<CTy> >(os));
-
-        if (fmt.formatted) {
-          io::basic_state_saver<CTy> const bss(os);
-          
-          os << std::fixed
-             << std::right
-             << std::setprecision(fmt.precision)
-             << std::setfill(fmt.space)
-             << fmt.delim_left
-             << std::setw(fmt.width) << a.x << fmt.separator
-             << std::setw(fmt.width) << a.y
-             << fmt.delim_right;
-        } else {
-          os << a.x << fmt.space << a.y;
-        }
-      }
-
-      return os;
-    }
-  
-    template <typename CTy, typename CTr, typename T, precision P>
-    GLM_FUNC_QUALIFIER std::basic_ostream<CTy,CTr>&
-    operator<<(std::basic_ostream<CTy,CTr>& os, tvec3<T,P> const& a)
-    {
-      typename std::basic_ostream<CTy,CTr>::sentry const cerberus(os);
-
-      if (cerberus) {
-        io::format_punct<CTy> const& fmt(io::get_facet<io::format_punct<CTy> >(os));
-
-        if (fmt.formatted) {
-          io::basic_state_saver<CTy> const bss(os);
-          
-          os << std::fixed
-             << std::right
-             << std::setprecision(fmt.precision)
-             << std::setfill(fmt.space)
-             << fmt.delim_left
-             << std::setw(fmt.width) << a.x << fmt.separator
-             << std::setw(fmt.width) << a.y << fmt.separator
-             << std::setw(fmt.width) << a.z
-             << fmt.delim_right;
-        } else {
-          os << a.x << fmt.space << a.y << fmt.space << a.z;
-        }
-      }
-      
-      return os;
-    }
-    
-    template <typename CTy, typename CTr, typename T, precision P>
-    GLM_FUNC_QUALIFIER std::basic_ostream<CTy,CTr>&
-    operator<<(std::basic_ostream<CTy,CTr>& os, tvec4<T,P> const& a)
-    {
-      typename std::basic_ostream<CTy,CTr>::sentry const cerberus(os);
-
-      if (cerberus) {
-        io::format_punct<CTy> const& fmt(io::get_facet<io::format_punct<CTy> >(os));
-
-        if (fmt.formatted) {
-          io::basic_state_saver<CTy> const bss(os);
-        
-          os << std::fixed
-             << std::right
-             << std::setprecision(fmt.precision)
-             << std::setfill(fmt.space)
-             << fmt.delim_left
-             << std::setw(fmt.width) << a.x << fmt.separator
-             << std::setw(fmt.width) << a.y << fmt.separator
-             << std::setw(fmt.width) << a.z << fmt.separator
-             << std::setw(fmt.width) << a.w
-             << fmt.delim_right;
-        } else {
-          os << a.x << fmt.space << a.y << fmt.space << a.z << fmt.space << a.w;
-        }
-      }
-      
-      return os;
-    }
-
-    template <typename CTy, typename CTr, typename T, precision P>
-    GLM_FUNC_QUALIFIER std::basic_ostream<CTy,CTr>&
-    operator<<(std::basic_ostream<CTy,CTr>& os, tmat2x2<T,P> const& a)
-    {
-      typename std::basic_ostream<CTy,CTr>::sentry const cerberus(os);
-
-      if (cerberus) {
-        io::format_punct<CTy> const& fmt(io::get_facet<io::format_punct<CTy> >(os));
-        tmat2x2<T,P>                 m(a);
-
-        if (io::row_major == fmt.order) {
-          m = transpose(a);
-        }
-
-        if (fmt.formatted) {
-          os << fmt.newline
-             << fmt.delim_left << m[0] << fmt.newline
-             << fmt.space      << m[1] << fmt.delim_right;
-        } else {
-          os << m[0] << fmt.space << m[1];
-        }
-      }
-
-      return os;
-    }
-
-    template <typename CTy, typename CTr, typename T, precision P>
-    GLM_FUNC_QUALIFIER std::basic_ostream<CTy,CTr>&
-    operator<<(std::basic_ostream<CTy,CTr>& os, tmat2x3<T,P> const& a)
-    {
-      typename std::basic_ostream<CTy,CTr>::sentry const cerberus(os);
-
-      if (cerberus) {
-        io::format_punct<CTy> const& fmt(io::get_facet<io::format_punct<CTy> >(os));
-        tmat3x2<T,P>                 m(a);
-
-        if (io::row_major == fmt.order) {
-          m = transpose(a);
-        }
-
-        if (fmt.formatted) {
-          os << fmt.newline
-             << fmt.delim_left << m[0] << fmt.newline
-             << fmt.space      << m[1] << fmt.newline
-             << fmt.space      << m[2] << fmt.delim_right;
-        } else {
-          os << m[0] << fmt.space << m[1] << fmt.space << m[2];
-        }
-      }
-
-      return os;
-    }
-
-    template <typename CTy, typename CTr, typename T, precision P>
-    GLM_FUNC_QUALIFIER std::basic_ostream<CTy,CTr>&
-    operator<<(std::basic_ostream<CTy,CTr>& os, tmat2x4<T,P> const& a)
-    {
-      typename std::basic_ostream<CTy,CTr>::sentry const cerberus(os);
-
-      if (cerberus) {
-        io::format_punct<CTy> const& fmt(io::get_facet<io::format_punct<CTy> >(os));
-        tmat4x2<T,P>                 m(a);
-
-        if (io::row_major == fmt.order) {
-          m = transpose(a);
-        }
-
-        if (fmt.formatted) {
-          os << fmt.newline
-             << fmt.delim_left << m[0] << fmt.newline
-             << fmt.space      << m[1] << fmt.newline
-             << fmt.space      << m[2] << fmt.newline
-             << fmt.space      << m[3] << fmt.delim_right;
-        } else {
-          os << m[0] << fmt.space << m[1] << fmt.space << m[2] << fmt.space << m[3];
-        }
-      }
-
-      return os;
-    }
-
-    template <typename CTy, typename CTr, typename T, precision P>
-    GLM_FUNC_QUALIFIER std::basic_ostream<CTy,CTr>&
-    operator<<(std::basic_ostream<CTy,CTr>& os, tmat3x2<T,P> const& a)
-    {
-      typename std::basic_ostream<CTy,CTr>::sentry const cerberus(os);
-
-      if (cerberus) {
-        io::format_punct<CTy> const& fmt(io::get_facet<io::format_punct<CTy> >(os));
-        tmat2x3<T,P>                 m(a);
-
-        if (io::row_major == fmt.order) {
-          m = transpose(a);
-        }
-
-        if (fmt.formatted) {
-          os << fmt.newline
-             << fmt.delim_left << m[0] << fmt.newline
-             << fmt.space      << m[1] << fmt.delim_right;
-        } else {
-          os << m[0] << fmt.space << m[1];
-        }
-      }
-
-      return os;
-    }
-
-    template <typename CTy, typename CTr, typename T, precision P>
-    GLM_FUNC_QUALIFIER std::basic_ostream<CTy,CTr>&
-    operator<<(std::basic_ostream<CTy,CTr>& os, tmat3x3<T,P> const& a)
-    {
-      typename std::basic_ostream<CTy,CTr>::sentry const cerberus(os);
-
-      if (cerberus) {
-        io::format_punct<CTy> const& fmt(io::get_facet<io::format_punct<CTy> >(os));
-        tmat3x3<T,P>                 m(a);
-
-        if (io::row_major == fmt.order) {
-          m = transpose(a);
-        }
-
-        if (fmt.formatted) {
-          os << fmt.newline
-             << fmt.delim_left << m[0] << fmt.newline
-             << fmt.space      << m[1] << fmt.newline
-             << fmt.space      << m[2] << fmt.delim_right;
-        } else {
-          os << m[0] << fmt.space << m[1] << fmt.space << m[2];
-        }
-      }
-
-      return os;
-    }
-
-    template <typename CTy, typename CTr, typename T, precision P>
-    GLM_FUNC_QUALIFIER std::basic_ostream<CTy,CTr>&
-    operator<<(std::basic_ostream<CTy,CTr>& os, tmat3x4<T,P> const& a)
-    {
-      typename std::basic_ostream<CTy,CTr>::sentry const cerberus(os);
-
-      if (cerberus) {
-        io::format_punct<CTy> const& fmt(io::get_facet<io::format_punct<CTy> >(os));
-        tmat4x3<T,P>                 m(a);
-
-        if (io::row_major == fmt.order) {
-          m = transpose(a);
-        }
-
-        if (fmt.formatted) {
-          os << fmt.newline
-             << fmt.delim_left << m[0] << fmt.newline
-             << fmt.space      << m[1] << fmt.newline
-             << fmt.space      << m[2] << fmt.newline
-             << fmt.space      << m[3] << fmt.delim_right;
-        } else {
-          os << m[0] << fmt.space << m[1] << fmt.space << m[2] << fmt.space << m[3];
-        }
-      }
-
-      return os;
-    }
-
-    template <typename CTy, typename CTr, typename T, precision P>
-    GLM_FUNC_QUALIFIER std::basic_ostream<CTy,CTr>&
-    operator<<(std::basic_ostream<CTy,CTr>& os, tmat4x2<T,P> const& a)
-    {
-      typename std::basic_ostream<CTy,CTr>::sentry const cerberus(os);
-
-      if (cerberus) {
-        io::format_punct<CTy> const& fmt(io::get_facet<io::format_punct<CTy> >(os));
-        tmat2x4<T,P>                 m(a);
-
-        if (io::row_major == fmt.order) {
-          m = transpose(a);
-        }
-
-        if (fmt.formatted) {
-          os << fmt.newline
-             << fmt.delim_left << m[0] << fmt.newline
-             << fmt.space      << m[1] << fmt.delim_right;
-        } else {
-          os << m[0] << fmt.space << m[1];
-        }
-      }
-
-      return os;
-    }
-
-    template <typename CTy, typename CTr, typename T, precision P>
-    GLM_FUNC_QUALIFIER std::basic_ostream<CTy,CTr>&
-    operator<<(std::basic_ostream<CTy,CTr>& os, tmat4x3<T,P> const& a)
-    {
-      typename std::basic_ostream<CTy,CTr>::sentry const cerberus(os);
-
-      if (cerberus) {
-        io::format_punct<CTy> const& fmt(io::get_facet<io::format_punct<CTy> >(os));
-        tmat3x4<T,P>                 m(a);
-
-        if (io::row_major == fmt.order) {
-          m = transpose(a);
-        }
-
-        if (fmt.formatted) {
-          os << fmt.newline
-             << fmt.delim_left << m[0] << fmt.newline
-             << fmt.space      << m[1] << fmt.newline
-             << fmt.space      << m[2] << fmt.delim_right;
-        } else {
-          os << m[0] << fmt.space << m[1] << fmt.space << m[2];
-        }
-      }
-
-      return os;
-    }
-
-    template <typename CTy, typename CTr, typename T, precision P>
-    GLM_FUNC_QUALIFIER std::basic_ostream<CTy,CTr>&
-    operator<<(std::basic_ostream<CTy,CTr>& os, tmat4x4<T,P> const& a)
-    {
-      typename std::basic_ostream<CTy,CTr>::sentry const cerberus(os);
-
-      if (cerberus) {
-        io::format_punct<CTy> const& fmt(io::get_facet<io::format_punct<CTy> >(os));
-        tmat4x4<T,P>                 m(a);
-
-        if (io::row_major == fmt.order) {
-          m = transpose(a);
-        }
-
-        if (fmt.formatted) {
-          os << fmt.newline
-             << fmt.delim_left << m[0] << fmt.newline
-             << fmt.space      << m[1] << fmt.newline
-             << fmt.space      << m[2] << fmt.newline
-             << fmt.space      << m[3] << fmt.delim_right;
-        } else {
-          os << m[0] << fmt.space << m[1] << fmt.space << m[2] << fmt.space << m[3];
-        }
-      }
-
-      return os;
-    }
-
-    template <typename CTy, typename CTr, typename T, precision P>
-    GLM_FUNC_QUALIFIER std::basic_ostream<CTy,CTr>&
-    operator<<(std::basic_ostream<CTy,CTr>& os,
-               std::pair<tmat4x4<T,P> const, tmat4x4<T,P> const> const& a)
-    {
-      typename std::basic_ostream<CTy,CTr>::sentry const cerberus(os);
-
-      if (cerberus) {
-        io::format_punct<CTy> const& fmt(io::get_facet<io::format_punct<CTy> >(os));
-        tmat4x4<T,P>                 ml(a.first);
-        tmat4x4<T,P>                 mr(a.second);
-
-        if (io::row_major == fmt.order) {
-          ml = transpose(a.first);
-          mr = transpose(a.second);
-        }
-
-        if (fmt.formatted) {
-          CTy const& l(fmt.delim_left);
-          CTy const& r(fmt.delim_right);
-          CTy const& s(fmt.space);
-        
-          os << fmt.newline
-             << l << ml[0] << s << s << l << mr[0] << fmt.newline
-             << s << ml[1] << s << s << s << mr[1] << fmt.newline
-             << s << ml[2] << s << s << s << mr[2] << fmt.newline
-             << s << ml[3] << r << s << s << mr[3] << r;
-        } else {
-          os << ml << fmt.space << mr;
-        }
-      }
-
-      return os;
-    }
-    
-  }//namespace detail
+	template <typename CTy>
+	/* explicit */ GLM_FUNC_QUALIFIER
+	format_punct<CTy>::format_punct(size_t a)
+		: std::locale::facet(a),
+		formatted         (true),
+		precision         (3),
+		width             (1 + 4 + 1 + precision),
+		separator         (','),
+		delim_left        ('['),
+		delim_right       (']'),
+		space             (' '),
+		newline           ('\n'),
+		order             (row_major)
+	{}
+
+	template <typename CTy>
+	/* explicit */ GLM_FUNC_QUALIFIER
+	format_punct<CTy>::format_punct(format_punct const& a)
+		: std::locale::facet(0),
+		formatted         (a.formatted),
+		precision         (a.precision),
+		width             (a.width),
+		separator         (a.separator),
+		delim_left        (a.delim_left),
+		delim_right       (a.delim_right),
+		space             (a.space),
+		newline           (a.newline),
+		order             (a.order)
+	{}
+
+	template <typename CTy> std::locale::id format_punct<CTy>::id;
+
+	template <typename CTy, typename CTr>
+	/* explicit */ GLM_FUNC_QUALIFIER basic_state_saver<CTy,CTr>::basic_state_saver(std::basic_ios<CTy,CTr>& a)
+		: state_    (a),
+		flags_    (a.flags()),
+		precision_(a.precision()),
+		width_    (a.width()),
+		fill_     (a.fill()),
+		locale_   (a.getloc())
+	{}
+
+	template <typename CTy, typename CTr>
+	GLM_FUNC_QUALIFIER basic_state_saver<CTy,CTr>::~basic_state_saver()
+	{
+		state_.imbue(locale_);
+		state_.fill(fill_);
+		state_.width(width_);
+		state_.precision(precision_);
+		state_.flags(flags_);
+	}
+
+	template <typename CTy, typename CTr>
+	/* explicit */ GLM_FUNC_QUALIFIER basic_format_saver<CTy,CTr>::basic_format_saver(std::basic_ios<CTy,CTr>& a)
+		: bss_(a)
+	{
+		a.imbue(std::locale(a.getloc(), new format_punct<CTy>(get_facet<format_punct<CTy> >(a))));
+	}
+
+	template <typename CTy, typename CTr>
+	GLM_FUNC_QUALIFIER
+	basic_format_saver<CTy,CTr>::~basic_format_saver()
+	{}
+
+	/* explicit */ GLM_FUNC_QUALIFIER precision::precision(unsigned a)
+		: value(a)
+	{}
+
+	/* explicit */ GLM_FUNC_QUALIFIER width::width(unsigned a)
+		: value(a)
+	{}
+
+	template <typename CTy>
+	/* explicit */ GLM_FUNC_QUALIFIER delimeter<CTy>::delimeter(CTy a, CTy b, CTy c)
+		: value()
+	{
+		value[0] = a;
+		value[1] = b;
+		value[2] = c;
+	}
+
+	/* explicit */ GLM_FUNC_QUALIFIER
+	order::order(order_type a)
+		: value(a)
+	{}
+
+	template <typename FTy, typename CTy, typename CTr>
+	GLM_FUNC_QUALIFIER FTy const& get_facet(std::basic_ios<CTy,CTr>& ios)
+	{
+		if (!std::has_facet<FTy>(ios.getloc())) {
+		ios.imbue(std::locale(ios.getloc(), new FTy));
+		}
+
+		return std::use_facet<FTy>(ios.getloc());
+	}
+
+	template <typename CTy, typename CTr>
+	GLM_FUNC_QUALIFIER std::basic_ios<CTy,CTr>& formatted(std::basic_ios<CTy,CTr>& ios)
+	{
+		const_cast<format_punct<CTy>&>(get_facet<format_punct<CTy> >(ios)).formatted = true;
+
+		return ios;
+	}
+
+	template <typename CTy, typename CTr>
+	GLM_FUNC_QUALIFIER std::basic_ios<CTy,CTr>& unformatted(std::basic_ios<CTy,CTr>& ios)
+	{
+		const_cast<format_punct<CTy>&>(get_facet<format_punct<CTy> >(ios)).formatted = false;
+
+		return ios;
+	}
+
+	template <typename CTy, typename CTr>
+	GLM_FUNC_QUALIFIER std::basic_ostream<CTy, CTr>& operator<<(std::basic_ostream<CTy, CTr>& os, precision const& a)
+	{
+		const_cast<format_punct<CTy>&>(get_facet<format_punct<CTy> >(os)).precision = a.value;
+
+		return os;
+	}
+
+	template <typename CTy, typename CTr>
+	GLM_FUNC_QUALIFIER std::basic_ostream<CTy, CTr>& operator<<(std::basic_ostream<CTy, CTr>& os, width const& a)
+	{
+		const_cast<format_punct<CTy>&>(get_facet<format_punct<CTy> >(os)).width = a.value;
+
+		return os;
+	}
+
+	template <typename CTy, typename CTr>
+	std::basic_ostream<CTy, CTr>& operator<<(std::basic_ostream<CTy, CTr>& os, delimeter<CTy> const& a)
+	{
+		format_punct<CTy> & fmt(const_cast<format_punct<CTy>&>(get_facet<format_punct<CTy> >(os)));
+
+		fmt.delim_left  = a.value[0];
+		fmt.delim_right = a.value[1];
+		fmt.separator   = a.value[2];
+
+		return os;
+	}
+
+	template <typename CTy, typename CTr>
+	GLM_FUNC_QUALIFIER std::basic_ostream<CTy, CTr>& operator<<(std::basic_ostream<CTy, CTr>& os, order const& a)
+	{
+		const_cast<format_punct<CTy>&>(get_facet<format_punct<CTy> >(os)).order = a.value;
+
+		return os;
+	}
+} // namespace io
+
+namespace detail
+{
+	template <typename CTy, typename CTr, typename T, precision P>
+	GLM_FUNC_QUALIFIER std::basic_ostream<CTy,CTr>& operator<<(std::basic_ostream<CTy,CTr>& os, tquat<T,P> const& a)
+	{
+		typename std::basic_ostream<CTy,CTr>::sentry const cerberus(os);
+
+		if(cerberus)
+		{
+			io::format_punct<CTy> const & fmt(io::get_facet<io::format_punct<CTy> >(os));
+
+			if(fmt.formatted)
+			{
+				io::basic_state_saver<CTy> const bss(os);
+
+				os << std::fixed
+					<< std::right
+					<< std::setprecision(fmt.precision)
+					<< std::setfill(fmt.space)
+					<< fmt.delim_left
+					<< std::setw(fmt.width) << a.w << fmt.separator
+					<< std::setw(fmt.width) << a.x << fmt.separator
+					<< std::setw(fmt.width) << a.y << fmt.separator
+					<< std::setw(fmt.width) << a.z
+					<< fmt.delim_right;
+			}
+			else
+			{
+				os << a.w << fmt.space << a.x << fmt.space << a.y << fmt.space << a.z;
+			}
+		}
+
+		return os;
+	}
+
+	template <typename CTy, typename CTr, typename T, precision P>
+	GLM_FUNC_QUALIFIER std::basic_ostream<CTy,CTr>& operator<<(std::basic_ostream<CTy,CTr>& os, tvec2<T,P> const& a)
+	{
+		typename std::basic_ostream<CTy,CTr>::sentry const cerberus(os);
+
+		if(cerberus)
+		{
+			io::format_punct<CTy> const & fmt(io::get_facet<io::format_punct<CTy> >(os));
+
+			if(fmt.formatted)
+			{
+				io::basic_state_saver<CTy> const bss(os);
+
+				os << std::fixed
+					<< std::right
+					<< std::setprecision(fmt.precision)
+					<< std::setfill(fmt.space)
+					<< fmt.delim_left
+					<< std::setw(fmt.width) << a.x << fmt.separator
+					<< std::setw(fmt.width) << a.y
+					<< fmt.delim_right;
+			}
+			else
+			{
+				os << a.x << fmt.space << a.y;
+			}
+		}
+
+		return os;
+	}
+
+	template <typename CTy, typename CTr, typename T, precision P>
+	GLM_FUNC_QUALIFIER std::basic_ostream<CTy,CTr>& operator<<(std::basic_ostream<CTy,CTr>& os, tvec3<T,P> const& a)
+	{
+		typename std::basic_ostream<CTy,CTr>::sentry const cerberus(os);
+
+		if(cerberus)
+		{
+			io::format_punct<CTy> const & fmt(io::get_facet<io::format_punct<CTy> >(os));
+
+			if(fmt.formatted)
+			{
+				io::basic_state_saver<CTy> const bss(os);
+
+				os << std::fixed
+					<< std::right
+					<< std::setprecision(fmt.precision)
+					<< std::setfill(fmt.space)
+					<< fmt.delim_left
+					<< std::setw(fmt.width) << a.x << fmt.separator
+					<< std::setw(fmt.width) << a.y << fmt.separator
+					<< std::setw(fmt.width) << a.z
+					<< fmt.delim_right;
+			}
+			else
+			{
+				os << a.x << fmt.space << a.y << fmt.space << a.z;
+			}
+		}
+
+		return os;
+	}
+
+	template <typename CTy, typename CTr, typename T, precision P>
+	GLM_FUNC_QUALIFIER std::basic_ostream<CTy,CTr>& operator<<(std::basic_ostream<CTy,CTr>& os, tvec4<T,P> const& a)
+	{
+		typename std::basic_ostream<CTy,CTr>::sentry const cerberus(os);
+
+		if(cerberus)
+		{
+			io::format_punct<CTy> const & fmt(io::get_facet<io::format_punct<CTy> >(os));
+
+			if(fmt.formatted)
+			{
+				io::basic_state_saver<CTy> const bss(os);
+
+				os << std::fixed
+					<< std::right
+					<< std::setprecision(fmt.precision)
+					<< std::setfill(fmt.space)
+					<< fmt.delim_left
+					<< std::setw(fmt.width) << a.x << fmt.separator
+					<< std::setw(fmt.width) << a.y << fmt.separator
+					<< std::setw(fmt.width) << a.z << fmt.separator
+					<< std::setw(fmt.width) << a.w
+					<< fmt.delim_right;
+			}
+			else
+			{
+				os << a.x << fmt.space << a.y << fmt.space << a.z << fmt.space << a.w;
+			}
+		}
+
+		return os;
+	}
+
+	template <typename CTy, typename CTr, typename T, precision P>
+	GLM_FUNC_QUALIFIER std::basic_ostream<CTy,CTr>& operator<<(std::basic_ostream<CTy,CTr>& os, tmat2x2<T,P> const& a)
+	{
+		typename std::basic_ostream<CTy,CTr>::sentry const cerberus(os);
+
+		if(cerberus)
+		{
+			io::format_punct<CTy> const & fmt(io::get_facet<io::format_punct<CTy> >(os));
+			tmat2x2<T,P> m(a);
+
+			if(io::row_major == fmt.order)
+				m = transpose(a);
+
+			if(fmt.formatted)
+			{
+				os << fmt.newline
+					<< fmt.delim_left << m[0] << fmt.newline
+					<< fmt.space      << m[1] << fmt.delim_right;
+			}
+			else
+			{
+				os << m[0] << fmt.space << m[1];
+			}
+		}
+
+		return os;
+	}
+
+	template <typename CTy, typename CTr, typename T, precision P>
+	GLM_FUNC_QUALIFIER std::basic_ostream<CTy,CTr>& operator<<(std::basic_ostream<CTy,CTr>& os, tmat2x3<T,P> const& a)
+	{
+		typename std::basic_ostream<CTy,CTr>::sentry const cerberus(os);
+
+		if(cerberus)
+		{
+			io::format_punct<CTy> const & fmt(io::get_facet<io::format_punct<CTy> >(os));
+			tmat3x2<T,P> m(a);
+
+			if(io::row_major == fmt.order)
+				m = transpose(a);
+
+			if(fmt.formatted)
+			{
+				os << fmt.newline
+					<< fmt.delim_left << m[0] << fmt.newline
+					<< fmt.space      << m[1] << fmt.newline
+					<< fmt.space      << m[2] << fmt.delim_right;
+			}
+			else
+			{
+				os << m[0] << fmt.space << m[1] << fmt.space << m[2];
+			}
+		}
+
+		return os;
+	}
+
+	template <typename CTy, typename CTr, typename T, precision P>
+	GLM_FUNC_QUALIFIER std::basic_ostream<CTy,CTr>& operator<<(std::basic_ostream<CTy,CTr>& os, tmat2x4<T,P> const& a)
+	{
+		typename std::basic_ostream<CTy,CTr>::sentry const cerberus(os);
+
+		if(cerberus)
+		{
+			io::format_punct<CTy> const & fmt(io::get_facet<io::format_punct<CTy> >(os));
+			tmat4x2<T,P> m(a);
+
+			if(io::row_major == fmt.order)
+				m = transpose(a);
+
+
+			if(fmt.formatted)
+			{
+				os << fmt.newline
+					<< fmt.delim_left << m[0] << fmt.newline
+					<< fmt.space      << m[1] << fmt.newline
+					<< fmt.space      << m[2] << fmt.newline
+					<< fmt.space      << m[3] << fmt.delim_right;
+			}
+			else
+			{
+				os << m[0] << fmt.space << m[1] << fmt.space << m[2] << fmt.space << m[3];
+			}
+		}
+
+		return os;
+	}
+
+	template <typename CTy, typename CTr, typename T, precision P>
+	GLM_FUNC_QUALIFIER std::basic_ostream<CTy,CTr>& operator<<(std::basic_ostream<CTy,CTr>& os, tmat3x2<T,P> const& a)
+	{
+		typename std::basic_ostream<CTy,CTr>::sentry const cerberus(os);
+
+		if(cerberus)
+		{
+			io::format_punct<CTy> const & fmt(io::get_facet<io::format_punct<CTy> >(os));
+			tmat2x3<T,P> m(a);
+
+			if(io::row_major == fmt.order)
+				m = transpose(a);
+
+			if(fmt.formatted)
+			{
+				os << fmt.newline
+					<< fmt.delim_left << m[0] << fmt.newline
+					<< fmt.space      << m[1] << fmt.delim_right;
+			}
+			else
+			{
+				os << m[0] << fmt.space << m[1];
+			}
+		}
+
+		return os;
+	}
+
+	template <typename CTy, typename CTr, typename T, precision P>
+	GLM_FUNC_QUALIFIER std::basic_ostream<CTy,CTr>& operator<<(std::basic_ostream<CTy,CTr>& os, tmat3x3<T,P> const& a)
+	{
+		typename std::basic_ostream<CTy,CTr>::sentry const cerberus(os);
+
+		if(cerberus)
+		{
+			io::format_punct<CTy> const & fmt(io::get_facet<io::format_punct<CTy> >(os));
+			tmat3x3<T,P> m(a);
+
+			if(io::row_major == fmt.order)
+				m = transpose(a);
+
+			if(fmt.formatted)
+			{
+				os << fmt.newline
+					<< fmt.delim_left << m[0] << fmt.newline
+					<< fmt.space      << m[1] << fmt.newline
+					<< fmt.space      << m[2] << fmt.delim_right;
+			}
+			else
+			{
+				os << m[0] << fmt.space << m[1] << fmt.space << m[2];
+			}
+		}
+
+		return os;
+	}
+
+	template <typename CTy, typename CTr, typename T, precision P>
+	GLM_FUNC_QUALIFIER std::basic_ostream<CTy,CTr> & operator<<(std::basic_ostream<CTy,CTr>& os, tmat3x4<T,P> const& a)
+	{
+		typename std::basic_ostream<CTy,CTr>::sentry const cerberus(os);
+
+		if(cerberus)
+		{
+			io::format_punct<CTy> const & fmt(io::get_facet<io::format_punct<CTy> >(os));
+			tmat4x3<T,P> m(a);
+
+			if(io::row_major == fmt.order)
+				m = transpose(a);
+
+			if (fmt.formatted)
+			{
+				os << fmt.newline
+					<< fmt.delim_left << m[0] << fmt.newline
+					<< fmt.space      << m[1] << fmt.newline
+					<< fmt.space      << m[2] << fmt.newline
+					<< fmt.space      << m[3] << fmt.delim_right;
+			}
+			else
+			{
+				os << m[0] << fmt.space << m[1] << fmt.space << m[2] << fmt.space << m[3];
+			}
+		}
+
+		return os;
+	}
+
+	template <typename CTy, typename CTr, typename T, precision P>
+	GLM_FUNC_QUALIFIER std::basic_ostream<CTy,CTr> & operator<<(std::basic_ostream<CTy,CTr>& os, tmat4x2<T,P> const& a)
+	{
+		typename std::basic_ostream<CTy,CTr>::sentry const cerberus(os);
+
+		if(cerberus)
+		{
+			io::format_punct<CTy> const & fmt(io::get_facet<io::format_punct<CTy> >(os));
+			tmat2x4<T,P> m(a);
+
+			if(io::row_major == fmt.order)
+				m = transpose(a);
+
+			if (fmt.formatted)
+			{
+				os << fmt.newline
+					<< fmt.delim_left << m[0] << fmt.newline
+					<< fmt.space      << m[1] << fmt.delim_right;
+			}
+			else
+			{
+				os << m[0] << fmt.space << m[1];
+			}
+		}
+
+		return os;
+	}
+
+	template <typename CTy, typename CTr, typename T, precision P>
+	GLM_FUNC_QUALIFIER std::basic_ostream<CTy,CTr> & operator<<(std::basic_ostream<CTy,CTr>& os, tmat4x3<T,P> const& a)
+	{
+		typename std::basic_ostream<CTy,CTr>::sentry const cerberus(os);
+
+		if(cerberus)
+		{
+			io::format_punct<CTy> const & fmt(io::get_facet<io::format_punct<CTy> >(os));
+			tmat3x4<T,P> m(a);
+
+			if(io::row_major == fmt.order)
+				m = transpose(a);
+
+			if(fmt.formatted)
+			{
+				os << fmt.newline
+					<< fmt.delim_left << m[0] << fmt.newline
+					<< fmt.space      << m[1] << fmt.newline
+					<< fmt.space      << m[2] << fmt.delim_right;
+			}
+			else
+			{
+				os << m[0] << fmt.space << m[1] << fmt.space << m[2];
+			}
+		}
+
+		return os;
+	}
+
+	template <typename CTy, typename CTr, typename T, precision P>
+	GLM_FUNC_QUALIFIER std::basic_ostream<CTy,CTr> & operator<<(std::basic_ostream<CTy,CTr>& os, tmat4x4<T,P> const& a)
+	{
+		typename std::basic_ostream<CTy,CTr>::sentry const cerberus(os);
+
+		if(cerberus)
+		{
+			io::format_punct<CTy> const & fmt(io::get_facet<io::format_punct<CTy> >(os));
+			tmat4x4<T,P> m(a);
+
+			if (io::row_major == fmt.order)
+				m = transpose(a);
+
+			if(fmt.formatted)
+			{
+				os << fmt.newline
+					<< fmt.delim_left << m[0] << fmt.newline
+					<< fmt.space      << m[1] << fmt.newline
+					<< fmt.space      << m[2] << fmt.newline
+					<< fmt.space      << m[3] << fmt.delim_right;
+			}
+			else
+			{
+				os << m[0] << fmt.space << m[1] << fmt.space << m[2] << fmt.space << m[3];
+			}
+		}
+
+		return os;
+	}
+
+	template <typename CTy, typename CTr, typename T, precision P>
+	GLM_FUNC_QUALIFIER std::basic_ostream<CTy,CTr>& operator<<(
+		std::basic_ostream<CTy,CTr> & os,
+		std::pair<tmat4x4<T,P> const, tmat4x4<T,P> const> const& a)
+	{
+		typename std::basic_ostream<CTy,CTr>::sentry const cerberus(os);
+
+		if(cerberus)
+		{
+			io::format_punct<CTy> const & fmt(io::get_facet<io::format_punct<CTy> >(os));
+			tmat4x4<T,P> ml(a.first);
+			tmat4x4<T,P> mr(a.second);
+
+			if(io::row_major == fmt.order)
+			{
+				ml = transpose(a.first);
+				mr = transpose(a.second);
+			}
+
+			if(fmt.formatted)
+			{
+				CTy const & l(fmt.delim_left);
+				CTy const & r(fmt.delim_right);
+				CTy const & s(fmt.space);
+
+				os << fmt.newline
+					<< l << ml[0] << s << s << l << mr[0] << fmt.newline
+					<< s << ml[1] << s << s << s << mr[1] << fmt.newline
+					<< s << ml[2] << s << s << s << mr[2] << fmt.newline
+					<< s << ml[3] << r << s << s << mr[3] << r;
+			}
+			else
+			{
+				os << ml << fmt.space << mr;
+			}
+		}
+
+		return os;
+	}
+}//namespace detail
 }//namespace glm

+ 30 - 24
glm/gtx/quaternion.inl

@@ -8,6 +8,7 @@
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
 #include <limits>
+#include "../gtc/constants.hpp"
 
 namespace glm
 {
@@ -40,7 +41,7 @@ namespace glm
 		detail::tquat<T, P> const & s2,
 		T const & h)
 	{
-		return mix(mix(q1, q2, h), mix(s1, s2, h), T(2) * (T(1) - h) * h);
+		return mix(mix(q1, q2, h), mix(s1, s2, h), static_cast<T>(2) * (static_cast<T>(1) - h) * h);
 	}
 
 	template <typename T, precision P>
@@ -52,7 +53,7 @@ namespace glm
 	)
 	{
 		detail::tquat<T, P> invQuat = inverse(curr);
-		return exp((log(next + invQuat) + log(prev + invQuat)) / T(-4)) * curr;
+		return exp((log(next + invQuat) + log(prev + invQuat)) / static_cast<T>(-4)) * curr;
 	}
 
 	template <typename T, precision P>
@@ -62,7 +63,10 @@ namespace glm
 	)
 	{
 		detail::tvec3<T, P> u(q.x, q.y, q.z);
-		float Angle = glm::length(u);
+		T Angle = glm::length(u);
+		if (Angle < epsilon<T>())
+			return detail::tquat<T, P>();
+
 		detail::tvec3<T, P> v(u / Angle);
 		return detail::tquat<T, P>(cos(Angle), sin(Angle) * v);
 	}
@@ -73,18 +77,20 @@ namespace glm
 		detail::tquat<T, P> const & q
 	)
 	{
-		if((q.x == static_cast<T>(0)) && (q.y == static_cast<T>(0)) && (q.z == static_cast<T>(0)))
+		detail::tvec3<T, P> u(q.x, q.y, q.z);
+		T Vec3Len = length(u);
+
+		if (Vec3Len < epsilon<T>())
 		{
-			if(q.w > T(0))
-				return detail::tquat<T, P>(log(q.w), T(0), T(0), T(0));
-			else if(q.w < T(0))
-				return detail::tquat<T, P>(log(-q.w), T(3.1415926535897932384626433832795), T(0),T(0));
+			if(q.w > static_cast<T>(0))
+				return detail::tquat<T, P>(log(q.w), static_cast<T>(0), static_cast<T>(0), static_cast<T>(0));
+			else if(q.w < static_cast<T>(0))
+				return detail::tquat<T, P>(log(-q.w), pi<T>(), static_cast<T>(0), static_cast<T>(0));
 			else
 				return detail::tquat<T, P>(std::numeric_limits<T>::infinity(), std::numeric_limits<T>::infinity(), std::numeric_limits<T>::infinity(), std::numeric_limits<T>::infinity());
 		}
 		else
 		{
-			T Vec3Len = sqrt(q.x * q.x + q.y * q.y + q.z * q.z);
 			T QuatLen = sqrt(Vec3Len * Vec3Len + q.w * q.w);
 			T t = atan(Vec3Len, T(q.w)) / Vec3Len;
 			return detail::tquat<T, P>(log(QuatLen), t * q.x, t * q.y, t * q.z);
@@ -98,11 +104,11 @@ namespace glm
 		T const & y
 	)
 	{
-		if(abs(x.w) > T(0.9999))
+		if(abs(x.w) > (static_cast<T>(1) - epsilon<T>()))
 			return x;
-		float Angle = acos(y);
-		float NewAngle = Angle * y;
-		float Div = sin(NewAngle) / sin(Angle);
+		T Angle = acos(y);
+		T NewAngle = Angle * y;
+		T Div = sin(NewAngle) / sin(Angle);
 		return detail::tquat<T, P>(
 			cos(NewAngle),
 			x.x * Div,
@@ -146,7 +152,7 @@ namespace glm
 		detail::tquat<T, P> const & q
 	)
 	{
-		T w = static_cast<T>(1.0) - q.x * q.x - q.y * q.y - q.z * q.z;
+		T w = static_cast<T>(1) - q.x * q.x - q.y * q.y - q.z * q.z;
 		if(w < T(0))
 			return T(0);
 		else
@@ -170,12 +176,12 @@ namespace glm
 		T const & a
 	)
 	{
-		if(a <= T(0)) return x;
-		if(a >= T(1)) return y;
+		if(a <= static_cast<T>(0)) return x;
+		if(a >= static_cast<T>(1)) return y;
 
 		T fCos = dot(x, y);
 		detail::tquat<T, P> y2(y); //BUG!!! tquat<T> y2;
-		if(fCos < T(0))
+		if(fCos < static_cast<T>(0))
 		{
 			y2 = -y;
 			fCos = -fCos;
@@ -183,7 +189,7 @@ namespace glm
 
 		//if(fCos > 1.0f) // problem
 		T k0, k1;
-		if(fCos > T(0.9999))
+		if(fCos > (static_cast<T>(1) - epsilon<T>()))
 		{
 			k0 = static_cast<T>(1) - a;
 			k1 = static_cast<T>(0) + a; //BUG!!! 1.0f + a;
@@ -193,8 +199,8 @@ namespace glm
 			T fSin = sqrt(T(1) - fCos * fCos);
 			T fAngle = atan(fSin, fCos);
 			T fOneOverSin = static_cast<T>(1) / fSin;
-			k0 = sin((T(1) - a) * fAngle) * fOneOverSin;
-			k1 = sin((T(0) + a) * fAngle) * fOneOverSin;
+			k0 = sin((static_cast<T>(1) - a) * fAngle) * fOneOverSin;
+			k1 = sin((static_cast<T>(0) + a) * fAngle) * fOneOverSin;
 		}
 
 		return detail::tquat<T, P>(
@@ -212,7 +218,7 @@ namespace glm
 		T const & a
 	)
 	{
-		return glm::normalize(x * (T(1) - a) + (y * a));
+		return glm::normalize(x * (static_cast<T>(1) - a) + (y * a));
 	}
 
 	template <typename T, precision P>
@@ -225,7 +231,7 @@ namespace glm
 		T cosTheta = dot(orig, dest);
 		detail::tvec3<T, P> rotationAxis;
 
-		if(cosTheta < T(-1) + epsilon<T>())
+		if(cosTheta < static_cast<T>(-1) + epsilon<T>())
 		{
 			// special case when vectors in opposite directions :
 			// there is no "ideal" rotation axis
@@ -243,11 +249,11 @@ namespace glm
 		// Implementation from Stan Melax's Game Programming Gems 1 article
 		rotationAxis = cross(orig, dest);
 
-		T s = sqrt((T(1) + cosTheta) * T(2));
+		T s = sqrt((T(1) + cosTheta) * static_cast<T>(2));
 		T invs = static_cast<T>(1) / s;
 
 		return detail::tquat<T, P>(
-			s * T(0.5f), 
+			s * static_cast<T>(0.5f), 
 			rotationAxis.x * invs,
 			rotationAxis.y * invs,
 			rotationAxis.z * invs);

+ 2 - 1
readme.txt

@@ -45,7 +45,7 @@ GLM 0.9.6.0: 2014-XX-XX
 - Added move contructors and assignment operators (#141)
 
 ================================================================================
-GLM 0.9.5.4: 2014-0X-XX
+GLM 0.9.5.4: 2014-06-21
 --------------------------------------------------------------------------------
 - Fixed non-utf8 character #196
 - Added FindGLM install for CMake #189
@@ -64,6 +64,7 @@ GLM 0.9.5.4: 2014-0X-XX
 - Fixed std::copy and std::vector with GLM types #214
 - Fixed strict aliasing issues #212, #152
 - Fixed std::nextafter not supported with C++11 on Android #213
+- Fixed corner cases in exp and log functions for quaternions #199
 
 ================================================================================
 GLM 0.9.5.3: 2014-04-02

+ 2 - 2
test/core/core_func_matrix.cpp

@@ -228,10 +228,10 @@ int test_inverse_perf(std::size_t Instance, char const * Message)
 	//glm::uint Ulp = 0;
 	//Ulp = glm::max(glm::float_distance(*Dst, *Src), Ulp);
 
-	printf("inverse<%s>(%f): %d\n", Message, Diff, EndTime - StartTime);
+	printf("inverse<%s>(%f): %lu\n", Message, Diff, EndTime - StartTime);
 
 	return 0;
-};
+}
 
 int main()
 {