aboutsummaryrefslogtreecommitdiffstats
path: root/src/main/java/com/softsynth/math/Polynomial.java
blob: 6c6f96a9f677b5f26ccf7720457d5120fe1077e7 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
/*
 * Copyright 1997 Phil Burk, Mobileer Inc
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.softsynth.math;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.Vector;

/**
 * Polynomial<br>
 * Implement polynomial using Vector as coefficient holder. Element index is power of X, value at a
 * given index is coefficient.<br>
 * <br>
 *
 * @author Nick Didkovsky, (C) 1997 Phil Burk and Nick Didkovsky
 */

public class Polynomial {

    private static final Logger LOGGER = LoggerFactory.getLogger(Polynomial.class);

    private final Vector terms;

    // TODO: Does this need to exist?
    static class DoubleHolder {
        double value;

        public DoubleHolder(double val) {
            value = val;
        }

        public double get() {
            return value;
        }

        public void set(double val) {
            value = val;
        }
    }

    /** create a polynomial with no terms */
    public Polynomial() {
        terms = new Vector();
    }

    /** create a polynomial with one term of specified constant */
    public Polynomial(double c0) {
        this();
        appendTerm(c0);
    }

    /** create a polynomial with two terms with specified coefficients */
    public Polynomial(double c1, double c0) {
        this(c0);
        appendTerm(c1);
    }

    /** create a polynomial with specified coefficients */
    public Polynomial(double c2, double c1, double c0) {
        this(c1, c0);
        appendTerm(c2);
    }

    /** create a polynomial with specified coefficients */
    public Polynomial(double c3, double c2, double c1, double c0) {
        this(c2, c1, c0);
        appendTerm(c3);
    }

    /** create a polynomial with specified coefficients */
    public Polynomial(double c4, double c3, double c2, double c1, double c0) {
        this(c3, c2, c1, c0);
        appendTerm(c4);
    }

    /**
     * Append a term with specified coefficient. Power will be next available order (ie if the
     * polynomial is of order 2, appendTerm will supply the coefficient for x^3
     */
    public void appendTerm(double coefficient) {
        terms.addElement(new DoubleHolder(coefficient));
    }

    /** Set the coefficient of given term */
    public void setTerm(double coefficient, int power) {
        // If setting a term greater than the current order of the polynomial, pad with zero terms
        int size = terms.size();
        if (power >= size) {
            for (int i = 0; i < (power - size + 1); i++) {
                appendTerm(0);
            }
        }
        ((DoubleHolder) terms.elementAt(power)).set(coefficient);
    }

    /**
     * Add the coefficient of given term to the specified coefficient. ex. addTerm(3, 1) add 3x to a
     * polynomial, addTerm(4, 3) adds 4x^3
     */
    public void addTerm(double coefficient, int power) {
        setTerm(coefficient + get(power), power);
    }

    /** @return coefficient of nth term (first term=0) */
    public double get(int power) {
        if (power >= terms.size())
            return 0.0;
        else
            return ((DoubleHolder) terms.elementAt(power)).get();
    }

    /** @return number of terms in this polynomial */
    public int size() {
        return terms.size();
    }

    /**
     * Add two polynomials together
     *
     * @return new Polynomial that is the sum of p1 and p2
     */
    public static Polynomial plus(Polynomial p1, Polynomial p2) {
        Polynomial sum = new Polynomial();
        for (int i = 0; i < Math.max(p1.size(), p2.size()); i++) {
            sum.appendTerm(p1.get(i) + p2.get(i));
        }
        return sum;
    }

    /**
     * Subtract polynomial from another. (First arg - Second arg)
     *
     * @return new Polynomial p1 - p2
     */
    public static Polynomial minus(Polynomial p1, Polynomial p2) {
        Polynomial sum = new Polynomial();
        for (int i = 0; i < Math.max(p1.size(), p2.size()); i++) {
            sum.appendTerm(p1.get(i) - p2.get(i));
        }
        return sum;
    }

    /**
     * Multiply two Polynomials
     *
     * @return new Polynomial that is the product p1 * p2
     */

    public static Polynomial mult(Polynomial p1, Polynomial p2) {
        Polynomial product = new Polynomial();
        for (int i = 0; i < p1.size(); i++) {
            for (int j = 0; j < p2.size(); j++) {
                product.addTerm(p1.get(i) * p2.get(j), i + j);
            }
        }
        return product;
    }

    /**
     * Multiply a Polynomial by a scaler
     *
     * @return new Polynomial that is the product p1 * p2
     */

    public static Polynomial mult(double scaler, Polynomial p1) {
        Polynomial product = new Polynomial();
        for (int i = 0; i < p1.size(); i++) {
            product.appendTerm(p1.get(i) * scaler);
        }
        return product;
    }

    /** Evaluate this polynomial for x */
    public double evaluate(double x) {
        double result = 0.0;
        for (int i = 0; i < terms.size(); i++) {
            result += get(i) * Math.pow(x, i);
        }
        return result;
    }

    @Override
    public String toString() {
        String s = "";
        if (size() == 0)
            s = "empty polynomial";
        boolean somethingPrinted = false;
        for (int i = size() - 1; i >= 0; i--) {
            if (get(i) != 0.0) {
                if (somethingPrinted)
                    s += " + ";
                String coeff = "";
                // if (get(i) == (int)(get(i)))
                // coeff = (int)(get(i)) + "";
                if ((get(i) != 1.0) || (i == 0))
                    coeff += get(i);
                if (i == 0)
                    s += coeff;
                else {
                    String power = "";
                    if (i != 1)
                        power = "^" + i;
                    s += coeff + "x" + power;
                }
                somethingPrinted = true;
            }
        }
        return s;
    }

    public static void main(String[] args) {
        Polynomial p1 = new Polynomial();
        LOGGER.debug("p1=" + p1);
        Polynomial p2 = new Polynomial(3);
        LOGGER.debug("p2=" + p2);
        Polynomial p3 = new Polynomial(2, 3);
        LOGGER.debug("p3=" + p3);
        Polynomial p4 = new Polynomial(1, 2, 3);
        LOGGER.debug("p4=" + p4);
        LOGGER.debug("p4*5=" + Polynomial.mult(5.0, p4));

        LOGGER.debug("{}", p4.evaluate(10));

        LOGGER.debug("{}", Polynomial.plus(p4, p1));
        LOGGER.debug("{}", Polynomial.minus(p4, p3));
        p4.setTerm(12.2, 5);
        LOGGER.debug("{}", p4);
        p4.addTerm(0.8, 5);
        LOGGER.debug("{}", p4);
        p4.addTerm(0.8, 7);
        LOGGER.debug("{}", p4);
        LOGGER.debug("{}", Polynomial.mult(p3, p2));
        LOGGER.debug("{}", Polynomial.mult(p3, p3));
        LOGGER.debug("{}", Polynomial.mult(p2, p2));

        Polynomial t2 = new Polynomial(2, 0, -1); // 2x^2-1, Chebyshev Polynomial of order 2
        Polynomial t3 = new Polynomial(4, 0, -3, 0); // 4x^3-3x, Chebyshev Polynomial of order 3
        // Calculate Chebyshev Polynomial of order 4 from relation Tk+1(x) = 2xTk(x) - Tk-1(x)
        Polynomial t4 = Polynomial.minus(Polynomial.mult(t3, (new Polynomial(2, 0))), t2);
        LOGGER.debug(t2 + "\n" + t3 + "\n" + t4);
        // com.softsynth.jmsl.util

    }
}