vec.hh

00001 // Copyright (C) 2001, 2002, 2003, 2004 EPITA Research and Development
00002 // Laboratory
00003 //
00004 // This file is part of the Olena Library.  This library is free
00005 // software; you can redistribute it and/or modify it under the terms
00006 // of the GNU General Public License version 2 as published by the
00007 // Free Software Foundation.
00008 //
00009 // This library is distributed in the hope that it will be useful,
00010 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00011 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00012 // General Public License for more details.
00013 //
00014 // You should have received a copy of the GNU General Public License
00015 // along with this library; see the file COPYING.  If not, write to
00016 // the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
00017 // Boston, MA 02110-1301, USA.
00018 //
00019 // As a special exception, you may use this file as part of a free
00020 // software library without restriction.  Specifically, if other files
00021 // instantiate templates or use macros or inline functions from this
00022 // file, or you compile this file and link it with other files to
00023 // produce an executable, this file does not by itself cause the
00024 // resulting executable to be covered by the GNU General Public
00025 // License.  This exception does not however invalidate any other
00026 // reasons why the executable file might be covered by the GNU General
00027 // Public License.
00028 
00029 #ifndef NTG_VECT_VEC_HH
00030 # define NTG_VECT_VEC_HH
00031 
00032 # include <ntg/basics.hh>
00033 # include <ntg/core/internal/macros.hh>
00034 # include <ntg/vect/vect_value.hh>
00035 
00036 # include <mlc/array/all.hh>
00037 # include <mlc/type.hh>
00038 
00039 /*--------------------.
00040 | assignements macros |
00041 `--------------------*/
00042 
00043 # define ASSIGN_VECTOR_VECTOR_OPERATOR(Name, Op)        \
00044 template <class T1, class T2> inline                    \
00045 static T1&                                              \
00046 Name(T1& lhs, const T2& rhs)                            \
00047 {                                                       \
00048   ntg_is_a(T1, ntg::vectorial)::ensure();               \
00049   ntg_is_a(T2, ntg::vectorial)::ensure();               \
00050   precondition(lhs.size() == rhs.size());               \
00051   unsigned s = lhs.size();                              \
00052   for (unsigned i = 0; i < s; ++i)                      \
00053     lhs[i] Op rhs[i];                                   \
00054   return lhs;                                           \
00055 }
00056 
00057 # define ASSIGN_VECTOR_SCALAR_OPERATOR(Name, Op)        \
00058 template <class T1, class T2> inline                    \
00059 static T1&                                              \
00060 Name(T1& lhs, const T2& rhs)                            \
00061 {                                                       \
00062   ntg_is_a(T1, ntg::vectorial)::ensure();               \
00063   ntg_is_a(T2, ntg::real)::ensure();                    \
00064   unsigned s = lhs.size();                              \
00065   for (unsigned i = 0; i < s; ++i)                      \
00066     lhs[i] Op rhs;                                      \
00067   return lhs;                                           \
00068 }
00069 
00070 # define ARITH_VECTOR_VECTOR_OPERATOR(Name, Op)         \
00071 template <class T1, class T2>                           \
00072 inline static                                           \
00073 ntg_return_type(Name,T1, T2)                            \
00074 Name(const T1& lhs, const T2& rhs)                      \
00075 {                                                       \
00076   ntg_is_a(T1, ntg::vectorial)::ensure();               \
00077   ntg_is_a(T2, ntg::vectorial)::ensure();               \
00078   typedef ntg_return_type(Name,T1, T2) return_type;     \
00079   return_type result(lhs);                              \
00080   result Op rhs;                                        \
00081   return result;                                        \
00082 }
00083 
00084 namespace ntg {
00085 
00086   namespace internal {
00087 
00088     /*----------------.
00089     | typetraits<vec> |
00090     `----------------*/
00091 
00092     template <unsigned N, class T, class Self>
00093     struct typetraits<vec<N, T, Self> > : public typetraits<vect_value<vec<N, T, Self> > >
00094     {
00095       enum { nb_comp = N };
00096 
00097       typedef vec<N, T, Self>   self;
00098       typedef vectorial         abstract_type;
00099       typedef self              ntg_type;
00100       typedef optraits<self>    optraits_type;
00101 
00102       ntg_build_value_type(vect_value<E>);
00103 
00104       // FIXME: document comp_type
00105       typedef T                                  comp_type;
00106       typedef self                               base_type;
00107       typedef T                                  storage_type[N];
00108       typedef typename typetraits<T>::cumul_type cumul_type[N];
00109 
00110       static const self &sup()
00111       {
00112         static self tmp = mkSup();
00113 
00114         return tmp;
00115       };
00116 
00117     protected:
00118       static self mkSup()
00119       {
00120         self tmp;
00121 
00122         for (unsigned i = 0; i < N; ++i)
00123           tmp[i] = ntg_sup_val(T);
00124         return tmp;
00125       };
00126     };
00127 
00128   } // end of internal.
00129 
00130   /*----------.
00131   | vec<N, T> |
00132   `----------*/
00133 
00134   template <unsigned N, class T, class E>
00135   class vec :
00136     public vect_value<typename mlc::exact_vt<vec<N, T, mlc::final>, E>::ret>
00137   {
00138   public :
00139 
00140     vec()
00141     {
00142       _fill (ntg_zero_val(T));
00143     }
00144 
00145     /* A vector can be built from a 1xM array.  */
00146     template<int ncols, class T2>
00147     vec(const mlc::array2d< mlc::array2d_info<1, ncols>, T2>& arr)
00148     {
00149       mlc::is_true< ncols == N >::ensure();
00150       for (unsigned i = 0; i < N; ++i)
00151         this->val_[i] = arr[i];
00152     }
00153 
00154     template<class U, class E2>
00155     vec(const vec<N, U, E2>& v)
00156     {
00157       for (unsigned i = 0; i < N; ++i)
00158         this->val_[i] = v[i];
00159     }
00160 
00161     template<class U, class E2>
00162     vec<N, T>& operator=(const vec<N, U, E2>& v)
00163     {
00164       for (unsigned i = 0; i < N; ++i)
00165         this->val_[i] = v[i];
00166       return *this;
00167     }
00168 
00169     static const vec<N,T> zero() { return vec(); }
00170     // There is no unit() for vec<>.
00171 
00172     ~vec() {}
00173 
00174   protected:
00175     vec& _fill(T t)
00176     {
00177       for (unsigned i = 0; i < N; ++i)
00178         this->val_[i] = t;
00179       return *this;
00180     }
00181   };
00182 
00183   template<unsigned N,class T> inline
00184   std::ostream&
00185   operator<<(std::ostream& ostr, const vec<N,T>& rhs)
00186   {
00187     // dev note: we use an ostringstream to make only one output
00188     // on the ostream. This allows calling procedures to consider
00189     // data type printing as atomic, thus ostr.width(...) can
00190     // work.
00191     std::ostringstream str;
00192     str << "[";
00193     for (unsigned i = 0; i < N; ++i)
00194       str << rhs[i] << ((i < N-1) ? "," : "]");
00195     ostr << str.str();
00196     return ostr;
00197   }
00198 
00199   namespace internal
00200   {
00201 
00202     /*--------------.
00203     | optraits<vec> |
00204     `--------------*/
00205 
00206     template <unsigned N, class T, class E>
00207     class optraits<vec<N, T, E> > : public optraits<vect_value<vec<N, T, E> > >
00208     {
00209       typedef vec<N, T, E> self;
00210       typedef ntgi_storage_type(self) storage_type_;
00211 
00212     public:
00213       static self zero ()
00214       {
00215         // A vectorial type MUST return a zero initialized value.
00216         return self();
00217       }
00218 
00219       static unsigned max_print_width ()
00220       {
00221         return (N * ntg_max_print_width(T)) + (N - 1) + 2;
00222       }
00223 
00224       static std::string
00225       name() {
00226         std::ostringstream out;
00227         out << "vec<" << N << ", " << ntg_name(T) << ">"<< std::ends;
00228         return out.str();
00229       }
00230 
00231       // No unit() for vector.
00232       // static storage_type_ unit ();
00233 
00234       ASSIGN_VECTOR_VECTOR_OPERATOR(plus_equal,  +=)
00235       ASSIGN_VECTOR_VECTOR_OPERATOR(minus_equal, -=)
00236       ASSIGN_VECTOR_SCALAR_OPERATOR(times_equal, *=)
00237       ASSIGN_VECTOR_SCALAR_OPERATOR(div_equal,   /=)
00238       ASSIGN_VECTOR_SCALAR_OPERATOR(mod_equal,   %=)
00239 
00240       ARITH_VECTOR_VECTOR_OPERATOR(plus, +=)
00241       ARITH_VECTOR_VECTOR_OPERATOR(minus, -=)
00242 
00243       // division
00244 
00245       template <class T1, class T2>
00246       inline static
00247       ntg_return_type(div, T1, T2)
00248       div(const T1& lhs, const T2& rhs)
00249       {
00250         ntg_is_a(T1, ntg::vectorial)::ensure();
00251         ntg_is_a(T2, ntg::real)::ensure();
00252         typedef ntg_return_type(div, T1, T2) return_type;
00253         return_type result(lhs);
00254         result /= rhs;
00255         return result;
00256       }
00257 
00258       // modulo
00259 
00260       template <class T1, class T2>
00261       inline static
00262       ntg_return_type(mod, T1, T2)
00263       mod(const T1& lhs, const T2& rhs)
00264       {
00265         ntg_is_a(T1, ntg::vectorial)::ensure();
00266         ntg_is_a(T2, ntg::real)::ensure();
00267         typedef ntg_return_type(mod, T1, T2) return_type;
00268         return_type result(lhs);
00269         result %= rhs;
00270         return result;
00271       }
00272 
00273       // multiplication
00274 
00275       // dot-product
00276       template <unsigned M, class T1, class T2>
00277       inline static typename
00278       internal::deduce_from_traits<internal::operator_times,
00279                                    vec<M, T1>,
00280                                    vec<M, T2> >::ret
00281       times(const vec<M, T1>& lhs, const vec<M, T2>& rhs)
00282       {
00283         typedef vec<M, T1> vec1;
00284         typedef vec<M, T2> vec2;
00285         ntg_is_a(vec1, ntg::vectorial)::ensure();
00286         ntg_is_a(vec2, ntg::vectorial)::ensure();
00287         typedef typename
00288           internal::deduce_from_traits<internal::operator_times,
00289           vec<M, T1>, vec<M, T2> >::ret return_type;
00290         precondition(lhs.size() == rhs.size());
00291 
00292         return_type result = optraits<return_type>::zero();
00293         unsigned s = lhs.size();
00294         for (unsigned i = 0; i < s; ++i)
00295           result += lhs[i] * rhs[i];
00296 
00297         return result;
00298       }
00299 
00300       // vector * scalar
00301       template <class T1, class T2>
00302       inline static
00303       ntg_return_type(times, T1, T2)
00304       times(const vect_value<T1>& lhs, const T2& rhs)
00305       {
00306         ntg_is_a(T1, ntg::vectorial)::ensure();
00307         ntg_is_a(T2, ntg::real)::ensure();
00308         typedef ntg_return_type(times, T1, T2) return_type;
00309         return_type result(lhs.exact());
00310         result *= rhs;
00311         return result;
00312       }
00313 
00314       // scalar * vector
00315       template <class T1, class T2>
00316       inline static
00317       ntg_return_type(times, T1, T2)
00318       times(const T1& lhs, const vect_value<T2>& rhs)
00319       {
00320         return times(rhs, lhs);
00321       }
00322 
00323 
00324       template <class T1, class T2>
00325       inline static bool
00326       cmp_eq (const T1& lhs, const T2& rhs)
00327       {
00328         ntg_is_a(T1, ntg::vectorial)::ensure();
00329         ntg_is_a(T2, ntg::vectorial)::ensure();
00330         ntg_assert(lhs.size() == rhs.size());
00331 
00332         typedef ntg_return_type(cmp, T1, T2) tmp_type;
00333 
00334         unsigned s = lhs.size();
00335         for (unsigned i = 0; i < s; ++i)
00336           if (lhs[i] != rhs[i])
00337             return false;
00338         return true;
00339       }
00340     };
00341 
00342     /*----------------.
00343     | operator traits |
00344     `----------------*/
00345 
00346     //
00347     // plus
00348     //
00349 
00350     // vec + vec
00351 
00352     template<unsigned N, class T1, class T2, class S1, class S2>
00353     struct operator_traits<operator_plus, vec<N, T1, S1>, vec<N, T2, S2> >
00354     {
00355       enum { commutative = true };
00356       typedef vec<N, ntg_return_type(plus, T1, T2)> ret;
00357       typedef vec<N, T1> impl;
00358     };
00359 
00360     //
00361     // minus
00362     //
00363 
00364     // vec - vec
00365 
00366     template<unsigned N, class T1, class T2>
00367     struct operator_traits<operator_minus, vec<N, T1>, vec<N, T2> >
00368     {
00369       enum { commutative = true };
00370       typedef vec<N, ntg_return_type(minus, T1, T2)> ret;
00371       typedef vec<N, T1> impl;
00372     };
00373 
00374     //
00375     // times
00376     //
00377 
00378     // vec * s; s * vec
00379 
00380     template<unsigned N, class T1, class T2>
00381     struct operator_traits<operator_times, vec<N, T1>, T2>
00382     {
00383       enum { commutative = true };
00384       typedef vec<N, ntg_return_type(times, T1, T2)> ret;
00385       typedef vec<N, T1> impl;
00386     };
00387 
00388     // vec * vec
00389 
00390     template<unsigned N, class T1, class T2>
00391     struct operator_traits<operator_times, vec<N, T1>, vec<N, T2> >
00392     {
00393       enum { commutative = true };
00394       typedef ntg_return_type(times,T1,T2) t;
00395       typedef typename typetraits<t>::cumul_type ret;
00396       typedef vec<N, T1> impl;
00397     };
00398 
00399     //
00400     // div
00401     //
00402 
00403     // vec / s
00404 
00405     template<unsigned N, class T1, class T2>
00406     struct operator_traits<operator_div, vec<N, T1>, T2>
00407     {
00408       enum { commutative = false };
00409       typedef vec<N, ntg_return_type(div, T1, T2)> ret;
00410       typedef vec<N, T1> impl;
00411     };
00412 
00413     //
00414     // mod
00415     //
00416 
00417     // vec % s
00418 
00419     template<unsigned N, class T1, class T2>
00420     struct operator_traits<operator_mod, vec<N, T1>, T2>
00421     {
00422       enum { commutative = false };
00423       typedef vec<N, ntg_return_type(mod, T1, T2)> ret;
00424       typedef vec<N, T1> impl;
00425     };
00426 
00427     //
00428     // Comparison operator
00429     //
00430 
00431     // vec compared with vec
00432 
00433     template<unsigned N, class T1, class T2, class S1, class S2>
00434     struct operator_traits<operator_cmp, vec<N, T1, S1>, vec<N, T2, S2> >
00435     {
00436       enum { commutative = true };
00437       typedef vec<N, ntg_return_type(cmp, T1, T2)> ret;
00438       typedef vec<N, T1> impl;
00439     };
00440 
00441   } // end of internal.
00442 
00443 } // end of ntg.
00444 
00445 #endif // !NTG_VECT_VEC_HH

Generated on Tue Feb 20 20:21:13 2007 for Olena by  doxygen 1.5.1