View Javadoc
1   /*
2    * Copyright (C) 2012 Alberto Irurueta Carro (alberto@irurueta.com)
3    *
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    *         http://www.apache.org/licenses/LICENSE-2.0
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  package com.irurueta.numerical.roots;
17  
18  import com.irurueta.algebra.Complex;
19  import com.irurueta.numerical.LockedException;
20  import com.irurueta.numerical.NotAvailableException;
21  import com.irurueta.numerical.NotReadyException;
22  
23  /**
24   * Class to estimate the root of a first degree polynomial along with other
25   * polynomial properties.
26   * A first degree polynomial is defined by its parameters as p(x) = a * x + b,
27   * hence the polynomial can be simply be defined by an array of length 2 [b, a].
28   */
29  @SuppressWarnings("DuplicatedCode")
30  public class FirstDegreePolynomialRootsEstimator extends PolynomialRootsEstimator {
31  
32      /**
33       * Constant defining machine precision.
34       */
35      public static final double EPS = 1e-10;
36  
37      /**
38       * Number of parameters valid for a first degree polynomial.
39       */
40      public static final int VALID_POLY_PARAMS_LENGTH = 2;
41  
42      /**
43       * Array containing parameters of a first degree polynomial.
44       */
45      private double[] realPolyParams;
46  
47      /**
48       * Empty constructor.
49       */
50      public FirstDegreePolynomialRootsEstimator() {
51          super();
52          realPolyParams = null;
53      }
54  
55      /**
56       * Constructor.
57       *
58       * @param polyParams Array containing polynomial parameters.
59       * @throws IllegalArgumentException Raised if the length of the provided
60       *                                  array is not valid.
61       */
62      public FirstDegreePolynomialRootsEstimator(final double[] polyParams) {
63          super();
64          internalSetPolynomialParameters(polyParams);
65      }
66  
67      /**
68       * Set array of first degree polynomial parameters.
69       * A first degree polynomial is defined by p(x) = a * x + b, and the array
70       * must be provided as [b, a].
71       * Note: This class only supports real polynomial parameters.
72       *
73       * @param polyParams Array containing polynomial parameters.
74       * @throws LockedException          Raised if this instance is locked.
75       * @throws IllegalArgumentException Raised if the length of the provided
76       *                                  array is not valid.
77       */
78      public void setPolynomialParameters(final double[] polyParams) throws LockedException {
79          if (isLocked()) {
80              throw new LockedException();
81          }
82          internalSetPolynomialParameters(polyParams);
83      }
84  
85      /**
86       * Internal method to set array of first degree polynomial parameters.
87       * A first degree polynomial is defined by p(x) = a * x + b, and the array
88       * must be provided as [b, a].
89       * Note: This class only supports real polynomial parameters.
90       * This method does not check if this instance is locked.
91       *
92       * @param polyParams Array containing polynomial parameters.
93       * @throws IllegalArgumentException Raised if the length of the provided
94       *                                  array is not valid.
95       */
96      private void internalSetPolynomialParameters(final double[] polyParams) {
97          if (polyParams.length < VALID_POLY_PARAMS_LENGTH) {
98              throw new IllegalArgumentException();
99          }
100         if (!isFirstDegree(polyParams)) {
101             throw new IllegalArgumentException();
102         }
103 
104         this.realPolyParams = polyParams;
105     }
106 
107     /**
108      * Returns array of first degree polynomial parameters.
109      * A first degree polynomial is defined by p(x) = a * x + b, and the array
110      * is returned as [b, a].
111      * Note: This class only supports real polynomial parameters.
112      *
113      * @return Array of first degree polynomial parameters.
114      * @throws NotAvailableException if parameters are not available for retrieval.
115      */
116     public double[] getRealPolynomialParameters() throws NotAvailableException {
117         if (!arePolynomialParametersAvailable()) {
118             throw new NotAvailableException();
119         }
120         return realPolyParams;
121     }
122 
123     /**
124      * Returns boolean indicating whether REAL polynomial parameters have been
125      * provided and is available for retrieval.
126      * Note: This class only supports real polynomial parameters.
127      *
128      * @return True if available, false otherwise.
129      */
130     @Override
131     public boolean arePolynomialParametersAvailable() {
132         return realPolyParams != null;
133     }
134 
135     /**
136      * This method will always raise a NotAvailableException because this class
137      * only supports REAL polynomial parameters.
138      *
139      * @return throws NotAvailableException.
140      * @throws NotAvailableException always throws this exception.
141      */
142     @Override
143     public Complex[] getPolynomialParameters() throws NotAvailableException {
144         throw new NotAvailableException();
145     }
146 
147 
148     /**
149      * This method will always raise an IllegalArgumentException because this
150      * class only supports REAL polynomial parameters.
151      */
152     @Override
153     protected void internalSetPolynomialParameters(final Complex[] polyParams) {
154         // complex values are not supported
155         throw new IllegalArgumentException();
156     }
157 
158     /**
159      * Estimates the root of provided polynomial.
160      *
161      * @throws LockedException   Raised if this instance is locked estimating a
162      *                           root.
163      * @throws NotReadyException Raised if this instance is not ready because
164      *                           polynomial parameters have not been provided.
165      */
166     @Override
167     public void estimate() throws LockedException, NotReadyException {
168 
169         if (isLocked()) {
170             throw new LockedException();
171         }
172         if (!isReady()) {
173             throw new NotReadyException();
174         }
175 
176         locked = true;
177 
178         roots = new Complex[VALID_POLY_PARAMS_LENGTH - 1];
179 
180         final var b = realPolyParams[0];
181         final var a = realPolyParams[1];
182 
183         final var x = solveLinear(a, b);
184 
185         roots[0] = new Complex(x, 0.0);
186 
187         locked = false;
188     }
189 
190     /**
191      * Returns boolean indicating whether provided array of polynomial
192      * parameters correspond to a valid first degree polynomial.
193      * A first degree polynomial is defined by p(x) = a * x + b, and the array
194      * is returned as [b, a].
195      * Note: This class only supports real polynomial parameters
196      *
197      * @param polyParams Array containing polynomial parameters
198      * @return True if is a first degree polynomial, false otherwise
199      */
200     public static boolean isFirstDegree(final double[] polyParams) {
201         final var length = polyParams.length;
202         if (length >= VALID_POLY_PARAMS_LENGTH && Math.abs(polyParams[VALID_POLY_PARAMS_LENGTH - 1]) > EPS) {
203             for (var i = VALID_POLY_PARAMS_LENGTH; i < length; i++) {
204                 if (Math.abs(polyParams[i]) > EPS) {
205                     return false;
206                 }
207             }
208             return true;
209         }
210         return false;
211     }
212 
213     /**
214      * Returns boolean indicating whether polynomial parameters provided to this
215      * instance correspond to a valid first degree polynomial.
216      * A first degree polynomial is defined by p(x) = a * x + b, and the array
217      * is returned as [b, a].
218      * Note: This class only supports real polynomial parameters.
219      *
220      * @return True if is a first degree polynomial, false otherwise.
221      * @throws NotReadyException Raised if this instance is not ready because
222      *                           an array of polynomial parameters has not yet been provided.
223      */
224     public boolean isFirstDegree() throws NotReadyException {
225         if (!isReady()) {
226             throw new NotReadyException();
227         }
228         return isFirstDegree(realPolyParams);
229     }
230 
231     /**
232      * Returns boolean indicating whether estimated root is real.
233      * Because this class only accepts real polynomial parameters, then the
234      * estimated root will always be real, and consequently this method always
235      * returns true.
236      *
237      * @return True if estimated root is real, false otherwise.
238      */
239     public boolean isRealSolution() {
240         return true;
241     }
242 
243     /**
244      * Internal method to estimate a root on a first degree polynomial.
245      *
246      * @param a A parameter.
247      * @param b B parameter.
248      * @return Root.
249      */
250     private double solveLinear(final double a, final double b) {
251         //a * x + b = 0
252         return -b / a;
253     }
254 }