Bill Allombert on Sat, 22 Nov 2014 20:58:23 +0100 |
[Date Prev] [Date Next] [Thread Prev] [Thread Next] [Date Index] [Thread Index]
Re: Growing ordered set |
On Fri, Nov 21, 2014 at 03:36:40PM +0100, Bill Allombert wrote: > On Fri, Nov 21, 2014 at 12:18:29PM +0100, Bill Allombert wrote: > > On Fri, Nov 21, 2014 at 01:04:26AM +0100, Karim Belabas wrote: > > Well, but writing everything in C is cheating... > > > > Running my code through gp2c leads > > > > ? setrand(1);#test(10^11) > > %1 = 537776 > > ? ## > > *** last result computed in 1,484 ms. > > ? setrand(1);#test2(10^11) > > %2 = 537776 > > ? ## > > *** last result computed in 41,908 ms. > > > > Thus we could provide a C interface to t_LIST trees that would be not much slower > > than your code. > > To give an example, the attached C file implement a function treeadd() > that can be used in GP as follow: The attached file implement self-balancing AVL trees. The interface is the same, but this is not subject to the worst-cases issues of the previous (not self-balancing) version. You can compile the file with gp2c-run treeavl.c Cheers, Bill.
/*-*- compile-command: "/usr/bin/gcc -c -o ../tree.gp.o -O3 -Wall -fno-strict-aliasing -fomit-frame-pointer -fPIC -I"/home/bill/pari/amd64/include" ../tree.gp.c && /usr/bin/gcc -o ../tree.gp.so -shared -O3 -Wall -fno-strict-aliasing -fomit-frame-pointer -fPIC -Wl,-shared ../tree.gp.o -lc -lm -L/home/bill/pari/amd64/lib -lpari"; -*-*/ #include <pari/pari.h> #include <pari/paripriv.h> /* GP;install("treeadd","lWG","treeadd","./treeavl.so"); */ #define value(i) gmael(list_data(T),(i),1) #define left(i) mael3(list_data(T),(i),2,1) #define right(i) mael3(list_data(T),(i),2,2) #define height(i) mael3(list_data(T),(i),2,3) static long treeheight(GEN T, long i) { return i? height(i): 0; } static long new_leaf(GEN T, GEN x) { pari_sp av = avma; listput(T, mkvec2(x, mkvecsmall3(0,0,1)), 0); avma = av; return lg(list_data(T))-1; } static void fix_height(GEN T, long x) { height(x) = maxss(treeheight(T,left(x)), treeheight(T,right(x)))+1; } static long treebalance(GEN T, long i) { return i ? treeheight(T,left(i)) - treeheight(T,right(i)): 0; } static long rotright(GEN T, long y) { long x = left(y); long t = right(x); right(x) = y; left(y) = t; fix_height(T, y); fix_height(T, x); return x; } static long rotleft(GEN T, long x) { long y = right(x); long t = left(y); left(y) = x; right(x) = t; fix_height(T, x); fix_height(T, y); return y; } static long treeinsert(GEN T, GEN x, long i, long *d) { long b, c; if (i==0 || !list_data(T)) return new_leaf(T, x); c = cmp_universal(x, value(i)); if (c < 0) { long s = treeinsert(T, x, left(i), d); if (s < 0) return s; left(i) = s; } else if (c > 0) { long s = treeinsert(T, x, right(i), d); if (s < 0) return s; right(i) = s; } else return -i; fix_height(T, i); b = treebalance(T, i); if (b > 1) { if (*d > 0) left(i) = rotleft(T, left(i)); return rotright(T, i); } if (b < -1) { if (*d < 0) right(i) = rotright(T, right(i)); return rotleft(T, i); } *d = c; return i; } long treeadd(GEN T, GEN x) { GEN d; long c = 0; long r = treeinsert(T, x, 1, &c); if (r < 0) return -r; if (r == 1) return 0; d = list_data(T); /* By convention we want the root to be 1 */ swap(gel(d,1), gel(d,r)); if (left(1) == 1) left(1)=r; else if (right(1) == 1) right(1)=r; else pari_err_BUG("treeadd"); return 0; }