001/*
002 * $Id$
003 */
004
005package edu.jas.root;
006
007
008import java.util.ArrayList;
009import java.util.List;
010
011import org.apache.logging.log4j.LogManager;
012import org.apache.logging.log4j.Logger;
013
014import edu.jas.arith.BigInteger;
015import edu.jas.arith.BigRational;
016
017
018/**
019 * Real arithmetic utilities.
020 * @author Heinz Kredel
021 */
022
023public class RealArithUtil {
024
025
026    private static final Logger logger = LogManager.getLogger(RealArithUtil.class);
027
028
029    private static final boolean debug = logger.isDebugEnabled();
030
031
032    /**
033     * Continued fraction.
034     * @param A real algebraic number.
035     * @param M approximation, length of continued fraction.
036     * @return continued fraction for A.
037     */
038    public static List<BigInteger> continuedFraction(RealAlgebraicNumber<BigRational> A, final int M) {
039        List<BigInteger> cf = new ArrayList<BigInteger>();
040        if (A == null) {
041            return cf;
042        }
043        RealAlgebraicRing<BigRational> fac = A.ring;
044        if (A.isZERO()) {
045            cf.add(BigInteger.ZERO);
046            return cf;
047        }
048        if (A.isONE()) {
049            cf.add(BigInteger.ONE);
050            return cf;
051        }
052        RealAlgebraicNumber<BigRational> x = A;
053        BigInteger q = new BigInteger(x.floor());
054        cf.add(q);
055        RealAlgebraicNumber<BigRational> xd = x.subtract(fac.fromInteger(q.val));
056        int m = 0;
057        while (!xd.isZERO() && m++ < M) {
058            //System.out.println("xd = " + xd + ", q = " + q + ", x = " + x);
059            x = xd.inverse();
060            q = new BigInteger(x.floor());
061            cf.add(q);
062            xd = x.subtract(fac.fromInteger(q.val));
063        }
064        if (debug) {
065            logger.info("cf = " + cf);
066        }
067        return cf;
068    }
069
070
071    /**
072     * Continued fraction approximation.
073     * @param A continued fraction.
074     * @return ratonal number approximation for A.
075     */
076    public static BigRational continuedFractionApprox(List<BigInteger> A) {
077        BigRational ab = BigRational.ZERO;
078        if (A == null || A.isEmpty()) {
079            return ab;
080        }
081        BigInteger a2, a1, b2, b1, a, b;
082        a2 = BigInteger.ZERO;
083        a1 = BigInteger.ONE;
084        b2 = BigInteger.ONE;
085        b1 = BigInteger.ZERO;
086        for (BigInteger q : A) {
087            a = q.multiply(a1).sum(a2);
088            b = q.multiply(b1).sum(b2);
089            //System.out.println("A/B = " + new BigRational(a,b));
090            a2 = a1;
091            a1 = a;
092            b2 = b1;
093            b1 = b;
094        }
095        ab = new BigRational(a1, b1);
096        return ab;
097    }
098
099}