001/* 002 * $Id: RootUtil.java 5934 2018-09-30 11:23:44Z kredel $ 003 */ 004 005package edu.jas.root; 006 007 008import java.util.List; 009 010import org.apache.logging.log4j.Logger; 011import org.apache.logging.log4j.LogManager; 012 013import edu.jas.arith.Rational; 014import edu.jas.poly.Complex; 015import edu.jas.structure.RingElem; 016import edu.jas.structure.RingFactory; 017 018 019/** 020 * Real root utilities. For example real root count. 021 * @author Heinz Kredel 022 */ 023public class RootUtil { 024 025 026 private static final Logger logger = LogManager.getLogger(RootUtil.class); 027 028 029 private static final boolean debug = logger.isDebugEnabled(); 030 031 032 /** 033 * Count changes in sign. 034 * @param <C> coefficient type. 035 * @param L list of coefficients. 036 * @return number of sign changes in L. 037 */ 038 public static <C extends RingElem<C>> long signVar(List<C> L) { 039 long v = 0; 040 if (L == null || L.isEmpty()) { 041 return v; 042 } 043 C A = L.get(0); 044 for (int i = 1; i < L.size(); i++) { 045 C B = L.get(i); 046 while (B == null || B.signum() == 0) { 047 i++; 048 if (i >= L.size()) { 049 return v; 050 } 051 B = L.get(i); 052 } 053 if (A.signum() * B.signum() < 0) { 054 v++; 055 } 056 A = B; 057 } 058 return v; 059 } 060 061 062 /** 063 * Parse interval for a real root from String. 064 * @param s String, syntax: [left, right] or [mid]. 065 * @return Interval from s. 066 */ 067 public static <C extends RingElem<C> & Rational> Interval<C> parseInterval(RingFactory<C> fac, String s) { 068 int r = s.length(); 069 int el = s.indexOf("["); 070 if (el >= 0) { 071 int ri = s.indexOf("]"); 072 if (ri > 0) { 073 r = ri; 074 } 075 } else { 076 el = -1; 077 } 078 //System.out.println("s = " + s); 079 String iv = s.substring(el + 1, r).trim(); 080 //System.out.println("iv = " + iv); 081 int k = iv.indexOf(","); 082 if (k < 0) { 083 k = s.indexOf(" "); 084 } 085 if (k < 0) { 086 C mid = fac.parse(iv); 087 return new Interval<C>(mid); 088 } 089 //System.out.println("k = " + k + ", len = " + iv.length()); 090 String ls = iv.substring(0, k).trim(); 091 String rs = iv.substring(k + 1, iv.length()).trim(); 092 //System.out.println("ls = " + ls + ", rs = " + rs); 093 C left = fac.parse(ls); 094 C right = fac.parse(rs); 095 if (debug) { 096 logger.debug("Interval: left = " + left + ", right = " + right); 097 } 098 return new Interval<C>(left, right); 099 } 100 101 102 /** 103 * Parse rectangle for a complex root from String. 104 * @param s String, syntax: [south-west, north-east] or [mid]. 105 * @return Interval from s. 106 */ 107 @SuppressWarnings("unchecked") 108 public static <C extends RingElem<C> & Rational> Rectangle<C> parseRectangle(RingFactory<Complex<C>> fac, 109 String s) { 110 int r = s.length(); 111 int el = s.indexOf("["); 112 if (el >= 0) { 113 int ri = s.indexOf("]"); 114 if (ri > 0) { 115 r = ri; 116 } 117 } else { 118 el = -1; 119 } 120 //System.out.println("s = " + s); 121 String iv = s.substring(el + 1, r).trim(); 122 //System.out.println("iv = " + iv); 123 int k = iv.indexOf(","); 124 if (k < 0) { 125 k = s.indexOf(" "); 126 } 127 if (k < 0) { 128 Complex<C> mid = fac.parse(iv); 129 return new Rectangle<C>(mid); 130 } 131 //System.out.println("k = " + k + ", len = " + iv.length()); 132 String ls = iv.substring(0, k).trim(); 133 String rs = iv.substring(k + 1, iv.length()).trim(); 134 //System.out.println("ls = " + ls + ", rs = " + rs); 135 Object osw = fac.parse(ls); 136 Object one = fac.parse(rs); 137 //System.out.println("osw = " + osw + ", one = " + one); 138 Complex<C> sw; 139 Complex<C> ne; 140 if (osw instanceof Complex) { 141 sw = (Complex<C>)osw; 142 ne = (Complex<C>)one; 143 } else if (osw instanceof ComplexAlgebraicNumber) { 144 ComplexAlgebraicNumber csw = (ComplexAlgebraicNumber) osw; 145 ComplexAlgebraicNumber cne = (ComplexAlgebraicNumber) one; 146 //System.out.println("csw::ring = " + csw.ring.algebraic.toScript()); 147 sw = (Complex<C>) csw.magnitude(); 148 ne = (Complex<C>) cne.magnitude(); 149 } else { 150 sw = fac.getONE().negate(); 151 ne = fac.getONE(); 152 } 153 //System.out.println("sw = " + sw + ", ne = " + ne); 154 if (debug) { 155 logger.debug("Rectangle: sw = " + sw + ", ne = " + ne); 156 } 157 return new Rectangle<C>(sw, ne); 158 } 159 160}