diff --git a/la_traits.h b/la_traits.h index 43efda4..be533a1 100644 --- a/la_traits.h +++ b/la_traits.h @@ -31,6 +31,22 @@ template class NRMat; template class NRSMat; template class SparseMat; +//for general sortable classes +template struct LA_sort_traits; + +template +struct LA_sort_traits + { + static inline bool compare(T object, I i, I j) {return object.bigger(i,j);}; + }; + +template +struct LA_sort_traits + { + static inline bool compare(T object, I i, I j) {return object.smaller(i,j);}; + }; + + //we will need to treat char and unsigned char as numbers in << and >> I/O operators template struct LA_traits_io diff --git a/qsort.h b/qsort.h index 7eed5b1..6f7f078 100644 --- a/qsort.h +++ b/qsort.h @@ -43,18 +43,19 @@ return parity; } -template -int genqsort2(INDEX l, INDEX r, bool (*bigger)(const INDEX, const INDEX), void (*swap)(const INDEX,const INDEX)) +//for SORTABLE classes which provide LA_sort_traits::compare and swap member functions +template +int memqsort(SORTABLE &object, INDEX l, INDEX r) { INDEX i,j,piv; int parity=0; if(r<=l) return parity; //1 element -if(bigger(l,r)) {parity^=1; swap(l,r);} +if(LA_sort_traits::compare(object,l,r)) {parity^=1; object.swap(l,r);} if(r-l==1) return parity; //2 elements and preparation for median piv= (l+r)/2; //pivoting by median of 3 - safer -if(bigger(l,piv)) {parity^=1; swap(l,piv);} //and change the pivot element implicitly -if(bigger(piv,r)) {parity^=1; swap(r,piv);} //and change the pivot element implicitly +if(LA_sort_traits::compare(object,l,piv)) {parity^=1; object.swap(l,piv);} //and change the pivot element implicitly +if(LA_sort_traits::compare(object,piv,r)) {parity^=1; object.swap(r,piv);} //and change the pivot element implicitly if(r-l==2) return parity; //in the case of 3 elements we are finished too //general case , l-th r-th already processed @@ -62,23 +63,23 @@ i=l+1; j=r-1; do{ //important sharp inequality - stops at sentinel element for efficiency // this is inefficient if all keys are equal - unnecessary n log n swaps are done, but we assume that it is atypical input - while(bigger(piv,i++)); + while(LA_sort_traits::compare(object,piv,i++)); i--; - while(bigger(j--,piv)); + while(LA_sort_traits::compare(object,j--,piv)); j++; if(i(object,l,j); if(i(object,i,r);} else - {if(i(object,i,r); if(l(object,l,j);} return parity; } diff --git a/sparsemat.h b/sparsemat.h index bc15f5a..1b611eb 100644 --- a/sparsemat.h +++ b/sparsemat.h @@ -3,14 +3,6 @@ #include "la_traits.h" -template -inline const T MAX(const T &a, const T &b) - {return b > a ? (b) : (a);} - -template -inline void SWAP(T &a, T &b) - {T dum=a; a=b; b=dum;} - //threshold for neglecting elements, if not defined, no tests are done except exact zero test in simplify - might be even faster //seems to perform better with a threshold, in spite of abs() tests diff --git a/vec.cc b/vec.cc index 88e5a40..df827e0 100644 --- a/vec.cc +++ b/vec.cc @@ -493,36 +493,11 @@ NRVec< complex >::operator|(const NRVec< complex > &b) const } -//sorting of elements in the vector template -static inline void SWAP(T &a, T &b) - {T dum=a; a=b; b=dum;} - -static void *sortbase; //global for sort !!! is not thread-safe - -template -static void myswap(int i, int j) -{ -SWAP(((T *)sortbase)[i],((T *)sortbase)[j]); -} - -template -static bool mybigger(int i, int j) -{ -return LA_traits::bigger(((T *)sortbase)[i],((T *)sortbase)[j]); -} - -template -static bool mysmaller(int i, int j) -{ -return LA_traits::smaller(((T *)sortbase)[i],((T *)sortbase)[j]); -} - -template -int NRVec::sort(int direction) +int NRVec::sort(int direction, int from, int to) { copyonwrite(); -sortbase = v; -if(direction) return genqsort2(0,nn-1,mysmaller,myswap); -else return genqsort2(0,nn-1,mybigger,myswap); +if(to == -1) to=nn-1; +if(direction) return memqsort<1,NRVec,int>(*this,from,to); +else return memqsort<0,NRVec,int>(*this,from,to); } diff --git a/vec.h b/vec.h index 85c7b85..e4d38b8 100644 --- a/vec.h +++ b/vec.h @@ -103,9 +103,13 @@ public: //sparse matrix concerning members explicit NRVec(const SparseMat &rhs); // dense from sparse matrix with one of dimensions =1 inline void simplify() {}; //just for compatibility with sparse ones - int sort(int direction=0); //sort, ascending by default, returns parity of permutation + bool bigger(int i, int j) const {return LA_traits::bigger(v[i],v[j]);}; + bool smaller(int i, int j) const {return LA_traits::smaller(v[i],v[j]);}; + void swap(int i, int j) {T tmp; tmp=v[i]; v[i]=v[j]; v[j]=tmp;}; + int sort(int direction=0, int from=0, int to= -1); //sort, ascending by default, returns parity of permutation }; + //due to mutual includes this has to be after full class declaration #include "mat.h" #include "smat.h"