names default to here(1); complementAsString = function({n},{default local}, // note: using a lookup table has neglible // impact on performance w = words(n,""); pos = nitems(w); str = ""; for (i=nitems(w),i>=1,i--, if (w[i]=="0", str ||= "0"; , str = char(9-num(w[i])+1) || str; //str = ns:arrComplements9Plus[w[i]] || str; break(); ); pos--; ); for (i=pos-1,i>=1,i--, str = char(9-num(w[i])) || str; //str = ::arrComplements9[w[i]] || str; ); return(str); ); addListItems = function({lst},{default local}, // build separate lists of // +ve & -ve numbers lstPos = {}; lstNeg = {}; for (i=1,i<=nitems(lst),i++, if (left(lst[i],1)=="-", s = substitute(lst[i],"-",""); insertinto(lstNeg,s) , insertinto(lstPos,lst[i]) ) ); if (nitems(lstPos)>0, strPos = lstPos[1]; for(i=2,i<=nitems(lstPos),i++, strPos = addIntegerPair(strPos,lstPos[i]) ); ); if (nitems(lstNeg)>0, strNeg = lstNeg[1]; for(i=2,i<=nitems(lstNeg),i++, strNeg = addIntegerPair(strNeg,lstNeg[i]) ); ); if (nitems(lstPos)>0, if (nitems(lstNeg)>0, result = subtractIntegerPair(strPos,strNeg) , result = strPos ) , result = strNeg ); return(result); ); addIntegerPair = function({n1,n2},{default local}, L1 = length(n1); L2 = length(n2); L = min(L1,L2); // arrange such that rN1 always represents // the largest of the two integers if (L1>=L2, r_n1 = reverse(n1); rN1 = words(r_n1,""); rN2 = words(reverse(n2),""); , r_n1 = reverse(n2); rN1 = words(r_n1,""); rN2 = words(reverse(n1),""); L1 = length(rN1); L2 = length(rN2); ); str = ""; carry = 0; for (i=1,i<=L,i++, s = num(rN1[i]) + num(rN2[i]); sc = s+carry; if (sc>=10, str ||= char(sc-10); carry = 1; , str ||= char(sc); carry = 0; ); ); i = L; while(carry, i++; if (i<=L1, s = num(rn1[i]); sc = s + carry; if (sc>=10, str ||= char(sc-10); carry = 1; , str ||= char(sc); carry = 0; ) , str ||= char(carry); carry = 0; ) ); if (i0, rN2 ||= repeat({"0"},diff); ); if (diff<0, rN1 ||= repeat({"0"},-diff); L = l2; ); str = ""; carry = 0; for (i=1,i<=L,i++, s = num(rN1[i]) - num(rN2[i]); sc = s-carry; if (sc<0, str ||= char(sc+10); carry = 1; , str ||= char(sc); carry = 0; ); ); if (carry, s2 = complementAsString(reverse(str)); pat = PatPos(0) + "0" + PatRem()>>s; trailingZeros = 1; while(trailingZeros, trailingZeros = PatMatch(s2,pat,s) ); result = "-" || s2 , result = reverse(str); pat = PatPos(0) + "0" + PatRem()>>s; trailingZeros = 1; while(trailingZeros, trailingZeros = PatMatch(result,pat,s) ); ); return(result); ); subtractBig = function({n1,n2},{default local}, sign1 = left(n1,1)=="-"; sign2 = left(n2,1)=="-"; if (sign1, substituteinto(n1,"-","") ); if (sign2, substituteinto(n2,"-","") ); sign = char(sign1) || char(sign2); match(sign, "00", answer = subtractIntegerPair(n1,n2), "11", answer = subtractIntegerPair(n2,n1), "01", answer = addIntegerPair(n1,n2), "10", answer = "-" || addIntegerPair(n1,n2) ); if (length(answer)==0,answer="0"); return(answer); ); addBig = function({n1,n2=.},{default local}, if (ismissing(n2), answer = addListItems(n1) , sign1 = left(n1,1)=="-"; sign2 = left(n2,1)=="-"; if (sign1, substituteinto(n1,"-","") ); if (sign2, substituteinto(n2,"-","") ); sign = char(sign1) || char(sign2); match(sign, "00", answer = addIntegerPair(n1,n2), "11", answer = "-" || addIntegerPair(n1,n2), "01", answer = subtractIntegerPair(n1,n2), "10", answer = subtractIntegerPair(n2,n1) ) ); if (length(answer)==0,answer="0"); return(answer); );