1 // ********** DO NOT REMOVE THIS BANNER **********
2 // ORIG-DATE:    29 fev 2000
3 // -*- Mode : c++ -*-
4 //
5 // SUMMARY  : array modelisation
6 // USAGE    : LGPL
7 // ORG      : LJLL Universite Pierre et Marie Curie, Paris,  FRANCE
8 // AUTHOR   : Frederic Hecht
9 // E-MAIL   : frederic.hecht@ann.jussieu.fr
10 //
11 
12 /*
13 
14 
15 
16  Freefem++ is free software; you can redistribute it and/or modify
17  it under the terms of the GNU Lesser General Public License as published by
18  the Free Software Foundation; either version 2.1 of the License, or
19  (at your option) any later version.
20 
21  Freefem++  is distributed in the hope that it will be useful,
22  but WITHOUT ANY WARRANTY; without even the implied warranty of
23  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
24  GNU Lesser General Public License for more details.
25 
26  You should have received a copy of the GNU Lesser General Public License
27  along with Freefem++; if not, write to the Free Software
28  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
29 
30 
31  */
32 #ifndef KNM_H_
33 #define KNM_H_
34 // version march  2010 FH.
35 // add iterator for compatibility with gmm++
36 // ----------------------
37 // une tentative qui ne marche pas
38 // de tableau constant
39 #include <complex>
40 #include <iostream>
41 #include <iomanip>
42 #include <cmath>
43 #include <cassert>
44 
45 
46 using namespace std;
47 #define const_R   R
48 
49 #include <cstdlib>
Check_Kn(const char * str,const char * file,int line)50 inline void Check_Kn(const char * str,const char * file,int line)
51 {
52  cerr << "CHECK_KN: " << str << " in file: " << file << ", line " << line <<endl;
53  assert(0);
54  abort();
55 }
56 
57 #define K_bigassert(i)  if (!(i)) Check_Kn(#i,__FILE__,__LINE__);
58 #define RNM_FATAL_ERROR(i) Check_Kn(i,__FILE__,__LINE__);
59 #ifdef CHECK_KN
60 
61 #define K_throwassert(i)  if (!(i)) Check_Kn(#i,__FILE__,__LINE__);
62 
63 #else
64 #define K_throwassert(i)
65 #endif
66 // version du 29 fev 2000
67 //  correction   for (... lj++,ui++  qui apelle le produit scalaire
68 //  petite correction  throwassert
69 // ajoute de operateur /= et *= sur des vecteurs
70 //   suppression de constructeur qui pose de probleme
71 //   correction oper +=  ...  dans RNM_op.h ligne 56  change = en oper
72 // version de 25 nov 99  sans const R
73 // ajoute de '.' pour extraire une colonne, ou ligne  , ...
74 //  version du 22 nov 1999   cast to KN_<const R>
75 //   version du 21 nov 1999  correction delete
76 //  version du 13 nov 1999
77 //  version du 18 mars 99
78 //  F. Hecht
79 // attention les indexations les indexations peuvent changer
80 //  puisque que l'on peut prendre la transposer d'une matrice
81 // tableau
82 // mais ils partent de 0
83 // version corrigee du 15/11/98
84 // version avec sous tableau  ---  mars 99
85 // -------
86 //  remarque du 8 mars 99 FH
87 // class pour prendre des sous-tableau
88 // attention aux PB de continute dans les tableaux
89 // on a supposer que les tableaux multi indices pouvait est vue comme
90 // un tableau continue ce qui est generalement faux quand l'on en
91 // prend un sous tableau
92 //   exemple: un tableau 3,5 est numerote comme:
93 //    0  3  6  9 12
94 //    1  4  7 10 13
95 //    2  5  8 11 14
96 //             step
97 //   indexi  n 1
98 //   indexj  m n
99 //   est le sous tableau  3,3  n'est pas numeroter consecutivement
100 //
101 //    Donc la fonction  IsVector1() nous dit si un tableau
102 //    a un 2 ou 3 indices est ou non consecutif en memoire
103 //
104 //  --  ajoute d'une classe VirtualMatrice
105 // pour modeliser le produit matrice vecteur
106 //  x = A*v; via des fonctions virtuelle
107 //  ----------------------------------
108 //   version du 6 mars 2001 FH
109 //   ---  initialisation --
110 //   --------------------------------
111 //   version du 9 oct 2001 FH
112 //   ajoute de constructeur par defaut d'une vecteur
113 //   +  set , pour definir le vecteur
114 //   ou l'affectation (bof bof)
115 // ---------------------
116 //  version sep 2002
117 //  ajoute  operateur >> pour  KN<R> et KN_<R>
118 //  --------------------
119 //  version  april 2003
120 //  ajoute un gestion auto de
121 //  la fonction InternalError pour les matriceVirtuel
122 //  --------------------
123 //   version jan 2004
124 //   correction pour go ++
125 //   des operateur  #=  pour les matrices et tenseurs
126 //  ----------------------
127 //   version  feb 2004
128 //   v(i(:)) =  w   //  i(1:10)
129 //   w=u(i(:))  //
130 //   version mars 2004 make small correction
131 //   in  ITAB operator problem if non type R a defi
132 //   -------------------
133 //   Modif pour version avec les Complex   mai 2004
134 //   (u,v)  donne le produit complex utiliser dans le produit matrice vecteur
135 //   (u,conj(v))  donne le produit hermitiene pour le gradient conjugue
136 //
137 //   -- de fonction dans le cas real
138 // modif for g++ 4.0 and xlc++   mai 2005
139 //  adding some this->
140 //   mars 2007
141 // correction in operator operation:b -1*c
142 // aout 2007,
143 //  correct y = A*x ; when y is unset
144 //  correct y += A*x ; when y is unset
145 //  re-correct += sep 2007
146 //  add size of the matrix in VirtualMatrix class.
147 //   mars 2010 add  unset KNM case ...
148 // ----------------
conj(const double & x)149 inline double  conj(const double & x){return x;}
conj(const float & x)150 inline float  conj(const float &x){return x;}
conj(const long & x)151 inline long  conj(const long &x){return x;}
real(const double & x)152 inline double  real(const double &x){return x;}
real(const float & x)153 inline float  real(const float &x){return x;}
154 
155 namespace RNM
156 {
Min(const T & a,const T & b)157   template<class T> inline T Min (const T &a,const T &b){return a < b ? a : b;}
Max(const T & a,const T & b)158   template<class T> inline T Max (const T &a,const T & b){return a > b ? a : b;}
Abs(const T & a)159   template<class T> inline T Abs (const T &a){return a <0 ? -a : a;}
160 
Exchange(T & a,T & b)161   template<class T> inline void Exchange (T& a,T& b) {T c=a;a=b;b=c;}
Max(const T & a,const T & b,const T & c)162   template<class T> inline T Max (const T &a,const T & b,const T & c){return Max(Max(a,b),c);}
Min(const T & a,const T & b,const T & c)163   template<class T> inline T Min (const T &a,const T & b,const T & c){return Min(Min(a,b),c);}
164   // specialisation cas complex ---
165   template<class T>
Min(const complex<T> & a,complex<T> & b)166   inline complex<T> Min(const complex<T> &a,complex<T> &b)
167   { return complex<T>(min(a.real(),b.real()),min(a.imag(),b.imag()));}
168   template<class T>
Max(const complex<T> & a,const complex<T> & b)169   inline complex<T> Max(const complex<T> &a,const complex<T> &b)
170   { return complex<T>(max(a.real(),b.real()),max(a.imag(),b.imag()));}
171 
172   /*inline complex<double> Min(const complex<double> &a,complex<double> &b)
173     { return complex<double>(Min(real(a),real(b)),Min(imag(a),imag(b)));}
174     inline complex<double> Max(const complex<double> &a,const complex<double> &b)
175     { return complex<double>(Max(real(a),real(b)),Max(imag(a),imag(b)));}
176   */
177 }
178 //  ----
179 
180 template<class R> class KNMK_ ;
181 template<class R> class KNM_ ;
182 template<class R> class KN_ ;
183 template<class R> class KN__iterator ;
184 template<class R> class KN__const_iterator ;
185 template<class R> class TKN_ ; // KN_ transpose
186 template<class R> class notKN_ ; // KN_ not
187 template<class R> class notnotKN_ ; // KN_ not not
188 
189 template<class R> class KNMK ;
190 template<class R> class KNM ;
191 template<class R> class KN ;
192 
193 template<class R> class conj_KN_ ;
194 template<class R> class Add_KN_;
195 template<class R> class Sub_KN_;
196 template<class R> class Mulc_KN_;
197 template<class R> class Add_Mulc_KN_;
198 template<class R> class Mul_KNM_KN_;
199 template<class R> class DotStar_KN_;
200 template<class R> class DotSlash_KN_;
201 
202 template<class R> class outProduct_KN_;
203 template<class R> class if_KN_;
204 template<class R> class if_arth_KN_;
205 template<class R> class ifnot_KN_;
206 template<class R,class I> class KN_ITAB;
207 
208 template<class R,typename A,typename B> class F_KN_;
209 
210 
211 #ifndef ffassert
212 #define ffassert assert
213 #endif
214 
215 // gestion des erreur interne --
216 #ifndef InternalError
217 typedef void (* TypeofInternalErrorRoutine)(const char *) ;
InternalErrorRoutinePtr()218 static TypeofInternalErrorRoutine &InternalErrorRoutinePtr()
219 {
220   static TypeofInternalErrorRoutine routine=0;
221   return routine;
222 }
223 
InternalError(const char * str)224 static void InternalError(const char * str) {
225   if (InternalErrorRoutinePtr() ) (*InternalErrorRoutinePtr())(str);
226   cerr << str;
227   exit(1);
228 }
SetInternalErrorRoutine(TypeofInternalErrorRoutine f)229 inline void  SetInternalErrorRoutine(TypeofInternalErrorRoutine f)
230 {
231   InternalErrorRoutinePtr()=f;
232 }
233 #endif
234 //  --
235 template<class P,class Q>
236    struct PplusQ { const P & p;const Q & q;
PplusQPplusQ237     PplusQ(const P & pp,const Q & qq) : p(pp),q(qq){}
238     };
239 
240 template<class R>
241 struct  VirtualMatrice { public:
242     int N,M;
VirtualMatriceVirtualMatrice243     VirtualMatrice(int nn,int mm): N(nn),M(mm) {}
VirtualMatriceVirtualMatrice244     VirtualMatrice(int nn): N(nn),M(nn) {}
245   //  y += A x
246   virtual void addMatMul(const KN_<R> &  x, KN_<R> & y) const =0;
addMatTransMulVirtualMatrice247   virtual void addMatTransMul(const KN_<R> &  , KN_<R> & ) const
248     { InternalError("VirtualMatrice::addMatTransMul not implemented "); }
WithSolverVirtualMatrice249   virtual bool WithSolver() const {return false;} // by default no solver
SolveVirtualMatrice250   virtual void Solve( KN_<R> &  ,const KN_<R> & ) const
251     { InternalError("VirtualMatrice::solve not implemented "); }
252 
253 #ifdef VersionFreeFempp
254   virtual bool ChecknbLine  (int n) const= 0;
255   virtual bool ChecknbColumn  (int m) const =0;
256 #else
ChecknbLineVirtualMatrice257   virtual bool ChecknbLine  (int n) const {return true;}
ChecknbColumnVirtualMatrice258   virtual bool ChecknbColumn  (int m) const {return true;}
259 #endif
260   struct  plusAx { const VirtualMatrice * A; const KN_<R>   x;
plusAxVirtualMatrice::plusAx261    plusAx( const VirtualMatrice * B,const KN_<R> &  y) :A(B),x(y)
262       { ffassert(B->ChecknbColumn(y.N())); }
263     };
264 
operator *VirtualMatrice265    plusAx operator*(const KN_<R> &  x) const {return plusAx(this,x);}
266 
267   struct  plusAtx { const VirtualMatrice * A; const KN_<R>   x;
plusAtxVirtualMatrice::plusAtx268    plusAtx( const VirtualMatrice * B,const KN_<R> &  y) :A(B),x(y)
269     {ffassert(B->ChecknbLine(y.N()));} };
270 
271   struct  solveAxeqb { const VirtualMatrice * A; const KN_<R>   b;
solveAxeqbVirtualMatrice::solveAxeqb272    solveAxeqb( const VirtualMatrice * B,const KN_<R> &  y) :A(B),b(y)
273     {ffassert(B->ChecknbColumn(y.N()));} };
274 
~VirtualMatriceVirtualMatrice275   virtual ~VirtualMatrice(){}
276 };
277 
278 
279 
280 //template <class R> class MatriceCreuseMulKN_;
281 //template <class R> class MatriceCreuseDivKN_;
282 
283 class ShapeOfArray;
284 
285 class FromTo{ public:
286   long from,to;
FromTo(long i,long j)287   FromTo(long i,long j):from(i),to(j) {K_throwassert(i<j);}
288  };
289 
290 class SubArray{ public:
291   const long n,step,start;
292 //  SubArray(char  nn): n(-1),step(1),start(0) {}
SubArray(long nn,long sta=0,long s=1)293  explicit SubArray(long nn,long sta=0,long s=1): n(nn),step(s),start(sta) {}
SubArray(const FromTo & ft)294   SubArray(const FromTo& ft) : n(ft.to-ft.from+1),step(1),start(ft.from) {}
295   SubArray(const ShapeOfArray & ); // all
end() const296   long end()  const  { return start+ step*n;}
last() const297   long last() const  { return start+ step*(n-1);}
len1() const298   long len1() const  { return step*(n-1);}
299 };
300 
301 
302 class ShapeOfArray{ protected:
303   public:
304 
305     long n;     //   n  nb of item
306     long step;  //   step  nb of between 2 item
307     long next;  //  the   next array of same type in matrix for subarray
308               // by default  no next ( in case of KN, and KNM  -next is
309               // a counter of destruction  (use in frefem++)
ShapeOfArray(const ShapeOfArray & s,long nn)310   ShapeOfArray(const ShapeOfArray & s,long nn): n(s.n),step(s.n),next(nn) {}
ShapeOfArray(long nn)311   ShapeOfArray(long nn): n(nn),step(1),next(-1) {}
312 
ShapeOfArray(long nn,long s)313   ShapeOfArray(long nn,long s): n(nn),step(s),next(-1) {}
314 
ShapeOfArray(long nn,long s,long nextt)315   ShapeOfArray(long nn,long s,long nextt): n(nn),step(s),next(nextt) {}
316 
ShapeOfArray(const ShapeOfArray & old,const SubArray & sub)317   ShapeOfArray(const ShapeOfArray &old,const SubArray &sub)
318          : n(sub.n),step(old.step*sub.step),next(old.next)
319           { K_throwassert((sub.last())*old.step <= old.last());} // a constructor
320 
ShapeOfArray(const ShapeOfArray & old,long stepo,long start)321   ShapeOfArray(const ShapeOfArray &old,long stepo,long start)
322          : n(old.n-start),step(old.step*stepo),next(old.next)
323           { K_throwassert(n>=0);}
324 
end() const325   long end()  const      { return n*step;}
last() const326   long last()      const      { return (n-1)*step;}
constant() const327   long constant()  const { return step==0;}
index(long k) const328   long index(long k) const { K_throwassert( (k>=0) && ( (k <n) || !step) );
329            return step*k;}
operator *(long stepp) const330   ShapeOfArray operator*(long stepp) const {return  ShapeOfArray(n,step*stepp,next);}
SameShape(const ShapeOfArray & a) const331   bool SameShape(const ShapeOfArray & a) const
332           { return  !step || !a.step || a.n == n ;}
N(const ShapeOfArray & a)333   long  N(const ShapeOfArray & a) { return step ? n : a.n;} // size of 2 shape
334 
335 
336 // protected:
operator [](long k) const337   long operator[](long k) const {
338     //if( k<0 || ( k<n && !step) )
339     //  cout << "k,n,step=" << k << " " << n << " " << step << endl;
340     K_throwassert( (k>=0) && ( (k <n) || !step) );
341            return step*k;}
init(long nn,long s=1,long nextt=-1)342   void init(long nn,long s=1,long nextt=-1) { n=nn; step=s; next=nextt;}
343 };
344 
345 ostream & operator<<(ostream & f,const ShapeOfArray & s);
346 
SameShape(const ShapeOfArray & a,const ShapeOfArray & b)347 inline bool  SameShape(const ShapeOfArray & a,const ShapeOfArray & b)
348            { return  !a.step || !b.step || a.n == b.n ;}
349 
N(const ShapeOfArray & a,const ShapeOfArray & b)350 inline long N(const ShapeOfArray & a,const ShapeOfArray & b)
351            { K_throwassert(SameShape(a,b)); return  a.step ? a.n :  b.n ;}
352 
SubArray(const ShapeOfArray & s)353 inline SubArray::SubArray(const ShapeOfArray & s)
354            :n(s.n),step(s.step),start(0) {}
355 
356 
357 
358 template<class R>
359 ostream & operator<<(ostream & f,const KN_<const_R> & v) ;
360 
361 template<class R> istream & operator>>(istream & f, KN_<R> & v);
362 template<class R> istream & operator>>(istream & f, KN<R> & v);
363 
364 template<class R>
365 class SetArray { public:
366     R o,step;
367     long n;
SetArray(long nn,R oo=R (),R sstep=R (1))368     explicit SetArray(long nn,R oo=R(),R sstep=R(1)): o(oo),n(nn),step(sstep) {}
SetArray(SetArray<K> sa)369     template<class K>   SetArray(SetArray<K> sa): o(sa.o),n(sa.n),step(sa.step) {}
370 
operator [](long i) const371   R operator[](long i) const { return i <= n ? o + R(i)*step : R();}
size() const372     long size() const {return n;}
373 };
374 
375 // add for gmm++  march 2010 ....
376   template<typename T> struct KN__iterator {
377     typedef T                   value_type;
378     typedef value_type*         pointer;
379     typedef value_type&         reference;
380     typedef size_t              size_type;
381     typedef ptrdiff_t           difference_type;
382     typedef std::bidirectional_iterator_tag iterator_category;
383     typedef KN__iterator<T> iterator;
384   private:
385     T* v;
386     long step;
387   public:
operator *KN__iterator388     reference operator *() const { return *v; }
operator ->KN__iterator389     pointer operator->() const { return &(operator*()); }
390 
operator ++KN__iterator391     iterator &operator ++() { v += step; return *this; }
operator ++KN__iterator392     iterator operator ++(int) { iterator tmp = *this; ++(*this); return tmp; }
operator --KN__iterator393     iterator &operator --() { v -= step; return *this; }
operator --KN__iterator394     iterator operator --(int) { iterator tmp = *this; --(*this); return tmp; }
395 
operator ==KN__iterator396     bool operator ==(const iterator &i) const { return v == i.v; }
operator !=KN__iterator397     bool operator !=(const iterator &i) const { return !(v == i.v); }
398 
KN__iteratorKN__iterator399     KN__iterator(T *vv,int s) : v(vv),step(s) {K_throwassert(v);}
400     friend class KN__const_iterator<T>;
401   };
402 
403 template<typename T> struct KN__const_iterator {
404   typedef T                   value_type;
405   typedef const value_type*   pointer;
406   typedef const value_type&   reference;
407   typedef size_t              size_type;
408   typedef ptrdiff_t           difference_type;
409   typedef std::forward_iterator_tag iterator_category;
410   typedef KN__const_iterator<T> iterator;
411 
412 private:
413   const T* v;
414   long step;
415 public:
416 
operator *KN__const_iterator417     reference operator *() const { return *v; }
operator ->KN__const_iterator418     pointer operator->() const { return &(operator*()); }
419 
operator ++KN__const_iterator420     iterator &operator ++() { v += step; return *this; }
operator ++KN__const_iterator421     iterator operator ++(int) { iterator tmp = *this; ++(*this); return tmp; }
operator --KN__const_iterator422     iterator &operator --() { v -= step; return *this; }
operator --KN__const_iterator423     iterator operator --(int) { iterator tmp = *this; --(*this); return tmp; }
424 
operator ==KN__const_iterator425     bool operator ==(const iterator &i) const { return v == i.v; }
operator !=KN__const_iterator426     bool operator !=(const iterator &i) const { return !(v == i.v); }
427 
KN__const_iteratorKN__const_iterator428   KN__const_iterator(const T *vv,int s) : v(vv),step(s) {K_throwassert(v);}
KN__const_iteratorKN__const_iterator429   KN__const_iterator(const KN__const_iterator<T> & i) : v(i.v),step(i.step){}
430 
431 };
432 
433 
434 template<class R>
435 class KN_: public  ShapeOfArray {
436 protected:
437   R *v;
438 public:
439   typedef R K; // type of data
440   typedef KN__iterator<R> iterator;
441   typedef KN__const_iterator<R> const_iterator;
end()442   iterator end(){ return iterator(v+n*step,step);}
begin()443   iterator begin(){ return iterator(v,step);}
end() const444   const_iterator end() const { return const_iterator(v+n*step,step);}
begin() const445   const_iterator begin() const { return const_iterator(v,step);}
clear()446   void clear() { *this=R();}
N() const447   long N() const {return n;}
unset() const448   bool unset() const { return !v;}
set(R * vv,int nn,int st=1,int nx=-1)449   void set(R * vv,int nn,int st=1,int nx=-1) {v=vv;n=nn;step=st;next=nx;}
size() const450   long size() const{return step?n*step:n;}
operator R*() const451   operator R *() const {return v;}
KN_(const KN_<R> & u)452   KN_(const KN_<R> & u) :ShapeOfArray(u),v(u.v){}
KN_(const KN_<R> & U,const SubArray & sa)453   KN_(const KN_<R> & U,const SubArray & sa)  : ShapeOfArray(U,sa),v(U.v + U.index(sa.start)) {}
454 
operator ()(const SubArray & sa) const455   KN_ operator()(const SubArray & sa) const { return KN_(*this,sa);} // sub array
456 
operator [](long i) const457   R & operator[](long i) const {return v[index(i)];}
operator ()(long i) const458   R & operator()(long i) const {return v[index(i)];}
operator [](int i) const459   R & operator[](int i) const {return v[index(i)];}
operator ()(int i) const460   R & operator()(int i) const {return v[index(i)];}
461 
462   R operator,(const KN_<const_R> & v) const; // dot  product
463 
464    KN_& operator  =(const SetArray<R> & u)  ;
465    KN_& operator +=(const SetArray<R> & u)  ;
466    KN_& operator -=(const SetArray<R> & u)  ;
467    KN_& operator *=(const SetArray<R> & u)  ;
468    KN_& operator /=(const SetArray<R> & u)  ;
469 
470     KN_& operator  =(const KN_<const_R> & u)  ;
471     KN_& operator +=(const KN_<const_R> & u)  ;
472     KN_& operator -=(const KN_<const_R> & u)  ;
473 
474     KN_& operator *=(const KN_<const_R> & u)  ;
475     KN_& operator /=(const KN_<const_R> & u)  ;
476 
477 
478    KN_& operator = (const_R  a) ;
479    KN_& operator +=(const_R  a) ;
480    KN_& operator -=(const_R  a) ;
481    KN_& operator /=(const_R  a) ;
482    KN_& operator *=(const_R  a) ;
483 
operator =(R * a)484    KN_& operator  = (R*  a) { return operator =(KN_<R>(a,n));}
operator +=(R * a)485    KN_& operator += (R*  a) { return operator+=(KN_<R>(a,n));}
operator -=(R * a)486    KN_& operator -= (R*  a) { return operator-=(KN_<R>(a,n));}
operator *=(R * a)487    KN_& operator *= (R*  a) { return operator*=(KN_<R>(a,n));}
operator /=(R * a)488    KN_& operator /= (R*  a) { return operator/=(KN_<R>(a,n));}
489 
490 
491 
492   R min() const ;
493   R max() const ;
494   R sum() const ;
495   double norm() const ;
496   double l2() const ;
497   double l1() const ;
498   double linfty() const ;
499   double lp(double p) const ;
500 
501   template<class T> long last(const T &) const;
502   template<class T> long first(const T &) const;
503 
504   void map(R (*f)(R )); // apply the f fonction a all element of the array
505   void map(R (*f)(const  R& )); // apply the f fonction a all element of the array
506 
507  template<class T>
508    void set(R (*f)(const  T& ),KN_<T> & u); // apply the f fonction a all element of the array u
509 
510    KN_& operator =(const DotStar_KN_<R> & u) ;
511    KN_& operator+=(const DotStar_KN_<R> & u) ;
512    KN_& operator-=(const DotStar_KN_<R> & u) ;
513    KN_& operator*=(const DotStar_KN_<R> & u) ;
514    KN_& operator/=(const DotStar_KN_<R> & u) ;
515 
516    KN_& operator =(const DotSlash_KN_<R> & u) ;
517    KN_& operator+=(const DotSlash_KN_<R> & u) ;
518    KN_& operator-=(const DotSlash_KN_<R> & u) ;
519    KN_& operator*=(const DotSlash_KN_<R> & u) ;
520    KN_& operator/=(const DotSlash_KN_<R> & u) ;
521 
522    KN_& operator =(const if_KN_<R> & u) ;
523    KN_& operator+=(const if_KN_<R> & u) ;
524    KN_& operator-=(const if_KN_<R> & u) ;
525    KN_& operator*=(const if_KN_<R> & u) ;
526    KN_& operator/=(const if_KN_<R> & u) ;
527 
528    KN_& operator =(const ifnot_KN_<R> & u) ;
529    KN_& operator+=(const ifnot_KN_<R> & u) ;
530    KN_& operator-=(const ifnot_KN_<R> & u) ;
531    KN_& operator*=(const ifnot_KN_<R> & u) ;
532    KN_& operator/=(const ifnot_KN_<R> & u) ;
533 
534    KN_& operator =(const Add_KN_<R> & u) ;
535    KN_& operator+=(const Add_KN_<R> & u) ;
536    KN_& operator-=(const Add_KN_<R> & u) ;
537    KN_& operator*=(const Add_KN_<R> & u) ;
538    KN_& operator/=(const Add_KN_<R> & u) ;
539 
540    template<class I,class T> KN_& operator =  (const KN_ITAB<T,I> & u);
541    template<class I,class T> KN_& operator +=  (const KN_ITAB<T,I> & u);
542    template<class I,class T> KN_& operator -=  (const KN_ITAB<T,I> & u);
543    template<class I,class T> KN_& operator *=  (const KN_ITAB<T,I> & u);
544    template<class I,class T> KN_& operator /=  (const KN_ITAB<T,I> & u);
545 
546 
547    KN_ITAB< KN_<R>,const KN_<int> >  operator()(const KN_<int> &itab) ;
548    KN_ITAB< KN_<R>,const KN_<long> >  operator()(const KN_<long> &itab) ;
549    KN_ITAB<const KN_<R>,const KN_<int> > operator()(const KN_<int> &itab) const ;
550    KN_ITAB<const KN_<R>,const KN_<long> >  operator()(const KN_<long> &itab) const ;
551 
552 
553 
554 
555 
556    KN_& operator =(const Sub_KN_<R> & u) ;
557    KN_& operator-=(const Sub_KN_<R> & u) ;
558    KN_& operator+=(const Sub_KN_<R> & u) ;
559    KN_& operator*=(const Sub_KN_<R> & u) ;
560    KN_& operator/=(const Sub_KN_<R> & u) ;
561 
562    KN_& operator =(const Mulc_KN_<R> & u) ;
563    KN_& operator+=(const Mulc_KN_<R> & u) ;
564    KN_& operator-=(const Mulc_KN_<R> & u) ;
565    KN_& operator*=(const Mulc_KN_<R> & u) ;
566    KN_& operator/=(const Mulc_KN_<R> & u) ;
567 
568    KN_& operator =(const Add_Mulc_KN_<R> & u) ;
569    KN_& operator+=(const Add_Mulc_KN_<R> & u) ;
570    KN_& operator-=(const Add_Mulc_KN_<R> & u) ;
571    KN_& operator*=(const Add_Mulc_KN_<R> & u) ;
572    KN_& operator/=(const Add_Mulc_KN_<R> & u) ;
573 
574    KN_& operator =(const if_arth_KN_<R> & u) ;
575    KN_& operator+=(const if_arth_KN_<R> & u) ;
576    KN_& operator-=(const if_arth_KN_<R> & u) ;
577    KN_& operator*=(const if_arth_KN_<R> & u) ;
578    KN_& operator/=(const if_arth_KN_<R> & u) ;
579 
580 
581    KN_& operator =(const Mul_KNM_KN_<R> & u) ;
582    KN_& operator+=(const Mul_KNM_KN_<R> & u) ;
583    KN_& operator-=(const Mul_KNM_KN_<R> & u) ;
584    KN_& operator*=(const Mul_KNM_KN_<R> & u) ;
585    KN_& operator/=(const Mul_KNM_KN_<R> & u) ;
586 
587  //  KN_& operator =(const MatriceCreuseMulKN_<R> & ) ;
588  //  KN_& operator +=(const MatriceCreuseMulKN_<R> & ) ;
operator =(const typename VirtualMatrice<R>::plusAx & Ax)589    KN_& operator =(const typename VirtualMatrice<R>::plusAx & Ax)
590     {*this=R(); Ax.A->addMatMul(Ax.x,*this);return *this;}
operator =(const typename VirtualMatrice<R>::plusAtx & Ax)591    KN_& operator =(const typename VirtualMatrice<R>::plusAtx & Ax)
592     {*this=R(); Ax.A->addMatTransMul(Ax.x,*this);return *this;}
operator +=(const typename VirtualMatrice<R>::plusAx & Ax)593    KN_& operator +=(const typename VirtualMatrice<R>::plusAx & Ax)
594     {  Ax.A->addMatMul(Ax.x,*this);return *this;}
operator +=(const typename VirtualMatrice<R>::plusAtx & Ax)595    KN_& operator +=(const typename VirtualMatrice<R>::plusAtx & Ax)
596     {  Ax.A->addMatTransMul(Ax.x,*this);return *this;}
operator =(const typename VirtualMatrice<R>::solveAxeqb & Ab)597    KN_& operator =(const typename VirtualMatrice<R>::solveAxeqb & Ab)
598     {*this=R(); Ab.A->Solve(*this,Ab.b);return *this;}
599 
600   template<class  A,class B,class C> KN_&  operator =  (const F_KN_<A,B,C>  & u) ;
601   template<class  A,class B,class C> KN_&  operator +=  (const F_KN_<A,B,C>  & u) ;
602   template<class  A,class B,class C> KN_&  operator -=  (const F_KN_<A,B,C>  & u) ;
603   template<class  A,class B,class C> KN_&  operator /=  (const F_KN_<A,B,C>  & u) ;
604   template<class  A,class B,class C> KN_&  operator *=  (const F_KN_<A,B,C>  & u) ;
605 
606 
607 //   KN_& operator =(const MatriceCreuseDivKN_<R> &)  ;
608 
609  friend   ostream & operator<< <R>(ostream & f,const KN_<const_R> & v)  ;
610 
KN_(R * u,const ShapeOfArray & s)611   KN_(R *u,const ShapeOfArray & s):ShapeOfArray(s),v(u){}
KN_(R * u,long nn,long s)612   KN_(R *u,long nn,long s):ShapeOfArray(nn,s),v(u){}
KN_(R * u,long nn,long s,long nextt)613   KN_(R *u,long nn,long s,long nextt):ShapeOfArray(nn,s,nextt),v(u){}
KN_(R * u,long nn)614   KN_(R *u,long nn):ShapeOfArray(nn),v(u){}
615 
616 
617   TKN_<R>  t() ; // transpose
618   const TKN_<R>  t() const ; // transpose
619   notKN_<R>  operator!()  ; //  not
620   const  notKN_<R>  operator!() const ; // not
621 
622   //  operator KN<R> &();
623   // operator const KN<R> &() const;
624 
625  private:
626 
operator ++()627   KN_&  operator++(){K_throwassert(next>=0);v += next;return *this;} //    ++U
operator --()628   KN_&  operator--(){K_throwassert(next>=0);v -= next;return *this;} //    --U
operator ++(int)629   KN_   operator++(int ){K_throwassert(next>=0); KN_ old=*this;v = v +next;return old;} // U++
operator --(int)630   KN_   operator--(int ){K_throwassert(next>=0); KN_ old=*this;v = v -next;return old;} // U++
631 
KN_(const KN_<R> & u,long offset)632   KN_(const KN_<R> & u,long offset) :ShapeOfArray(u),v(&u[offset]){}
KN_(const KN_<R> & u,const ShapeOfArray & sh,long startv=0)633   KN_(const KN_<R> & u,const ShapeOfArray &sh,long startv=0)
634          :ShapeOfArray(sh*u.step),v(&u[startv]){}
KN_(const KN_<R> & u,long nnext,const ShapeOfArray & sh,long startv=0)635   KN_(const KN_<R> & u,long nnext,const ShapeOfArray &sh,long startv=0)
636          :ShapeOfArray(sh.n,sh.step*u.step,nnext),v(&u[startv]){ }
637   // Add for gmm++ compatibityly ...................
638   //  iterator end() {return iterator(v,step)
639 
640 
641 // friend class KN_<R>;
642  friend class KNM_<R>;
643  friend class KNMK_<R>;
644  friend class KN<R>;
645  friend class KNM<R>;
646  friend class KNMK<R>;
647 
648 };
649 
650 template<class R>
651 class KNM_: public KN_<R> {
652   public:
653   ShapeOfArray shapei;
654   ShapeOfArray shapej;
655   public:
IsVector1() const656   long IsVector1() const  {  return (shapei.n*shapej.n) ==  this->n ;}
N() const657   long N() const {return shapei.n;}
M() const658   long M() const {return shapej.n;}
size() const659   long size() const { return shapei.n*shapej.n;}
660 
KNM_(R * u,const ShapeOfArray & s,const ShapeOfArray & si,const ShapeOfArray & sj)661   KNM_(R* u,const ShapeOfArray & s,
662             const ShapeOfArray & si,
663             const ShapeOfArray & sj)
664              : KN_<R>(u,s),shapei(si),shapej(sj){}
KNM_(R * u,long n,long m)665   KNM_(R* u,long n,long m)
666              : KN_<R>(u,ShapeOfArray(n*m)),shapei(n,1,n),shapej(m,n,1){}
KNM_(R * u,long n,long m,long s)667   KNM_(R* u,long n,long m,long s)
668              : KN_<R>(u,ShapeOfArray(n*m,s)),shapei(n,1,n),shapej(m,n,1){}
KNM_(KN_<R> u,long n,long m)669   KNM_(KN_<R> u,long n,long m)
670              : KN_<R>(u,ShapeOfArray(m*n)),shapei(n,1,n),shapej(m,n,1){ }
671 
KNM_(const KN_<R> & u,const ShapeOfArray & si,const ShapeOfArray & sj,long offset=0)672   KNM_(const KN_<R> &u,const ShapeOfArray & si,const ShapeOfArray & sj,long offset=0)
673              : KN_<R>(&u[offset],si.last()+sj.last()+1,u.step),shapei(si),shapej(sj)
674              {K_throwassert( offset>=0 && this->n+ (this->v-(R*)u) <= u.n);}
KNM_(const KN_<R> & u,const ShapeOfArray & si,const ShapeOfArray & sj,long offset,long nnext)675   KNM_(const KN_<R> &u,const ShapeOfArray & si,const ShapeOfArray & sj,long offset,long nnext)
676              : KN_<R>(&u[offset],si.last()+sj.last()+1,u.step,nnext),shapei(si),shapej(sj)
677              {K_throwassert( offset>=0 && this->n+ (this->v-(R*)u) <= u.n);}
678 
KNM_(KNM_<R> U,const SubArray & si,const SubArray & sj)679   KNM_(KNM_<R> U,const SubArray & si,const SubArray & sj)
680              :KN_<R>(U,SubArray(U.ij(si.len1(),sj.len1())+1,U.ij(si.start,sj.start))),
681                      shapei(U.shapei,si),shapej(U.shapej,sj){}
682 
KNM_(KNM_<R> U,const SubArray & sa,const SubArray & si,const SubArray & sj)683   KNM_(KNM_<R> U,const SubArray & sa,const SubArray & si,const SubArray & sj)
684              :KN_<R>(U,SubArray(sa)),shapei(U.shapei,si),shapej(U.shapej,sj){}
685 
KNM_(const KNM_<R> & u)686   KNM_(const KNM_<R> & u)
687              :KN_<R>(u),shapei(u.shapei),shapej(u.shapej) {}
688 
operator ()(const SubArray & sa,const SubArray & sb) const689   KNM_ operator()(const SubArray & sa,const SubArray & sb) const
690             { return KNM_(*this,sa,sb);} // sub array
691 
ij(long i,long j) const692   long ij(long i,long j) const
693             { return shapei.index(i)+shapej.index(j);}
indexij(long i,long j) const694   long indexij(long i,long j)        const
695             { return this->index(shapei.index(i)+shapej.index(j));}
operator ()(long i,long j) const696   R & operator()(long i,long j)     const
697             { return this->v[indexij(i,j)];}
operator ()(int i,int j) const698   R & operator()(int i,int j)     const
699             { return this->v[indexij(i,j)];}
700 
701 
operator ()(const char,long j) const702   KN_<R> operator()(const char,long j    )  const   // une colonne j  ('.',j)
703             { return KN_<R>(&this->v[this->index(shapej.index(j))],shapei*this->step);}
operator ()(long i,const char) const704   KN_<R> operator()(long i    ,const char)  const   // une ligne i  (i,'.')
705             { return KN_<R>(&this->v[this->index(shapei.index(i))],shapej*this->step);}
operator ()(const char,int j) const706   KN_<R> operator()(const char,int j    )  const   // une colonne j  ('.',j)
707             { return KN_<R>(&this->v[this->index(shapej.index(j))],shapei*this->step);}
operator ()(int i,const char) const708   KN_<R> operator()(int i    ,const char)  const   // une ligne i  (i,'.')
709             { return KN_<R>(&this->v[this->index(shapei.index(i))],shapej*this->step);}
operator ()(const char,const char) const710   KN_<R> operator()(const char,const char)  const   // tous
711             { return *this;}
t() const712   KNM_<R> t() const
713     { return KNM_<R>(this->v,*this,shapej,shapei);} //  before  { return KNM_<R>(*this,shapej,shapei,v);}
714 
715    KNM_& operator =(const KNM_<const_R> & u) ;
716    KNM_& operator =(const_R a)               ;
717    KNM_& operator+=(const_R a)               ;
718    KNM_& operator-=(const_R a)               ;
719    KNM_& operator/=(const_R a)               ;
720    KNM_& operator*=(const_R a)               ;
721    KNM_& operator+=(const KNM_<const_R> & u) ;
722    KNM_& operator-=(const KNM_<const_R> & u) ;
723    KNM_& operator*=(const KNM_<const_R> & u) ;
724    KNM_& operator/=(const KNM_<const_R> & u) ;
725 
726    KNM_ &operator =(const outProduct_KN_<R> &);
727    KNM_ &operator +=(const outProduct_KN_<R> &);
728    KNM_ &operator -=(const outProduct_KN_<R> &);
729    KNM_ &operator /=(const outProduct_KN_<R> &); // bofbof
730    KNM_ &operator *=(const outProduct_KN_<R> &); // bofbof
731 
732 private:
operator ++()733   KNM_& operator++() {this->v += this->next;return *this;} // ++U
operator --()734   KNM_& operator--() {this->v -= this->next;return *this;} // ++U
operator ++(int)735   KNM_  operator++(int ){KNM_<R> old=*this;this->v = this->v +this->next;return old;} // U++
operator --(int)736   KNM_  operator--(int ){KNM_<R> old=*this;this->v = this->v -this->next;return old;} // U--
737 
738 
739  friend class KN_<R>;
740 // friend class KNM_<R>;
741  friend class KNMK_<R>;
742  friend class KN<R>;
743  friend class KNM<R>;
744  friend class KNMK<R>;
745 };
746 
747 template<class T,class I>
748 struct KN_ITAB
749 {
KN_ITABKN_ITAB750   KN_ITAB(const T &vv,const I &iindex) : v(vv),index(iindex) {}
751   T  v;
752   I  index;
753   KN_ITAB & operator=(const T & t);
754   KN_ITAB & operator+=(const T & t);
755   KN_ITAB & operator-=(const T & t);
756   KN_ITAB & operator*=(const T & t);
757   KN_ITAB & operator/=(const T & t);
operator []KN_ITAB758   typename T::R & operator[](long i){ return v[index[i]];}
operator []KN_ITAB759   const typename T::R &  operator[](long i) const { return v[index[i]];}
NKN_ITAB760   long N() const { return index.N();}
761 };
762 
operator ()(const KN_<int> & itab) const763 template<class R>  KN_ITAB<const KN_<R>,const KN_<int> >  KN_<R>::operator()(const KN_<int>  &itab) const { return KN_ITAB<const KN_<R>,const KN_<int> > (*this,itab);}
operator ()(const KN_<long> & itab) const764 template<class R>  KN_ITAB<const KN_<R>,const KN_<long> >  KN_<R>::operator()(const KN_<long>  &itab) const { return KN_ITAB<const KN_<R>,const KN_<long> > (*this,itab);}
operator ()(const KN_<int> & itab)765 template<class R>  KN_ITAB< KN_<R>,const KN_<int> >  KN_<R>::operator()(const KN_<int>  &itab) { return KN_ITAB<KN_<R>,const KN_<int> > (*this,itab);}
operator ()(const KN_<long> & itab)766 template<class R>  KN_ITAB< KN_<R>,const KN_<long> >  KN_<R>::operator()(const KN_<long>  &itab) { return KN_ITAB<KN_<R>,const KN_<long> > (*this,itab);}
767 
768 
769 template<class R>
770 struct TKN_:public KN_<R> {
TKN_TKN_771     TKN_(const KN_<R> &x) : KN_<R>(x) {}
772 };
773 
774 template<class R>
775 struct notKN_:public KN_<R> {
notKN_notKN_776     notKN_(const KN_<R> &x) : KN_<R>(x) {}
777     notnotKN_<R>  operator!()  ; //  not
778     const  notnotKN_<R>  operator!() const ; // not
779 };
780 
781 template<class R>
782 struct notnotKN_:public KN_<R> {
notnotKN_notnotKN_783     notnotKN_(const notKN_<R> &x) : KN_<R>(x) {}
784     notKN_<R>  operator!()  ; //  notnot
785     const  notKN_<R>  operator!() const ; // notnot
786 };
787 
788 template<class R>
t()789 TKN_<R>  KN_<R>::t() { return *this;} // transpose
790 
791 template<class R>
t() const792 const TKN_<R>  KN_<R>::t() const { return *this;} // transpose
793 
794 template<class R>
operator !()795 notKN_<R>  KN_<R>::operator!() { return *this;} // not
796 
797 template<class R>
operator !() const798 const notKN_<R>  KN_<R>::operator!() const { return *this;} // not
799 
800 template<class R>
operator !()801 notnotKN_<R>  notKN_<R>::operator!() { return *this;} // not
802 
803 template<class R>
operator !() const804 const notnotKN_<R>  notKN_<R>::operator!() const { return *this;} // not
805 
806 
807 template<class R>
808 struct outProduct_KN_ {
809     const KN_<R>  a,b;
810     R c;
NoutProduct_KN_811     long N() const {return a.N();    }
MoutProduct_KN_812     long M() const {return b.N();    }
outProduct_KN_outProduct_KN_813     outProduct_KN_(const KN_<R> & aa, const KN_<R> &bb,R cc=(R)1) : a(aa),b(bb),c(cc) {}
outProduct_KN_outProduct_KN_814     outProduct_KN_(const KN_<R> * aa, const KN_<R> &bb,R cc=(R)1) : a(*aa),b(bb),c(cc) {}
outProduct_KN_outProduct_KN_815     outProduct_KN_(const KN_<R> * aa, const KN_<R> *bb,R cc=(R)1) : a(*aa),b(*bb),c(cc) {}
outProduct_KN_outProduct_KN_816     outProduct_KN_(const Mulc_KN_<R> & aa,const KN_<R> & bb) : a(aa.a),b(bb),c(aa.b) {}
operator *outProduct_KN_817     outProduct_KN_ operator * (R cc) { return outProduct_KN_(a,b,c*cc);}
818 };
819 
820 template<class R>
821 struct if_KN_ {
822     const KN_<R> & a,&b;
823     R c;
if_KN_if_KN_824     if_KN_(const KN_<R> & aa, const KN_<R> &bb,R cc=1.) : a(aa),b(bb),c(cc) {}
operator *if_KN_825     if_KN_ operator * (R cc) { return if_KN_(a,b,c*cc);}
826 };
827 
828 template<class R>
829 struct ifnot_KN_ {
830     const KN_<R> & a,&b;
831     R c;
ifnot_KN_ifnot_KN_832     ifnot_KN_(const KN_<R> & aa, const KN_<R> &bb,R cc=1.) : a(aa),b(bb),c(cc) {}
operator *ifnot_KN_833     ifnot_KN_ operator * (R cc) { return ifnot_KN_(a,b,c*cc);}
834 };
835 
836 
837 template<class R>
operator *(const KN_<R> & a,const TKN_<R> & b)838 outProduct_KN_<R> operator*(const KN_<R> &a,const TKN_<R> &b)
839 { return outProduct_KN_<R>(a,b);}
840 
841 template<class R>
operator *(const KN_<R> & a,const notKN_<R> & b)842 ifnot_KN_<R> operator*(const KN_<R> &a,const notKN_<R> &b)
843 { return ifnot_KN_<R>(b,a);}
844 
845 template<class R>
operator *(const KN_<R> & a,const notnotKN_<R> & b)846 ifnot_KN_<R> operator*(const KN_<R> &a,const notnotKN_<R> &b)
847 { return if_KN_<R>(b,a);}
848 
849 template<class R>
operator *(const notKN_<R> & b,const KN_<R> & a)850 ifnot_KN_<R> operator*(const notKN_<R> &b,const KN_<R> &a)
851 { return ifnot_KN_<R>(b,a);}
852 
853 template<class R>
operator *(const notnotKN_<R> & b,const KN_<R> & a)854 ifnot_KN_<R> operator*(const notnotKN_<R> &b,const KN_<R> & a)
855 { return if_KN_<R>(b,a);}
856 
857 
858 template<class R>
operator *(const TKN_<R> & a,const KN_<R> & b)859 R operator*(const TKN_<R> &a,const KN_<R> &b)
860 { return (a,b);}
861 
862 template<class R>
863 class KNMK_: public KN_<R> {
864   friend class KNMK<R>;
865   public:
866   ShapeOfArray shapei;
867   ShapeOfArray shapej;
868   ShapeOfArray shapek;
869   public:
IsVector1() const870   long IsVector1() const {  return (shapei.n*shapej.n*shapek.n) == this->n ;}
N() const871   long N() const {return shapei.n;}
M() const872   long M() const {return shapej.n;}
K() const873   long K() const {return shapek.n;}
size() const874   long size() const { return shapei.n*shapej.n*shapek.n;}
KNMK_(const ShapeOfArray & s,const ShapeOfArray & si,const ShapeOfArray & sj,const ShapeOfArray & sk,R * u)875   KNMK_(const ShapeOfArray & s,
876         const ShapeOfArray & si,
877         const ShapeOfArray & sj,
878         const ShapeOfArray & sk,
879 	    R * u)
880     : KN_<R>(u,s),shapei(si),shapej(sj),shapek(sk){}
881 
KNMK_(R * u,long n,long m,long k)882   KNMK_(R* u,long n,long m,long k)
883     : KN_<R>(u, ShapeOfArray(n*m*k)),shapei(n,1,n),shapej(m,n,1),shapek(k,n*m,n*m){};
884 
885 //  KNMK_(const KN_<R> & u,long n,long m,long k)
886 //   : KN_<R>(ShapeOfArray(n*m*k)),shapei(n,1,n),shapekj(m,n,1),u),
887 //     shapek(k,n*m,n*m){};
888 
KNMK_(const KNMK_<R> & U,const SubArray & si,const SubArray & sj,const SubArray & sk)889   KNMK_(const KNMK_<R> &U,const SubArray & si,const SubArray & sj,const SubArray & sk)  :
890     KN_<R>(U,SubArray(U.ijk(si.len1(),sj.len1(),sk.len1())+1,
891                        U.ijk(si.start,sj.start,sk.start))),
892                        shapei(U.shapei,si),
893                        shapej(U.shapej,sj),
894                        shapek(U.shapek,sk){}
895 
KNMK_(const KNMK_<R> & u)896   KNMK_(const KNMK_<R> & u) :KN_<R>(u),shapei(u.shapei),shapej(u.shapej),shapek(u.shapek) {}
897 
898 
ijk(long i,long j,long k) const899   long ijk(long i,long j,long k) const
900               { return shapei.index(i)+shapej.index(j)+shapek.index(k);}
indexijk(long i,long j,long k) const901   long indexijk(long i,long j,long k) const
902               {return this->index(shapei.index(i)+shapej.index(j)+shapek.index(k));}
903 
operator ()(long i,long j,long k) const904   R & operator()(long i,long j,long k)   const   {return this->v[indexijk(i,j,k)];}
operator ()(int i,int j,int k) const905   R & operator()(int i,int j,int k)   const   {return this->v[indexijk(i,j,k)];}
906 
907 //  pas de tableau suivant
operator ()(const char,long j,long k) const908  KN_<R>  operator()(const char ,long j,long k)  const  { // le tableau (.,j,k)
909         return KN_<R>(*this,-1,shapei,shapej[j]+shapek[k]);}
operator ()(long i,const char,long k) const910  KN_<R>  operator()(long i,const char ,long k)  const  { // le tableau (i,.,k)
911         return KN_<R>(*this,-1,shapej,shapei[i]+shapek[k]);}
operator ()(long i,long j,const char) const912  KN_<R>  operator()(long i,long j,const char )  const  { // le tableau (i,j,.)
913         return KN_<R>(*this,-1,shapek,shapei[i]+shapej[j]);}
914 
operator ()(const char,int j,int k) const915  KN_<R>  operator()(const char ,int j,int k)  const  { // le tableau (.,j,k)
916         return KN_<R>(*this,-1,shapei,shapej[j]+shapek[k]);}
operator ()(int i,const char,int k) const917  KN_<R>  operator()(int i,const char ,int k)  const  { // le tableau (i,.,k)
918         return KN_<R>(*this,-1,shapej,shapei[i]+shapek[k]);}
operator ()(int i,int j,const char) const919  KN_<R>  operator()(int i,int j,const char )  const  { // le tableau (i,j,.)
920         return KN_<R>(*this,-1,shapek,shapei[i]+shapej[j]);}
921 //
operator ()(const char,const char,long k) const922  KNM_<R>  operator()(const char ,const char ,long k)  const  { // le tableau (.,.,k)
923         return KNM_<R>(*this,shapei,shapej,shapek[k],shapek.next);} // step = n*m
924  //attention les suivants ne marche pas
operator ()(const char,long j,const char) const925  KNM_<R>  operator()(const char ,long j,const char )  const  { // le tableau (.,j,.)
926         return KNM_<R>(*this,shapei,shapek,shapej[j],-1/*shapej.next*/);} // step = n
927 
operator ()(long i,const char,const char) const928  KNM_<R>  operator()(long i,const char ,const char )  const  { // le tableau (i,.,.)
929         return KNM_<R>(*this,shapej,shapek,shapei[i],-1/*shapei.next*/);}  // step = 1
930 
operator ()(const char,const char,int k) const931  KNM_<R>  operator()(const char ,const char ,int k)  const  { // le tableau (.,.,k)
932         return KNM_<R>(*this,shapei,shapej,shapek[k],shapek.next);} // step = n*m
933  //attention les suivants ne marche pas
operator ()(const char,int j,const char) const934  KNM_<R>  operator()(const char ,int j,const char )  const  { // le tableau (.,j,.)
935         return KNM_<R>(*this,shapei,shapek,shapej[j],-1/*shapej.next*/);} // step = n
936 
operator ()(int i,const char,const char) const937  KNM_<R>  operator()(int i,const char ,const char )  const  { // le tableau (i,.,.)
938         return KNM_<R>(*this,shapej,shapek,shapei[i],-1/*shapei.next*/);}  // step = 1
939 
940    KNMK_& operator =(const KNMK_<const_R> & u) ;
941    KNMK_& operator+=(const KNMK_<const_R> & u)  ;
942    KNMK_& operator-=(const KNMK_<const_R> & u)  ;
943    KNMK_& operator/=(const KNMK_<const_R> & u)  ;
944    KNMK_& operator*=(const KNMK_<const_R> & u)  ;
945    KNMK_& operator =(const_R a)  ;
946    KNMK_& operator+=(const_R a)  ;
947    KNMK_& operator-=(const_R a)  ;
948    KNMK_& operator/=(const_R a)  ;
949    KNMK_& operator*=(const_R a)  ;
950 
operator ()(SubArray si,SubArray sj,SubArray sk) const951   KNMK_  operator()(SubArray si,SubArray sj,SubArray sk) const
952         {return KNMK_(*this,si,sj,sk);}
953 
954   private:
955 //  KNMK_&  operator++(){v += next;return *this;} // ++U
956 //  KNMK_&  operator--(){v -= next;return *this;} // --U
957 //  KNMK_  operator++(long ){KNMK_ old=*this;v = v +next;return old;} // U++
958 //  KNMK_  operator--(long ){KNMK_ old=*this;v = v -next;return old;} // U--
959 
960 
961 friend class KNM_<R>;
962 friend class KN_<R>;
963 
964 };
965 
966 
967 
968 template<class R>
969 class KN :public KN_<R> { public:
970 
971   typedef R K;
972 
973  // explicit  KN(const R & u):KN_<R>(new R(uu),1,0) {}
KN()974   KN() : KN_<R>(0,0) {}
KN(long nn)975   KN(long nn) : KN_<R>(new R[nn],nn)         {}
KN(long nn,R * p)976   KN(long nn, R * p) : KN_<R>(new R[nn],nn)
977     { KN_<R>::operator=(KN_<R>(p,nn));}
KN(long nn,R (* f)(long i))978   KN(long nn,R (*f)(long i) ) : KN_<R>(new R[nn],nn)
979         {for(long i=0;i<this->n;i++) this->v[i]=f(i);}
KN(long nn,const R & a)980   KN(long nn,const  R & a) : KN_<R>(new R[nn],nn)
981         { KN_<R>::operator=(a);}
KN(long nn,long s,const R a)982   KN(long nn,long s,const  R  a) : KN_<R>(new R[nn],nn,s)
983         { KN_<R>::operator=(a);}
KN(const KN_<S> & s)984   template<class S>   KN(const KN_<S> & s):KN_<R>(new R[s.n],s.n)
985         {for (long i=0;i<this->n;i++) this->v[i] = s[i];}
KN(const KN_<S> & s,R (* f)(S))986   template<class S>  KN(const KN_<S> & s,R (*f)(S )):KN_<R>(new R[s.n],s.n)
987         {for (long i=0;i<this->n;i++) this->v[i] = f(s[i]);}
KN(const KN<R> & u)988   KN(const KN<R> & u):KN_<R>(new R[u.n],u.n)
989         { KN_<R>::operator=(u);}
KN(bool,KN<R> & u)990   KN(bool ,KN<R> & u):KN_<R>(u) {u.v=0;u.n=0;}// remove copy for return of local KN.
991 
992   //  explicit KN(const KN_<R> & u):KN_<R>(new R[u.n],u.n)
993   //      { KN_<R>::operator=(u);}
994 
~KN()995   ~KN(){delete [] this->v;}
996 
CheckSet()997   void CheckSet() { if(!(this->n)) {cerr << "Error RNM set array\n";K_throwassert(0); exit(1);}}
operator =(R * a)998    KN& operator  = (R*  a) { CheckSet(); return operator =(KN_<R>(a,this->n));}
operator +=(R * a)999    KN& operator += (R*  a) { CheckSet(); return operator+=(KN_<R>(a,this->n));}
operator -=(R * a)1000    KN& operator -= (R*  a) { CheckSet(); return operator-=(KN_<R>(a,this->n));}
operator *=(R * a)1001    KN& operator *= (R*  a) { CheckSet(); return operator*=(KN_<R>(a,this->n));}
operator /=(R * a)1002    KN& operator /= (R*  a) { CheckSet(); return operator/=(KN_<R>(a,this->n));}
1003 
operator =(const SetArray<R> & u)1004    KN& operator  =(const SetArray<R> & u)
1005      { if(this->unset())
1006 	 this->set(new R[u.size()],u.size(),0,0);
1007        KN_<R>::operator= (u);
1008        return *this;}
operator +=(const SetArray<R> & u)1009    KN& operator +=(const SetArray<R> & u)
1010      { if(this->unset())
1011 	 this->set(new R[u.size()],u.size(),0,0);
1012        KN_<R>::operator+= (u);
1013        return *this;}
operator -=(const SetArray<R> & u)1014    KN& operator -=(const SetArray<R> & u)
1015      { if(this->unset())  this->set(new R[u.size()],u.size(),0,0); KN_<R>::operator-= (u);return *this;}
operator *=(const SetArray<R> & u)1016    KN& operator *=(const SetArray<R> & u)
1017      { if(this->unset())  this->set(new R[u.size()],u.size(),0,0); KN_<R>::operator*= (u);return *this;}
operator /=(const SetArray<R> & u)1018    KN& operator /=(const SetArray<R> & u)
1019      { if(this->unset())  this->set(new R[u.size()],u.size(),0,0); KN_<R>::operator/= (u);return *this;}
1020 
operator =(const_R a)1021    KN& operator =(const_R a)
1022         { if(this->unset()) this->set(new R[1],1,0,0); KN_<R>::operator= (a);return *this;}
operator =(const KN_<R> & a)1023    KN& operator =(const KN_<R>& a)
1024         { if(this->unset())  this->set(new R[a.N()],a.N()); KN_<R>::operator= (a);return *this;}
operator =(const KN<R> & a)1025    KN& operator =(const KN<R>& a)
1026         { if(this->unset()) this->set(new R[a.N()],a.N()); KN_<R>::operator= (a);return *this;}
operator =(const Add_KN_<R> & u)1027    KN& operator =(const Add_KN_<R> & u)
1028         { if(this->unset())  this->set(new R[u.a.N()],u.a.N());KN_<R>::operator=(u);return *this;}
operator =(const DotStar_KN_<R> & u)1029    KN& operator =(const DotStar_KN_<R> & u)
1030         { if(this->unset())  this->set(new R[u.a.N()],u.a.N());KN_<R>::operator=(u);return *this;}
operator =(const if_KN_<R> & u)1031    KN& operator =(const if_KN_<R> & u)
1032         { if(this->unset())  this->set(new R[u.a.N()],u.a.N());KN_<R>::operator=(u);return *this;}
operator =(const ifnot_KN_<R> & u)1033    KN& operator =(const ifnot_KN_<R> & u)
1034         { if(this->unset())  this->set(new R[u.a.N()],u.a.N());KN_<R>::operator=(u);return *this;}
operator =(const DotSlash_KN_<R> & u)1035    KN& operator =(const DotSlash_KN_<R> & u)
1036         { if(this->unset())  this->set(new R[u.a.N()],u.a.N());KN_<R>::operator=(u);return *this;}
operator =(const Sub_KN_<R> & u)1037    KN& operator =(const Sub_KN_<R> & u)
1038         { if(this->unset())  this->set(new R[u.a.N()],u.a.N());KN_<R>::operator=(u);return *this;}
operator =(const Mulc_KN_<R> & u)1039    KN& operator =(const Mulc_KN_<R> & u)
1040         { if(this->unset())  this->set(new R[u.a.N()],u.a.N());KN_<R>::operator=(u);return *this;}
operator =(const Add_Mulc_KN_<R> & u)1041    KN& operator =(const Add_Mulc_KN_<R> & u)
1042         { if(this->unset())  this->set(new R[u.a.N()],u.a.N());KN_<R>::operator=(u);return *this;}
operator =(const if_arth_KN_<R> & u)1043    KN& operator =(const if_arth_KN_<R> & u)
1044         { if(this->unset())  this->set(new R[u.a.N()],u.a.N());KN_<R>::operator=(u);return *this;}
1045 
1046 
operator =(const Mul_KNM_KN_<R> & u)1047    KN& operator =(const Mul_KNM_KN_<R> & u)
1048         { if(this->unset())  this->set(new R[u.b.N()],u.b.N());KN_<R>::operator=(u);return *this;}
1049 //   KN& operator =(const MatriceCreuseMulKN_<R> & Ax)
1050 //       {if(this->unset())  this->set(new R[Ax.v.N()],Ax.v.N()); KN_<R>::operator=(Ax);return *this;}
1051 //   KN& operator +=(const MatriceCreuseMulKN_<R> & Ax)
1052 //       {if(this->unset())  this->set(new R[Ax.v.N()],Ax.v.N()); KN_<R>::operator+=(Ax);return *this;}
1053 //   KN& operator =(const MatriceCreuseDivKN_<R> & A1x)
1054 //       { if(this->unset())  this->set(new R[A1x.v.N()],A1x.v.N());KN_<R>::operator=(A1x);return *this;}
1055   // correcton aout 2007 FH  add N,M flied in VirtualMatrice
operator =(const typename VirtualMatrice<R>::plusAx & Ax)1056    KN& operator =(const typename VirtualMatrice<R>::plusAx & Ax)
1057         { if(this->unset() && Ax.A->N )  this->set(new R[Ax.A->N],Ax.A->N);KN_<R>::operator=(Ax);return *this;}
operator =(const typename VirtualMatrice<R>::solveAxeqb & Ab)1058    KN& operator =(const typename VirtualMatrice<R>::solveAxeqb & Ab)
1059         { if(this->unset())  this->set(new R[Ab.b.N()],Ab.b.N());KN_<R>::operator=(Ab);return *this;}
operator +=(const typename VirtualMatrice<R>::plusAx & Ax)1060    KN& operator +=(const typename  VirtualMatrice<R>::plusAx & Ax)
1061   { if(this->unset()  && Ax.A->N) {
1062          this->set(new R[Ax.A->N],Ax.A->N);
1063         KN_<R>::operator=(R());}
1064     KN_<R>::operator+=(Ax);
1065     return *this;}
operator =(const typename VirtualMatrice<R>::plusAtx & Ax)1066    KN& operator =(const typename VirtualMatrice<R>::plusAtx & Ax)
1067         { if(this->unset()&&Ax.A->M)  this->set(new R[Ax.A->M],Ax.A->M);KN_<R>::operator=(Ax);return *this;}
operator +=(const typename VirtualMatrice<R>::plusAtx & Ax)1068    KN& operator +=(const typename VirtualMatrice<R>::plusAtx & Ax)
1069   { if(this->unset()&&Ax.A->M) {
1070         this->set(new R[Ax.A->M],Ax.A->M);
1071       KN_<R>::operator=(R());}
1072       KN_<R>::operator+=(Ax);
1073      return *this;}
1074 // end correcton FH
1075    template<class P,class Q>
operator =(const PplusQ<P,Q> & PQ)1076      KN& operator =(const  PplusQ<P,Q> & PQ)
1077       { *this=PQ.p; *this+=PQ.q;return *this; }
1078    template<class P,class Q>
operator +=(const PplusQ<P,Q> & PQ)1079      KN& operator +=(const  PplusQ<P,Q> & PQ)
1080       { *this+=PQ.p; *this+=PQ.q;return *this; }
1081 
operator -=(const_R a)1082    KN& operator -=(const_R a)
1083         { KN_<R>::operator-=(a);return *this;}
operator -=(const KN_<R> & a)1084    KN& operator -=(const KN_<R>& a)
1085         { KN_<R>::operator-= (a);return *this;}
operator -=(const Add_KN_<R> & u)1086    KN& operator -=(const Add_KN_<R> & u)
1087         { KN_<R>::operator-=(u);return *this;}
operator -=(const DotStar_KN_<R> & u)1088    KN& operator -=(const DotStar_KN_<R> & u)
1089         { KN_<R>::operator-=(u);return *this;}
operator -=(const DotSlash_KN_<R> & u)1090    KN& operator -=(const DotSlash_KN_<R> & u)
1091         { KN_<R>::operator-=(u);return *this;}
operator -=(const Sub_KN_<R> & u)1092    KN& operator -=(const Sub_KN_<R> & u)
1093         { KN_<R>::operator-=(u);return *this;}
operator -=(const Mulc_KN_<R> & u)1094    KN& operator -=(const Mulc_KN_<R> & u)
1095         { KN_<R>::operator-=(u);return *this;}
operator -=(const Add_Mulc_KN_<R> & u)1096    KN& operator -=(const Add_Mulc_KN_<R> & u)
1097         { KN_<R>::operator-=(u);return *this;}
operator -=(const if_arth_KN_<R> & u)1098    KN& operator -=(const if_arth_KN_<R> & u)
1099         { KN_<R>::operator-=(u);return *this;}
operator -=(const Mul_KNM_KN_<R> & u)1100    KN& operator -=(const Mul_KNM_KN_<R> & u)
1101         { KN_<R>::operator-=(u);return *this;}
1102 
operator +=(const_R a)1103    KN& operator +=(const_R a)
1104         { KN_<R>::operator += (a);return *this;}
operator +=(const KN_<R> & a)1105    KN& operator += (const KN_<R>& a)
1106         { KN_<R>::operator+= (a);return *this;}
operator +=(const Add_KN_<R> & u)1107    KN& operator +=(const Add_KN_<R> & u)
1108         { KN_<R>::operator+=(u);return *this;}
operator +=(const DotStar_KN_<R> & u)1109    KN& operator +=(const DotStar_KN_<R> & u)
1110         { KN_<R>::operator+=(u);return *this;}
operator +=(const DotSlash_KN_<R> & u)1111    KN& operator +=(const DotSlash_KN_<R> & u)
1112         { KN_<R>::operator+=(u);return *this;}
operator +=(const Sub_KN_<R> & u)1113    KN& operator +=(const Sub_KN_<R> & u)
1114         { KN_<R>::operator+=(u);return *this;}
operator +=(const Mulc_KN_<R> & u)1115    KN& operator +=(const Mulc_KN_<R> & u)
1116         { KN_<R>::operator+=(u);return *this;}
operator +=(const Add_Mulc_KN_<R> & u)1117    KN& operator +=(const Add_Mulc_KN_<R> & u)
1118         { KN_<R>::operator+=(u);return *this;}
operator +=(const if_arth_KN_<R> & u)1119    KN& operator +=(const if_arth_KN_<R> & u)
1120         { KN_<R>::operator+=(u);return *this;}
operator +=(const Mul_KNM_KN_<R> & u)1121    KN& operator +=(const Mul_KNM_KN_<R> & u)
1122         { KN_<R>::operator+=(u);return *this;}
1123 
1124 
operator /=(const_R a)1125    KN& operator/=(const_R a)
1126         { KN_<R>::operator/=(a);return *this;}
operator /=(const KN_<R> & a)1127    KN& operator /= (const KN_<R>& a)
1128         { KN_<R>::operator/= (a);return *this;}
operator /=(const Add_KN_<R> & u)1129    KN& operator /=(const Add_KN_<R> & u)
1130         { KN_<R>::operator/=(u);return *this;}
operator /=(const Sub_KN_<R> & u)1131    KN& operator /=(const Sub_KN_<R> & u)
1132         { KN_<R>::operator/=(u);return *this;}
operator /=(const Mulc_KN_<R> & u)1133    KN& operator /=(const Mulc_KN_<R> & u)
1134         { KN_<R>::operator/=(u);return *this;}
operator /=(const Add_Mulc_KN_<R> & u)1135    KN& operator /=(const Add_Mulc_KN_<R> & u)
1136         { KN_<R>::operator/=(u);return *this;}
operator /=(const if_arth_KN_<R> & u)1137    KN& operator /=(const if_arth_KN_<R> & u)
1138         { KN_<R>::operator/=(u);return *this;}
1139 
operator /=(const Mul_KNM_KN_<R> & u)1140    KN& operator /=(const Mul_KNM_KN_<R> & u)
1141         { KN_<R>::operator/=(u);return *this;}
1142 
operator *=(const_R a)1143    KN& operator*=(const_R a)
1144         { KN_<R>::operator*=(a);return *this;}
operator *=(const KN_<const_R> & a)1145    KN& operator*=(const KN_<const_R>& a)
1146         { KN_<R>::operator*= (a);return *this;}
operator *=(const Add_KN_<R> & u)1147    KN& operator *=(const Add_KN_<R> & u)
1148         { KN_<R>::operator*=(u);return *this;}
operator *=(const Sub_KN_<R> & u)1149    KN& operator *=(const Sub_KN_<R> & u)
1150         { KN_<R>::operator*=(u);return *this;}
operator *=(const Mulc_KN_<R> & u)1151    KN& operator *=(const Mulc_KN_<R> & u)
1152         { KN_<R>::operator*=(u);return *this;}
operator *=(const Add_Mulc_KN_<R> & u)1153    KN& operator *=(const Add_Mulc_KN_<R> & u)
1154         { KN_<R>::operator*=(u);return *this;}
operator *=(const if_arth_KN_<R> & u)1155    KN& operator *=(const if_arth_KN_<R> & u)
1156         { KN_<R>::operator*=(u);return *this;}
operator *=(const Mul_KNM_KN_<R> & u)1157    KN& operator *=(const Mul_KNM_KN_<R> & u)
1158         { KN_<R>::operator*=(u);return *this;}
1159 
1160 
operator =(const KN_ITAB<T,I> & ui)1161   template<class I,class T> KN& operator =   (const KN_ITAB<T ,I> & ui)
1162      {  KN_<R>::operator =(ui);  return *this;}
operator +=(const KN_ITAB<T,I> & ui)1163   template<class I,class T> KN& operator +=   (const KN_ITAB<T ,I> & ui)
1164      {  KN_<R>::operator +=(ui);  return *this;}
operator -=(const KN_ITAB<T,I> & ui)1165   template<class I,class T> KN& operator -=   (const KN_ITAB<T ,I> & ui)
1166      {  KN_<R>::operator -=(ui);  return *this;}
operator *=(const KN_ITAB<T,I> & ui)1167   template<class I,class T> KN& operator *=   (const KN_ITAB<T ,I> & ui)
1168      {  KN_<R>::operator *=(ui);  return *this;}
operator /=(const KN_ITAB<T,I> & ui)1169   template<class I,class T> KN& operator /=   (const KN_ITAB<T ,I> & ui)
1170      {  KN_<R>::operator /=(ui);  return *this;}
1171 
1172 
1173   //  two opertor to cast to an array of constant
1174 //    operator KN_<const_R> & ()
1175 //          { return *  (KN_<const_R>*) this;}
1176 //    operator KN_<const_R> const & ()  const
1177 //          { return *(const KN_<const_R>*) this;}
1178 //    operator KN<const_R> & ()
1179 //          { return   (KN<const_R> &) *this;}
1180 //    operator KN<const_R> const & ()  const
1181 //          { return (const KN<const_R>& ) *this;}
init(long nn)1182   void init(long nn) {this->n=nn;this->step=1;this->next=-1;this->v=new R[nn];}
init()1183   void init() {this->n=0;this->step=1;this->next=-1;this->v=0;}
init(const KN_<R> & a)1184   void init(const KN_<R> & a){init(a.N()); operator=(a);}
resize(long nn)1185   void resize(long nn) {
1186     if ( nn != this->n)
1187      {
1188        R *vo=this->v;
1189        long no=std::min(this->n,nn), so=this->step;
1190        ShapeOfArray::init(nn);
1191        this->v=new R[this->n];
1192        // copy
1193        if(this->v && vo)
1194          for(long i=0,j=0;j<no;i++,j+=so)
1195            this->v[i]=vo[j];
1196         delete [] vo;} }//  mars 2010
destroy()1197     void destroy(){ if(this->next++ ==-1) {delete [] this->v; this->v=0;this->n=0;}}//  mars 2010
increment()1198     void increment() { this->next--;}
1199 };
1200 
1201 //  Array with 2 indices
1202 //  ---------------------
1203 
1204 template<class R>
1205 class KNM: public KNM_<R>{ public:
1206 
KNM(long nn,long mm)1207   KNM(long nn,long mm)
1208         :KNM_<R>(new R[nn*mm],nn,mm){}
KNM(const KNM<R> & u)1209    KNM(const KNM<R> & u)  // PB si stepi ou stepj nulle
1210         :KNM_<R>(new R[u.size()],u.N(),u.M())
1211        { KN_<R>::operator=(u);}
KNM(const KNM_<R> & u)1212   explicit KNM(const KNM_<R> & u)
1213         :KNM_<R>(new R[u.size()],u.N(),u.M())
1214         { KNM_<R>::operator=(u);}
1215 
~KNM()1216   ~KNM(){delete [] this->v;}
1217 
operator =(const KNM_<const_R> & u)1218    KNM& operator=(const KNM_<const_R> & u)
1219     { if(this->unset()) this->init(u.N(),u.M()) ; KNM_<R>::operator=(u);return *this;}
operator =(const_R a)1220    KNM& operator=(const_R a)
1221     { if(this->unset()) RNM_FATAL_ERROR(" KNM operator=(double)"); KNM_<R>::operator=(a);return *this;}
operator +=(const_R a)1222    KNM& operator+=(const_R  a)
1223         { if(this->unset()) RNM_FATAL_ERROR(" KNM operator+=(double)"); KNM_<R>::operator+=(a);return *this;}
operator -=(const_R a)1224    KNM& operator-=(const_R  a)
1225         {if(this->unset()) RNM_FATAL_ERROR(" KNM operator-=(double)"); KNM_<R>::operator-=(a);return *this;}
operator /=(const_R a)1226    KNM& operator/=(const_R  a)
1227         {if(this->unset()) RNM_FATAL_ERROR(" KNM operator/=(double)"); KNM_<R>::operator/=(a);return *this;}
operator *=(const_R a)1228    KNM& operator*=(const_R  a)
1229         {if(this->unset()) RNM_FATAL_ERROR(" KNM operator*=(double)"); KNM_<R>::operator*=(a);return *this;}
operator +=(const KNM_<const_R> & u)1230    KNM& operator+=(const KNM_<const_R> & u)
1231         { if(this->unset()) this->init(u.N(),u.M()) ; KNM_<R>::operator+=(u);return *this;}
operator -=(const KNM_<const_R> & u)1232    KNM& operator-=(const KNM_<const_R> & u)
1233         {  if(this->unset()) this->init(u.N(),u.M()) ;KNM_<R>::operator-=(u);return *this;}
1234 
operator /=(const KNM_<const_R> & u)1235    KNM& operator/=(const KNM_<const_R> & u)
1236         {  if(this->unset()) this->init(u.N(),u.M()) ;KNM_<R>::operator/=(u);return *this;}
operator *=(const KNM_<const_R> & u)1237    KNM& operator*=(const KNM_<const_R> & u)
1238         { if(this->unset()) this->init(u.N(),u.M()) ; KNM_<R>::operator*=(u);return *this;}
1239 
1240 
operator =(const outProduct_KN_<R> & u)1241    KNM &operator  =(const outProduct_KN_<R> & u)
1242         { if(this->unset()) this->init(u.N(),u.M()) ; KNM_<R>::operator =(u);return *this;}
operator +=(const outProduct_KN_<R> & u)1243    KNM &operator +=(const outProduct_KN_<R> & u)
1244         { if(this->unset()) this->init(u.N(),u.M()) ; KNM_<R>::operator+=(u);return *this;}
operator -=(const outProduct_KN_<R> & u)1245    KNM &operator -=(const outProduct_KN_<R> & u)
1246         { if(this->unset()) this->init(u.N(),u.M()) ; KNM_<R>::operator-=(u);return *this;}
operator /=(const outProduct_KN_<R> & u)1247    KNM &operator /=(const outProduct_KN_<R> & u)
1248         {  if(this->unset()) this->init(u.N(),u.M()) ;KNM_<R>::operator/=(u);return *this;}
operator *=(const outProduct_KN_<R> & u)1249    KNM &operator *=(const outProduct_KN_<R> & u)
1250         {  if(this->unset()) this->init(u.N(),u.M()) ;KNM_<R>::operator*=(u);return *this;}
1251 
1252 
1253   //  two opertors to cast to un array of constant
1254 //    operator KNM_<const_R> & ()
1255 //          { return *  (KNM_<const_R>*) this;}
1256 //    operator KNM_<const_R> const & ()  const
1257 //          { return *(const KNM_<const_R>*) this;}
1258 
1259 //    operator KNM<const_R> & ()
1260 //          { return *  (KNM<const_R>*) this;}
1261 //    operator KNM<const_R> const & ()  const
1262 //          { return *(const KNM<const_R>*) this;}
1263 
init()1264     void init() { //  add mars 2010 ...
1265 	this->n=0;this->step=1;this->next=-1;this->v=0;
1266 	this->shapei.init(0);
1267 	this->shapej.init(0);}
1268 
init(long nn,long mm)1269   void init(long nn,long mm) {
1270     ShapeOfArray::init(nn*mm);
1271     this->shapei.init(nn,1,nn);
1272     this->shapej.init(mm,nn,1),
1273     this->v=new R[nn*mm];}
1274 
resize(long nn,long mm)1275   void resize(long nn,long mm) {
1276     long kk=nn*mm;
1277 
1278     long lso = this->size();
1279     long n = this->shapei.n;
1280     long m = this->shapej.n;
1281 
1282     if( n !=nn && m != mm)
1283      {
1284     KNM_ <R> old(*this);
1285     long no=std::min(n,nn);
1286     long mo=std::min(m,mm);
1287     R *vo=this->v;
1288 
1289     // new mat
1290     ShapeOfArray::init(kk);
1291     this->v=new R[this->n];
1292     this->shapei.init(nn,1,nn);
1293     this->shapej.init(mm,nn,1);
1294 
1295     if(this->v && vo)  // copy
1296         (*this)(SubArray(no),SubArray(mo)) = old(SubArray(no),SubArray(mo));
1297 
1298     delete []vo;
1299     }
1300 
1301    }
destroy()1302     void destroy(){ if(this->next++ ==-1) {delete [] this->v; this->v=0;this->n=0;}}
increment()1303     void increment() {  this->next--;}
1304 
1305 //  void destroy(){delete [] this->v;this->n=0 ;}
1306 
1307 };
1308 
1309 //  Array with 3 indices
1310 //  ---------------------
1311 template<class R>
1312 class KNMK: public KNMK_<R>{ public:
1313 
KNMK(long n,long m,long k)1314   KNMK(long n,long m,long k)
1315      :KNMK_<R>(new R[n*m*k],n,m,k){}
KNMK(const KNMK_<R> & u)1316   explicit KNMK(const KNMK_<R> & u)
1317      :KNMK_<R>(new R[u.size()],u.N(),u.M(),u.K())
1318      { KNMK_<R>::operator=(u);}
KNMK(const KNMK<R> & u)1319    KNMK(const KNMK<R> & u)
1320      :KNMK_<R>(new R[u.size()],u.N(),u.M(),u.K())
1321      { KNMK_<R>::operator=(u);}
1322 
~KNMK()1323   ~KNMK(){delete [] this->v;}
1324 
operator =(const KNMK_<const_R> & u)1325   KNMK& operator=(const KNMK_<const_R> & u)
1326      { KNMK_<R>::operator=(u);return *this;}
operator =(const_R a)1327   KNMK& operator=(const_R a)
1328      { KNMK_<R>::operator=(a);return *this;}
operator +=(const_R a)1329   KNMK& operator+=(const_R  a)
1330      { KNMK_<R>::operator+=(a);return *this;}
operator -=(const_R a)1331   KNMK& operator-=(const_R  a)
1332      { KNMK_<R>::operator-=(a);return *this;}
operator /=(const_R a)1333   KNMK& operator/=(const_R  a)
1334      { KNMK_<R>::operator/=(a);return *this;}
operator *=(const_R a)1335   KNMK& operator*=(const_R  a)
1336      { KNMK_<R>::operator*=(a);return *this;}
operator +=(const KNMK_<const_R> & u)1337   KNMK& operator+=(const KNMK_<const_R> & u)
1338      { KNMK_<R>::operator+=(u);return *this;}
1339   // ici jd
operator -=(const KNMK_<const_R> & u)1340   KNMK& operator-=(const KNMK_<const_R> & u)
1341      { KNMK_<R>::operator-=(u);return *this;}
operator *=(const KNMK_<const_R> & u)1342   KNMK& operator*=(const KNMK_<const_R> & u)
1343      { KNMK_<R>::operator*=(u);return *this;}
operator /=(const KNMK_<const_R> & u)1344   KNMK& operator/=(const KNMK_<const_R> & u)
1345      { KNMK_<R>::operator/=(u);return *this;}
1346 
1347 //  two opertor to cast to un array of constant
1348 //    operator KNMK_<const_R> & ()
1349 //       { return *  (KNMK_<const_R>*) this;}
1350 //    operator KNMK_<const_R> const & ()  const
1351 //       { return *(const KNMK_<const_R>*) this;}
1352 
1353 //    operator KNMK<const_R> & ()
1354 //       { return *  (KNMK<const_R>*) this;}
1355 //    operator KNMK<const_R> const & ()  const
1356 //       { return *(const KNMK<const_R>*) this;}
1357 };
1358 
1359 //  -------------  optimization ---------------------
1360 template<class R>
1361 class conj_KN_{public:
1362   const KN_<const_R> & a;
conj_KN_(const KN_<const_R> & aa)1363   conj_KN_(const KN_<const_R> & aa) : a(aa){}
1364 };
1365 
1366 
conj(const KN_<long> & a)1367 inline const KN_<long> conj(const KN_<long> &a){ return a;}
conj(const KN_<double> & a)1368 inline const KN_<double> conj(const KN_<double> &a){ return a;}
conj(const KN_<float> & a)1369 inline const KN_<float> conj(const KN_<float> &a){ return a;}
1370 
1371 //template<class R> conj_KN_<R> conj(const KN<R> &a){ return a;}
conj(const KN_<R> & a)1372 template<class R> conj_KN_<R> conj(const KN_<R> &a){ return a;}
1373 
1374 template<class R>
1375 class DotStar_KN_{public:
1376   const KN_<const_R>  a; const KN_<const_R>  b;
DotStar_KN_(const KN_<const_R> & aa,const KN_<const_R> & bb)1377   DotStar_KN_(const KN_<const_R> & aa,const KN_<const_R> & bb) : a(aa),b(bb)  {}
1378  };
1379 
1380 
1381 template<class R>
1382 class DotSlash_KN_{public:
1383   const KN_<const_R>  a; const KN_<const_R>  b;
DotSlash_KN_(const KN_<const_R> & aa,const KN_<const_R> & bb)1384   DotSlash_KN_(const KN_<const_R> & aa,const KN_<const_R> & bb) : a(aa),b(bb)  {}
1385  };
1386 
1387 template<class R>
1388 class Add_KN_{public:
1389   const KN_<const_R>  a; const KN_<const_R>  b;
Add_KN_(const KN_<const_R> & aa,const KN_<const_R> & bb)1390   Add_KN_(const KN_<const_R> & aa,const KN_<const_R> & bb)
1391      : a(aa),b(bb)  { K_throwassert(SameShape(a,b));}
1392  };
1393 
1394 template<class R>
1395 class Sub_KN_{public:
1396   const KN_<const_R>  a; const KN_<const_R>  b;
Sub_KN_(const KN_<const_R> & aa,const KN_<const_R> & bb)1397   Sub_KN_(const KN_<const_R> & aa,const KN_<const_R> & bb)
1398     : a(aa),b(bb) { K_throwassert(SameShape(a,b));}
1399  };
1400 
1401 template<class R>
1402 class Mulc_KN_ { public:
1403   const KN_<const_R>  a;  const_R  b;
Mulc_KN_(const KN_<const_R> & aa,const_R bb)1404   Mulc_KN_(const KN_<const_R> & aa,const_R  bb) : a(aa),b(bb) {}
Mulc_KN_(const Mulc_KN_<R> & aa,const_R bb)1405   Mulc_KN_(const Mulc_KN_<R> & aa,const_R  bb) : a(aa.a),b(aa.b*bb) {}
operator -() const1406   Mulc_KN_ operator-() const {return Mulc_KN_(a,-b);}
operator *(const TKN_<double> & bb)1407   outProduct_KN_<R> operator*(const  TKN_<double> & bb)
1408 {  return outProduct_KN_<R>(a,bb,b);}
1409 
1410  };
1411 
1412 template<class R>
1413 class Add_Mulc_KN_ { public:
1414   const KN_<const_R> a,b;
1415   const R ca,cb;
Add_Mulc_KN_(const Mulc_KN_<R> & aa,const Mulc_KN_<R> & bb)1416   Add_Mulc_KN_(const Mulc_KN_<R> & aa,const Mulc_KN_<R> & bb)
1417         : a(aa.a),b(bb.a),ca(aa.b),cb(bb.b) { K_throwassert(SameShape(a,b));}
Add_Mulc_KN_(const Mulc_KN_<R> & aa,const KN_<const_R> & bb,const R cbb)1418   Add_Mulc_KN_(const Mulc_KN_<R> & aa,const KN_<const_R> & bb,const R cbb)
1419         : a(aa.a),b(bb),ca(aa.b),cb(cbb)  { K_throwassert(SameShape(a,b));}
Add_Mulc_KN_(const KN_<const_R> & aa,const R caa,const KN_<const_R> & bb,const R cbb)1420   Add_Mulc_KN_(const KN_<const_R> & aa,const R caa,const KN_<const_R> & bb,const R cbb)
1421         : a(aa),b(bb),ca(caa),cb(cbb) { K_throwassert(SameShape(a,b));}
1422  };
1423 
1424 template<class R>
1425 class if_arth_KN_ { public:
1426   const KN_<const_R> a,b,c;
if_arth_KN_(const KN_<R> & aa,const KN_<R> & bb,const KN_<R> & cc)1427   if_arth_KN_(const KN_<R> & aa,const KN_<R> & bb,const KN_<R> & cc)
1428         : a(aa),b(bb),c(cc){ K_throwassert(SameShape(a,b)&&SameShape(a,c));}
1429  };
1430 
1431 
1432 
1433 template<class R>
1434 class Mul_KNM_KN_ { public:
1435   const KNM_<const_R> &A;
1436   const KN_<const_R> &b;
Mul_KNM_KN_(const KNM_<const_R> & aa,const KN_<const_R> & bb)1437   Mul_KNM_KN_(const  KNM_<const_R>  &aa,const KN_<const_R>  &bb)
1438         : A(aa),b(bb) {K_throwassert(SameShape(A.shapej,b));}
1439 };
1440 
1441 
1442 ostream & operator<<(ostream & f,const ShapeOfArray & s);
1443 
1444 template<class R> ostream & operator<<(ostream & f,const KN_<const_R>   & v);
1445 template<class R> ostream & operator<<(ostream & f,const KNM_<const_R>  & v);
1446 template<class R> ostream & operator<<(ostream & f,const KNMK_<const_R> & v);
operator <<(ostream & f,const KN<const_R> & v)1447 template<class R> inline ostream & operator<<(ostream & f,const KN<const_R>   & v)
1448     { return f << (const KN_<const_R> &) v;}
operator <<(ostream & f,const KNM<const_R> & v)1449 template<class R> inline ostream & operator<<(ostream & f,const KNM<const_R>  & v)
1450     { return f << (const KNM_<const_R> &) v;}
operator <<(ostream & f,const KNMK<const_R> & v)1451 template<class R> inline ostream & operator<<(ostream & f,const KNMK<const_R> & v)
1452     { return f << (const KNMK_<const_R> &) v;}
1453 
1454 
operator +(const KN_<const_R> & a,const KN_<const_R> & b)1455 template<class R> inline Add_KN_<R> operator+(const KN_<const_R> &a,const KN_<const_R> &b)
1456     { return Add_KN_<R>(a,b);}
operator -(const KN_<const_R> & a,const KN_<const_R> & b)1457 template<class R> inline Sub_KN_<R> operator-(const KN_<const_R> &a,const KN_<const_R> &b)
1458     { return Sub_KN_<R>(a,b);}
operator *(const KN_<const_R> & a,const R & b)1459 template<class R> inline Mulc_KN_<R> operator*(const KN_<const_R> &a,const R &b)
1460     { return Mulc_KN_<R>(a,b);}
operator /(const KN_<const_R> & a,const R & b)1461 template<class R> inline Mulc_KN_<R> operator/(const KN_<const_R> &a,const R &b)
1462     { return Mulc_KN_<R>(a,1/b);}
operator *(const R & b,const KN_<const_R> & a)1463 template<class R> inline Mulc_KN_<R> operator*(const R &b,const KN_<const_R> &a)
1464     { return Mulc_KN_<R>(a,b);}
operator -(const KN_<const_R> & a)1465 template<class R> inline Mulc_KN_<R> operator-(const KN_<const_R> &a)
1466     { return Mulc_KN_<R>(a,-1);}
1467 
1468 
1469 
operator +(const Mulc_KN_<R> & a,const Mulc_KN_<R> & b)1470 template<class R> inline Add_Mulc_KN_<R> operator+(const  Mulc_KN_<R>& a,const Mulc_KN_<R> &b)
1471     { return Add_Mulc_KN_<R>(a,b);}
operator -(const Mulc_KN_<R> & a,const Mulc_KN_<R> & b)1472 template<class R> inline Add_Mulc_KN_<R> operator-(const  Mulc_KN_<R>& a,const Mulc_KN_<R> &b)
1473     { return Add_Mulc_KN_<R>(a,b.a,-b.b);}
1474 
operator +(const Mulc_KN_<R> & a,const KN_<const_R> & b)1475 template<class R> inline Add_Mulc_KN_<R> operator+(const  Mulc_KN_<R>& a,const KN_<const_R> &b)
1476    { return Add_Mulc_KN_<R>(a,b,R(1));}
operator -(const Mulc_KN_<R> & a,const KN_<const_R> & b)1477 template<class R> inline Add_Mulc_KN_<R> operator-(const  Mulc_KN_<R>& a,const KN_<const_R> &b)
1478    { return Add_Mulc_KN_<R>(a,b,R(-1));}
1479 
operator +(const KN_<const_R> & b,const Mulc_KN_<R> & a)1480 template<class R> inline Add_Mulc_KN_<R> operator+(const KN_<const_R> & b,const  Mulc_KN_<R>& a)
1481    { return Add_Mulc_KN_<R>(a,b,R(1));}
1482 
1483 // modif FH mars 2007
operator -(const KN_<const_R> & a,const Mulc_KN_<R> & b)1484 template<class R> inline Add_Mulc_KN_<R> operator-(const KN_<const_R> & a,const  Mulc_KN_<R>& b)
1485    { return Add_Mulc_KN_<R>(a,R(1),b.a,-b.b);}// modif FH mars 2007
1486 
operator *(const KNM_<const_R> & A,const KN_<const_R> & b)1487 template<class R> inline Mul_KNM_KN_<R> operator*(const  KNM_<const_R> & A,const  KN_<const_R> & b)
1488     { return Mul_KNM_KN_<R>(A,b);}
1489 
1490 
SameShape(const ShapeOfArray & a,const Add_Mulc_KN_<R> & b)1491 template<class R> inline bool  SameShape(const ShapeOfArray & a,const Add_Mulc_KN_<R> & b)
1492            { return SameShape(a,b.a) ;}
SameShape(const ShapeOfArray & a,const if_arth_KN_<R> & b)1493 template<class R> inline bool  SameShape(const ShapeOfArray & a,const if_arth_KN_<R> & b)
1494            { return SameShape(a,b.a) ;}
SameShape(const ShapeOfArray & a,const Add_KN_<R> & b)1495 template<class R> inline bool  SameShape(const ShapeOfArray & a,const Add_KN_<R> & b)
1496            { return SameShape(a,b.a) ;}
SameShape(const ShapeOfArray & a,const Sub_KN_<R> & b)1497 template<class R> inline bool  SameShape(const ShapeOfArray & a,const Sub_KN_<R> & b)
1498            { return SameShape(a,b.a) ;}
SameShape(const ShapeOfArray & a,const Mulc_KN_<R> & b)1499 template<class R> inline bool  SameShape(const ShapeOfArray & a,const Mulc_KN_<R> & b)
1500            { return SameShape(a,b.a) ;}
SameShape(const ShapeOfArray & a,const DotStar_KN_<R> & b)1501 template<class R> inline bool  SameShape(const ShapeOfArray & a,const DotStar_KN_<R> & b)
1502            { return SameShape(a,b.a) ;}
SameShape(const ShapeOfArray & a,const DotSlash_KN_<R> & b)1503 template<class R> inline bool  SameShape(const ShapeOfArray & a,const DotSlash_KN_<R> & b)
1504            { return SameShape(a,b.a) ;}
SameShape(const ShapeOfArray & a,const Mul_KNM_KN_<R> & b)1505 template<class R> inline bool  SameShape(const ShapeOfArray & a,const Mul_KNM_KN_<R> & b)
1506            { return a.n==b.A.N() ;}
SameShape(const ShapeOfArray &,const VirtualMatrice<double>::plusAx &)1507  inline bool  SameShape(const ShapeOfArray & ,const VirtualMatrice<double>::plusAx & )
1508            { return true ;} //  pas de test car la matrice peut etre rectangulaire
SameShape(const ShapeOfArray &,const VirtualMatrice<double>::plusAtx &)1509  inline bool  SameShape(const ShapeOfArray & ,const VirtualMatrice<double>::plusAtx & )
1510            { return true ;} //  pas de test car la matrice peut etre rectangulaire
SameShape(const ShapeOfArray &,const VirtualMatrice<complex<double>>::plusAx &)1511  inline bool  SameShape(const ShapeOfArray & ,const VirtualMatrice<complex<double> >::plusAx & )
1512            { return true ;} //  pas de test car la matrice peut etre rectangulaire
SameShape(const ShapeOfArray &,const VirtualMatrice<complex<double>>::plusAtx &)1513  inline bool  SameShape(const ShapeOfArray & ,const VirtualMatrice<complex<double> >::plusAtx & )
1514            { return true ;} //  pas de test car la matrice peut etre rectangulaire
1515 
SameShape(const ShapeOfArray &,const double)1516  inline bool  SameShape(const ShapeOfArray & ,const double)
1517            { return true;}
SameShape(const ShapeOfArray &,const complex<double>)1518  inline bool  SameShape(const ShapeOfArray & ,const complex<double>)
1519            { return true;}
SameShape(const ShapeOfArray &,const complex<float>)1520  inline bool  SameShape(const ShapeOfArray & ,const complex<float>)
1521            { return true;}
1522 
1523 template<class R>
SameShape(KNM<R> & m,const outProduct_KN_<R> & p)1524  inline bool SameShape(KNM<R>& m, const outProduct_KN_<R>& p)
1525  { return p.a.N()>=m.N() && m.M()>=p.b.N(); }
1526 
SameAdress(const KN_<R> & a,const KN_<R> & b)1527 template<class R> inline long SameAdress(const KN_<R> &a, const KN_<R> &b) { return &a[0]==&b[0];}
1528 // bof -bof
1529 //template<class R> inline
1530 //  KN_<R>::operator KN<R> &() { return *(KN<R> *) (void *) this;}
1531 //template<class R> inline
1532 //  KN_<R>::operator const KN<R> &() const { return *(const KN<R> *) ( const void *) this;}
1533 
1534 //  operateur y=Ax-b ou y=Ax + b pour le GC
1535 template<class R>
operator -(const typename VirtualMatrice<R>::plusAx & A,const KN_<R> & B)1536    PplusQ< typename VirtualMatrice<R>::plusAx, Mulc_KN_<R> >  operator-(const typename VirtualMatrice<R>::plusAx & A,const KN_<R> & B)
1537     { return PplusQ< typename VirtualMatrice<R>::plusAx, Mulc_KN_<R> >(A,Mulc_KN_<R>(B,R(-1.)));}
1538 
1539 template<class R>
operator +(const typename VirtualMatrice<R>::plusAx & A,const KN_<R> & B)1540    PplusQ< typename VirtualMatrice<R>::plusAx, KN_<R> >  operator+(const typename VirtualMatrice<R>::plusAx & A,const KN_<R> & B)
1541     { return PplusQ< typename VirtualMatrice<R>::plusAx, KN_<R> >(A,B);}
1542 
1543 template<class R>
operator -(const typename VirtualMatrice<R>::plusAx & A,const KN<R> & B)1544    PplusQ< typename VirtualMatrice<R>::plusAx, Mulc_KN_<R> >  operator-(const typename VirtualMatrice<R>::plusAx & A,const KN<R> & B)
1545     { return PplusQ< typename VirtualMatrice<R>::plusAx, Mulc_KN_<R> >(A,Mulc_KN_<R>(B,R(-1.)));}
1546 
1547 template<class R>
operator +(const typename VirtualMatrice<R>::plusAx & A,const KN<R> & B)1548    PplusQ< typename VirtualMatrice<R>::plusAx, KN_<R> >  operator+(const typename VirtualMatrice<R>::plusAx & A,const KN<R> & B)
1549     { return PplusQ< typename VirtualMatrice<R>::plusAx, KN_<R> >(A,B);}
1550 
1551 
1552 template<class R>
diagonal(const KNM<R> & A)1553 KN_<R> diagonal(const KNM<R> & A) {
1554   K_throwassert(A.N() == A.M());
1555   return KN_<R>(A,SubArray(A.N(),0,A.N()+1));}
1556 
1557 // to def  inv permutation FH mars 2006
1558 class Inv_KN_long{ public:
1559   KN_<long>  t;
Inv_KN_long(const KN_<long> & v)1560   Inv_KN_long(const KN_<long> & v)
1561    : t(v) {}
Inv_KN_long(KN_<long> const * & v)1562   Inv_KN_long( KN_<long> const  * & v)
1563    : t(*v) {}
operator const KN_<long>&() const1564   operator const KN_<long> & () const {return t;}
1565 };
1566 
1567 
1568 template<class R,typename A,typename B=R> class  F_KN_
1569 {
1570   public:
1571   A (*f)(B);
1572   KN_<R> a;
N() const1573   long N() const {return a.N();}
F_KN_(A (* ff)(B),const KN_<R> & aa)1574   F_KN_( A (*ff)(B),const KN_<R> & aa): f(ff),a(aa) {}
operator [](long i) const1575   A operator[](long i) const { return f(a[i]);}
check(long n) const1576   bool check(long n)  const { return  n <= a.N() || a.constant(); }
constant() const1577   bool constant() const {return a.constant();}
1578 };
1579 
1580 template<class R,typename A,typename B>
SameShape(const ShapeOfArray & a,const F_KN_<R,A,B> & b)1581 inline bool  SameShape(const ShapeOfArray & a,const F_KN_<R,A,B>  & b)
1582            { return  !a.step || b.constant()  || a.n == b.N() ;}
1583 
1584 #include "RNM_tpl.hpp"
1585 #ifdef K_throwassert
1586 #undef K_throwassert
1587 #endif
1588 #endif
1589