00001
00002 #ifndef DUNE_FVECTOR_HH
00003 #define DUNE_FVECTOR_HH
00004
00005 #include<cmath>
00006 #include<cstddef>
00007 #include<cstdlib>
00008 #include<complex>
00009
00010 #include "exceptions.hh"
00011 #include "genericiterator.hh"
00012
00013 #ifdef DUNE_EXPRESSIONTEMPLATES
00014 #include "exprtmpl.hh"
00015 #endif
00016
00017 namespace Dune {
00018
00019 #ifndef DUNE_EXPRESSIONTEMPLATES
00020
00031
00032 template<class K, int SIZE> class FieldVector;
00033
00034 #endif
00035
00036 #ifndef DUNE_EXPRESSIONTEMPLATES
00037
00038 template<class K>
00039 inline double fvmeta_absreal (const K& k)
00040 {
00041 return std::abs(k);
00042 }
00043
00044 template<class K>
00045 inline double fvmeta_absreal (const std::complex<K>& c)
00046 {
00047 return fvmeta_abs(c.real()) + fvmeta_abs(c.imag());
00048 }
00049
00050 template<class K>
00051 inline double fvmeta_abs2 (const K& k)
00052 {
00053 return k*k;
00054 }
00055
00056 template<class K>
00057 inline double fvmeta_abs2 (const std::complex<K>& c)
00058 {
00059 return c.real()*c.real() + c.imag()*c.imag();
00060 }
00061
00062 #endif
00063
00065 template<class C, class T>
00066 class FieldIterator :
00067 public Dune::RandomAccessIteratorFacade<FieldIterator<C,T>,T, T&, int>
00068 {
00069 friend class FieldIterator<typename remove_const<C>::type, typename remove_const<T>::type >;
00070 friend class FieldIterator<const typename remove_const<C>::type, const typename remove_const<T>::type >;
00071
00072 public:
00073
00077 typedef std::ptrdiff_t DifferenceType;
00078
00079
00080 FieldIterator()
00081 : container_(0), position_(0)
00082 {}
00083
00084 FieldIterator(C& cont, DifferenceType pos)
00085 : container_(&cont), position_(pos)
00086 {}
00087
00088 FieldIterator(const FieldIterator<typename remove_const<C>::type, typename remove_const<T>::type >& other)
00089 : container_(other.container_), position_(other.position_)
00090 {}
00091
00092 #if 0
00093 FieldIterator(const FieldIterator<const typename remove_const<C>::type, const typename remove_const<T>::type >& other)
00094 : container_(other.container_), position_(other.position_)
00095 {}
00096 #endif
00097 #if 0
00098 FieldIterator(const FieldIterator<C,T>& other)
00099 : container_(other.container_), position_(other.position_)
00100 {}
00101 #endif
00102
00103 bool equals(const FieldIterator<typename remove_const<C>::type,typename remove_const<T>::type>& other) const
00104 {
00105 return position_ == other.position_ && container_ == other.container_;
00106 }
00107
00108
00109 bool equals(const FieldIterator<const typename remove_const<C>::type,const typename remove_const<T>::type>& other) const
00110 {
00111 return position_ == other.position_ && container_ == other.container_;
00112 }
00113
00114 T& dereference() const{
00115 return container_->operator[](position_);
00116 }
00117
00118 void increment(){
00119 ++position_;
00120 }
00121
00122
00123 void decrement(){
00124 --position_;
00125 }
00126
00127
00128 T& elementAt(DifferenceType i)const{
00129 return container_->operator[](position_+i);
00130 }
00131
00132 void advance(DifferenceType n){
00133 position_=position_+n;
00134 }
00135
00136 std::ptrdiff_t distanceTo(FieldIterator<const typename remove_const<C>::type,const typename remove_const<T>::type> other)const
00137 {
00138 assert(other.container_==container_);
00139 return other.position_ - position_;
00140 }
00141
00142 std::ptrdiff_t distanceTo(FieldIterator<typename remove_const<C>::type, typename remove_const<T>::type> other)const
00143 {
00144 assert(other.container_==container_);
00145 return other.position_ - position_;
00146 }
00147
00149 DifferenceType index () const
00150 {
00151 return this->position_;
00152 }
00153
00154 private:
00155 C *container_;
00156 DifferenceType position_;
00157 };
00158
00160 template<class T>
00161 struct IteratorType
00162 {
00163 typedef typename T::Iterator type;
00164 };
00165
00166 template<class T>
00167 struct IteratorType<const T>
00168 {
00169 typedef typename T::ConstIterator type;
00170 };
00171
00172 #ifdef DUNE_EXPRESSIONTEMPLATES
00174 template<class V>
00175 class FlatIterator :
00176 public ForwardIteratorFacade<FlatIterator<V>,
00177 typename Dune::FieldType<V>::type,
00178 typename Dune::FieldType<V>::type&,
00179 int>
00180 {
00181 public:
00182 typedef typename IteratorType<V>::type BlockIterator;
00183 typedef std::ptrdiff_t DifferenceType;
00184
00185 typedef typename BlockType<V>::type block_type;
00186 typedef typename FieldType<V>::type field_type;
00187 typedef FlatIterator<block_type> SubBlockIterator;
00188 FlatIterator(const BlockIterator & i) :
00189 it(i), bit(i->begin()), bend(i->end()) {};
00190 void increment ()
00191 {
00192 ++bit;
00193 if (bit == bend)
00194 {
00195 ++it;
00196 bit = it->begin();
00197 bend = it->end();
00198 }
00199 }
00200 bool equals (const FlatIterator & fit) const
00201 {
00202 return fit.it == it && fit.bit == bit;
00203 }
00204 field_type& dereference() const
00205 {
00206 return *bit;
00207 }
00209 DifferenceType index () const
00210 {
00211 return bit.index();
00212 }
00213 private:
00214 BlockIterator it;
00215 SubBlockIterator bit;
00216 SubBlockIterator bend;
00217 };
00218
00221 template<class K, int N>
00222 class FlatIterator< FieldVector<K,N> > :
00223 public ForwardIteratorFacade<FlatIterator< FieldVector<K,N> >,
00224 K, K&, int>
00225 {
00226 public:
00227 typedef typename FieldVector<K,N>::Iterator BlockIterator;
00228 typedef std::ptrdiff_t DifferenceType;
00229
00230 typedef typename FieldVector<K,N>::field_type field_type;
00231 FlatIterator(const BlockIterator & i) : it(i) {};
00232 void increment ()
00233 {
00234 ++it;
00235 }
00236 bool equals (const FlatIterator & fit) const
00237 {
00238 return fit.it == it;
00239 }
00240 field_type& dereference() const
00241 {
00242 return *it;
00243 }
00245 DifferenceType index () const
00246 {
00247 return it.index();
00248 }
00249 private:
00250 BlockIterator it;
00251 };
00252
00255 template<class K, int N>
00256 class FlatIterator< const FieldVector<K,N> > :
00257 public ForwardIteratorFacade<FlatIterator< const FieldVector<K,N> >,
00258 const K, const K&, int>
00259 {
00260 public:
00261 typedef typename FieldVector<K,N>::ConstIterator BlockIterator;
00262 typedef std::ptrdiff_t DifferenceType;
00263
00264 typedef typename FieldVector<K,N>::field_type field_type;
00265 FlatIterator(const BlockIterator & i) : it(i) {};
00266 void increment ()
00267 {
00268 ++it;
00269 }
00270 bool equals (const FlatIterator & fit) const
00271 {
00272 return fit.it == it;
00273 }
00274 const field_type& dereference() const
00275 {
00276 return *it;
00277 }
00279 DifferenceType index () const
00280 {
00281 return it.index();
00282 }
00283 private:
00284 BlockIterator it;
00285 };
00286 #endif
00287
00288
00297 template< class K, int SIZE >
00298 class FieldVector
00299 #ifdef DUNE_EXPRESSIONTEMPLATES
00300 : public Dune :: ExprTmpl :: Vector< FieldVector< K, SIZE > >
00301 #endif
00302 {
00303 public:
00304
00305 enum { dimension = SIZE };
00306
00307
00308
00309
00310
00312 typedef K field_type;
00313
00315 typedef K block_type;
00316
00318 typedef std::size_t size_type;
00319
00321 enum {
00323 blocklevel = 1
00324 };
00325
00327 enum {
00329 size = SIZE
00330 };
00331
00333 FieldVector() {}
00334
00335 #ifndef DUNE_EXPRESSIONTEMPLATES
00337 explicit FieldVector (const K& t)
00338 {
00339 for (size_type i=0; i<SIZE; i++) p[i] = t;
00340 }
00341
00342
00344 FieldVector& operator= (const K& k)
00345 {
00346
00347 for (size_type i=0; i<SIZE; i++)
00348 p[i] = k;
00349 return *this;
00350 }
00351
00352 #else
00354 explicit FieldVector (const K& t)
00355 {
00356 #ifdef DUNE_VVERBOSE
00357 Dune::dvverb << INDENT << "FieldVector Copy Constructor Scalar\n";
00358 #endif
00359 assignFrom(t);
00360 }
00362 FieldVector& operator= (const K& k)
00363 {
00364 #ifdef DUNE_VVERBOSE
00365 Dune::dvverb << INDENT << "FieldVector Assignment Operator Scalar\n";
00366 #endif
00367 return assignFrom(k);
00368 }
00369 template <class E>
00370 FieldVector (Dune::ExprTmpl::Expression<E> op) {
00371 #ifdef DUNE_VVERBOSE
00372 Dune::dvverb << INDENT << "FieldVector Copy Constructor Expression\n";
00373 #endif
00374 assignFrom(op);
00375 }
00376 template <class V>
00377 FieldVector (const Dune::ExprTmpl::Vector<V> & op) {
00378 #ifdef DUNE_VVERBOSE
00379 Dune::dvverb << INDENT << "FieldVector Copy Operator Vector\n";
00380 #endif
00381 assignFrom(op);
00382 }
00383 template <class E>
00384 FieldVector& operator = (Dune::ExprTmpl::Expression<E> op) {
00385 #ifdef DUNE_VVERBOSE
00386 Dune::dvverb << INDENT << "FieldVector Assignment Operator Expression\n";
00387 #endif
00388 return assignFrom(op);
00389 }
00390 template <class V>
00391 FieldVector& operator = (const Dune::ExprTmpl::Vector<V> & op) {
00392 #ifdef DUNE_VVERBOSE
00393 Dune::dvverb << INDENT << "FieldVector Assignment Operator Vector\n";
00394 #endif
00395 return assignFrom(op);
00396 }
00397 #endif
00398
00400 FieldVector& operator= (const FieldVector& other) {
00401 for (size_type i=0; i<SIZE; i++)
00402 p[i] = other[i];
00403 return *this;
00404 }
00405
00406
00407
00408
00410 K& operator[] (size_type i)
00411 {
00412 #ifdef DUNE_ISTL_WITH_CHECKING
00413 if (i<0 || i>=SIZE) DUNE_THROW(MathError,"index out of range");
00414 #endif
00415 return p[i];
00416 }
00417
00419 const K& operator[] (size_type i) const
00420 {
00421 #ifdef DUNE_ISTL_WITH_CHECKING
00422 if (i<0 || i>=SIZE) DUNE_THROW(MathError,"index out of range");
00423 #endif
00424 return p[i];
00425 }
00426
00428 typedef FieldIterator<FieldVector<K,SIZE>,K> Iterator;
00430 typedef Iterator iterator;
00431
00433 Iterator begin ()
00434 {
00435 return Iterator(*this,0);
00436 }
00437
00439 Iterator end ()
00440 {
00441 return Iterator(*this,SIZE);
00442 }
00443
00445 Iterator rbegin ()
00446 {
00447 return Iterator(*this,SIZE-1);
00448 }
00449
00451 Iterator rend ()
00452 {
00453 return Iterator(*this,-1);
00454 }
00455
00457 Iterator find (size_type i)
00458 {
00459 if (i<SIZE)
00460 return Iterator(*this,i);
00461 else
00462 return Iterator(*this,SIZE);
00463 }
00464
00466 typedef FieldIterator<const FieldVector<K,SIZE>,const K> ConstIterator;
00468 typedef ConstIterator const_iterator;
00469
00471 ConstIterator begin () const
00472 {
00473 return ConstIterator(*this,0);
00474 }
00475
00477 ConstIterator end () const
00478 {
00479 return ConstIterator(*this,SIZE);
00480 }
00481
00483 ConstIterator rbegin () const
00484 {
00485 return ConstIterator(*this,SIZE-1);
00486 }
00487
00489 ConstIterator rend () const
00490 {
00491 return ConstIterator(*this,-1);
00492 }
00493
00495 ConstIterator find (size_type i) const
00496 {
00497 if (i<SIZE)
00498 return ConstIterator(*this,i);
00499 else
00500 return ConstIterator(*this,SIZE);
00501 }
00502
00503 #ifndef DUNE_EXPRESSIONTEMPLATES
00504
00505
00507 FieldVector& operator+= (const FieldVector& y)
00508 {
00509 for (size_type i=0; i<SIZE; i++)
00510 p[i] += y.p[i];
00511 return *this;
00512 }
00513
00515 FieldVector& operator-= (const FieldVector& y)
00516 {
00517 for (size_type i=0; i<SIZE; i++)
00518 p[i] -= y.p[i];
00519 return *this;
00520 }
00521
00523 FieldVector<K, size> operator+ (const FieldVector<K, size>& b) const
00524 {
00525 FieldVector<K, size> z = *this;
00526 return (z+=b);
00527 }
00528
00530 FieldVector<K, size> operator- (const FieldVector<K, size>& b) const
00531 {
00532 FieldVector<K, size> z = *this;
00533 return (z-=b);
00534 }
00535
00537 FieldVector& operator+= (const K& k)
00538 {
00539 for (size_type i=0; i<SIZE; i++)
00540 p[i] += k;
00541 return *this;
00542 }
00543
00545 FieldVector& operator-= (const K& k)
00546 {
00547 for (size_type i=0; i<SIZE; i++)
00548 p[i] -= k;
00549 return *this;
00550 }
00551
00553 FieldVector& operator*= (const K& k)
00554 {
00555 for (size_type i=0; i<SIZE; i++)
00556 p[i] *= k;
00557 return *this;
00558 }
00559
00561 FieldVector& operator/= (const K& k)
00562 {
00563 for (size_type i=0; i<SIZE; i++)
00564 p[i] /= k;
00565 return *this;
00566 }
00567
00568 #endif
00569
00571 bool operator== (const FieldVector& y) const
00572 {
00573 for (size_type i=0; i<SIZE; i++)
00574 if (p[i]!=y.p[i])
00575 return false;
00576
00577 return true;
00578 }
00579
00581 bool operator!= (const FieldVector& y) const
00582 {
00583 return !operator==(y);
00584 }
00585
00586
00588 FieldVector& axpy (const K& a, const FieldVector& y)
00589 {
00590 #ifndef DUNE_EXPRESSIONTEMPLATES
00591 for (size_type i=0; i<SIZE; i++)
00592 p[i] += a*y.p[i];
00593 #else
00594 *this += a*y;
00595 #endif
00596 return *this;
00597 }
00598
00599 #ifndef DUNE_EXPRESSIONTEMPLATES
00600
00601
00603 K operator* (const FieldVector& y) const
00604 {
00605 K result = 0;
00606 for (int i=0; i<size; i++)
00607 result += p[i]*y[i];
00608 return result;
00609 }
00610
00611
00612
00614 double one_norm() const {
00615 double result = 0;
00616 for (int i=0; i<size; i++)
00617 result += std::abs(p[i]);
00618 return result;
00619 }
00620
00621
00623 double one_norm_real () const
00624 {
00625 double result = 0;
00626 for (int i=0; i<size; i++)
00627 result += fvmeta_absreal(p[i]);
00628 return result;
00629 }
00630
00632 double two_norm () const
00633 {
00634 double result = 0;
00635 for (int i=0; i<size; i++)
00636 result += fvmeta_abs2(p[i]);
00637 return std::sqrt(result);
00638 }
00639
00641 double two_norm2 () const
00642 {
00643 double result = 0;
00644 for (int i=0; i<size; i++)
00645 result += fvmeta_abs2(p[i]);
00646 return result;
00647 }
00648
00650 double infinity_norm () const
00651 {
00652 double result = 0;
00653 for (int i=0; i<size; i++)
00654 result = std::max(result, std::abs(p[i]));
00655 return result;
00656 }
00657
00659 double infinity_norm_real () const
00660 {
00661 double result = 0;
00662 for (int i=0; i<size; i++)
00663 result = std::max(result, fvmeta_absreal(p[i]));
00664 return result;
00665 }
00666 #endif
00667
00668
00669
00671 size_type N () const
00672 {
00673 return SIZE;
00674 }
00675
00677 size_type dim () const
00678 {
00679 return SIZE;
00680 }
00681
00682 private:
00683
00684 K p[(SIZE > 0) ? SIZE : 1];
00685 };
00686
00695 template<typename K, int n>
00696 std::ostream& operator<< (std::ostream& s, const FieldVector<K,n>& v)
00697 {
00698 for (typename FieldVector<K,n>::size_type i=0; i<n; i++)
00699 s << ((i>0) ? " " : "") << v[i];
00700 return s;
00701 }
00702
00714 template< class K, int SIZE >
00715 inline std :: istream &operator>> ( std :: istream &in,
00716 FieldVector< K, SIZE > &v )
00717 {
00718 FieldVector< K, SIZE > w;
00719 for( typename FieldVector< K, SIZE > :: size_type i = 0; i < SIZE; ++i )
00720 in >> w[ i ];
00721 if( in )
00722 v = w;
00723 return in;
00724 }
00725
00726
00727
00728 template<class K, int n, int m> class FieldMatrix;
00729
00730
00731
00734 template< class K >
00735 class FieldVector< K, 1 >
00736 #ifdef DUNE_EXPRESSIONTEMPLATES
00737 : public Dune :: ExprTmpl :: Vector< FieldVector< K, 1 > >
00738 #endif
00739 {
00740 enum { n = 1 };
00741 public:
00742 friend class FieldMatrix<K,1,1>;
00743
00744
00745
00747 typedef K field_type;
00748
00750 typedef K block_type;
00751
00753 typedef std::size_t size_type;
00754
00756 enum {blocklevel = 1};
00757
00759 enum {size = 1};
00760
00762 enum {dimension = 1};
00763
00764
00765
00767 FieldVector ()
00768 { }
00769
00771 FieldVector (const K& k)
00772 {
00773 p = k;
00774 }
00775
00777 FieldVector& operator= (const K& k)
00778 {
00779 p = k;
00780 return *this;
00781 }
00782
00783 #ifdef DUNE_EXPRESSIONTEMPLATES
00784 template <class E>
00785 FieldVector (Dune::ExprTmpl::Expression<E> op) {
00786 #ifdef DUNE_VVERBOSE
00787 Dune::dvverb << INDENT << "FieldVector<1> Copy Constructor Expression\n";
00788 #endif
00789 assignFrom(op);
00790 }
00791 template <class V>
00792 FieldVector (const Dune::ExprTmpl::Vector<V> & op) {
00793 #ifdef DUNE_VVERBOSE
00794 Dune::dvverb << INDENT << "FieldVector<1> Copy Operator Vector\n";
00795 #endif
00796 assignFrom(op);
00797 }
00798 template <class E>
00799 FieldVector& operator = (Dune::ExprTmpl::Expression<E> op) {
00800 #ifdef DUNE_VVERBOSE
00801 Dune::dvverb << INDENT << "FieldVector<1> Assignment Operator Expression\n";
00802 #endif
00803 return assignFrom(op);
00804 }
00805 template <class V>
00806 FieldVector& operator = (const Dune::ExprTmpl::Vector<V> & op) {
00807 #ifdef DUNE_VVERBOSE
00808 Dune::dvverb << INDENT << "FieldVector<1> Assignment Operator Vector\n";
00809 #endif
00810 return assignFrom(op);
00811 }
00812 #endif
00813
00814
00815
00817 K& operator[] (size_type i)
00818 {
00819 #ifdef DUNE_ISTL_WITH_CHECKING
00820 if (i != 0) DUNE_THROW(MathError,"index out of range");
00821 #endif
00822 return p;
00823 }
00824
00826 const K& operator[] (size_type i) const
00827 {
00828 #ifdef DUNE_ISTL_WITH_CHECKING
00829 if (i != 0) DUNE_THROW(MathError,"index out of range");
00830 #endif
00831 return p;
00832 }
00833
00835 typedef FieldIterator<FieldVector<K,n>,K> Iterator;
00837 typedef Iterator iterator;
00838
00840 Iterator begin ()
00841 {
00842 return Iterator(*this,0);
00843 }
00844
00846 Iterator end ()
00847 {
00848 return Iterator(*this,n);
00849 }
00850
00852 Iterator rbegin ()
00853 {
00854 return Iterator(*this,n-1);
00855 }
00856
00858 Iterator rend ()
00859 {
00860 return Iterator(*this,-1);
00861 }
00862
00864 Iterator find (size_type i)
00865 {
00866 if (i<n)
00867 return Iterator(*this,i);
00868 else
00869 return Iterator(*this,n);
00870 }
00871
00873 typedef FieldIterator<const FieldVector<K,n>,const K> ConstIterator;
00875 typedef ConstIterator const_iterator;
00876
00878 ConstIterator begin () const
00879 {
00880 return ConstIterator(*this,0);
00881 }
00882
00884 ConstIterator end () const
00885 {
00886 return ConstIterator(*this,n);
00887 }
00888
00890 ConstIterator rbegin () const
00891 {
00892 return ConstIterator(*this,n-1);
00893 }
00894
00896 ConstIterator rend () const
00897 {
00898 return ConstIterator(*this,-1);
00899 }
00900
00902 ConstIterator find (size_type i) const
00903 {
00904 if (i<n)
00905 return ConstIterator(*this,i);
00906 else
00907 return ConstIterator(*this,n);
00908 }
00909
00910
00912 FieldVector& operator+= (const K& k)
00913 {
00914 p += k;
00915 return *this;
00916 }
00917
00919 FieldVector& operator-= (const K& k)
00920 {
00921 p -= k;
00922 return *this;
00923 }
00924
00926 FieldVector& operator*= (const K& k)
00927 {
00928 p *= k;
00929 return *this;
00930 }
00931
00933 FieldVector& operator/= (const K& k)
00934 {
00935 p /= k;
00936 return *this;
00937 }
00938
00940 FieldVector& axpy (const K& a, const FieldVector& y)
00941 {
00942 p += a*y.p;
00943 return *this;
00944 }
00945
00947 inline K operator* ( const K & k ) const
00948 {
00949 return p * k;
00950 }
00951
00952
00953
00955 double one_norm () const
00956 {
00957 return std::abs(p);
00958 }
00959
00961 double one_norm_real () const
00962 {
00963 return fvmeta_abs_real(p);
00964 }
00965
00967 double two_norm () const
00968 {
00969 return sqrt(fvmeta_abs2(p));
00970 }
00971
00973 double two_norm2 () const
00974 {
00975 return fvmeta_abs2(p);
00976 }
00977
00979 double infinity_norm () const
00980 {
00981 return std::abs(p);
00982 }
00983
00985 double infinity_norm_real () const
00986 {
00987 return fvmeta_abs_real(p);
00988 }
00989
00990
00991
00993 size_type N () const
00994 {
00995 return 1;
00996 }
00997
00999 size_type dim () const
01000 {
01001 return 1;
01002 }
01003
01004
01005
01007 operator K () {return p;}
01008
01010 operator K () const {return p;}
01011
01012 private:
01013
01014 K p;
01015 };
01016
01017 #ifndef DUNE_EXPRESSIONTEMPLATES
01019 template<class K>
01020 inline FieldVector<K,1> operator+ (const FieldVector<K,1>& a, const FieldVector<K,1>& b)
01021 {
01022 FieldVector<K,1> z = a;
01023 return (z+=b);
01024 }
01025
01027 template<class K>
01028 inline FieldVector<K,1> operator- (const FieldVector<K,1>& a, const FieldVector<K,1>& b)
01029 {
01030 FieldVector<K,1> z = a;
01031 return (z-=b);
01032 }
01033
01035 template<class K>
01036 inline FieldVector<K,1> operator+ (const FieldVector<K,1>& a, const K b)
01037 {
01038 FieldVector<K,1> z = a;
01039 return (z[0]+=b);
01040 }
01041
01043 template<class K>
01044 inline FieldVector<K,1> operator- (const FieldVector<K,1>& a, const K b)
01045 {
01046 FieldVector<K,1> z = a;
01047 return (z[0]-=b);
01048 }
01049
01051 template<class K>
01052 inline FieldVector<K,1> operator+ (const K a, const FieldVector<K,1>& b)
01053 {
01054 FieldVector<K,1> z = a;
01055 return (z[0]+=b);
01056 }
01057
01059 template<class K>
01060 inline FieldVector<K,1> operator- (const K a, const FieldVector<K,1>& b)
01061 {
01062 FieldVector<K,1> z = a;
01063 return (z[0]-=b);
01064 }
01065 #endif
01066
01069 }
01070
01071 #endif