/***** * arrayop * John Bowman * * Array operations *****/ #ifndef ARRAYOP_H #define ARRAYOP_H #include #include "util.h" #include "stack.h" #include "array.h" #include "types.h" #include "fileio.h" #include "callable.h" #include "mathop.h" namespace run { using vm::pop; using vm::read; using vm::array; using camp::tab; vm::array *copyArray(vm::array *a); vm::array *copyArray2(vm::array *a); template class op> void arrayOp(vm::stack *s) { U b=pop(s); array *a=pop(s); size_t size=checkArray(a); array *c=new array(size); for(size_t i=0; i < size; i++) (*c)[i]=op()(read(a,i),b,i); s->push(c); } template class op> void opArray(vm::stack *s) { array *a=pop(s); T b=pop(s); size_t size=checkArray(a); array *c=new array(size); for(size_t i=0; i < size; i++) (*c)[i]=op()(b,read(a,i),i); s->push(c); } template class op> void arrayArrayOp(vm::stack *s) { array *b=pop(s); array *a=pop(s); size_t size=checkArrays(a,b); array *c=new array(size); for(size_t i=0; i < size; i++) (*c)[i]=op()(read(a,i),read(b,i),i); s->push(c); } template inline void arrayNegate(vm::stack *s) { array *a=pop(s); size_t size=checkArray(a); array *c=new array(size); for(size_t i=0; i < size; i++) (*c)[i]=-read(a,i); s->push(c); } template<> inline void arrayNegate(vm::stack *s) { array *a=pop(s); size_t size=checkArray(a); array *c=new array(size); for(size_t i=0; i < size; i++) (*c)[i]=Negate(read(a,i),i); s->push(c); } template void sumArray(vm::stack *s) { array *a=pop(s); size_t size=checkArray(a); T sum=0; for(size_t i=0; i < size; i++) sum += read(a,i); s->push(sum); } extern const char *arrayempty; template class op> void binopArray(vm::stack *s) { array *a=pop(s); size_t size=checkArray(a); if(size == 0) vm::error(arrayempty); T m=read(a,0); for(size_t i=1; i < size; i++) m=op()(m,read(a,i)); s->push(m); } template class op> void binopArray2(vm::stack *s) { array *a=pop(s); size_t size=checkArray(a); bool empty=true; T m=0; for(size_t i=0; i < size; i++) { array *ai=read(a,i); size_t aisize=checkArray(ai); if(aisize) { if(empty) { m=read(ai,0); empty=false; } for(size_t j=0; j < aisize; j++) m=op()(m,read(ai,j)); } } if(empty) vm::error(arrayempty); s->push(m); } template class op> void binopArray3(vm::stack *s) { array *a=pop(s); size_t size=checkArray(a); bool empty=true; T m=0; for(size_t i=0; i < size; i++) { array *ai=read(a,i); size_t aisize=checkArray(ai); for(size_t j=0; j < aisize; j++) { array *aij=read(ai,j); size_t aijsize=checkArray(aij); if(aijsize) { if(empty) { m=read(aij,0); empty=false; } for(size_t k=0; k < aijsize; k++) { m=op()(m,read(aij,k)); } } } } if(empty) vm::error(arrayempty); s->push(m); } template bool Array2Equals(vm::stack *s) { array *b=pop(s); array *a=pop(s); size_t n=checkArray(a); if(n != checkArray(b)) return false; if(n == 0) return true; size_t n0=checkArray(read(a,0)); if(n0 != checkArray(read(b,0))) return false; for(size_t i=0; i < n; ++i) { array *ai=read(a,i); array *bi=read(b,i); for(size_t j=0; j < n0; ++j) { if(read(ai,j) != read(bi,j)) return false; } } return true; } template void array2Equals(vm::stack *s) { s->push(Array2Equals(s)); } template void array2NotEquals(vm::stack *s) { s->push(!Array2Equals(s)); } template struct compare { bool operator() (const vm::item& a, const vm::item& b) { return vm::get(a) < vm::get(b); } }; template void sortArray(vm::stack *s) { array *c=copyArray(pop(s)); sort(c->begin(),c->end(),compare()); s->push(c); } template struct compare2 { bool operator() (const vm::item& A, const vm::item& B) { array *a=vm::get(A); array *b=vm::get(B); size_t size=a->size(); if(size != b->size()) return false; for(size_t j=0; j < size; j++) { if(read(a,j) < read(b,j)) return true; if(read(a,j) > read(b,j)) return false; } return false; } }; // Sort the rows of a 2-dimensional array by the first column, breaking // ties with successively higher columns. template void sortArray2(vm::stack *s) { array *c=copyArray(pop(s)); stable_sort(c->begin(),c->end(),compare2()); s->push(c); } // Search a sorted ordered array of n elements to find an interval containing // a given key. Returns n-1 if the key is greater than or equal to the last // element, -1 if the key is less than the first element, and otherwise the // index corresponding to the left-hand endpoint of the matching interval. template void searchArray(vm::stack *s) { T key=pop(s); array *a=pop(s); Int size=(Int) a->size(); if(size == 0) {s->push(0); return;} if(key < read(a,0)) {s->push(-1); return;} Int u=size-1; if(key >= read(a,u)) {s->push(u); return;} Int l=0; while (l < u) { Int i=(l+u)/2; if(read(a,i) <= key && key < read(a,i+1)) {s->push(i); return;} if(key < read(a,i)) u=i; else l=i+1; } s->push(0); } extern string emptystring; void writestring(vm::stack *s); template void write(vm::stack *s) { array *a=pop(s); vm::callable *suffix=pop(s,NULL); T first=pop(s); string S=pop(s,emptystring); vm::item it=pop(s); bool defaultfile=isdefault(it); camp::file *f=defaultfile ? &camp::Stdout : vm::get(it); size_t size=checkArray(a); if(!f->isOpen()) return; if(S != "") f->write(S); f->write(first); for(size_t i=0; i < size; ++i) { f->write(tab); f->write(read(a,i)); } if(f->text()) { if(suffix) { s->push(f); suffix->call(s); } else if(defaultfile) { try { f->writeline(); } catch (quit&) { } } } } template void writeArray(vm::stack *s) { array *A=pop(s); array *a=pop(s); string S=pop(s,emptystring); vm::item it=pop(s); bool defaultfile=isdefault(it); camp::file *f=defaultfile ? &camp::Stdout : vm::get(it); size_t asize=checkArray(a); size_t Asize=checkArray(A); if(f->Standard()) interact::lines=0; else if(!f->isOpen()) return; try { if(S != "") {f->write(S); f->writeline();} size_t i=0; bool cont=true; while(cont) { cont=false; bool first=true; if(i < asize) { vm::item& I=(*a)[i]; if(defaultfile) cout << i << ":\t"; if(!I.empty()) f->write(vm::get(I)); cont=true; first=false; } unsigned count=0; for(size_t j=0; j < Asize; ++j) { array *Aj=read(A,j); size_t Ajsize=checkArray(Aj); if(i < Ajsize) { if(f->text()) { if(first && defaultfile) cout << i << ":\t"; for(unsigned k=0; k <= count; ++k) f->write(tab); count=0; } vm::item& I=(*Aj)[i]; if(!I.empty()) f->write(vm::get(I)); cont=true; first=false; } else count++; } ++i; if(cont && f->text()) f->writeline(); } } catch (quit&) { } f->flush(); } template void writeArray2(vm::stack *s) { array *a=pop(s); camp::file *f=pop(s,&camp::Stdout); size_t size=checkArray(a); if(f->Standard()) interact::lines=0; else if(!f->isOpen()) return; try { for(size_t i=0; i < size; i++) { vm::item& I=(*a)[i]; if(!I.empty()) { array *ai=vm::get(I); size_t aisize=checkArray(ai); for(size_t j=0; j < aisize; j++) { if(j > 0 && f->text()) f->write(tab); vm::item& I=(*ai)[j]; if(!I.empty()) f->write(vm::get(I)); } } if(f->text()) f->writeline(); } } catch (quit&) { } f->flush(); } template void writeArray3(vm::stack *s) { array *a=pop(s); camp::file *f=pop(s,&camp::Stdout); size_t size=checkArray(a); if(f->Standard()) interact::lines=0; else if(!f->isOpen()) return; try { for(size_t i=0; i < size;) { vm::item& I=(*a)[i]; if(!I.empty()) { array *ai=vm::get(I); size_t aisize=checkArray(ai); for(size_t j=0; j < aisize; j++) { vm::item& I=(*ai)[j]; if(!I.empty()) { array *aij=vm::get(I); size_t aijsize=checkArray(aij); for(size_t k=0; k < aijsize; k++) { if(k > 0 && f->text()) f->write(tab); vm::item& I=(*aij)[k]; if(!I.empty()) f->write(vm::get(I)); } } if(f->text()) f->writeline(); } } ++i; if(i < size && f->text()) f->writeline(); } } catch (quit&) { } f->flush(); } template void arrayFunc(vm::stack *s) { array *a=pop(s); size_t size=checkArray(a); array *c=new array(size); for(size_t i=0; i < size; i++) (*c)[i]=func(read(a,i)); s->push(c); } vm::array *Identity(Int n); camp::triple operator *(const vm::array& a, const camp::triple& v); camp::triple multshiftless(const vm::array& t, const camp::triple& v); double norm(double *a, size_t n); double norm(camp::triple *a, size_t n); } // namespace run #endif // ARRAYOP_H