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}