core/vnl/vnl_vector_fixed.h
Go to the documentation of this file.
00001 // This is core/vnl/vnl_vector_fixed.h
00002 #ifndef vnl_vector_fixed_h_
00003 #define vnl_vector_fixed_h_
00004 #ifdef VCL_NEEDS_PRAGMA_INTERFACE
00005 #pragma interface
00006 #endif
00007 //:
00008 // \file
00009 // \brief Fixed length stack-stored vector
00010 //
00011 // The operators are inlined because (1) they are small and
00012 // (2) we then have less explicit instantiation trouble.
00013 //
00014 // \author Andrew W. Fitzgibbon, Oxford RRG
00015 // \date   04 Aug 96
00016 //
00017 // \verbatim
00018 //  Modifications
00019 //   LSB Manchester 16/3/01 Binary I/O added
00020 //   Feb.2002 - Peter Vanroose - brief doxygen comment placed on single line
00021 //   Oct.2002 - Amitha Perera - decoupled vnl_vector and vnl_vector_fixed for
00022 //              space efficiency, removed necessity for vnl_vector_fixed_ref
00023 //   Jun.2003 - Paul Smyth - added as_fixed_ref() to convert to fixed-size ref
00024 //              removed duplicate cross_3d
00025 //   Jun.2003 - Peter Vanroose - added cross_2d
00026 //   Oct.2003 - Peter Vanroose - removed deprecated x(), y(), z(), t()
00027 //   Mar.2009 - Peter Vanroose - added arg_min() and arg_max()
00028 //   Oct.2010 - Peter Vanroose - mutators and setters now return *this
00029 // \endverbatim
00030 
00031 #include <vcl_cstring.h> // memcpy()
00032 #include <vcl_cassert.h>
00033 #include <vcl_iosfwd.h>
00034 #include "vnl_vector.h"
00035 #include "vnl_vector_ref.h"
00036 #include <vnl/vnl_c_vector.h>
00037 #include <vnl/vnl_matrix.h> // outerproduct
00038 #include <vnl/vnl_config.h> // for VNL_CONFIG_CHECK_BOUNDS
00039 
00040 export template <class T, unsigned int n> class vnl_vector_fixed;
00041 export template <class T, unsigned int num_rows, unsigned int num_cols> class vnl_matrix_fixed;
00042 
00043 //: Fixed length stack-stored, space-efficient vector.
00044 // vnl_vector_fixed is a fixed-length, stack storage vector. It has
00045 // the same storage size as a C-style array. It is not related via
00046 // inheritance to vnl_vector. However, it can be converted cheaply to
00047 // a vnl_vector_ref.
00048 //
00049 // In most cases, a vnl_vector_fixed can be used where a vnl_vector is
00050 // expected. There are some situations, however, when the automatic
00051 // conversion cannot be applied. In those cases, you need to call the
00052 // as_ref() method to perform an explicit conversion. This occurs most
00053 // often when the called function is templated, since the user-defined
00054 // conversion operators are then suppressed.
00055 // \code
00056 //    template<class T>
00057 //    void do_something( const vnl_vector<T>& v );
00058 //    ...
00059 //    vnl_vector_fixed<double,4> my_vec;
00060 //
00061 //    do_something( my_vec );
00062 //      // Error: no do_something( vnl_vector_fixed<double,4> ) found
00063 //
00064 //    do_something( my_vec.as_ref() );  // works
00065 // \endcode
00066 //
00067 // Since the conversion operator creates a temporary vnl_vector_ref
00068 // object, the conversion cannot be used directly to a function that
00069 // expects a non-const vnl_vector reference. Use
00070 // vnl_vector_ref::non_const method for this (and only this).
00071 // \code
00072 //    void mutator( vnl_vector<double>& v );
00073 //    ...
00074 //    vnl_vector_fixed<double,4> my_vec;
00075 //    mutator( my_vec.as_ref().non_const() );
00076 // \endcode
00077 // If the mutator only accesses the data, all should be fine. If the
00078 // mutator attempts to resize the vector, you are doomed.
00079 //
00080 // vnl_vector_fixed defines most of the operators defined by
00081 // vnl_vector, and does so efficiently. If you try to mix
00082 // vnl_vector_fixed and vnl_vector, however, you will probably get a
00083 // vnl_vector result, with the corresponding malloc cost.
00084 template <class T, unsigned int n>
00085 class vnl_vector_fixed
00086 {
00087  protected:
00088   T data_[n];
00089 
00090  public:
00091   typedef vnl_vector_fixed<T,n> self;
00092   typedef unsigned int size_type;
00093   // Compile-time accessible attribute to get the dimensionality of the vector.
00094   enum { SIZE = n };
00095 
00096   // Don't out-of-line the constructors, as extra the function call
00097   // adds a significant overhead. (memcpy is often implemented with a
00098   // couple of assembly instructions.)
00099 
00100   //: Construct an uninitialized n-vector
00101   vnl_vector_fixed() {}
00102 
00103   //: Copy constructor
00104   //  The dimensions must match.
00105   vnl_vector_fixed( const vnl_vector_fixed<T,n>& rhs )
00106   {
00107     vcl_memcpy( data_, rhs.data_, sizeof data_ );
00108   }
00109 
00110   //: Construct a fixed-n-vector copy of \a rhs.
00111   //  The dimensions must match.
00112   vnl_vector_fixed( const vnl_vector<T>& rhs )
00113   {
00114     assert( n == rhs.size() );
00115     vcl_memcpy( data_, rhs.data_block(), sizeof data_ );
00116   }
00117 
00118   //: Constructs n-vector with all elements initialised to \a v
00119   explicit vnl_vector_fixed( const T& v ) { fill( v ); }
00120 
00121   //: Construct a fixed-n-vector initialized from \a datablck
00122   //  The data \e must have enough data. No checks performed.
00123   explicit vnl_vector_fixed( const T* datablck )
00124   {
00125     vcl_memcpy( data_, datablck, sizeof data_ );
00126   }
00127 
00128   //: Convenience constructor for 2-D vectors
00129   // While this constructor is sometimes useful, consider using
00130   // vnl_double_2 or vnl_float_2 instead.
00131   vnl_vector_fixed( const T& x0, const T& x1 )
00132   {
00133     assert( n == 2 );
00134     data_[0] = x0; data_[1] = x1;
00135   }
00136 
00137   //: Convenience constructor for 3-D vectors
00138   // While this constructor is sometimes useful, consider using
00139   // vnl_double_3 or vnl_float_3 instead.
00140   vnl_vector_fixed( const T& x0, const T& x1, const T& x2 )
00141   {
00142     assert( n == 3 );
00143     data_[0] = x0; data_[1] = x1; data_[2] = x2;
00144   }
00145 
00146   //: Convenience constructor for 4-D vectors
00147   vnl_vector_fixed( const T& x0, const T& x1, const T& x2, const T& x3 )
00148   {
00149     assert( n == 4 );
00150     data_[0] = x0; data_[1] = x1; data_[2] = x2; data_[3] = x3;
00151   }
00152 
00153   //: Copy operator
00154   vnl_vector_fixed<T,n>& operator=( const vnl_vector_fixed<T,n>& rhs ) {
00155     vcl_memcpy( data_, rhs.data_, sizeof data_ );
00156     return *this;
00157   }
00158 
00159   //: Copy data from a dynamic vector
00160   // The dimensions must match.
00161   vnl_vector_fixed<T,n>& operator=( const vnl_vector<T>& rhs) {
00162     assert( n == rhs.size() );
00163     vcl_memcpy( data_, rhs.data_block(), sizeof data_ );
00164     return *this;
00165   }
00166 
00167   //: Length of the vector.
00168   // This is always \a n.
00169   unsigned size() const { return n; }
00170 
00171   //: Put value at given position in vector.
00172   void put (unsigned int i, T const& v) { data_[i] = v; }
00173 
00174   //: Get value at element i
00175   T get (unsigned int i) const { return data_[i]; }
00176 
00177   //: Set all values to v
00178   vnl_vector_fixed& fill( T const& v )
00179   {
00180     for ( size_type i = 0; i < n; ++i )
00181       data_[i] = v;
00182     return *this;
00183   }
00184 
00185   //: Sets elements to ptr[i]
00186   //  Note: ptr[i] must be valid for i=0..size()-1
00187   vnl_vector_fixed& copy_in( T const * ptr )
00188   {
00189     for ( size_type i = 0; i < n; ++i )
00190       data_[i] = ptr[i];
00191     return *this;
00192   }
00193 
00194   //: Copy elements to ptr[i]
00195   //  Note: ptr[i] must be valid for i=0..size()-1
00196   void copy_out( T* ptr ) const
00197   {
00198     for ( size_type i = 0; i < n; ++i )
00199       ptr[i] = data_[i];
00200   }
00201 
00202   //: Sets elements to ptr[i]
00203   //  Note: ptr[i] must be valid for i=0..size()-1
00204   vnl_vector_fixed& set( T const *ptr ) { return copy_in(ptr); }
00205 
00206   //: Return reference to the element at specified index.
00207   // There are assert style boundary checks - #define NDEBUG to turn them off.
00208   T       & operator() (unsigned int i)
00209   {
00210 #if VNL_CONFIG_CHECK_BOUNDS  && (!defined NDEBUG)
00211     assert(i<n);   // Check the index is valid.
00212 #endif
00213     return data_[i];
00214   }
00215 
00216   //: Return reference to the element at specified index.
00217   // There are assert style boundary checks - #define NDEBUG to turn them off.
00218   T const & operator() (unsigned int i) const
00219   {
00220 #if VNL_CONFIG_CHECK_BOUNDS  && (!defined NDEBUG)
00221     assert(i<n);   // Check the index is valid
00222 #endif
00223     return data_[i];
00224   }
00225 
00226   //: Return the i-th element
00227   T& operator[] ( unsigned int i ) { return data_[i]; }
00228 
00229   //: Return the i-th element
00230   const T& operator[] ( unsigned int i ) const { return data_[i]; }
00231 
00232   //: Access the contiguous block storing the elements in the vector.
00233   //  O(1).
00234   //  data_block()[0] is the first element of the vector
00235   T const* data_block() const { return data_; }
00236 
00237   //: Access the contiguous block storing the elements in the vector.
00238   //  O(1).
00239   //  data_block()[0] is the first element of the vector
00240   T      * data_block() { return data_; }
00241 
00242   //----------------------------------------------------------------------
00243   // Conversion to vnl_vector_ref.
00244 
00245   // The const version of as_ref should return a const vnl_vector_ref
00246   // so that the vnl_vector_ref::non_const() cannot be used on
00247   // it. This prevents a const vnl_vector_fixed from being cast into a
00248   // non-const vnl_vector reference, giving a slight increase in type safety.
00249 
00250   //: Explicit conversion to a vnl_vector_ref.
00251   // This is a cheap conversion for those functions that have an interface
00252   // for vnl_vector but not for vnl_vector_fixed. There is also a
00253   // conversion operator that should work most of the time.
00254   // \sa vnl_vector_ref::non_const
00255   vnl_vector_ref<T> as_ref() { return vnl_vector_ref<T>( n, data_ ); }
00256 
00257   //: Explicit conversion to a vnl_vector_ref.
00258   // This is a cheap conversion for those functions that have an interface
00259   // for vnl_vector but not for vnl_vector_fixed. There is also a
00260   // conversion operator that should work most of the time.
00261   // \sa vnl_vector_ref::non_const
00262   const vnl_vector_ref<T> as_ref() const { return vnl_vector_ref<T>( n, const_cast<T*>(data_) ); }
00263 
00264   //: Cheap conversion to vnl_vector_ref
00265   // Sometimes, such as with templated functions, the compiler cannot
00266   // use this user-defined conversion. For those cases, use the
00267   // explicit as_ref() method instead.
00268   operator const vnl_vector_ref<T>() const { return vnl_vector_ref<T>( n, const_cast<T*>(data_) ); }
00269 
00270   //----------------------------------------------------------------------
00271 
00272   //: Type defs for iterators
00273   typedef T element_type;
00274   //: Type defs for iterators
00275   typedef T       *iterator;
00276   //: Iterator pointing to start of data
00277   iterator begin() { return data_; }
00278 
00279   //: Iterator pointing to element beyond end of data
00280   iterator end() { return data_+n; }
00281 
00282   //: Const iterator type
00283   typedef T const *const_iterator;
00284   //: Iterator pointing to start of data
00285   const_iterator begin() const { return data_; }
00286   //: Iterator pointing to element beyond end of data
00287   const_iterator end() const { return data_+n; }
00288 
00289 
00290   //: Apply f to each element.
00291   // Returns a new vector with the result.
00292   vnl_vector_fixed<T,n> apply(T (*f)(T));
00293 
00294   //: Apply f to each element.
00295   // Returns a new vector with the result.
00296   vnl_vector_fixed<T,n> apply(T (*f)(const T&));
00297 
00298   //:
00299   vnl_vector_fixed<T,n>& operator+=( T s ) { self::add( data_, s, data_ ); return *this; }
00300 
00301   //:
00302   vnl_vector_fixed<T,n>& operator-=( T s ) { self::sub( data_, s, data_ ); return *this; }
00303 
00304   //:
00305   vnl_vector_fixed<T,n>& operator*=( T s ) { self::mul( data_, s, data_ ); return *this; }
00306 
00307   //:
00308   vnl_vector_fixed<T,n>& operator/=( T s ) { self::div( data_, s, data_ ); return *this; }
00309 
00310   //:
00311   vnl_vector_fixed<T,n>& operator+=( const vnl_vector_fixed<T,n>& v ) { self::add( data_, v.data_block(), data_ ); return *this; }
00312 
00313   //:
00314   vnl_vector_fixed<T,n>& operator-=( const vnl_vector_fixed<T,n>& v ) { self::sub( data_, v.data_block(), data_ ); return *this; }
00315 
00316   //:
00317   vnl_vector_fixed<T,n>& operator+=( const vnl_vector<T>& v )
00318   {
00319     assert( v.size() == n );
00320     self::add( data_, v.data_block(), data_ ); return *this;
00321   }
00322 
00323   //:
00324   vnl_vector_fixed<T,n>& operator-=( const vnl_vector<T>& v )
00325   {
00326     assert( v.size() == n );
00327     self::sub( data_, v.data_block(), data_ ); return *this;
00328   }
00329 
00330   //:
00331   vnl_vector_fixed<T,n> operator-() const
00332   {
00333     vnl_vector_fixed<T,n> result;
00334     self::sub( (T)0, data_, result.data_ );
00335     return result;
00336   }
00337 
00338   //: Returns a subvector specified by the start index and length. O(n).
00339   vnl_vector<T> extract (unsigned int len, unsigned int start=0) const;
00340 
00341   //: Convert to a vnl_vector.
00342   vnl_vector<T> as_vector() const { return extract(n); }
00343 
00344   //: Replaces elements with index beginning at start, by values of v. O(n).
00345   vnl_vector_fixed& update (vnl_vector<T> const&, unsigned int start=0);
00346 
00347   // norms etc
00348   typedef typename vnl_c_vector<T>::abs_t abs_t;
00349 
00350   //: Return sum of squares of elements
00351   abs_t squared_magnitude() const { return vnl_c_vector<T>::two_nrm2(begin(), size()); }
00352 
00353   //: Return magnitude (length) of vector
00354   abs_t magnitude() const { return two_norm(); }
00355 
00356   //: Return sum of absolute values of the elements
00357   abs_t one_norm() const { return vnl_c_vector<T>::one_norm(begin(), size()); }
00358 
00359   //: Return sqrt of sum of squares of values of elements
00360   abs_t two_norm() const { return vnl_c_vector<T>::two_norm(begin(), size()); }
00361 
00362   //: Return largest absolute element value
00363   abs_t inf_norm() const { return vnl_c_vector<T>::inf_norm(begin(), size()); }
00364 
00365   //: Normalise by dividing through by the magnitude
00366   vnl_vector_fixed<T,n>& normalize() { vnl_c_vector<T>::normalize(begin(), size()); return *this; }
00367 
00368   // These next 6 functions are should really be helper functions since they aren't
00369   // really proper functions on a vector in a philosophical sense.
00370 
00371   //: Root Mean Squares of values
00372   abs_t rms     () const { return vnl_c_vector<T>::rms_norm(begin(), size()); }
00373 
00374   //: Smallest value
00375   T min_value () const { return vnl_c_vector<T>::min_value(begin(), size()); }
00376 
00377   //: Largest value
00378   T max_value () const { return vnl_c_vector<T>::max_value(begin(), size()); }
00379 
00380   //: Location of smallest value
00381   unsigned arg_min() const { return vnl_c_vector<T>::arg_min(begin(), size()); }
00382 
00383   //: Location of largest value
00384   unsigned arg_max() const { return vnl_c_vector<T>::arg_max(begin(), size()); }
00385 
00386   //: Mean of values in vector
00387   T mean() const { return vnl_c_vector<T>::mean(begin(), size()); }
00388 
00389   //: Sum of values in a vector
00390   T sum() const { return vnl_c_vector<T>::sum(begin(), size()); }
00391 
00392   //: Reverse the order of the elements
00393   //  Element i swaps with element size()-1-i
00394   vnl_vector_fixed& flip();
00395 
00396   //: Check that size()==sz if not, abort();
00397   // This function does or tests nothing if NDEBUG is defined
00398   void assert_size( unsigned sz ) const { assert( sz == n ); }
00399 
00400   //: Check that this is finite if not, abort();
00401   // This function does or tests nothing if NDEBUG is defined
00402   void assert_finite() const
00403   {
00404 #ifndef NDEBUG
00405     assert_finite_internal();
00406 #endif
00407   }
00408 
00409   //: Return true if it's finite
00410   bool is_finite() const;
00411 
00412   //: Return true iff all the entries are zero.
00413   bool is_zero() const;
00414 
00415   //: Return true iff the size is zero.
00416   bool empty() const { return n==0; }
00417 
00418   //: Return true if *this == v
00419   bool operator_eq (vnl_vector_fixed<T,n> const& v) const
00420   {
00421     for ( size_type i = 0; i < n; ++i )
00422       if ( (*this)[i] != v[i] )
00423         return false;
00424     return true;
00425   }
00426 
00427   //: Return true if *this == v
00428   bool operator_eq (vnl_vector<T> const& v) const
00429   {
00430     assert( v.size() == n );
00431     for ( size_type i = 0; i < n; ++i )
00432       if ( (*this)[i] != v[i] )
00433         return false;
00434     return true;
00435   }
00436 
00437 
00438   //: Read from text stream
00439   bool read_ascii(vcl_istream& s);
00440 
00441   //: Display the vector
00442   // Output each element separated by a single space.
00443   void print( vcl_ostream& s ) const;
00444 
00445  public:
00446   // Helper routines for arithmetic. n is the size, and is the
00447   // template parameter.
00448 
00449   inline static void add( const T* a, const T* b, T* r )
00450   {
00451     for ( unsigned int i=0; i < n; ++i,++r,++a,++b )
00452       *r = *a + *b;
00453   }
00454 
00455   inline static void add( const T* a, T b, T* r )
00456   {
00457     for ( unsigned int i=0; i < n; ++i,++r,++a )
00458       *r = *a + b;
00459   }
00460 
00461   inline static void sub( const T* a, const T* b, T* r )
00462   {
00463     for ( unsigned int i=0; i < n; ++i,++r,++a,++b )
00464       *r = *a - *b;
00465   }
00466 
00467   inline static void sub( const T* a, T b, T* r )
00468   {
00469     for ( unsigned int i=0; i < n; ++i,++r,++a )
00470       *r = *a - b;
00471   }
00472 
00473   inline static void sub( T a, const T* b, T* r )
00474   {
00475     for ( unsigned int i=0; i < n; ++i,++r,++b )
00476       *r = a - *b;
00477   }
00478 
00479   inline static void mul( const T* a, const T* b, T* r )
00480   {
00481     for ( unsigned int i=0; i < n; ++i,++r,++a,++b )
00482       *r = *a * *b;
00483   }
00484 
00485   inline static void mul( const T* a, T b, T* r )
00486   {
00487     for ( unsigned int i=0; i < n; ++i,++r,++a )
00488       *r = *a * b;
00489   }
00490 
00491   inline static void div( const T* a, const T* b, T* r )
00492   {
00493     for ( unsigned int i=0; i < n; ++i,++r,++a,++b )
00494       *r = *a / *b;
00495   }
00496 
00497   inline static void div( const T* a, T b, T* r )
00498   {
00499     for ( unsigned int i=0; i < n; ++i,++r,++a )
00500       *r = *a / b;
00501   }
00502 
00503  private:
00504   //: See assert_finite().
00505   void assert_finite_internal() const;
00506 };
00507 
00508 
00509 // --- Vector-scalar operators ----------------------------------------
00510 
00511 //:
00512 // \relatesalso vnl_vector_fixed
00513 template<class T, unsigned int n>
00514 inline vnl_vector_fixed<T,n> operator+( const vnl_vector_fixed<T,n>& v, T s )
00515 {
00516   vnl_vector_fixed<T,n> r;
00517   vnl_vector_fixed<T,n>::add( v.data_block(), s, r.data_block() );
00518   return r;
00519 }
00520 
00521 //:
00522 // \relatesalso vnl_vector_fixed
00523 template<class T, unsigned int n>
00524 inline vnl_vector_fixed<T,n> operator+( const T& s,
00525                                         const vnl_vector_fixed<T,n>& v )
00526 {
00527   vnl_vector_fixed<T,n> r;
00528   vnl_vector_fixed<T,n>::add( v.data_block(), s, r.data_block() );
00529   return r;
00530 }
00531 
00532 //:
00533 // \relatesalso vnl_vector_fixed
00534 template<class T, unsigned int n>
00535 inline vnl_vector_fixed<T,n> operator-( const vnl_vector_fixed<T,n>& v, T s )
00536 {
00537   vnl_vector_fixed<T,n> r;
00538   vnl_vector_fixed<T,n>::sub( v.data_block(), s, r.data_block() );
00539   return r;
00540 }
00541 
00542 //:
00543 // \relatesalso vnl_vector_fixed
00544 template<class T, unsigned int n>
00545 inline vnl_vector_fixed<T,n> operator-( const T& s,
00546                                         const vnl_vector_fixed<T,n>& v )
00547 {
00548   vnl_vector_fixed<T,n> r;
00549   vnl_vector_fixed<T,n>::sub( s, v.data_block(), r.data_block() );
00550   return r;
00551 }
00552 
00553 //:
00554 // \relatesalso vnl_vector_fixed
00555 template<class T, unsigned int n>
00556 inline vnl_vector_fixed<T,n> operator*( const vnl_vector_fixed<T,n>& v, T s )
00557 {
00558   vnl_vector_fixed<T,n> r;
00559   vnl_vector_fixed<T,n>::mul( v.data_block(), s, r.data_block() );
00560   return r;
00561 }
00562 
00563 //:
00564 // \relatesalso vnl_vector_fixed
00565 template<class T, unsigned int n>
00566 inline vnl_vector_fixed<T,n> operator*( const T& s,
00567                                         const vnl_vector_fixed<T,n>& v )
00568 {
00569   vnl_vector_fixed<T,n> r;
00570   vnl_vector_fixed<T,n>::mul( v.data_block(), s, r.data_block() );
00571   return r;
00572 }
00573 
00574 //:
00575 // \relatesalso vnl_vector_fixed
00576 template<class T, unsigned int n>
00577 inline vnl_vector_fixed<T,n> operator/( const vnl_vector_fixed<T,n>& v, T s )
00578 {
00579   vnl_vector_fixed<T,n> r;
00580   vnl_vector_fixed<T,n>::div( v.data_block(), s, r.data_block() );
00581   return r;
00582 }
00583 
00584 
00585 // --- Vector-vector operators ----------------------------------------
00586 //
00587 // Includes overloads for the common case of mixing a fixed with a
00588 // non-fixed. Because the operators are templated, the fixed will not
00589 // be automatically converted to a non-fixed-ref. These do it for you.
00590 
00591 //:
00592 // \relatesalso vnl_vector_fixed
00593 template<class T, unsigned int n>
00594 inline vnl_vector_fixed<T,n> operator+( const vnl_vector_fixed<T,n>& a, const vnl_vector_fixed<T,n>& b )
00595 {
00596   vnl_vector_fixed<T,n> r;
00597   vnl_vector_fixed<T,n>::add( a.data_block(), b.data_block(), r.data_block() );
00598   return r;
00599 }
00600 
00601 //:
00602 // \relatesalso vnl_vector
00603 // \relatesalso vnl_vector_fixed
00604 template<class T, unsigned int n>
00605 inline vnl_vector<T> operator+( const vnl_vector_fixed<T,n>& a, const vnl_vector<T>& b )
00606 {
00607   return a.as_ref() + b;
00608 }
00609 
00610 //:
00611 // \relatesalso vnl_vector
00612 // \relatesalso vnl_vector_fixed
00613 template<class T, unsigned int n>
00614 inline vnl_vector<T> operator+( const vnl_vector<T>& a, const vnl_vector_fixed<T,n>& b )
00615 {
00616   return a + b.as_ref();
00617 }
00618 
00619 //:
00620 // \relatesalso vnl_vector_fixed
00621 template<class T, unsigned int n>
00622 inline vnl_vector_fixed<T,n> operator-( const vnl_vector_fixed<T,n>& a, const vnl_vector_fixed<T,n>& b )
00623 {
00624   vnl_vector_fixed<T,n> r;
00625   vnl_vector_fixed<T,n>::sub( a.data_block(), b.data_block(), r.data_block() );
00626   return r;
00627 }
00628 
00629 //:
00630 // \relatesalso vnl_vector
00631 // \relatesalso vnl_vector_fixed
00632 template<class T, unsigned int n>
00633 inline vnl_vector<T> operator-( const vnl_vector_fixed<T,n>& a, const vnl_vector<T>& b )
00634 {
00635   return a.as_ref() - b;
00636 }
00637 
00638 //:
00639 // \relatesalso vnl_vector
00640 // \relatesalso vnl_vector_fixed
00641 template<class T, unsigned int n>
00642 inline vnl_vector<T> operator-( const vnl_vector<T>& a, const vnl_vector_fixed<T,n>& b )
00643 {
00644   return a - b.as_ref();
00645 }
00646 
00647 //:
00648 // \relatesalso vnl_vector_fixed
00649 template<class T, unsigned int n>
00650 inline vnl_vector_fixed<T,n> element_product( const vnl_vector_fixed<T,n>& a, const vnl_vector_fixed<T,n>& b )
00651 {
00652   vnl_vector_fixed<T,n> r;
00653   vnl_vector_fixed<T,n>::mul( a.data_block(), b.data_block(), r.data_block() );
00654   return r;
00655 }
00656 
00657 //:
00658 // \relatesalso vnl_vector
00659 // \relatesalso vnl_vector_fixed
00660 template<class T, unsigned int n>
00661 inline vnl_vector<T> element_product( const vnl_vector_fixed<T,n>& a, const vnl_vector<T>& b )
00662 {
00663   assert( b.size() == n );
00664   vnl_vector<T> r(n);
00665   vnl_vector_fixed<T,n>::mul( a.data_block(), b.data_block(), r.data_block() );
00666   return r;
00667 }
00668 
00669 //:
00670 // \relatesalso vnl_vector
00671 // \relatesalso vnl_vector_fixed
00672 template<class T, unsigned int n>
00673 inline vnl_vector<T> element_product( const vnl_vector<T>& a, const vnl_vector_fixed<T,n>& b )
00674 {
00675   assert( a.size() == n );
00676   vnl_vector<T> r(n);
00677   vnl_vector_fixed<T,n>::mul( a.data_block(), b.data_block(), r.data_block() );
00678   return r;
00679 }
00680 
00681 //:
00682 // \relatesalso vnl_vector_fixed
00683 template<class T, unsigned int n>
00684 inline vnl_vector_fixed<T,n> element_quotient( const vnl_vector_fixed<T,n>& a, const vnl_vector_fixed<T,n>& b )
00685 {
00686   vnl_vector_fixed<T,n> r;
00687   vnl_vector_fixed<T,n>::div( a.data_block(), b.data_block(), r.data_block() );
00688   return r;
00689 }
00690 
00691 //:
00692 // \relatesalso vnl_vector
00693 // \relatesalso vnl_vector_fixed
00694 template<class T, unsigned int n>
00695 inline vnl_vector<T> element_quotient( const vnl_vector_fixed<T,n>& a, const vnl_vector<T>& b )
00696 {
00697   assert( b.size() == n );
00698   vnl_vector<T> r(n);
00699   vnl_vector_fixed<T,n>::div( a.data_block(), b.data_block(), r.data_block() );
00700   return r;
00701 }
00702 
00703 //:
00704 // \relatesalso vnl_vector
00705 // \relatesalso vnl_vector_fixed
00706 template<class T, unsigned int n>
00707 inline vnl_vector<T> element_quotient( const vnl_vector<T>& a, const vnl_vector_fixed<T,n>& b )
00708 {
00709   assert( a.size() == n );
00710   vnl_vector<T> r(n);
00711   vnl_vector_fixed<T,n>::div( a.data_block(), b.data_block(), r.data_block() );
00712   return r;
00713 }
00714 
00715 //:
00716 // \relatesalso vnl_vector_fixed
00717 template<class T, unsigned n>
00718 inline T dot_product( const vnl_vector_fixed<T,n>& a, const vnl_vector_fixed<T,n>& b )
00719 {
00720   return dot_product( a.as_ref(), b.as_ref() );
00721 }
00722 
00723 //:
00724 // \relatesalso vnl_vector
00725 // \relatesalso vnl_vector_fixed
00726 template<class T, unsigned n>
00727 inline T dot_product( const vnl_vector_fixed<T,n>& a, const vnl_vector<T>& b )
00728 {
00729   return dot_product( a.as_ref(), b );
00730 }
00731 
00732 //:
00733 // \relatesalso vnl_vector
00734 // \relatesalso vnl_vector_fixed
00735 template<class T, unsigned n>
00736 inline T dot_product( const vnl_vector<T>& a, const vnl_vector_fixed<T,n>& b )
00737 {
00738   return dot_product( a, b.as_ref() );
00739 }
00740 
00741 //:
00742 // \relatesalso vnl_vector
00743 // \relatesalso vnl_vector_fixed
00744 template<class T, unsigned int n>
00745 inline vnl_matrix<T> outer_product( const vnl_vector<T>& a, const vnl_vector_fixed<T,n>& b )
00746 {
00747   return outer_product( a, b.as_ref());
00748 }
00749 
00750 //:
00751 // \relatesalso vnl_vector
00752 // \relatesalso vnl_vector_fixed
00753 template<class T, unsigned int n>
00754 inline vnl_matrix<T> outer_product( const vnl_vector_fixed<T,n>& a, const vnl_vector<T>& b )
00755 {
00756   return outer_product( a.as_ref(), b);
00757 }
00758 
00759 //:
00760 // \relatesalso vnl_vector_fixed
00761 template<class T, unsigned n>
00762 inline T angle( const vnl_vector_fixed<T,n>& a, const vnl_vector_fixed<T,n>& b )
00763 {
00764   return angle( a.as_ref(), b.as_ref() );
00765 }
00766 
00767 //:
00768 // \relatesalso vnl_vector
00769 // \relatesalso vnl_vector_fixed
00770 template<class T, unsigned n>
00771 inline T angle( const vnl_vector_fixed<T,n>& a, const vnl_vector<T>& b )
00772 {
00773   return angle( a.as_ref(), b );
00774 }
00775 
00776 //:
00777 // \relatesalso vnl_vector
00778 // \relatesalso vnl_vector_fixed
00779 template<class T, unsigned n>
00780 inline T angle( const vnl_vector<T>& a, const vnl_vector_fixed<T,n>& b )
00781 {
00782   return angle( a, b.as_ref() );
00783 }
00784 
00785 
00786 //:
00787 // \relatesalso vnl_vector_fixed
00788 template<class T, unsigned n>
00789 inline T vnl_vector_ssd( const vnl_vector_fixed<T,n>& a, const vnl_vector_fixed<T,n>& b )
00790 {
00791   return vnl_vector_ssd( a.as_ref(), b.as_ref() );
00792 }
00793 
00794 //:
00795 // \relatesalso vnl_vector
00796 // \relatesalso vnl_vector_fixed
00797 template<class T, unsigned n>
00798 inline T vnl_vector_ssd( const vnl_vector_fixed<T,n>& a, const vnl_vector<T>& b )
00799 {
00800   return vnl_vector_ssd( a.as_ref(), b );
00801 }
00802 
00803 //:
00804 // \relatesalso vnl_vector
00805 // \relatesalso vnl_vector_fixed
00806 template<class T, unsigned n>
00807 inline T vnl_vector_ssd( const vnl_vector<T>& a, const vnl_vector_fixed<T,n>& b )
00808 {
00809   return vnl_vector_ssd( a, b.as_ref() );
00810 }
00811 
00812 
00813 //:
00814 // \relatesalso vnl_vector_fixed
00815 template<class T, unsigned int n>
00816 inline bool operator==( const vnl_vector_fixed<T,n>& a, const vnl_vector_fixed<T,n>& b )
00817 {
00818   return a.operator_eq(b);
00819 }
00820 
00821 //:
00822 // \relatesalso vnl_vector
00823 // \relatesalso vnl_vector_fixed
00824 template<class T, unsigned int n>
00825 inline bool operator==( vnl_vector_fixed<T,n> const& a, vnl_vector<T> const& b )
00826 {
00827   return a.operator_eq(b);
00828 }
00829 
00830 //:
00831 // \relatesalso vnl_vector
00832 // \relatesalso vnl_vector_fixed
00833 template<class T, unsigned int n>
00834 inline bool operator==( vnl_vector<T> const& a, vnl_vector_fixed<T,n> const& b )
00835 {
00836   return b.operator_eq(a);
00837 }
00838 
00839 //:
00840 // \relatesalso vnl_vector_fixed
00841 template<class T, unsigned int n>
00842 inline bool operator!=( const vnl_vector_fixed<T,n>& a, const vnl_vector_fixed<T,n>& b )
00843 {
00844   return ! a.operator_eq(b);
00845 }
00846 
00847 //:
00848 // \relatesalso vnl_vector
00849 // \relatesalso vnl_vector_fixed
00850 template<class T, unsigned int n>
00851 inline bool operator!=( vnl_vector_fixed<T,n> const& a, vnl_vector<T> const& b )
00852 {
00853   return ! a.operator_eq(b);
00854 }
00855 
00856 //:
00857 // \relatesalso vnl_vector
00858 // \relatesalso vnl_vector_fixed
00859 template<class T, unsigned int n>
00860 inline bool operator!=( vnl_vector<T> const& a, vnl_vector_fixed<T,n> const& b )
00861 {
00862   return ! b.operator_eq(a);
00863 }
00864 
00865 
00866 // --- I/O operators -------------------------------------------------
00867 
00868 
00869 //:
00870 // \relatesalso vnl_vector_fixed
00871 template<class T, unsigned int n>
00872 inline
00873 vcl_ostream& operator<< ( vcl_ostream& ostr, const vnl_vector_fixed<T,n>& v )
00874 {
00875   v.print( ostr );
00876   return ostr;
00877 }
00878 
00879 //:
00880 // \relatesalso vnl_vector_fixed
00881 template<class T, unsigned int n>
00882 inline
00883 vcl_istream& operator>> ( vcl_istream& ostr, vnl_vector_fixed<T,n>& v )
00884 {
00885   v.read_ascii( ostr );
00886   return ostr;
00887 }
00888 
00889 #endif // vnl_vector_fixed_h_