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}