I'm implementing arithmetic functions for numbers in a quote notation representation, which is a form of p-adic numbers. Taking the basic idea from this paper, I have a struct and a constructor.
enum { base = 10 };
/*
d[n+m-1] ... d[n+1] d[n] ' d[n-1] ... d[2] d[1] d[0]
Sum(i=0..n d[i]*b^i) + Sum(i=n+1..n+m d[i]*b^i/(b^m-1))
*/
typedef struct q {
int b,n,m,d[];
} *q;
This is mostly the same as the paper, but I've changed the indexing a little.
/* nb. not defined for LONG_MIN */
q qlong(long i){
if (i<0) return qneg(qlong(-i));
int m=0;
int n=i?ceil(log(i)/log(base)):0;
q z=malloc(sizeof*z + (n+m)*sizeof*z->d);
z->b=base; z->n=n; z->m=m;
int j;
for(j=0; j<n; j++){
z->d[j] = i % base;
i /= base;
}
qprint(z);
return z;
}
Using the bounds presented in the paper, I can estimate the digits of the result of addition.
q qadd(q x,q y){
int m=lcm(x->m,y->m);
int n=max(x->n,y->n)+m+2;
int t,c=0;
q z=malloc(sizeof*z + (n+m)*sizeof*z->d);
z->b=base; z->n=n; z->m=m;
int k;
for(k=0; k<n+m; k++){
t = qdig(x,k) + qdig(y,k) + c;
z->d[k] = t % base;
c = t / base;
}
findrepetition(z);
return z;
}
But this may perform unnecessary calculations once it hits a repeated state. And even more calculations in the normalization step.
In his earlier paper, Hehner presents an algorithm for detecting repetitions.
void findrepetition(q z){
int i;
int j;
qprint(z);
for(i=1; i<z->n+z->m-1; i*=2) {
for(j=i+1; j<2*i; j++) {
if (z->d[j-1]==z->d[i-1]) {
z->n=i;
z->m=j-i;
return;
}
}
}
}
But can I incorporate this into my existing calculation loop instead of making a second pass? I've avoided i and j in qadd
so their use in these loops doesn't conflict with my usage.
Some of this material was previously posted to comp.lang.c and there is a linked video which is an excellent introduction to the whole topic.