001/*
002 * $Id: RootUtil.java 5872 2018-07-20 16:01:46Z 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    public static <C extends RingElem<C> & Rational> Rectangle<C> parseRectangle(RingFactory<Complex<C>> fac,
108                    String s) {
109        int r = s.length();
110        int el = s.indexOf("[");
111        if (el >= 0) {
112            int ri = s.indexOf("]");
113            if (ri > 0) {
114                r = ri;
115            }
116        } else {
117            el = -1;
118        }
119        //System.out.println("s  = " + s);
120        String iv = s.substring(el + 1, r).trim();
121        //System.out.println("iv = " + iv);
122        int k = iv.indexOf(",");
123        if (k < 0) {
124            k = s.indexOf(" ");
125        }
126        if (k < 0) {
127            Complex<C> mid = fac.parse(iv);
128            return new Rectangle<C>(mid);
129        }
130        //System.out.println("k  = " + k + ", len = " + iv.length());
131        String ls = iv.substring(0, k).trim();
132        String rs = iv.substring(k + 1, iv.length()).trim();
133        //System.out.println("ls = " + ls + ", rs = " + rs);
134        Object osw = fac.parse(ls);
135        Object one = fac.parse(rs);
136        //System.out.println("osw = " + osw + ", one = " + one);
137        Complex<C> sw;
138        Complex<C> ne;
139        if (osw instanceof Complex) {
140            sw = (Complex<C>)osw;
141            ne = (Complex<C>)one;
142        } else if (osw instanceof ComplexAlgebraicNumber) {
143            ComplexAlgebraicNumber csw = (ComplexAlgebraicNumber) osw;
144            ComplexAlgebraicNumber cne = (ComplexAlgebraicNumber) one;
145            //System.out.println("csw::ring = " + csw.ring.algebraic.toScript());
146            sw = (Complex<C>) csw.magnitude();
147            ne = (Complex<C>) cne.magnitude();
148        } else {
149            sw = fac.getONE().negate();
150            ne = fac.getONE();
151        }
152        //System.out.println("sw = " + sw + ", ne = " + ne);
153        if (debug) {
154            logger.debug("Rectangle: sw = " + sw + ", ne = " + ne);
155        }
156        return new Rectangle<C>(sw, ne);
157    }
158
159}