00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #ifndef SGE_MATH_VECTOR_HPP_INCLUDED
00022 #define SGE_MATH_VECTOR_HPP_INCLUDED
00023
00024 #include "basic_sequence.hpp"
00025
00026 namespace sge
00027 {
00028 namespace math
00029 {
00030 namespace detail
00031 {
00032
00033 template<
00034 typename T,
00035 dim_type Dim>
00036 class vector_policy;
00037
00038 template<
00039 typename T>
00040 class vector_policy<T, 1> {
00041 protected:
00042 typedef T &reference;
00043 typedef T const &const_reference;
00044 typedef T* pointer;
00045 public:
00046 reference x();
00047 const_reference x() const;
00048 protected:
00049 vector_policy(
00050 pointer);
00051 pointer data_;
00052 };
00053
00054 template<
00055 typename T>
00056 class vector_policy<T, 2>
00057 : public vector_policy<T, 1> {
00058 protected:
00059 typedef vector_policy<T, 1> base;
00060 typedef typename base::reference reference;
00061 typedef typename base::const_reference const_reference;
00062 typedef typename base::pointer pointer;
00063 public:
00064 reference y();
00065 const_reference y() const;
00066 protected:
00067 vector_policy(
00068 pointer);
00069 };
00070
00071 template<
00072 typename T>
00073 class vector_policy<T, 3>
00074 : public vector_policy<T, 2> {
00075 protected:
00076 typedef vector_policy<T, 2> base;
00077 typedef typename base::reference reference;
00078 typedef typename base::const_reference const_reference;
00079 typedef typename base::pointer pointer;
00080 public:
00081 reference z();
00082 const_reference z() const;
00083 protected:
00084 vector_policy(
00085 pointer);
00086 };
00087
00088 template<
00089 typename T,
00090 dim_type Dim>
00091 class vector_policy
00092 : public vector_policy<T, 3> {
00093 typedef vector_policy<T, 3> base;
00094 typedef typename base::reference reference;
00095 typedef typename base::const_reference const_reference;
00096 typedef typename base::pointer pointer;
00097 public:
00098 reference x();
00099 const_reference x() const;
00100 reference y();
00101 const_reference y() const;
00102 reference z();
00103 const_reference z() const;
00104 protected:
00105 vector_policy(
00106 pointer);
00107 private:
00108 pointer data_;
00109 };
00110
00111 }
00112
00113 }
00114 }
00115
00116
00117 #define basic_vector_ext(T, Dim) sge::math::basic_sequence<T, Dim, sge::math::detail::vector_policy>
00118
00119 #include "../config.h"
00120 #include "compare.hpp"
00121 #include "mod.hpp"
00122 #include "../exception.hpp"
00123 #include "../text.hpp"
00124 #include "../assert.hpp"
00125 #include "../su.hpp"
00126 #include "../no_initialization_tag.hpp"
00127 #include "../exception.hpp"
00128 #ifndef SGE_HAVE_VARIADIC_TEMPLATES
00129 #include <boost/static_assert.hpp>
00130 #include <boost/preprocessor/enum_params.hpp>
00131 #include <boost/preprocessor/repetition/repeat.hpp>
00132 #include <boost/preprocessor/arithmetic/add.hpp>
00133 #endif
00134 #include <boost/utility/enable_if.hpp>
00135 #include <iterator>
00136 #include <istream>
00137 #include <ostream>
00138 #include <cstddef>
00139 #include <cmath>
00140
00141 #ifndef SGE_HAVE_VARIADIC_TEMPLATES
00142 #ifndef SGE_MATH_VECTOR_MAX_SIZE
00143 #define SGE_MATH_VECTOR_MAX_SIZE 4
00144 #endif
00145 #endif
00146
00147 namespace sge
00148 {
00149 namespace math
00150 {
00151
00160 template<typename T, std::size_t Dim>
00161 class basic_vector {
00162 #ifndef SGE_HAVE_VARIADIC_TEMPLATES
00163 BOOST_STATIC_ASSERT(Dim <= SGE_MATH_VECTOR_MAX_SIZE);
00164 #endif
00165 public:
00166 typedef T value_type;
00167 typedef T& reference;
00168 typedef const T& const_reference;
00169 typedef std::ptrdiff_t difference_type;
00170 typedef std::size_t size_type;
00171 typedef T* pointer;
00172 typedef const T* const_pointer;
00173 typedef pointer iterator;
00174 typedef const_pointer const_iterator;
00175 typedef std::reverse_iterator<iterator> reverse_iterator;
00176 typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
00177
00178 #ifdef SGE_HAVE_VARIADIC_TEMPLATES
00179 template<typename... Args>
00180 explicit basic_vector(Args... args)
00181 {
00182 #ifdef SGE_HAVE_STATIC_ASSERT
00183 static_assert(sizeof...(args) == Dim, "Invalid number of arguments to math::vector ctor!");
00184 #else
00185 BOOST_STATIC_ASSERT(sizeof...(args) == Dim);
00186 #endif
00187 set(args...);
00188 }
00189 #else
00190 #define SGE_MATH_VECTOR_CTOR_ASSIGN_N(z, n, text) (*this)[n] = text##n;
00191 #define SGE_MATH_VECTOR_CTOR(z, n, text) basic_vector(BOOST_PP_ENUM_PARAMS(BOOST_PP_ADD(n,1), T const& param)) { BOOST_STATIC_ASSERT(BOOST_PP_ADD(n,1)==Dim); BOOST_PP_REPEAT(BOOST_PP_ADD(n,1), SGE_MATH_VECTOR_CTOR_ASSIGN_N, param) }
00192 BOOST_PP_REPEAT(SGE_MATH_VECTOR_MAX_SIZE, SGE_MATH_VECTOR_CTOR, void)
00193 #endif
00194
00198 basic_vector()
00199 {
00200 for(size_type i = 0; i < Dim; ++i)
00201 data_[i] = static_cast<T>(0);
00202 }
00203
00207 basic_vector(no_initialization_tag)
00208 {
00209 }
00210
00217 template<std::size_t U>
00218 basic_vector(const basic_vector<T,U>& v, typename boost::enable_if_c<U == Dim - 1, const_reference>::type n = 0)
00219 {
00220 for(size_type i = 0; i < U; ++i)
00221 data_[i] = v[i];
00222 data_[U] = n;
00223 }
00224
00225 basic_vector(const basic_vector& r)
00226 {
00227 for(size_type i = 0; i < Dim; ++i)
00228 data_[i] = r[i];
00229 }
00230
00231 basic_vector& operator=(const basic_vector& r)
00232 {
00233 for(size_type i = 0; i < Dim; ++i)
00234 data_[i] = r[i];
00235 return *this;
00236 }
00237
00238 basic_vector& operator+=(const basic_vector& r)
00239 {
00240 for(size_type i = 0; i < Dim; ++i)
00241 data_[i] += r[i];
00242 return *this;
00243 }
00244
00245 basic_vector& operator-=(const basic_vector& r)
00246 {
00247 for(size_type i = 0; i < Dim; ++i)
00248 data_[i] -= r[i];
00249 return *this;
00250 }
00251
00252 basic_vector operator+(const basic_vector& r) const
00253 {
00254 return basic_vector(*this) += r;
00255 }
00256
00257 basic_vector operator-(const basic_vector& r) const
00258 {
00259 return basic_vector(*this) -= r;
00260 }
00261
00262 basic_vector operator+() const
00263 {
00264 basic_vector ret = basic_vector(no_initialization_tag());
00265 for(size_type i = 0; i < Dim; ++i)
00266 ret[i] = +data_[i];
00267 return ret;
00268 }
00269
00270 basic_vector operator-() const
00271 {
00272 basic_vector ret = basic_vector(no_initialization_tag());
00273 for(size_type i = 0; i < Dim; ++i)
00274 ret[i] = -data_[i];
00275 return ret;
00276 }
00277
00281 basic_vector& operator*=(const_reference r)
00282 {
00283 for(size_type i = 0; i < Dim; ++i)
00284 (*this)[i] *= r;
00285 return *this;
00286 }
00287
00291 basic_vector& operator*=(const basic_vector& r)
00292 {
00293 for(size_type i = 0; i < Dim; ++i)
00294 (*this)[i] *= r[i];
00295 return *this;
00296 }
00297
00301 basic_vector operator*(const_reference r) const
00302 {
00303 return basic_vector(*this) *= r;
00304 }
00305
00309 basic_vector operator*(const basic_vector& r) const
00310 {
00311 return basic_vector(*this) *= r;
00312 }
00313
00317 friend basic_vector operator*(const_reference l, basic_vector r)
00318 {
00319 return r *= l;
00320 }
00321
00322 basic_vector& operator/=(const_reference r)
00323 {
00324 for(size_type i = 0; i < Dim; ++i)
00325 (*this)[i] /= r;
00326 return *this;
00327 }
00328
00329 basic_vector& operator/=(const basic_vector& r)
00330 {
00331 for(size_type i = 0; i < Dim; ++i)
00332 (*this)[i] /= r[i];
00333 return *this;
00334 }
00335
00336 basic_vector operator/(const_reference r) const
00337 {
00338 return basic_vector(*this) /= r;
00339 }
00340
00341 basic_vector operator/(const basic_vector& r) const
00342 {
00343 return basic_vector(*this) /= r;
00344 }
00345
00349 basic_vector& operator%=(const_reference r)
00350 {
00351 for(size_type i = 0; i < Dim; ++i)
00352 mod_assign((*this)[i], r);
00353 return *this;
00354 }
00355
00359 basic_vector& operator%=(const basic_vector& r)
00360 {
00361 for(size_type i = 0; i < Dim; ++i)
00362 mod_assign((*this)[i], r[i]);
00363 return *this;
00364 }
00365
00369 basic_vector operator%(const_reference r) const
00370 {
00371 return basic_vector(*this) %= r;
00372 }
00373
00377 basic_vector operator%(const basic_vector& r) const
00378 {
00379 return basic_vector(*this) %= r;
00380 }
00381
00382 value_type dot(const basic_vector& r) const
00383 {
00384 value_type ret(0);
00385 for(size_type i = 0; i < Dim; ++i)
00386 ret += (*this)[i] * r[i];
00387 return ret;
00388 }
00389
00393 reference operator[](const size_type pos)
00394 {
00395 SGE_ASSERT(pos < Dim);
00396 return data_[pos];
00397 }
00398
00402 const_reference operator[](const size_type pos) const
00403 {
00404 SGE_ASSERT(pos < Dim);
00405 return data_[pos];
00406 }
00407
00411 reference at(const size_type pos)
00412 {
00413 if(pos >= Dim)
00414 throw exception(SGE_TEXT("basic_vector<T, N>::at(): out of range!"));
00415 return data_[pos];
00416 }
00417
00421 const_reference at(const size_type pos) const
00422 {
00423 if(pos >= Dim)
00424 throw exception(SGE_TEXT("basic_vector<T, N>::at(): out of range!"));
00425 return data_[pos];
00426 }
00427
00431 bool operator==(const basic_vector& r) const
00432 {
00433 for(size_type i = 0; i < Dim; ++i)
00434 if(!compare(data_[i], r[i]))
00435 return false;
00436 return true;
00437 }
00438
00442 bool operator!=(const basic_vector& r) const
00443 {
00444 return !((*this)==r);
00445 }
00446
00450 value_type length_quad() const
00451 {
00452 return dot(*this);
00453 }
00454
00458 value_type length() const
00459 {
00460 return static_cast<value_type>(std::sqrt(length_quad()));
00461 }
00462
00466 basic_vector unit() const
00467 {
00468 SGE_ASSERT(!is_null());
00469 return (*this) * (static_cast<T>(1) / length());
00470 }
00471
00472 basic_vector& normalize()
00473 {
00474 return *this = unit();
00475 }
00476
00477 reference x()
00478 {
00479 return (*this)[0];
00480 }
00481
00482 const_reference x() const
00483 {
00484 return (*this)[0];
00485 }
00486
00487 reference y()
00488 {
00489 return (*this)[1];
00490 }
00491
00492 const_reference y() const
00493 {
00494 return (*this)[1];
00495 }
00496
00497
00498 reference z()
00499 {
00500 SGE_ASSERT(Dim > 2);
00501 return (*this)[2];
00502 }
00503
00504
00505 const_reference z() const
00506 {
00507 SGE_ASSERT(Dim > 2);
00508 return (*this)[2];
00509 }
00510
00511 reference w()
00512 {
00513 SGE_ASSERT(Dim > 3);
00514 return (*this)[3];
00515 }
00516
00517 const_reference w() const
00518 {
00519 SGE_ASSERT(Dim > 3);
00520 return (*this)[3];
00521 }
00522
00523
00524
00525 basic_vector cross(const basic_vector& r) const
00526 {
00527 return basic_vector(y()*r.z() - z()*r.y(),
00528 z()*r.x() - x()*r.z(),
00529 x()*r.y() - y()*r.x());
00530 }
00531
00536 bool is_null() const
00537 {
00538 return *this == basic_vector();
00539 }
00540
00541 void swap(basic_vector& r)
00542 {
00543 std::swap(*this,r);
00544 }
00545
00546 #ifdef SGE_HAVE_VARIADIC_TEMPLATES
00547 template<typename... Args>
00548 void set(const_reference arg, Args... args)
00549 {
00550 #ifdef SGE_HAVE_STATIC_ASSERT
00551 static_assert(sizeof...(args) == Dim-1, "Invalid number of arguments to math::vector::set!");
00552 #else
00553 BOOST_STATIC_ASSERT(sizeof...(args) == Dim);
00554 #endif
00555 set_impl(0, arg, args...);
00556 }
00557 private:
00558 template<typename... Args>
00559 void set_impl(const size_type i, const_reference arg, Args... args)
00560 {
00561 (*this)[i] = arg;
00562 set_impl(i+1, args...);
00563 }
00564
00565 void set_impl(const size_type i, const_reference arg)
00566 {
00567 (*this)[i] = arg;
00568 }
00569 public:
00570 #else
00571 #define SGE_MATH_VECTOR_SET(z, n, text) void set(BOOST_PP_ENUM_PARAMS(BOOST_PP_ADD(n,1), T const& param)) { BOOST_STATIC_ASSERT(BOOST_PP_ADD(n,1)==Dim); BOOST_PP_REPEAT(BOOST_PP_ADD(n,1), SGE_MATH_VECTOR_CTOR_ASSIGN_N, param) }
00572 BOOST_PP_REPEAT(SGE_MATH_VECTOR_MAX_SIZE, SGE_MATH_VECTOR_SET, void)
00573 #endif
00574
00575 bool nearly_equals(const basic_vector& r, const value_type& radius) const
00576 {
00577 const basic_vector tmp(*this - r);
00578 return dot(tmp,tmp) < radius * radius;
00579 }
00580
00581 size_type size() const
00582 {
00583 return Dim;
00584 }
00585
00586 size_type dim() const
00587 {
00588 return Dim;
00589 }
00590
00591 iterator begin()
00592 {
00593 return data_;
00594 }
00595
00596 iterator end()
00597 {
00598 return &data_[Dim];
00599 }
00600
00601 const_iterator begin() const
00602 {
00603 return data_;
00604 }
00605
00606 const_iterator end() const
00607 {
00608 return &data_[Dim];
00609 }
00610
00611 reverse_iterator rbegin()
00612 {
00613 return reverse_iterator(end());
00614 }
00615
00616 reverse_iterator rend()
00617 {
00618 return reverse_iterator(begin());
00619 }
00620
00621 const_reverse_iterator rbegin() const
00622 {
00623 return reverse_iterator(end());
00624 }
00625
00626 const_reverse_iterator rend() const
00627 {
00628 return reverse_iterator(begin());
00629 }
00630
00631 pointer data()
00632 {
00633 return data_;
00634 }
00635
00636 const_pointer data() const
00637 {
00638 return data_;
00639 }
00640 private:
00641 T data_[Dim];
00642 };
00643
00644 template<typename T, std::size_t Dim>
00645 void place(basic_vector<T,Dim>& v,
00646 const typename basic_vector<T,Dim>::const_reference radius,
00647 const typename basic_vector<T,Dim>::const_reference high_angle,
00648 const typename basic_vector<T,Dim>::const_reference plane_angle,
00649 typename boost::enable_if_c<Dim==3,T>::type* = 0)
00650 {
00651 v.x() = radius * std::sin(high_angle) * std::cos(plane_angle);
00652 v.z() = radius * std::sin(high_angle) * std::sin(plane_angle);
00653 v.y() = radius * std::cos(high_angle);
00654 }
00655
00656 template<typename T, std::size_t Dim>
00657 void swap(basic_vector<T,Dim>& a, basic_vector<T,Dim>& b)
00658 {
00659 a.swap(b);
00660 }
00661
00662 template<typename T, std::size_t Dim>
00663 basic_vector<T,Dim> cross(const basic_vector<T,Dim>& l, const basic_vector<T,Dim>& r)
00664 {
00665 return l.cross(r);
00666 }
00667
00668 template<typename T, std::size_t Dim>
00669 basic_vector<T,Dim> normalize(basic_vector<T,Dim> l)
00670 {
00671 return l.normalize();
00672 }
00673
00674 template<typename T, std::size_t Dim>
00675 typename basic_vector<T,Dim>::value_type dot(const basic_vector<T,Dim>& l, const basic_vector<T,Dim>& r)
00676 {
00677 return l.dot(r);
00678 }
00679
00683 template<typename T, std::size_t Dim,typename Ch, typename Traits>
00684 inline std::basic_ostream<Ch,Traits>& operator<< (std::basic_ostream<Ch,Traits>& s, const basic_vector<T,Dim>& v)
00685 {
00686 s << s.widen('(');
00687 for(typename basic_vector<T,Dim>::size_type i = 0; i < Dim-1; ++i)
00688 s << v[i] << s.widen(',');
00689 return s << v[Dim-1] << s.widen(')');
00690 }
00691
00695 template<typename T, std::size_t Dim,typename Ch, typename Traits>
00696 std::basic_istream<Ch,Traits>& operator>> (std::basic_istream<Ch,Traits>& s, basic_vector<T,Dim>& v)
00697 {
00698 Ch c;
00699 s >> c;
00700 if(c != s.widen('('))
00701 s.setstate(std::ios_base::failbit);
00702 for(typename basic_vector<T,Dim>::size_type i = 0; i < Dim-1; ++i)
00703 {
00704 s >> v[i] >> c;
00705 if(c != s.widen(','))
00706 s.setstate(std::ios_base::failbit);
00707 }
00708 s >> v[Dim-1] >> c;
00709 if(c != s.widen(')'))
00710 s.setstate(std::ios_base::failbit);
00711 return s;
00712 }
00713
00717 template<typename D, typename S, std::size_t Dim>
00718 basic_vector<D, Dim> structure_cast(const basic_vector<S, Dim>& s)
00719 {
00720 typedef basic_vector<D, Dim> ret_type;
00721 ret_type ret = ret_type(no_initialization_tag());
00722 for(typename ret_type::size_type i = 0; i < Dim; ++i)
00723 ret[i] = static_cast<D>(s[i]);
00724 return ret;
00725
00726 }
00727
00728 typedef basic_vector<space_unit,2> vector2;
00729 typedef basic_vector<space_unit,3> vector3;
00730 typedef basic_vector<space_unit,4> vector4;
00731
00732 }
00733 }
00734
00735 #endif