"""This module contains templates and classes for generating type specific versions of various sort functions. WARNING: This module exists solely as a mechanism to generate a portion of numarray and is not intended to provide any post-installation functionality. """ from basecode import CodeGenerator, template, all_types, _HEADER SORT_HEADER = _HEADER + \ ''' #define STDC_LT(a,b) ((a) < (b)) #define STDC_LE(a,b) ((a) <= (b)) #define STDC_EQ(a,b) ((a) == (b)) #define SWAP(a,b) { SWAP_temp = a; a = b; b = SWAP_temp;} #define swap(i, j) { temp=v[i]; v[i]=v[j]; v[j]=temp; } #define wswap(i, j) { temp=v[i]; v[i]=v[j]; v[j]=temp; wtemp=w[i]; w[i]=w[j]; w[j]=wtemp; } ''' SORT_TEMPLATE = \ ''' void quicksort0( *pl, *pr) { vp, SWAP_temp; *stack[100], **sptr = stack, *pm, *pi, *pj, *pt; for(;;) { while ((pr - pl) > 15) { /* quicksort partition */ pm = pl + ((pr - pl) >> 1); if ((*pm,*pl)) SWAP(*pm,*pl); if ((*pr,*pm)) SWAP(*pr,*pm); if ((*pm,*pl)) SWAP(*pm,*pl); vp = *pm; pi = pl; pj = pr - 1; SWAP(*pm,*pj); for(;;) { do ++pi; while ((*pi,vp)); do --pj; while ((vp,*pj)); if (pi >= pj) break; SWAP(*pi,*pj); } SWAP(*pi,*(pr-1)); /* push largest partition on stack */ if (pi - pl < pr - pi) { *sptr++ = pi + 1; *sptr++ = pr; pr = pi - 1; }else{ *sptr++ = pl; *sptr++ = pi - 1; pl = pi + 1; } } /* insertion sort */ for(pi = pl + 1; pi <= pr; ++pi) { vp = *pi; for(pj = pi, pt = pi - 1; pj > pl && (vp, *pt);) { *pj-- = *pt--; } *pj = vp; } if (sptr == stack) break; pr = *(--sptr); pl = *(--sptr); } } static int quicksort(long niter, long ninargs, long noutargs, void **buffers, long *bsizes) { *pl = ( *) buffers[0]; *pr = pl + niter - 1; quicksort0(pl, pr); return 0; } UFUNC_DESCR1(quicksort, sizeof()); void aquicksort0(long *pl, long *pr, *v) { vp; long SWAP_temp; long *stack[100], **sptr = stack, *pm, *pi, *pj, *pt, vi; for(;;) { while ((pr - pl) > 15) { /* quicksort partition */ pm = pl + ((pr - pl) >> 1); if ((v[*pm],v[*pl])) SWAP(*pm,*pl); if ((v[*pr],v[*pm])) SWAP(*pr,*pm); if ((v[*pm],v[*pl])) SWAP(*pm,*pl); vp = v[*pm]; pi = pl; pj = pr - 1; SWAP(*pm,*pj); for(;;) { do ++pi; while ((v[*pi],vp)); do --pj; while ((vp,v[*pj])); if (pi >= pj) break; SWAP(*pi,*pj); } SWAP(*pi,*(pr-1)); /* push largest partition on stack */ if (pi - pl < pr - pi) { *sptr++ = pi + 1; *sptr++ = pr; pr = pi - 1; }else{ *sptr++ = pl; *sptr++ = pi - 1; pl = pi + 1; } } /* insertion sort */ for(pi = pl + 1; pi <= pr; ++pi) { vi = *pi; vp = v[vi]; for(pj = pi, pt = pi - 1; pj > pl && (vp, v[*pt]);) { *pj-- = *pt--; } *pj = vi; } if (sptr == stack) break; pr = *(--sptr); pl = *(--sptr); } } static int aquicksort(long niter, long ninargs, long noutargs, void **buffers, long *bsizes) { *v = ( *) buffers[0]; long *pl = (long *) buffers[1]; long *pr = pl + niter - 1; aquicksort0(pl, pr, v); return 0; } UFUNC_DESCR2(aquicksort, sizeof(), sizeof(long)); void mergesort0( *pl, *pr, *pw) { vp, *pi, *pj, *pk, *pm; if (pr - pl > 20) { /* merge sort */ pm = pl + ((pr - pl + 1)>>1); mergesort0(pl,pm-1,pw); mergesort0(pm,pr,pw); for(pi = pw, pj = pl; pj < pm; ++pi, ++pj) { *pi = *pj; } for(pk = pw, pm = pl; pk < pi && pj <= pr; ++pm) { if ((*pk,*pj)) { *pm = *pk; ++pk; }else{ *pm = *pj; ++pj; } } for(; pk < pi; ++pm, ++pk) { *pm = *pk; } }else{ /* insertion sort */ for(pi = pl + 1; pi <= pr; ++pi) { vp = *pi; for(pj = pi, pk = pi - 1; pj > pl && (vp, *pk); --pj, --pk) { *pj = *pk; } *pj = vp; } } } static int mergesort(long niter, long ninargs, long noutargs, void **buffers, long *bsizes) { *pl = ( *) buffers[0]; *pr = pl + niter - 1; *pw = ( *) malloc(((1 + niter/2))*sizeof()); if (pw != NULL) { mergesort0(pl, pr, pw); free(pw); return 0; }else{ return -1; } } UFUNC_DESCR1(mergesort, sizeof()); void amergesort0(long *pl, long *pr, *v, long *pw) { vp; long vi, *pi, *pj, *pk, *pm; if (pr - pl > 20) { /* merge sort */ pm = pl + ((pr - pl + 1)>>1); amergesort0(pl,pm-1,v,pw); amergesort0(pm,pr,v,pw); for(pi = pw, pj = pl; pj < pm; ++pi, ++pj) { *pi = *pj; } for(pk = pw, pm = pl; pk < pi && pj <= pr; ++pm) { if ((v[*pk],v[*pj])) { *pm = *pk; ++pk; }else{ *pm = *pj; ++pj; } } for(; pk < pi; ++pm, ++pk) { *pm = *pk; } }else{ /* insertion sort */ for(pi = pl + 1; pi <= pr; ++pi) { vi = *pi; vp = v[vi]; for(pj = pi, pk = pi - 1; pj > pl && (vp, v[*pk]); --pj, --pk) { *pj = *pk; } *pj = vi; } } } static int amergesort(long niter, long ninargs, long noutargs, void **buffers, long *bsizes) { *v = ( *) buffers[0]; long *pl = (long *) buffers[1]; long *pr = pl + niter - 1; long *pw = (long *) malloc(((1 + niter/2))*sizeof(long)); if (pw != NULL) { amergesort0(pl, pr, v, pw); free(pw); return 0; }else{ return -1; } } UFUNC_DESCR2(amergesort, sizeof(), sizeof(long)); void heapsort0( *a, long n) { tmp; long i,j,l; /* The array needs to be offset by one for heapsort indexing */ a -= 1; for (l = n>>1; l > 0; --l) { tmp = a[l]; for (i = l, j = l<<1; j <= n;) { if (j < n && (a[j], a[j+1])) j += 1; if ((tmp, a[j])) { a[i] = a[j]; i = j; j += j; }else break; } a[i] = tmp; } for (; n > 1;) { tmp = a[n]; a[n] = a[1]; n -= 1; for (i = 1, j = 2; j <= n;) { if (j < n && (a[j], a[j+1])) j++; if ((tmp, a[j])) { a[i] = a[j]; i = j; j += j; }else break; } a[i] = tmp; } } static int heapsort(long niter, long ninargs, long noutargs, void **buffers, long *bsizes) { *pl = ( *) buffers[0]; heapsort0(pl, niter); return 0; } UFUNC_DESCR1(heapsort, sizeof()); void aheapsort0(long *a, long n, *v) { long i,j,l, tmp; /* The arrays need to be offset by one for heapsort indexing */ a -= 1; for (l = n>>1; l > 0; --l) { tmp = a[l]; for (i = l, j = l<<1; j <= n;) { if (j < n && (v[a[j]], v[a[j+1]])) j += 1; if ((v[tmp], v[a[j]])) { a[i] = a[j]; i = j; j += j; }else break; } a[i] = tmp; } for (; n > 1;) { tmp = a[n]; a[n] = a[1]; n -= 1; for (i = 1, j = 2; j <= n;) { if (j < n && (v[a[j]], v[a[j+1]])) j++; if ((v[tmp], v[a[j]])) { a[i] = a[j]; i = j; j += j; }else break; } a[i] = tmp; } } static int aheapsort(long niter, long ninargs, long noutargs, void **buffers, long *bsizes) { *v = ( *) buffers[0]; long *pl = (long *) buffers[1]; aheapsort0(pl, niter, v); return 0; } UFUNC_DESCR2(aheapsort, sizeof(), sizeof(long)); void sort0( *v, long left, long right) { temp; long i, last, lastl, lastr, diff; diff = right - left; if (diff <= 0) return; /* choose the pivot randomly. */ i = left + (int) (((right-left)*1.0*rand())/(RAND_MAX+1.0)); /* Split array into values < pivot, and values > pivot. */ swap(left, i); last = left; for(i=left+1; i<=right; i++) if ((v[i], v[left])) { ++ last; swap(last, i); } swap(left, last); lastl = last-1; lastr = last+1; /* Exclude values equal to pivot from recursion */ while((left < lastl) && (v[last],v[lastl])) --lastl; while((lastr < right) && (v[last],v[lastr])) ++lastr; sort0(v, left, lastl); sort0(v, lastr, right); } static int sort(long niter, long ninargs, long noutargs, void **buffers, long *bsizes) { BEGIN_THREADS sort0( ( *) buffers[0], 0, niter-1); END_THREADS return 0; } UFUNC_DESCR1(sort, sizeof()); void asort0( *v, long *w, long left, long right) { temp; long wtemp, i, last, lastl, lastr; if (left >= right) return; /* choose the pivot randomly. */ i = left + (int) (((right-left)*1.0*rand())/(RAND_MAX+1.0)); wswap(left, i); last = left; for(i=left+1; i<=right; i++) if ((v[i], v[left])) { ++ last; wswap(last, i); } wswap(left, last); lastl = last-1; lastr = last+1; /* Exclude values equal to pivot from recursion */ while((left < lastl) && (v[last],v[lastl])) --lastl; while((lastr < right) && (v[last],v[lastr])) ++lastr; asort0(v, w, left, lastl); asort0(v, w, lastr, right); } static int asort(long niter, long ninargs, long noutargs, void **buffers, long *bsizes) { BEGIN_THREADS asort0( ( *) buffers[0], (long *) buffers[1], 0, niter-1); END_THREADS return 0; } CFUNC_DESCR(asort, CFUNC_UFUNC, CHECK_ALIGN, 0, 2, sizeof(), sizeof(long), 0, 0, 0, 0); static long search(long na, *a, v) { long i = 0; *b; while(na > 10) { long mid = na>>1; if ((v, a[mid])) na = mid; else { i += mid; a += mid; na -= mid; } } b = a; while(((*b, v)) && na--) ++ b; return i+(b-a); } static int searchsorted(int niter, int ninargs, int noutargs, void **buffers, long *bsizes) { maybelong nbins; *bins; *values; long *indices; maybelong i; if (NA_checkOneCBuffer("searchsorted", 1, buffers[0], bsizes[0], sizeof(maybelong))) return -1; nbins = *(maybelong *) buffers[0]; if (NA_checkOneCBuffer("searchsorted", nbins, buffers[1], bsizes[1], sizeof())) return -1; bins = ( *) buffers[1]; if (NA_checkOneCBuffer("searchsorted", niter, buffers[2], bsizes[2], sizeof())) return -1; values = ( *) buffers[2]; if (NA_checkOneCBuffer("searchsorted", niter, buffers[3], bsizes[3], sizeof(long))) return -1; indices = (long *) buffers[3]; if (NA_checkIo("searchsorted", 3, 1, ninargs, noutargs)) return -1; BEGIN_THREADS for(i=0; i(nbins, bins, values[i]); END_THREADS return 0; } SELF_CHECKED_CFUNC_DESCR(searchsorted, CFUNC_UFUNC); static int fillarray (long niter, long ninargs, long noutargs, void **buffers, long *bsizes) { long i; start, delta; *tin; *tparams; Int8 itemsizes[2] = { sizeof(), sizeof() }; Int8 iters[2] = { 0, 2 }; if (NA_checkIo("fillarray", 1, 1, ninargs, noutargs) || NA_checkNCBuffers("fillarray", 2, niter, buffers, bsizes, itemsizes, iters)) return -1; tin = ( *) buffers[0]; tparams = ( *) buffers[1]; start = tparams[0]; delta = tparams[1]; BEGIN_THREADS for (i=0; i } END_THREADS return 0; } SELF_CHECKED_CFUNC_DESCR(fillarray, CFUNC_UFUNC); static int nonzeroCoords(long niter, long ninargs, long noutargs, void **buffers, long *bsizes) { *source; maybelong *sstride; long **output; long i, minbsize, next = 0; if (NA_checkIo("nonzeroCoords", 2, noutargs, ninargs, noutargs)) return -1; if (NA_checkOneCBuffer("nonzeroCoords", niter, buffers[0], bsizes[0], sizeof())) return -1; if (NA_checkOneCBuffer("nonzeroCoords", noutargs, buffers[1], bsizes[1], sizeof(maybelong))) return -1; /* Check alignment only. Storage optimization makes numarray shorter than niter likely, possibly even 0! */ for (i=0; i", 0, buffers[2+i], bsizes[2+i], sizeof(long))) return -1; source = ( *) buffers[0]; sstride = (maybelong *) buffers[1]; output = (long **) &buffers[2]; minbsize = bsizes[0]; for(i=0; i: bad stride[%%ld].\\n", i); return -1; } else if (bsizes[i+2] < minbsize) minbsize = bsizes[i+2]; next = 0; for(i=0; i) { long j, index = i; if (next >= minbsize) { PyErr_Format(PyExc_ValueError, "nonzeroCoords: insufficient index space.\\n"); return -1; } for(j=0; j, CFUNC_UFUNC); ''' # ============================================================================ # IMPORTANT: no <>-sugared strings below this point # translate --> %(var)s in templates seen *so far* template.sugar_dict(globals()) # ============================================================================ sort_operator_td = { "lessthan" : "STDC_LT", "lessequal" : "STDC_LE", "equals" : "STDC_EQ", "clear" : "s = 0;", "dotstep" : "s += *ap * *bp;", "fillstep" : "*tin = start; start += delta;", "nonzero" : "source[i] != 0" } sort_complex_td = { "lessthan" : "NUM_CLT", "lessequal" : "NUM_CLE", "equals" : "NUM_CEQ", "clear" : "s.r = 0; s.i=0;", "dotstep" : "Complex64 t; NUM_CMUL(*ap, *bp, t); NUM_CADD(s, t, s);", "fillstep" : "NUM_CASS(*tin, start); NUM_CADD(start, delta, start);", "nonzero" : "((source[i].r !=0) || (source[i].i != 0))" } class SortCodeGenerator(CodeGenerator): def __init__(self, *components): CodeGenerator.__init__(self, *components) self.module = "_sort" self.qualified_module = "numarray._sort" def addcfunc(self, type, name): CodeGenerator.addcfunc(self, name+type, key=repr((type, name))) def gen_body(self): for t in all_types(): d = {} d["typename"] = t if t in ["Complex32","Complex64"]: d.update(sort_complex_td) else: d.update(sort_operator_td) self.codelist.append((self.separator + SORT_TEMPLATE) % d) self.addcfunc(t, "sort") self.addcfunc(t, "asort") self.addcfunc(t, "searchsorted") self.addcfunc(t, "fillarray") self.addcfunc(t, "nonzeroCoords") self.addcfunc(t, "quicksort") self.addcfunc(t, "aquicksort") self.addcfunc(t, "mergesort") self.addcfunc(t, "amergesort") self.addcfunc(t, "heapsort") self.addcfunc(t, "aheapsort") generate_sort_code = SortCodeGenerator(SORT_HEADER)