[BACK]Return to oh_number.rr CVS log [TXT][DIR] Up to [local] / OpenXM / src / asir-contrib / packages / src

File: [local] / OpenXM / src / asir-contrib / packages / src / oh_number.rr (download)

Revision 1.9, Fri Sep 24 04:51:02 2021 UTC (2 years, 8 months ago) by takayama
Branch: MAIN
CVS Tags: HEAD
Changes since 1.8: +3 -2 lines

For bigfloat.

/* $OpenXM: OpenXM/src/asir-contrib/packages/src/oh_number.rr,v 1.9 2021/09/24 04:51:02 takayama Exp $ */
module oh_number;
localf rats_prec;
localf rats;
localf to_continued_fraction;
localf continued_fraction_to_rat;
localf sign, abs;
localf deval;

def sign(X) {
    return (X==0)? 0: (X<0)? -1: 1;
}

def abs(A) {
    return A>=0? A: -A;
}

def deval(A) {
    return eval(A*exp(0));
}

def rats_prec(X,K) {
    O = cons(["rev",no],getopt());
    L = to_continued_fraction(X,K|option_list=O);
    return L[2];
}

def to_continued_fraction(X,K) {
    R=getopt(round);
    Round=0;
    if (R==floor) { 
        Round=-1;
    }else if (R==ceil) {
        Round=1;
    }
    Sign = 1;
    if (X<0) {
        Sign = -1; X = -X; 
    }
/* continued fraction (X ~= reverse(L)) */
    if (ntype(X) > 1) Bound=2^number_floor(setprec()*deval(log(10)/log(2)));
    else Bound = 2^62;
    if (X==0 || (ntype(X) && Bound*X < 1)) {
        return [Sign, [0], 0];
    }
    L = [];
    if (ntype(X)==1) {
        X = deval(X);
    }
    N1 = 1; N2 = 0;
    D1 = 0; D2 = 1; 
    Prec=10^K; // absolute error is less than 1/Prec
    for(I=0; ;I++,X=1/X) {
        Q = number_floor(X);
        L = cons(Q,L);
        X = X - Q;
        N = Q*N1 + N2; N2=N1; N1=N;
        D = Q*D1 + D2; D2=D1; D1=D;
        if ( X==0 || (ntype(X) && Bound*X < 1) || Prec < D1*D2 ) {
            break;
        }
    }
    R = (2*irem(I,2)-1)*Sign*Round;
    if (X && (!Round || R < 0) ) {
        if (length(L)>1) {
            L = cdr(L); D1=D2; N1=N2;
        }else {
            N1 = L[0] + Round; D1 = 1;
            L  = [N1];
        }
    }
    if(getopt(rev)!=no) {
        L = reverse(L);
    }
    return [Sign,L,Sign*(N1/D1)];
}

/* continued fraction to rational number */
def continued_fraction_to_rat(L) {
    Sign = 1;
    if (type(L[1])==4) { /* if L ~= [Sign, List] */
        Sign = L[0];
        L = L[1];
    }
    if(getopt(rev)!=no) {
        L = reverse(L);
    }
    for(R=car(L),L=cdr(L); L!=[]; L=cdr(L)) {
        R = car(L) + 1/R;
    }
    return Sign*R;
}

def rats(X) {
   P=getopt(prec);
   if (type(P) == 1 || P == 0) return rats_prec(X,P|option_list=getopt());
   else return rats_prec(X,14|option_list=getopt());
}

endmodule;
end$
/*
ctrl("bigfloat",1);
setprec(100);
ctrl("real_digit",32);

printf("\n")$
Z=deval(@pi);
R=rats(Z);
printf("Error=%a\n",number_abs(Z-R));

printf("\n")$
Z=0.7595;
R=rats(Z);
printf("Error=%a\n",number_abs(Z-R));

printf("\n")$
Z=deval(2^(1/2));
R=rats(Z);
printf("Error=%a\n",number_abs(Z-R));

printf("\n")$
Z=deval(3^(1/2));
R=rats(Z);
printf("Error=%a\n",number_abs(Z-R));

end;
*/