> Exact arithmetic on the Stern-Brocot tree
Thanks for those. The video really helps.
I've ordered a pile of books on the subject so I'm kinda stalled
until they arrive. Here are two drafts that may not work,
and are definitely incomplete. But it's something to look at.
$ cat q.c
#include <math.h>
#include <stdlib.h>
#include <string.h>
typedef struct field {
int (*add)();
int (*mul)();
int (*le)();
} *field;
typedef struct B {
field f;
int b;
} B;
typedef struct I {
field f;
int b,d[1];
} I;
typedef struct Qpq {
field f;
I p,q;
} Qpq;
typedef struct Qnmd {
field f;
int n,m,b,d[1];
} Qnmd;
typedef struct Qenmd {
field f;
int e,n,m,b,d[1];
} Qenmd;
Qnmd *qneg(Qnmd *q){
Qnmd *z;
z=malloc(sizeof*z + (q->n+q->m)*sizeof*z->d);
*z=*q;
for (int j=0;j<=q->n;j++){
z->d[j]= q->b-1 - q->d[j];
}
return z;
}
Qnmd *Qnmd_(int i){
Qnmd *t=&(Qnmd){.b=10};
if (i < 0) return qneg(Qnmd_(-i));
t->m=0;
t->n=ceil(log(i==0?1:i)/log(t->b));
if (t->n==0) t->n=1;
Qnmd *z;
z=malloc(sizeof*z + t->n*sizeof*z->d);
*z=*t;
for (int j=0; j<=z->n; j++){
z->d[j]= i % z->b;
i /= z->b;
}
return z;
}
#include <stdio.h>
void prnq(Qnmd *q){
printf("(%d, %d, (", q->n,q->m);
for (int j=0; j< q->n+q->m; j++)
printf("%s%d", j?", ":"", q->d[j]);
printf(")\n");
}
int main() {
for (int j=0; j<10; j++){
Qnmd *q=Qnmd_(j);
prnq(q);
}
for (int j=0; j<10; j++){
Qnmd *q=Qnmd_(-(j+1));
prnq(q);
}
}
$ cat qn.c
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;
q qneg(q x){
return qsub(qlong(0),x);
}
q qlong(long i){
if (i<0) return qneg(qlong(-i));
int m=0;
int n=ceiling(log(i)/log(base));
q z=malloc(sizeof*z + (n+m)*sizeof*z->d);
z->b=base; z->n=n; z->m=m;
for(int j=0; j<n; j++){
z->d[j] = i % base;
i /= base;
}
return z;
}
int qsign(q x){
switch(((x->n==0))<<1+(x->m==0)){
case (1<<1)+1: return 0;
case 1<<1: return -1;
case 1: return 1;
case 0: return x->d[x->n-1] - x->d[x->n+x->m-1];
}
}
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,tt=0;
q z=malloc(sizeof*z + (n+m)*sizeof*z->d);
z->b=base; z->n=n; z->m=m;
for(int k=0; k<n+m; k++){
t = x->d[k] + y->d[k] + c;
z->d[k] = t % base;
c = t / base;
tt=t;
}
}
q qsub(q x,q y){
int m=lcm(x->m,y->m);
int n=max(x->n,y->n)+m+2;
q z=malloc(sizeof*z + (n+m)*sizeof*z->d);
z->b=base; z->n=n; z->m=m;
}
q qmul(q x,q y){
int m=lcm(x->m,y->m);
int n=x->n+y->n+m+1;
q z=malloc(sizeof*z + (n+m)*sizeof*z->d);
z->b=base; z->n=n; z->m=m;
}
q qdiv(q x,q y){
int m=lcm(x->m,euler_phi(y));
int n= y->n<=y->m ? x->n + y->n + m + 1 :
y->m<y->n && y->n<=x->n ? x->n - y->n + m + 1:
m+1;
q z=malloc(sizeof*z + (n+m)*sizeof*z->d);
z->b=base; z->n=n; z->m=m;
}
fwiw