FOX/ObjCryst++  1.10.X (development)
CrystVector.cpp
1 /* ObjCryst++ Object-Oriented Crystallographic Library
2  (c) 2000-2002 Vincent Favre-Nicolin vincefn@users.sourceforge.net
3  2000-2001 University of Geneva (Switzerland)
4 
5  This program is free software; you can redistribute it and/or modify
6  it under the terms of the GNU General Public License as published by
7  the Free Software Foundation; either version 2 of the License, or
8  (at your option) any later version.
9 
10  This program is distributed in the hope that it will be useful,
11  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  GNU General Public License for more details.
14 
15  You should have received a copy of the GNU General Public License
16  along with this program; if not, write to the Free Software
17  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 */
19 #include "ObjCryst/CrystVector/CrystVector.h"
20 #include "ObjCryst/Quirks/VFNStreamFormat.h"
21 #include "ObjCryst/ObjCryst/General.h"
22 
23 #ifdef __LIBCRYST_VECTOR_USE_BLITZ__
24 
25 #define CrystVector Array<REAL,1>
26 #define CrystMatrix Array<REAL,2>
27 
28 template<class T> T MaxDifference(const Array<T,1> &a,const Array<T,1> &b)
29 {
30  return max(fabs(a-b));
31 }
32 
33 template<class T> T MaxDifference(const Array<T,2> &a,const Array<T,2> &b)
34 {
35  return max(fabs(a-b));
36 }
37 
38 #else // __LIBCRYST_VECTOR_USE_BLITZ__
39 
40 //Still using pointers instead of blitz for geometrical structure factor,
41 //due to huge memory requirements with gcc when using blitz.
42 #define __VFN_GEOM_STRUCT_FACTOR_USE_POINTERS
43 
44 #include "ObjCryst/Quirks/VFNDebug.h"
45 #include "ObjCryst/Quirks/VFNStreamFormat.h"
46 
47 //######################################################################
48 // CrystVector
49 //######################################################################
50 template<class T> CrystVector<T>::CrystVector():mpData(0),mNumElements(0),mIsAreference(false) {}
51 
52 template<class T> CrystVector<T>::CrystVector(const long nbElements):
53 mNumElements(nbElements),mIsAreference(false)
54 {
55  mpData=new T[mNumElements];
56 }
57 
58 template<class T> CrystVector<T>::CrystVector(const CrystVector &old):
59 mNumElements(old.numElements()),mIsAreference(false)
60 {
61  mpData=new T[mNumElements];
62  T *p1=mpData;
63  const T *p2=old.data();
64  for(long i=0;i<mNumElements;i++) *p1++=*p2++;
65 }
66 
67 template<class T> CrystVector<T>::~CrystVector()
68 {
69  if(!mIsAreference)
70  {
71  delete[] mpData;
72  }
73 }
74 template<class T> void CrystVector<T>::operator=(const CrystVector &old)
75 {
76  VFN_DEBUG_MESSAGE("CrystVector<T>::operator=()",0)
77  this->resize(old.numElements());
78  mIsAreference=false;
79  T *p1=mpData;
80  const T *p2=old.data();
81  for(long i=0;i<mNumElements;i++) *p1++=*p2++;
82 }
83 
84 template<class T> void CrystVector<T>::reference(CrystVector &old, const long imin, const long imax)
85 {
86  if(!mIsAreference)
87  {
88  delete[] mpData ;
89  }
90  if(imax>imin)
91  {
92  mNumElements=imax-imin;
93  mpData=old.data()+imin;
94  }
95  else
96  {
97  mNumElements=old.numElements();
98  mpData=old.data();
99  }
100  mIsAreference=true;
101 }
102 
103 template<class T> long CrystVector<T>::numElements()const {return mNumElements;}
104 template<class T> long CrystVector<T>::size()const {return mNumElements;}
105 
106 template<class T> T CrystVector<T>::sum()const
107 {
108  register T tmp=0;
109  register const T *p=this->data();
110  for(long i=0;i<this->numElements();i++) tmp += *p++ ;
111  return tmp;
112 }
113 template<class T> T CrystVector<T>::min()const
114 {
115  register T tmp=0;
116  register const T *p=this->data();
117  tmp=*p++;
118  for(long i=1;i<this->numElements();i++)
119  {
120  if(tmp>*p) tmp=*p;
121  p++;
122  }
123  return tmp;
124 }
125 template<class T> T CrystVector<T>::max()const
126 {
127  register T tmp=0;
128  register const T *p=this->data();
129  tmp=*p++;
130  for(long i=1;i<this->numElements();i++)
131  {
132  if(tmp<*p) tmp=*p;
133  p++;
134  }
135  return tmp;
136 }
137 
138 template<class T> unsigned long CrystVector<T>::imin(const unsigned long start0,const unsigned long finish0)const
139 {
140  unsigned long start=start0,finish=finish0;
141  if(start0==finish0)
142  {
143  start=0;
144  finish=this->numElements();
145  }
146  register T tmp=0;
147  register const T *p=this->data()+start;
148  tmp=*p++;
149  long im=0;
150  for(unsigned long i=start+1;i<finish;i++)
151  {
152  if(tmp>*p) {tmp=*p;im=i;}
153  p++;
154  }
155  return (unsigned long)im;
156 }
157 template<class T> unsigned long CrystVector<T>::imax(const unsigned long start0,const unsigned long finish0)const
158 {
159  unsigned long start=start0,finish=finish0;
160  if(start0==finish0)
161  {
162  start=0;
163  finish=this->numElements();
164  }
165  register T tmp=0;
166  register const T *p=this->data()+start;
167  tmp=*p++;
168  long im=start;
169  for(unsigned long i=start+1;i<finish;i++)
170  {
171  if(tmp<*p) {tmp=*p;im=i;}
172  p++;
173  }
174  return (unsigned long)im;
175 }
176 
177 template<class T> T * CrystVector<T>::data() {return mpData;}
178 template<class T> const T * CrystVector<T>::data() const {return mpData;}
179 
180 template<class T> void CrystVector<T>::resize(const long newNbElements)
181 {
182  if(mNumElements==newNbElements) return;
183  VFN_DEBUG_MESSAGE("CrystVector<T>::resize():("<<mNumElements<<"->"
184  <<newNbElements<<").",0)
185  if((mIsAreference==false) && (mNumElements != 0))
186  {
187  delete[] mpData ;
188  }
189  mpData=0;
190  mNumElements=newNbElements;
191  if(mNumElements>0)
192  {
193  mpData=new T[mNumElements];
194  }
195  mIsAreference=false;
196 }
197 
198 template<class T> void CrystVector<T>::resizeAndPreserve(const long newNbElements)
199 {
200  //:TODO: check memory allocation
201  if(newNbElements == mNumElements) return;
202  register T * RESTRICT p=mpData;
203  register T * RESTRICT p2,*p1;
204  mpData=0;
205  mpData=new T[newNbElements];
206  p2=mpData;
207  p1=p;
208  const long tmp= (newNbElements > mNumElements) ? mNumElements : newNbElements ;
209  for(long i=tmp;i>0;i--) *p2++ = *p1++ ;
210  if(mIsAreference==false)
211  {
212  delete[] p ;
213  }
214  mNumElements=newNbElements;
215  mIsAreference=false;
216 }
217 
218 template<class T> void CrystVector<T>::operator*=(const T num)
219 {
220  register T * RESTRICT p=mpData;
221  for(int i=mNumElements;i>0;i--) *p++ *= num;
222 }
223 
224 template<class T> void CrystVector<T>::operator*=(const CrystVector<T> &vect)
225 {
226  #ifdef __DEBUG__
227  if( vect.numElements() != mNumElements)
228  {
229  cout<<"CrystVector::operator*=(&vect)(i): Number of elements differ:"<< mNumElements \
230  << "!="<< vect.numElements() <<endl;
231  //throw 0;
232  }
233  #endif
234  if(mpData!=vect.data())
235  {
236  register T * RESTRICT p=mpData;
237  register const T * RESTRICT rhs=vect.data();
238  for(int i=mNumElements;i>0;i--) { *p *= *rhs; p++ ; rhs++;}
239  }
240  else
241  {
242  register T *p=mpData;
243  for(int i=mNumElements;i>0;i--) { *p *= *p; p++ ;}
244  }
245 }
246 
247 template<class T> void CrystVector<T>::operator/=(const T num)
248 {
249  register T * RESTRICT p=mpData;
250  const REAL d=1/num;
251  for(int i=mNumElements;i>0;i--) *p++ *= d;
252 }
253 
254 template<class T> void CrystVector<T>::operator/=(const CrystVector<T> &vect)
255 {
256  #ifdef __DEBUG__
257  if( vect.numElements() != mNumElements)
258  {
259  cout<<"CrystVector::operator/=(&vect)(i): Number of elements differ:"<< mNumElements \
260  << "!="<< vect.numElements() <<endl;
261  //throw 0;
262  }
263  #endif
264  if(mpData!=vect.data())
265  {
266  register T * RESTRICT p=mpData;
267  register const T * RESTRICT rhs=vect.data();
268  for(int i=mNumElements;i>0;i--) { *p /= *rhs; p++ ; rhs++;}
269  }
270  else *this=1;
271 }
272 
273 template<class T> void CrystVector<T>::operator+=(const T num)
274 {
275  register T * RESTRICT p=mpData;
276  for(int i=mNumElements;i>0;i--) *p++ += num;
277 }
278 
279 template<class T> void CrystVector<T>::operator+=(const CrystVector<T> &vect)
280 {
281  #ifdef __DEBUG__
282  if( vect.numElements() != mNumElements)
283  {
284  cout<<"CrystVector::operator+=(&vect)(i): Number of elements differ:"<< mNumElements \
285  << "!="<< vect.numElements() <<endl;
286  //throw 0;
287  }
288  #endif
289  if(mpData!=vect.data())
290  {
291  register T * RESTRICT p=mpData;
292  const T * RESTRICT rhs=vect.data();
293  for(int i=mNumElements;i>0;i--) *p++ += *rhs++;
294  }
295  else
296  {
297  register T *p=mpData;
298  for(int i=mNumElements;i>0;i--) {*p += *p; p++;}
299  }
300 }
301 
302 template<class T> void CrystVector<T>::operator-=(const CrystVector<T> &vect)
303 {
304  #ifdef __DEBUG__
305  if( vect.numElements() != mNumElements)
306  {
307  cout<<"CrystVector::operator-=(&vect)(i): Number of elements differ:"<< mNumElements \
308  << "!="<< vect.numElements() <<endl;
309  //throw 0;
310  }
311  #endif
312  if(mpData!=vect.data())
313  {
314  register T * RESTRICT p=mpData;
315  const T * RESTRICT rhs=vect.data();
316  for(int i=mNumElements;i>0;i--) *p++ -= *rhs++;
317  }
318  else (*this)=0;
319 }
320 
321 template<class T> void CrystVector<T>::operator=(const T num)
322 {
323  register T *p=mpData;
324  for(int i=mNumElements;i>0;i--) *p++ = num;
325 }
326 
327 template<class T> T CrystVector<T>::operator()(const long i) const
328 {
329  #ifdef __DEBUG__
330  if( (i<0) || (i>=mNumElements))
331  {
332  cout<<"CrystVector::operator()(i): Tried to access an element out of bounds :"<<i<<endl;
333  //throw 0;
334  }
335  #endif
336  return mpData[i];
337 }
338 
339 template<class T> T& CrystVector<T>::operator()(const long i)
340 {
341  #ifdef __DEBUG__
342  if( (i<0) || (i>=mNumElements))
343  {
344  cout<<"CrystVector::operator()(i): Tried to access an element out of bounds !"<<i<<endl;
345  //throw 0;
346  }
347  #endif
348  return mpData[i];
349 }
350 //######################################################################
351 // CrystVector functions
352 //######################################################################
353 
354 template<class T> ostream& operator<<(ostream &os, CrystVector<T> &vect)
355 {
356  //return os << FormatHorizVector(vect);
357  for(long i=0;i<vect.numElements();i++) os << vect(i) <<endl;
358  return os;
359 }
360 
361 template<class T> CrystVector<long> SortSubs(const CrystVector<T> &vect)
362 {
363  CrystVector<long> subscript(vect.numElements());
364  {
365  long *pLong=subscript.data();
366  for(long i=0;i<subscript.numElements();i++) *pLong++ = i;
367  }
368  CrystVector<T> v;
369  v=vect;
370  QuickSortSubs(v,subscript,v.numElements()-1,0,0);
371  return subscript;
372 }
373 
374 template<class T> long QuickSortSubs(CrystVector<T> &vect,
375  CrystVector<long> &subscript,
376  long last,long first, int depth)
377 {
378  //assert(depth++ <50);//for up to 2^50 elements
379  static long count=0;
380  long low, high;
381  T tmpT, sepValeur ;
382  long tmpSubs;
383  low = first;
384  high = last;
385  sepValeur = vect( (first + last) / 2 );
386  do
387  {
388  while( vect(low) < sepValeur ) low++;
389  while( vect(high) > sepValeur ) high--;
390  if( low <= high )
391  {
392  count++;
393  tmpT = vect(low);
394  vect(low) = vect(high);
395  vect(high) = tmpT;
396  tmpSubs = subscript(low);
397  subscript(low++) = subscript(high);
398  subscript(high--) = tmpSubs;
399  }
400  } while( low <= high);
401  if( first < high ) QuickSortSubs(vect,subscript, high, first,depth);
402  if( low < last ) QuickSortSubs(vect,subscript, last, low,depth);
403  return count ;
404 }
405 
406 template<class T> CrystVector<T> cos(const CrystVector<T> &vect)
407 {
408  CrystVector<T> cosVect(vect.numElements());
409  for(long i=0;i<vect.numElements();i++) cosVect(i) = (T) cos(vect(i));
410  return cosVect;
411 }
412 
413 template<class T> CrystVector<T> sin(const CrystVector<T> &vect)
414 {
415  CrystVector<T> sinVect(vect.numElements());
416  for(long i=0;i<vect.numElements();i++) sinVect(i) = (T) sin(vect(i));
417  return sinVect;
418 }
419 
420 template<class T> CrystVector<T> tan(const CrystVector<T> &vect)
421 {
422  CrystVector<T> tanVect(vect.numElements());
423  for(long i=0;i<vect.numElements();i++) tanVect(i) = (T) tan(vect(i));
424  return tanVect;
425 }
426 
427 template<class T> CrystVector<T> sqrt(const CrystVector<T> &vect)
428 {
429  CrystVector<T> tanVect(vect.numElements());
430  for(long i=0;i<vect.numElements();i++) tanVect(i) = (T) sqrt(vect(i));
431  return tanVect;
432 }
433 
434 //######################################################################
435 // CrystMatrix
436 //######################################################################
437 template<class T> CrystMatrix<T> ::CrystMatrix():
438 mpData(0),mNumElements(0),mXSize(0),mYSize(0),mIsAreference(false){}
439 
440 template<class T> CrystMatrix<T>::CrystMatrix(const long ySize,const long xSize):
441 mNumElements(xSize*ySize),mXSize(xSize),mYSize(ySize),mIsAreference(false)
442 {
443  mpData=new T[mNumElements];
444 }
445 
446 template<class T> CrystMatrix<T>::CrystMatrix(const CrystMatrix &old):
447 mNumElements(old.numElements()),mXSize(old.cols()),mYSize(old.rows()),mIsAreference(false)
448 {
449  mpData=new T[mNumElements];
450  register T *p1=mpData;
451  register const T *p2=old.data();
452  for(long i=0;i<mNumElements;i++) *p1++=*p2++;
453 }
454 
455 template<class T> CrystMatrix<T>::~CrystMatrix()
456 {
457  if(!mIsAreference)
458  {
459  delete[] mpData;
460  }
461 }
462 
463 template<class T> void CrystMatrix<T>::operator=(const CrystMatrix<T> &old)
464 {
465  mXSize=old.cols();
466  mYSize=old.rows();
467  mIsAreference=false;
468  if(mNumElements!=old.numElements())
469  {
470  if(mIsAreference==false)
471  {
472  delete[] mpData ;
473  }
474  mNumElements=old.numElements();
475  mpData=new T[mNumElements];
476  }
477  register T *p1=mpData;
478  register const T *p2=old.data();
479  for(long i=0;i<mNumElements;i++) *p1++=*p2++;
480 }
481 
482 template<class T> void CrystMatrix<T>::reference(CrystMatrix<T> &old)
483 {
484  if(mIsAreference==false)
485  {
486  delete[] mpData ;
487  }
488  mIsAreference=true;
489  mNumElements=old.numElements();
490  mpData=old.data();
491 }
492 
493 template<class T> long CrystMatrix<T>::numElements()const {return mNumElements;}
494 template<class T> long CrystMatrix<T>::size()const {return mNumElements;}
495 
496 template<class T> T CrystMatrix<T>::sum()const
497 {
498  register T tmp=0;
499  register const T *p=this->data();
500  for(long i=0;i<this->numElements();i++) tmp += *p++ ;
501  return tmp;
502 }
503 
504 template<class T> T CrystMatrix<T>::min()const
505 {
506  register T tmp=0;
507  register const T *p=this->data();
508  tmp=*p++;
509  for(long i=1;i<this->numElements();i++)
510  {
511  if(tmp>*p) tmp=*p;
512  p++;
513  }
514  return tmp;
515 }
516 
517 template<class T> T CrystMatrix<T>::max()const
518 {
519  register T tmp=0;
520  register const T *p=this->data();
521  tmp=*p++;
522  for(long i=1;i<this->numElements();i++)
523  {
524  if(tmp<*p) tmp=*p;
525  p++;
526  }
527  return tmp;
528 }
529 
530 template<class T> long CrystMatrix<T>::cols()const {return mXSize;}
531 
532 template<class T> long CrystMatrix<T>::rows()const {return mYSize;}
533 
534 template<class T> T* CrystMatrix<T>::data() {return mpData;}
535 template<class T> const T* CrystMatrix<T>::data() const {return mpData;}
536 
537 template<class T> void CrystMatrix<T>::resize(const long ySize,const long xSize)
538 {
539  mXSize=xSize;
540  mYSize=ySize;
541  if(xSize*ySize == mNumElements) return;
542  if(!mIsAreference)
543  {
544  delete[] mpData ;
545  }
546  mpData=0;
547  mXSize=xSize;
548  mYSize=ySize;
549  mNumElements=xSize*ySize;
550  if(mNumElements>0)
551  {
552  mpData=new T[mNumElements];
553  }
554 }
555 
556 template<class T> void CrystMatrix<T>::resizeAndPreserve(const long ySize,const long xSize)
557 {
558  mXSize=xSize;
559  mYSize=ySize;
560  if(xSize*ySize == mNumElements) return;
561  register T *p=mpData;
562  register T *p2,*p1;
563  mpData=0;
564  mpData=new T[xSize*ySize];
565  p2=mpData;
566  p1=p;
567  long tmp= ( (xSize*ySize) > mNumElements) ? mNumElements : xSize*ySize;
568  for(long i=0;i<tmp;i++) *p2++ = *p1++ ;
569  if(!mIsAreference)
570  {
571  delete[] p ;
572  }
573  mNumElements=xSize*ySize;
574  mIsAreference=false;
575 }
576 /*
577 template<class T> void CrystMatrix<T>::operator=(const T num)
578 {
579  register T *p=mpData;
580  for(int i=0;i<mNumElements;i++) *p++ = num;
581 }
582 */
583 template<class T> void CrystMatrix<T>::operator*=(const T num)
584 {
585  register T *p=mpData;
586  for(int i=0;i<mNumElements;i++) *p++ *= num;
587 }
588 
589 template<class T> void CrystMatrix<T>::operator*=(const CrystMatrix<T> &vect)
590 {
591  #ifdef __DEBUG__
592  if( this->numElements() != vect.numElements())
593  {
594  cout<<"CrystMatrix::operator*=(): Number of elements differ !"<<endl;
595  //throw 0;
596  }
597  #endif
598  register T *p=mpData;
599  register const T *rhs=vect.data();
600  for(int i=0;i<mNumElements;i++) *p++ *= *rhs++;
601 }
602 
603 template<class T> void CrystMatrix<T>::operator/=(const T num)
604 {
605  register T *p=mpData;
606  for(int i=0;i<mNumElements;i++) *p++ /= num;
607 }
608 
609 template<class T> void CrystMatrix<T>::operator+=(const T num)
610 {
611  register T *p=mpData;
612  for(int i=0;i<mNumElements;i++) *p++ += num;
613 }
614 
615 template<class T> void CrystMatrix<T>::operator-=(const T num)
616 {
617  register T *p=mpData;
618  for(int i=0;i<mNumElements;i++) *p++ -= num;
619 }
620 
622 {
623  if((this->cols()!=rhs.rows())||(this->rows()!=rhs.cols()))
624  {
625  //throw ObjCrystException("CrystMatrix<T>::Mult(...): matrix sizes do not match !!");
626  }
627  CrystMatrix<T> mult(this->rows(),rhs.cols());
628  for(unsigned int r=0;r<this->rows();r++)
629  for(unsigned int c=0;r<rhs.cols();c++)
630  {
631  T tmp=0;
632  for(unsigned int i=0;i<this->cols();i++)
633  tmp+=(*this)(r,i)*rhs(i,c);
634  mult(r,c)=tmp;
635  }
636  return mult;
637 }
638 
639 template<class T> T CrystMatrix<T>::operator()(const long i) const
640 {
641  #ifdef __DEBUG__
642  if( (i<0) || (i>=mNumElements))
643  {
644  cout<<"CrystMatrix::operator()(i): element out of bounds !"<<i<<endl;
645  //throw 0;
646  }
647  #endif
648  return mpData[i];
649 }
650 
651 template<class T> T CrystMatrix<T>::operator()(const long i,const long j) const
652 {
653  #ifdef __DEBUG__
654  if( (i<0) || (j<0) || (i>=mYSize) || (j>=mXSize) )
655  {
656  cout<<"CrystMatrix::operator()(i,j): element out of bounds:"<<i<<","<<j<<endl;
657  cout<<"dimensions:"<<mYSize<<","<<mXSize<<endl;
658  //throw 0;
659  }
660  #endif
661  return mpData[i*mXSize+j];
662 }
663 
664 template<class T> T& CrystMatrix<T>::operator()(const long i)
665 {
666  #ifdef __DEBUG__
667  if( (i<0) || (i>=mNumElements))
668  {
669  cout<<"CrystMatrix::operator()(i): element out of bounds !"<<i<<endl;
670  //throw 0;
671  }
672  #endif
673  return mpData[i];
674 }
675 
676 template<class T> T& CrystMatrix<T>::operator()(const long i,const long j)
677 {
678  #ifdef __DEBUG__
679  if( (i<0) || (j<0) || (i>=mYSize) || (j>=mXSize) )
680  {
681  cout<<"CrystMatrix::operator()(i,j): element out of bounds:"<<i<<","<<j<<endl;
682  //throw 0;
683  }
684  #endif
685  return mpData[i*mXSize+j];
686 }
687 
688 template<class T> CrystMatrix<T> CrystMatrix<T>::transpose()const
689 {
690  CrystMatrix<T> newM(this->cols(),this->rows());
691  for(long i=0;i<this->cols();i++)
692  for(long j=0;j<this->rows();j++) newM(i,j)=(*this)(j,i);
693  return newM;
694 }
695 
696 //######################################################################
697 // CrystArray3D
698 //######################################################################
699 template<class T> CrystArray3D<T> ::CrystArray3D():
700 mpData(0),mNumElements(0),mXSize(0),mYSize(0),mZSize(0),mIsAreference(false){}
701 
702 template<class T> CrystArray3D<T>::CrystArray3D(const long zSize,
703  const long ySize,
704  const long xSize):
705 mNumElements(xSize*ySize*zSize),mXSize(xSize),mYSize(ySize),mZSize(zSize),
706 mIsAreference(false)
707 {
708  mpData=new T[mNumElements];
709 }
710 
711 template<class T> CrystArray3D<T>::CrystArray3D(const CrystArray3D &old):
712 mNumElements(old.numElements()),
713 mXSize(old.cols()),mYSize(old.rows()),mZSize(old.depth()),
714 mIsAreference(false)
715 {
716  mpData=new T[mNumElements];
717  register T *p1=mpData;
718  register const T *p2=old.data();
719  for(long i=0;i<mNumElements;i++) *p1++=*p2++;
720 }
721 
722 template<class T> CrystArray3D<T>::~CrystArray3D()
723 { if(!mIsAreference)delete[] mpData;}
724 
725 template<class T> void CrystArray3D<T>::operator=(const CrystArray3D<T> &old)
726 {
727  mXSize=old.cols();
728  mYSize=old.rows();
729  mZSize=old.depth();
730  mIsAreference=false;
731  if(mNumElements!=old.numElements())
732  {
733  mNumElements=old.numElements();
734  if(mIsAreference==false)delete[] mpData ;
735  mpData=new T[mNumElements];
736  }
737  register T *p1=mpData;
738  register const T *p2=old.data();
739  for(long i=0;i<mNumElements;i++) *p1++=*p2++;
740 }
741 
742 template<class T> void CrystArray3D<T>::reference(CrystArray3D<T> &old)
743 {
744  if(mIsAreference==false) delete[] mpData ;
745  mIsAreference=true;
746  mNumElements=old.numElements();
747  mpData=old.data();
748 }
749 
750 template<class T> long CrystArray3D<T>::numElements()const{return mNumElements;}
751 template<class T> long CrystArray3D<T>::size()const{return mNumElements;}
752 
753 template<class T> T CrystArray3D<T>::sum()const
754 {
755  register T tmp=0;
756  register const T *p=this->data();
757  for(long i=0;i<this->numElements();i++) tmp += *p++ ;
758  return tmp;
759 }
760 
761 template<class T> T CrystArray3D<T>::min()const
762 {
763  register T tmp=0;
764  register const T *p=this->data();
765  tmp=*p++;
766  for(long i=1;i<this->numElements();i++)
767  {
768  if(tmp>*p) tmp=*p;
769  p++;
770  }
771  return tmp;
772 }
773 
774 template<class T> T CrystArray3D<T>::max()const
775 {
776  register T tmp=0;
777  register const T *p=this->data();
778  tmp=*p++;
779  for(long i=1;i<this->numElements();i++)
780  {
781  if(tmp<*p) tmp=*p;
782  p++;
783  }
784  return tmp;
785 }
786 
787 template<class T> long CrystArray3D<T>::cols()const {return mXSize;}
788 
789 template<class T> long CrystArray3D<T>::rows()const {return mYSize;}
790 
791 template<class T> long CrystArray3D<T>::depth()const {return mZSize;}
792 
793 template<class T> T* CrystArray3D<T>::data() {return mpData;}
794 template<class T> const T* CrystArray3D<T>::data() const {return mpData;}
795 
796 template<class T> void CrystArray3D<T>::resize(const long zSize,
797  const long ySize,
798  const long xSize)
799 {
800  mXSize=xSize;
801  mYSize=ySize;
802  mZSize=zSize;
803  if(xSize*ySize*zSize == mNumElements) return;
804  if(!mIsAreference)delete[] mpData ;
805  mpData=0;
806  mNumElements=xSize*ySize*zSize;
807  if(mNumElements>0) mpData=new T[mNumElements];
808 }
809 
810 template<class T> void CrystArray3D<T>::resizeAndPreserve(const long zSize,
811  const long ySize,
812  const long xSize)
813 {
814  mXSize=xSize;
815  mYSize=ySize;
816  mZSize=zSize;
817  if(xSize*ySize*zSize == mNumElements) return;
818  register T *p=mpData;
819  register T *p2,*p1;
820  mpData=new T[xSize*ySize*zSize];
821  p2=mpData;
822  p1=p;
823  long tmp= ( (xSize*ySize*zSize) > mNumElements) ? mNumElements : xSize*ySize*zSize;
824  for(long i=0;i<tmp;i++) *p2++ = *p1++ ;
825  mNumElements=xSize*ySize*zSize;
826  if(!mIsAreference)delete[] p ;
827  mIsAreference=false;
828 }
829 
830 template<class T> void CrystArray3D<T>::operator=(const T num)
831 {
832  VFN_DEBUG_MESSAGE("CrystArray3D<T>::operator=():"<<num,1)
833  register T *p=mpData;
834  for(int i=0;i<mNumElements;i++) *p++ = num;
835 }
836 template<class T> void CrystArray3D<T>::operator*=(const T num)
837 {
838  register T *p=mpData;
839  for(int i=0;i<mNumElements;i++) *p++ *= num;
840 }
841 
842 template<class T> void CrystArray3D<T>::operator*=(const CrystArray3D<T> &vect)
843 {
844  #ifdef __DEBUG__
845  if( this->numElements() != vect.numElements())
846  {
847  cout<<"CrystArray3D::operator*=(): Number of elements differ !"<<endl;
848  //throw 0;
849  }
850  #endif
851  register T *p=mpData;
852  register const T *rhs=vect.data();
853  for(int i=0;i<mNumElements;i++) *p++ *= *rhs++;
854 }
855 
856 template<class T> void CrystArray3D<T>::operator/=(const T num)
857 {
858  register T *p=mpData;
859  for(int i=0;i<mNumElements;i++) *p++ /= num;
860 }
861 
862 template<class T> void CrystArray3D<T>::operator+=(const T num)
863 {
864  register T *p=mpData;
865  for(int i=0;i<mNumElements;i++) *p++ += num;
866 }
867 
868 template<class T> void CrystArray3D<T>::operator-=(const T num)
869 {
870  register T *p=mpData;
871  for(int i=0;i<mNumElements;i++) *p++ -= num;
872 }
873 
874 template<class T> T CrystArray3D<T>::operator()(const long i) const
875 {
876  #ifdef __DEBUG__
877  if( (i<0) || (i>=mNumElements))
878  {
879  cout<<"CrystArray3D::operator()(i): element out of bounds !"<<i<<endl;
880  //throw 0;
881  }
882  #endif
883  return mpData[i];
884 }
885 
886 template<class T> T CrystArray3D<T>::operator()(const long i,const long j,const long k) const
887 {
888  #ifdef __DEBUG__
889  if( (i<0) || (j<0) || (k<0) || (i>=mZSize) || (j>=mYSize) || (k>=mXSize))
890  {
891  cout<<"CrystArray3D::operator()(i,j,k): element out of bounds:"<<i<<","<<j<<","<<k<<endl;
892  cout<<"dimensions:"<<mZSize<<","<<mYSize<<","<<mXSize<<endl;
893  //throw 0;
894  }
895  #endif
896  return mpData[i*mYSize*mXSize+j*mXSize+k];
897 }
898 
899 template<class T> T& CrystArray3D<T>::operator()(const long i)
900 {
901  #ifdef __DEBUG__
902  if( (i<0) || (i>=mNumElements))
903  {
904  cout<<"CrystArray3D::operator()(i): element out of bounds !"<<i<<endl;
905  //throw 0;
906  }
907  #endif
908  return mpData[i];
909 }
910 
911 template<class T> T& CrystArray3D<T>::operator()(const long i,const long j,const long k)
912 {
913  #ifdef __DEBUG__
914  if( (i<0) || (j<0) || (k<0) || (i>=mZSize) || (j>=mYSize) || (k>=mXSize))
915  {
916  cout<<"CrystArray3D::operator()(i,j,k): element out of bounds:"<<i<<","<<j<<","<<k<<endl;
917  cout<<"dimensions:"<<mZSize<<","<<mYSize<<","<<mXSize<<endl;
918  //throw 0;
919  }
920  #endif
921  return mpData[i*mYSize*mXSize+j*mXSize+k];
922 }
923 
924 //######################################################################
925 // Other functions
926 //######################################################################
927 
928 template<class T> ostream& operator<<(ostream &os, const CrystMatrix<T> &vect)
929 {
930  //return os << FormatHorizVector(vect);
931  for(long i=0;i<vect.rows();i++)
932  {
933  for(long j=0;j<vect.cols();j++) os << FormatFloat(vect(i,j)) ;
934  os << endl;
935  }
936  return os;
937 }
938 
939 template<class T> ostream& operator<<(ostream &os, const CrystArray3D<T> &vect)
940 {
941  for(long i=0;i<vect.depth();i++)
942  {
943  for(long j=0;j<vect.rows();j++)
944  {
945  for(long k=0;k<vect.cols();k++) os << FormatFloat(vect(i,j,k)) ;
946  os << endl;
947  }
948  os << endl;
949  }
950  return os;
951 }
952 
953 template<class T> T MaxDifference(const CrystVector<T> &a,const CrystVector<T> &b)
954 {
955  const T *p1=a.data();
956  const T *p2=b.data();
957  REAL max=0;
958  REAL tmp=0;
959  for(long i=0;i<a.numElements();i++)
960  {
961  tmp=(T)fabs((REAL) (*p1++ - *p2++));
962  if(tmp>max) max=tmp;
963  }
964  return (T)max;
965 }
966 
967 template<class T> T MaxDifference(const CrystMatrix<T> &a,const CrystMatrix<T> &b)
968 {
969  const T *p1=a.data();
970  const T *p2=b.data();
971  T max=0;
972  T tmp=0;
973  for(long i=0;i<a.numElements();i++)
974  {
975  tmp=(T)fabs((REAL)(*p1++ - *p2++));
976  if(tmp>max) max=tmp;
977  }
978  return max;
979 }
980 
981 template<class T> CrystMatrix<T> product(const CrystMatrix<T> &a,const CrystMatrix<T> &b)
982 {
983  VFN_DEBUG_ENTRY("CrystMatrix<T> product()",2)
984  //:TODO: check a.cols()==b.rows()
985  CrystMatrix<T> ab(a.rows(),b.cols());
986  for(long i=0;i<ab.rows();i++)
987  {
988  for(long j=0;j<ab.cols();j++)
989  {
990  ab(i,j)=0;
991  for(long k=0;k<b.rows();k++) ab(i,j) += a(i,k)*b(k,j);
992  }
993  }
994  VFN_DEBUG_EXIT("CrystMatrix<T> product()",2)
995  return ab;
996 }
997 
998 //######################################################################
999 // explicit instantiation
1000 //######################################################################
1001 
1002 template class CrystVector<REAL>;
1003 template REAL MaxDifference(const CrystVector<REAL>&,const CrystVector<REAL>&);
1004 template ostream& operator<<(ostream &os, CrystVector<REAL> &vect);
1005 template CrystVector<long> SortSubs(const CrystVector<REAL> &vect);
1006 template long QuickSortSubs(CrystVector<REAL> &vect,CrystVector<long> &subscript,
1007  long last,long first, int depth);
1008 template class CrystMatrix<REAL>;
1009 template REAL MaxDifference(const CrystMatrix<REAL>&,const CrystMatrix<REAL>&);
1010 template CrystMatrix<REAL> product(const CrystMatrix<REAL>&,const CrystMatrix<REAL>&);
1011 template ostream& operator<<(ostream &os, const CrystMatrix<REAL> &vect);
1012 template CrystVector<REAL> cos<REAL>(const CrystVector<REAL>&);
1013 template CrystVector<REAL> sin<REAL>(const CrystVector<REAL>&);
1014 template CrystVector<REAL> tan<REAL>(const CrystVector<REAL>&);
1015 template CrystVector<REAL> sqrt<REAL>(const CrystVector<REAL>&);
1016 template class CrystArray3D<REAL>;
1017 template ostream& operator<<(ostream &os, const CrystArray3D<REAL> &vect);
1018 
1019 template class CrystVector<long>;
1020 template long MaxDifference(const CrystVector<long>&,const CrystVector<long>&);
1021 template ostream& operator<<(ostream &os, CrystVector<long> &vect);
1022 template CrystVector<long> SortSubs(const CrystVector<long> &vect);
1023 template long QuickSortSubs(CrystVector<long> &vect,CrystVector<long> &subscript,
1024  long last,long first, int depth);
1025 template class CrystMatrix<long>;
1026 template long MaxDifference(const CrystMatrix<long>&,const CrystMatrix<long>&);
1027 template CrystMatrix<long> product(const CrystMatrix<long>&,const CrystMatrix<long>&);
1028 template ostream& operator<<(ostream &os, const CrystMatrix<long> &vect);
1029 
1030 
1031 template class CrystVector<int>;
1032 template int MaxDifference(const CrystVector<int>&,const CrystVector<int>&);
1033 template ostream& operator<<(ostream &os, CrystVector<int> &vect);
1034 template CrystVector<long> SortSubs(const CrystVector<int> &vect);
1035 template long QuickSortSubs(CrystVector<int> &vect,CrystVector<long> &subscript,
1036  long last,long first, int depth);
1037 template class CrystMatrix<int>;
1038 template int MaxDifference(const CrystMatrix<int>&,const CrystMatrix<int>&);
1039 template CrystMatrix<int> product(const CrystMatrix<int>&,const CrystMatrix<int>&);
1040 template ostream& operator<<(ostream &os, const CrystMatrix<int> &vect);
1041 
1042 template class CrystVector<unsigned int>;
1043 template unsigned int MaxDifference(const CrystVector<unsigned int>&,const CrystVector<unsigned int>&);
1044 template ostream& operator<<(ostream &os, CrystVector<unsigned int> &vect);
1045 template CrystVector<long> SortSubs(const CrystVector<unsigned int> &vect);
1046 template long QuickSortSubs(CrystVector<unsigned int> &vect,CrystVector<long> &subscript,
1047  long last,long first, int depth);
1048 template class CrystMatrix<unsigned int>;
1049 template unsigned int MaxDifference(const CrystMatrix<unsigned int>&,const CrystMatrix<unsigned int>&);
1050 template CrystMatrix<unsigned int> product(const CrystMatrix<unsigned int>&,const CrystMatrix<unsigned int>&);
1051 template ostream& operator<<(ostream &os, const CrystMatrix<unsigned int> &vect);
1052 
1053 
1054 template class CrystVector<bool>;
1055 template ostream& operator<<(ostream &os, CrystVector<bool> &vect);
1056 template class CrystMatrix<bool>;
1057 template bool MaxDifference(const CrystMatrix<bool>&,const CrystMatrix<bool>&);
1058 template ostream& operator<<(ostream &os, const CrystMatrix<bool> &vect);
1059 
1060 
1061 
1062 #endif // __LIBCRYST_VECTOR_USE_BLITZ__
1063 
1064 //######################################################################
1065 // Functions
1066 //######################################################################
1067 
1068 
1069 CrystMatrix_REAL InvertMatrix(const CrystMatrix_REAL &m)
1070 {//:TODO: Check Pivoting...
1071  VFN_DEBUG_ENTRY("InvertMatrix()",2)
1072  VFN_DEBUG_MESSAGE("->Matrix to invert :"<<endl<<m,1)
1073  //REAL eps = 1e-8;
1074  //check matrix is square
1075  if( (m.rows() != m.cols()) || (m.rows() <2))
1076  {//DoSomethingBad
1077  cout << "Matrix inversion: Cannot invert matrix !" <<endl;
1078  //throw 0;
1079  }
1080  //prepare...
1081  long size=m.rows();
1082  CrystMatrix_REAL im(size,size),cm(size,size);//(future) invert matrix & copy of matrix
1083  cm=m;
1084  im=0;
1085  for(long i=0;i<size;i++) im(i,i)=1.;
1086  CrystMatrix_long rowIndex(size,1);//Keep track of pivoted rows
1087  for(long i=0;i<size;i++) rowIndex(i)=i;
1088  //Make an upper triangular matrix
1089  for(long i=0;i<size;i++)
1090  {
1091  //get absolute maximum the ith column
1092  long rowMax=i;
1093  {
1094  REAL max=fabs(m(i,i));
1095  for(long j=i+1;j<m.rows();j++)
1096  if(fabs(m(j,i)) > max)
1097  {
1098  max=fabs(m(j,i));
1099  rowMax=j;
1100  }
1101 
1102  //Check if pivot is non-singular :TODO:
1103  /*
1104  if(max < eps)
1105  {
1106  throw i;
1107  }
1108  */
1109  }
1110  //pivot
1111  if(rowMax != i)
1112  {
1113  //cout << "Exchanging rows: "<< i << " and " << rowMax <<endl;
1114  MatrixExchangeRows(cm,i,(long)rowMax);
1115  MatrixExchangeRows(im,i,(long)rowMax);
1116  MatrixExchangeRows(rowIndex,i,(long)rowMax);
1117  }
1118  //cout << cm <<endl;
1119  /*
1120  */
1121  //substract
1122  for(long j=i+1;j<size;j++)
1123  {
1124  const REAL a=cm(j,i)/cm(i,i);
1125  for(long k=0;k<size;k++) im(j,k) -= im(i,k)*a;
1126  for(long k=0;k<size;k++) cm(j,k) -= cm(i,k)*a;
1127  }
1128  //cout << cm <<endl;
1129  //cout << im <<endl;
1130  }
1131  VFN_DEBUG_MESSAGE("Finish solving from the upper triangular matrix...",1);
1132  for(long i=0;i<size;i++)
1133  {
1134  REAL a;
1135  for(long j=i-1;j>=0;j--)
1136  {
1137  a=cm(j,i)/cm(i,i);
1138  for(long k=0;k<size;k++) im(j,k) -= im(i,k)*a;
1139  for(long k=0;k<size;k++) cm(j,k) -= cm(i,k)*a;
1140  }
1141  a=cm(i,i);
1142  for(long k=0;k<size;k++) im(i,k) /= a;
1143  for(long k=0;k<size;k++) cm(i,k) /= a;
1144  //cout << cm <<endl;
1145  //cout << im <<endl;
1146  }
1147  //bring back to initial order of rows
1148  /*
1149  for(long i=0;i<size;i++)
1150  {
1151  if(rowIndex(i) != i)
1152  {
1153  long rowExch=0;
1154  for(; rowIndex(rowExch) != i ; rowExch++);
1155  cout << rowExch << endl;
1156  MatrixExchangeRows(im,i,rowExch);
1157  }
1158  }
1159  */
1160  VFN_DEBUG_MESSAGE("->Inverted Matrix :"<<endl<<im,1)
1161  VFN_DEBUG_EXIT("InvertMatrix()",2)
1162  return im;
1163 }
1164 
1165 template<class T> void MatrixExchangeRows(CrystMatrix_T &m, const long row1, const long row2)
1166 {
1167  //cout << "Exchanging rows:begin" <<endl;
1168  if(row1 == row2) return;
1169  long rowSize=m.cols();
1170  T tmp;
1171  for(long i=0;i<rowSize;i++)
1172  {
1173  tmp=m(row1,i);
1174  m(row1,i)=m(row2,i);
1175  m(row2,i)=tmp;
1176  }
1177  //cout << "Exchanging rows:end" <<endl;
1178 }
1179 
1180 template void MatrixExchangeRows(CrystMatrix_REAL &m, const long row1, const long row2);
1181 
1182 
1183 
1184 template<class T> T MaxAbs(const CrystVector_T &vector)
1185 {
1186  const T* pData=vector.data();
1187  T max =(T) fabs((REAL) *pData++);
1188  for(long i=1;i<vector.numElements();i++)
1189  {
1190  if ( fabs((REAL) *pData) > max) max=(T) fabs((REAL) *pData);
1191  pData++;
1192  }
1193  return max;
1194 }
1195 
1196 //Explicit instatiation
1197 template REAL MaxAbs(const CrystVector_REAL &vector);
1198 template int MaxAbs(const CrystVector_int &vector);
1199 template unsigned int MaxAbs(const CrystVector_uint &vector);
1200 template long MaxAbs(const CrystVector_long &vector);
1201 
1202 
1203 template<class T> T MinAbs(const CrystVector_T &vector)
1204 {
1205  const T* pData=vector.data();
1206  T min =(T) fabs((REAL) *pData++);
1207  for(long i=1;i<vector.numElements();i++)
1208  {
1209  if ( fabs((REAL) *pData) < min) min=(T) fabs((REAL) *pData);
1210  pData++;
1211  }
1212  return min;
1213 }
1214 
1215 //Explicit instatiation
1216 template REAL MinAbs(const CrystVector_REAL &vector);
1217 template int MinAbs(const CrystVector_int &vector);
1218 template unsigned int MinAbs(const CrystVector_uint &vector);
1219 template long MinAbs(const CrystVector_long &vector);
1220 
1221 //######################################################################
1222 // CubicSpline
1223 //######################################################################
1225 mX(0),mY(0),mYsecond(0)
1226 {}
1227 
1228 CubicSpline::CubicSpline(const CrystVector_REAL &x, const CrystVector_REAL &y,
1229  const REAL yp0, const REAL ypn)
1230 {
1231  this->Init(x,y,yp0,ypn);
1232 }
1233 
1234 CubicSpline::CubicSpline(const REAL *px, const REAL *py, const unsigned long nbPoints,
1235  const REAL yp0, const REAL ypn)
1236 {
1237  this->Init(px,py,nbPoints,yp0,ypn);
1238 }
1239 
1240 CubicSpline::CubicSpline(const CrystVector_REAL &x, const CrystVector_REAL &y)
1241 {
1242  this->Init(x,y);
1243 }
1244 
1245 CubicSpline::CubicSpline(const REAL *px, const REAL *py, const unsigned long nbPoints)
1246 {
1247  this->Init(px,py,nbPoints);
1248 }
1249 
1250 void CubicSpline::Init(const CrystVector_REAL &x, const CrystVector_REAL &y,
1251  const REAL yp0, const REAL ypn)
1252 {
1253  VFN_DEBUG_ENTRY("CubicSpline::Init(x,y,yp0,ypn)",5)
1254  mX=x;
1255  mY=y;
1256  mYsecond.resize(x.numElements());
1257  this->InitSpline(yp0,ypn);
1258  VFN_DEBUG_EXIT("CubicSpline::Init(x,y,yp0,ypn)",5)
1259 }
1260 void CubicSpline::Init(const REAL *px, const REAL *py, const unsigned long nbPoints,
1261  const REAL yp0, const REAL ypn)
1262 {
1263  VFN_DEBUG_ENTRY("CubicSpline::Init(px,py,yp0,ypn)",5)
1264  mX.resize(nbPoints);
1265  mY.resize(nbPoints);
1266  mYsecond.resize(nbPoints);
1267  for(unsigned long i=0;i<nbPoints;i++)
1268  {
1269  mX(i)=px[i];
1270  mY(i)=py[i];
1271  }
1272  this->InitSpline(yp0,ypn);
1273  VFN_DEBUG_EXIT("CubicSpline::Init(x,y,yp0,ypn)",5)
1274 }
1275 
1276 void CubicSpline::Init(const CrystVector_REAL &x, const CrystVector_REAL &y)
1277 {
1278  VFN_DEBUG_ENTRY("CubicSpline::Init(x,y)",5)
1279  mX=x;
1280  mY=y;
1281  mYsecond.resize(x.numElements());
1282  this->InitNaturalSpline();
1283  VFN_DEBUG_EXIT("CubicSpline::Init(x,y)",5)
1284 }
1285 
1286 void CubicSpline::Init(const REAL *px, const REAL *py, const unsigned long nbPoints)
1287 {
1288  VFN_DEBUG_ENTRY("CubicSpline::Init(px,py,n)",5)
1289  mX.resize(nbPoints);
1290  mY.resize(nbPoints);
1291  mYsecond.resize(nbPoints);
1292  for(unsigned long i=0;i<nbPoints;i++)
1293  {
1294  mX(i)=px[i];
1295  mY(i)=py[i];
1296  }
1297  this->InitNaturalSpline();
1298  VFN_DEBUG_EXIT("CubicSpline::Init(x,y,n)",5)
1299 }
1300 
1301 CubicSpline::~CubicSpline()
1302 {
1303 }
1304 
1305 REAL CubicSpline::operator()(const REAL x) const
1306 {
1307  //:TODO: faster!
1308  //:TODO: take into account beginning and end derivatives for out-of-bounds points
1309  long i;
1310  if(x<mX(0)) return mY(0);
1311  for(i=0;i<(mX.numElements()-1);i++)
1312  if(x<mX(i+1))
1313  {
1314  VFN_DEBUG_MESSAGE("CubicSpline::operator()(x):"<<x<<":"<<mX(i+1)<<":"<<i,0)
1315  const REAL e=mX(i+1)-mX(i);
1316  const REAL a=(mX(i+1)-x)/e;
1317  const REAL b=1.-a;
1318  const REAL c=1./6.*(a*a*a-a)*e*e;
1319  const REAL d=1./6.*(b*b*b-b)*e*e;
1320  return a*mY(i)+b*mY(i+1)+c*mYsecond(i)+d*mYsecond(i+1);
1321  }
1322  return mY(mY.numElements()-1);
1323 }
1324 
1325 CrystVector_REAL CubicSpline::operator()(const CrystVector_REAL &x) const
1326 {
1327  const long nb=x.numElements();
1328  CrystVector_REAL y(nb);
1329  //for(long i=0;i<nb;++i)y(i)=(*this)(x(i));
1330  //return y;
1331  const REAL *px=x.data();
1332  long i=0;
1333  REAL *py=y.data();
1334  const REAL *pX=mX.data();
1335  const REAL *pY=mY.data();
1336  const REAL *pY2=mYsecond.data();
1337  while((*px<*pX)&&(i<nb))
1338  {
1339  *py++=*pY;px++;i++;
1340  }
1341 
1342  for(long j=0;j<(mX.numElements()-1);j++)
1343  {
1344  while((*px<*(pX+1))&&(i<nb))
1345  {
1346  const REAL e= *(pX+1) - *pX;
1347  const REAL a= (*(pX+1)- *px)/e;
1348  const REAL b=1.-a;
1349  const REAL c=0.16666666666666666*(a*a*a-a)*e*e;
1350  const REAL d=0.16666666666666666*(b*b*b-b)*e*e;
1351  *py++ = a* *pY +b* *(pY+1) +c* *pY2 +d* *(pY2+1);
1352  px++;i++;
1353  }
1354  pX++;pY++;pY2++;
1355  if(i==nb) break;
1356  }
1357  for(;i<nb;++i) *py++ = *pY;
1358  return y;
1359 }
1360 
1361 CrystVector_REAL CubicSpline::operator()(const REAL xmin,const REAL xstep, const long nb) const
1362 {
1363  CrystVector_REAL y(nb);
1364  REAL x=xmin;
1365  long i=0;
1366  REAL *py=y.data();
1367  const REAL *pX=mX.data();
1368  const REAL *pY=mY.data();
1369  const REAL *pY2=mYsecond.data();
1370  while((x<*pX)&&(i<nb))
1371  {
1372  *py++=*pY;x += xstep;i++;
1373  }
1374 
1375  for(long j=0;j<(mX.numElements()-1);j++)
1376  {
1377  while((x<*(pX+1))&&(i<nb))
1378  {
1379  const REAL e= *(pX+1) - *pX;
1380  const REAL a= (*(pX+1)- x)/e;
1381  const REAL b=1.-a;
1382  const REAL c=0.16666666666666666*(a*a*a-a)*e*e;
1383  const REAL d=0.16666666666666666*(b*b*b-b)*e*e;
1384  *py++ = a* *pY +b* *(pY+1) +c* *pY2 +d* *(pY2+1);
1385  x+=xstep;i++;
1386  }
1387  pX++;pY++;pY2++;
1388  if(i==nb) break;
1389  }
1390  for(;i<nb;++i) *py++ = *pY;
1391  return y;
1392 }
1393 
1394 void CubicSpline::InitSpline(const REAL yp0, const REAL ypn)
1395 {
1396  const long n=mX.numElements();
1397  CrystVector_REAL u(mX.numElements());
1398  mYsecond(0)=-0.5;
1399  u(0)=(3/(mX(1)-mX(0)))*((mY(1)-mY(0))/(mX(1)-mX(0))-yp0);
1400  REAL a,b;
1401  for(long i=1;i<(n-1);i++)
1402  {
1403  a=(mX(i)-mX(i-1))/(mX(i+1)-mX(i-1));
1404  b=a*mYsecond(i-1)+2;
1405  mYsecond(i)=(a-1.)/b;
1406  u(i)=(6*((mY(i+1)-mY(i))/(mX(i+1)-mX(i))-(mY(i)-mY(i-1))/(mX(i)-mX(i-1)))
1407  /(mX(i+1)-mX(i-1))-a*u(i-1))/b;
1408  }
1409  const REAL c=(3./(mX(n-1)-mX(n-2)))*(ypn-(mY(n-1)-mY(n-2))/(mX(n-1)-mX(n-2)));
1410  mYsecond(n-1)=(c-.5*u(n-2))/(0.5*mYsecond(n-2)+1);
1411  for(long i=(n-2);i>=0;i--) mYsecond(i)=mYsecond(i)*mYsecond(i+1)+u(i);
1412 }
1413 
1414 void CubicSpline::InitNaturalSpline()
1415 {
1416  const long n=mX.numElements();
1417  CrystVector_REAL u(mX.numElements());
1418  mYsecond(0)=0;
1419  u(0)=0;
1420  REAL a,b;
1421  for(long i=1;i<=(n-2);i++)
1422  {
1423  a=(mX(i)-mX(i-1))/(mX(i+1)-mX(i-1));
1424  b=a*mYsecond(i-1)+2;
1425  mYsecond(i)=(a-1)/b;
1426  u(i)=(6*((mY(i+1)-mY(i))/(mX(i+1)-mX(i))-(mY(i)-mY(i-1))/(mX(i)-mX(i-1)))
1427  /(mX(i+1)-mX(i-1))-a*u(i-1))/b;
1428  }
1429  mYsecond(n-1)=0;
1430  for(long i=(n-2);i>=0;i--) mYsecond(i)=mYsecond(i)*mYsecond(i+1)+u(i);
1431 }
1432 
1433 //######################################################################
1434 // Savitzky-Golay interpolation
1435 //######################################################################
1436 // Coefficients for smoothing (deriv=0) - is there a general formula for these ?
1437 REAL sgcoeffs_0_5[]={-0.08571429, 0.34285714, 0.48571429, 0.34285714, -0.08571429};
1438 REAL sgcoeffs_0_7[]={-0.0952381 , 0.14285714, 0.28571429, 0.33333333, 0.28571429,
1439  0.14285714, -0.0952381};
1440 REAL sgcoeffs_0_9[]={-0.09090909, 0.06060606, 0.16883117, 0.23376623, 0.25541126,
1441  0.23376623, 0.16883117, 0.06060606, -0.09090909};
1442 REAL sgcoeffs_0_11[]={-0.08391608, 0.02097902, 0.1025641 , 0.16083916, 0.1958042 , 0.20745921,
1443  0.1958042 , 0.16083916, 0.1025641 , 0.02097902, -0.08391608};
1444 REAL sgcoeffs_0_13[]={-7.69230769e-02, 1.73472348e-18, 6.29370629e-02, 1.11888112e-01,
1445  1.46853147e-01, 1.67832168e-01, 1.74825175e-01, 1.67832168e-01,
1446  1.46853147e-01, 1.11888112e-01, 6.29370629e-02, 1.73472348e-18,
1447  -7.69230769e-02};
1448 REAL sgcoeffs_0_15[]={-0.07058824, -0.01176471, 0.03800905, 0.07873303, 0.11040724, 0.13303167,
1449  0.14660633, 0.15113122, 0.14660633, 0.13303167, 0.11040724,
1450  0.07873303, 0.03800905, -0.01176471, -0.07058824};
1451 REAL sgcoeffs_0_17[]={-0.06501548, -0.01857585, 0.02167183, 0.05572755, 0.08359133, 0.10526316,
1452  0.12074303, 0.13003096, 0.13312693, 0.13003096, 0.12074303,
1453  0.10526316, 0.08359133, 0.05572755, 0.02167183, -0.01857585,
1454  -0.06501548};
1455 REAL sgcoeffs_0_19[]={-0.06015038, -0.02255639, 0.01061477, 0.03936311, 0.06368863, 0.08359133,
1456  0.09907121, 0.11012826, 0.11676249, 0.11897391, 0.11676249,
1457  0.11012826, 0.09907121, 0.08359133, 0.06368863, 0.03936311,
1458  0.01061477, -0.02255639, -0.06015038};
1459 REAL sgcoeffs_0_21[]={-0.05590062, -0.02484472, 0.00294214, 0.02745995, 0.04870873, 0.06668846,
1460  0.08139915, 0.0928408 , 0.1010134 , 0.10591697, 0.10755149,
1461  0.10591697, 0.1010134 , 0.0928408 , 0.08139915, 0.06668846,
1462  0.04870873, 0.02745995, 0.00294214, -0.02484472, -0.05590062};
1463 REAL sgcoeffs_0_23[]={-0.05217391, -0.02608696, -0.00248447, 0.01863354, 0.03726708, 0.05341615,
1464  0.06708075, 0.07826087, 0.08695652, 0.0931677 , 0.09689441,
1465  0.09813665, 0.09689441, 0.0931677 , 0.08695652, 0.07826087,
1466  0.06708075, 0.05341615, 0.03726708, 0.01863354, -0.00248447,
1467  -0.02608696, -0.05217391};
1468 CrystVector_REAL SavitzkyGolay(const CrystVector_REAL &v, const unsigned int um, const unsigned int deriv)
1469 {
1470  const int m=(int)um;
1471  REAL *sgcoeffs=0;
1472  if(deriv==0)
1473  {
1474  if(m==2)sgcoeffs=sgcoeffs_0_5;
1475  if(m==3)sgcoeffs=sgcoeffs_0_7;
1476  if(m==4)sgcoeffs=sgcoeffs_0_9;
1477  if(m==5)sgcoeffs=sgcoeffs_0_11;
1478  if(m==6)sgcoeffs=sgcoeffs_0_13;
1479  if(m==7)sgcoeffs=sgcoeffs_0_15;
1480  if(m==8)sgcoeffs=sgcoeffs_0_17;
1481  if(m==9)sgcoeffs=sgcoeffs_0_19;
1482  if(m==10)sgcoeffs=sgcoeffs_0_21;
1483  if(m==11)sgcoeffs=sgcoeffs_0_23;
1484  }
1485  if(deriv==1)
1486  {
1487  sgcoeffs=new REAL[2*m+1];
1488  REAL *p=sgcoeffs;
1489  const REAL f=3/(REAL) (m*(m+1)*(2*m+1));
1490  for(int j=-m;j<=m;++j) *p++ = f*j;
1491  }
1492  if(deriv==2)
1493  {
1494  sgcoeffs=new REAL[2*m+1];
1495  REAL *p=sgcoeffs;
1496  const REAL f1=45/(REAL) (m*(m+1)*(2*m+1)*(4*m*(m+1)-3));
1497  const REAL f2=-15/(REAL) ((2*m+1)*(4*m*(m+1)-3));
1498  for(int j=-m;j<=m;++j) *p++ = f1*j*j + f2;
1499  }
1500  //cout<<__FILE__<<":"<<__LINE__<<"Savitzky-Golay coeeficients(m="<<m<<",deriv="<<deriv<<"): ";
1501  //for(int j=-m;j<=m;++j) cout<<m<<"="<<sgcoeffs[m+j]<<" ";
1502  //cout<<endl;
1503  const unsigned int n=v.numElements();
1504  CrystVector_REAL d(n);
1505  d=0;
1506  const unsigned int nm=n-m;
1507  REAL *pd=d.data()+m;
1508  for(unsigned int i=m;i<nm;++i)
1509  {
1510  const REAL *c=sgcoeffs,*p=v.data()+i-m;
1511  for(int j=-m;j<=m;++j) *pd += *c++ * *p++;
1512  pd++;
1513  }
1514  if(deriv!=0) delete[]sgcoeffs;
1515  return d;
1516 }
3D Vector (Blitz++ mimic) for ObjCryst++
Definition: CrystVector.h:492
void operator/=(const T num)
Element-by element division (array-like)
CrystVector_REAL operator()(const CrystVector_REAL &x) const
Get spline value at a series of point - x is assumed to be sorted by increasing values.
void operator-=(const T num)
Element-by element substraction (array-like)
void operator+=(const T num)
Element-by element addition (array-like)
CubicSpline()
Default constructor - CubicSpline::Init() should be called afterwards.
Vector library (Blitz++ mimic) for ObjCryst++.
Definition: CrystVector.h:122
void Init(const CrystVector_REAL &x, const CrystVector_REAL &y, const REAL yp1, const REAL ypn)
Spline with given extremum derivatives.
output a number as a formatted float:
CrystMatrix Mult(const CrystMatrix &rhs)
matrix multiplication (linear algebra)
2D Vector library (Blitz++ mimic) for ObjCryst++
Definition: CrystVector.h:339
unsigned long imax(const unsigned long start=0, const unsigned long finish=0) const
Find index of maximum, between start and end (if start==end, use full vector)
unsigned long imin(const unsigned long start=0, const unsigned long finish=0) const
Find index of minimum, between start and end (if start==end, use full vector)
void operator*=(const T num)
Element-by element multiplication (array-like)