diff --git a/lib/modules/Array.pmod b/lib/modules/Array.pmod index 595653f4b3d9e9045895950d32772a768121a96a..f0292798d16808d16421067e6e6f5502dccba3b3 100644 --- a/lib/modules/Array.pmod +++ b/lib/modules/Array.pmod @@ -186,3 +186,153 @@ array transpose(array x) for(int e=0;e<sizeof(x[0]);e++) ret[e]=column(x,e); return ret; } + +// diff3, complement to diff (alpha stage) + +array(array(array(mixed))) diff3(array mid,array left,array right) +{ + array lmid,ldst; + array rmid,rdst; + + [lmid,ldst]=diff(mid,left); + [rmid,rdst]=diff(mid,right); + + array res=({}); + int pos; + int lpos=0,rpos=0; + int l=0,r=0; + array eq=({}); + + for (l=0; l<sizeof(lmid); l++) + { + lpos=-1; + // find next equal l--m + while (l<sizeof(lmid) && lmid[l]!=ldst[l]) + { + res+=({({lmid[l],ldst[l],({})})}); + + // skip these + + for (lpos=0; r<sizeof(rmid) && lpos<sizeof(lmid[l]); lpos++) + { + mixed x=lmid[l][lpos]; + for(;;) + { + if (rpos>=sizeof(rmid[r])) + { + if (rpos<sizeof(rdst[r])) + res+=({({({}),({}),rdst[r][rpos..]})}); + rpos=0; + r++; + if (r==sizeof(rmid)) break; + } + else if (rmid[r][rpos]==x) + { + if (rpos<sizeof(rdst[r])) + res+=({({({}),({}),({rdst[r][rpos]})})}); + rpos++; + break; + } + else + { + if (rpos<sizeof(rdst[r])) + res+=({({({}),({}),({rdst[r][rpos]})})}); + rpos++; + } + } + } + l++; + } + if (l==sizeof(lmid)) break; + + // loop over this, find this in r + for (lpos=0; r<sizeof(rmid) && lpos<sizeof(lmid[l]); lpos++) + { + mixed x=lmid[l][lpos]; + for(;;) + { + if (rpos>=sizeof(rmid[r])) + { + if (rpos<sizeof(rdst[r])) + res+=({({({}),({}),rdst[r][rpos..]})}); + rpos=0; + r++; + if (r==sizeof(rmid)) break; + } + else if (rmid[r][rpos]==x) + { + if (rmid[r]!=rdst[r]) // unequal + if (r<sizeof(rdst[r])) + res+=({({({x}),({x}),({rdst[r][rpos]})})}); + else + res+=({({({x}),({x}),({})})}); + else // equal! + { + array ax=({x}); + res+=({({ax,ax,ax})}); + } + rpos++; + break; + } + else + { + if (rpos<sizeof(rdst[r])) + res+=({({({}),({}),({rdst[r][rpos]})})}); + rpos++; + } + } + } + } + + // flush what's left + + if (r<sizeof(rmid)) + { + if (rmid[r]!=rdst[r]) + { + if (rpos<sizeof(rmid[r])) + res+=({({rmid[r][rpos..],({}),({})})}); + if (rpos<sizeof(rdst[r])) + res+=({({({}),({}),rdst[r][rpos..]})}); + } + else + res+=({({rmid[r][rpos..],({}),rdst[r][rpos..]})}); + r++; + } + + if (l<sizeof(lmid) && lpos!=-1) + { + if (lpos<sizeof(lmid[l])) + res+=({({lmid[l][lpos..],({}),({})})}); + if (lpos<sizeof(ldst[l])) + res+=({({({}),({}),ldst[l][lpos..]})}); + } + + res+=transpose( ({ldst[l..],lmid[l..], + map(allocate(sizeof(lmid)-l), + lambda(int x) { return ({}); })}) ); + + res+=transpose( ({rmid[r..], + map(allocate(sizeof(rmid)-r), + lambda(int x) { return ({}); }), + rdst[r..]}) ); + + array res2=({}); + + for (l=0; l<sizeof(res); ) + { + int ol; + for (ol=l; + l<sizeof(res) && res[l][0]==res[l][1] && res[l][1]==res[l][2]; + l++); + if (ol!=l) // got some equal + res2+=({sum_arrays(`+,@res[ol..l-1])}); + for (ol=l; + l<sizeof(res) && !(res[l][0]==res[l][1] && res[l][1]==res[l][2]); + l++); + if (ol!=l) // got some unequal + res2+=({sum_arrays(`+,@res[ol..l-1])}); + } + + return transpose(res2); +}