1919
2020import org .apache .commons .math4 .legacy .exception .MathIllegalArgumentException ;
2121import org .apache .commons .math4 .legacy .exception .NullArgumentException ;
22+ import org .apache .commons .math4 .legacy .exception .util .LocalizedFormats ;
2223import org .apache .commons .math4 .legacy .stat .descriptive .AbstractUnivariateStatistic ;
2324import org .apache .commons .math4 .legacy .core .MathArrays ;
2425
3536 *
3637 * <p>The cutoff value defaults to the mean, bias correction defaults to <code>true</code>
3738 * and the "variance direction" (upside or downside) defaults to downside. The variance direction
38- * and bias correction may be set using property setters or their values can provided as
39- * parameters to {@link #evaluate(double[], double, Direction, boolean, int, int)}.</p>
39+ * and bias correction may be set using property setters.</p>
4040 *
4141 * <p>If the input array is null, <code>evaluate</code> methods throw
4242 * <code>IllegalArgumentException.</code> If the array has length 1, <code>0</code>
5151 */
5252public class SemiVariance extends AbstractUnivariateStatistic {
5353
54- /**
55- * The UPSIDE Direction is used to specify that the observations above the
56- * cutoff point will be used to calculate SemiVariance.
57- */
58- public static final Direction UPSIDE_VARIANCE = Direction .UPSIDE ;
59-
60- /**
61- * The DOWNSIDE Direction is used to specify that the observations below.
62- * the cutoff point will be used to calculate SemiVariance
63- */
64- public static final Direction DOWNSIDE_VARIANCE = Direction .DOWNSIDE ;
65-
6654 /**
6755 * Determines whether or not bias correction is applied when computing the
6856 * value of the statistic. True means that bias is corrected.
@@ -79,56 +67,7 @@ public class SemiVariance extends AbstractUnivariateStatistic {
7967 * property and default (Downside) <code>varianceDirection</code> property.
8068 */
8169 public SemiVariance () {
82- }
83-
84- /**
85- * Constructs a SemiVariance with the specified <code>biasCorrected</code>
86- * property and default (Downside) <code>varianceDirection</code> property.
87- *
88- * @param biasCorrected setting for bias correction - true means
89- * bias will be corrected and is equivalent to using the "no arg"
90- * constructor
91- */
92- public SemiVariance (final boolean biasCorrected ) {
93- this .biasCorrected = biasCorrected ;
94- }
95-
96- /**
97- * Constructs a SemiVariance with the specified <code>Direction</code> property.
98- * and default (true) <code>biasCorrected</code> property
99- *
100- * @param direction setting for the direction of the SemiVariance
101- * to calculate
102- */
103- public SemiVariance (final Direction direction ) {
104- this .varianceDirection = direction ;
105- }
106-
107- /**
108- * Constructs a SemiVariance with the specified <code>isBiasCorrected</code>
109- * property and the specified <code>Direction</code> property.
110- *
111- * @param corrected setting for bias correction - true means
112- * bias will be corrected and is equivalent to using the "no arg"
113- * constructor
114- *
115- * @param direction setting for the direction of the SemiVariance
116- * to calculate
117- */
118- public SemiVariance (final boolean corrected , final Direction direction ) {
119- this .biasCorrected = corrected ;
120- this .varianceDirection = direction ;
121- }
122-
123- /**
124- * Copy constructor, creates a new {@code SemiVariance} identical
125- * to the {@code original}.
126- *
127- * @param original the {@code SemiVariance} instance to copy
128- * @throws NullArgumentException if original is null
129- */
130- public SemiVariance (final SemiVariance original ) throws NullArgumentException {
131- copy (original , this );
70+ // Do nothing
13271 }
13372
13473 /**
@@ -137,27 +76,11 @@ public SemiVariance(final SemiVariance original) throws NullArgumentException {
13776 @ Override
13877 public SemiVariance copy () {
13978 SemiVariance result = new SemiVariance ();
140- // No try-catch or advertised exception because args are guaranteed non-null
141- copy ( this , result ) ;
79+ result . biasCorrected = biasCorrected ;
80+ result . varianceDirection = varianceDirection ;
14281 return result ;
14382 }
14483
145- /**
146- * Copies source to dest.
147- * <p>Neither source nor dest can be null.</p>
148- *
149- * @param source SemiVariance to copy
150- * @param dest SemiVariance to copy to
151- * @throws NullArgumentException if either source or dest is null
152- */
153- public static void copy (final SemiVariance source , SemiVariance dest )
154- throws NullArgumentException {
155- NullArgumentException .check (source );
156- NullArgumentException .check (dest );
157- dest .biasCorrected = source .biasCorrected ;
158- dest .varianceDirection = source .varianceDirection ;
159- }
160-
16184 /**
16285 * <p>Returns the {@link SemiVariance} of the designated values against the mean, using
16386 * instance properties varianceDirection and biasCorrection.</p>
@@ -177,24 +100,7 @@ public double evaluate(final double[] values, final int start, final int length)
177100 throws MathIllegalArgumentException {
178101 MathArrays .verifyValues (values , start , length );
179102 double m = org .apache .commons .statistics .descriptive .Mean .ofRange (values , start , start + length ).getAsDouble ();
180- return evaluate (values , m , varianceDirection , biasCorrected , 0 , values .length );
181- }
182-
183- /**
184- * This method calculates {@link SemiVariance} for the entire array against the mean, using
185- * the current value of the biasCorrection instance property.
186- *
187- * @param values the input array
188- * @param direction the {@link Direction} of the semivariance
189- * @return the SemiVariance
190- * @throws MathIllegalArgumentException if values is null
191- *
192- */
193- public double evaluate (final double [] values , Direction direction )
194- throws MathIllegalArgumentException {
195- MathArrays .verifyValues (values , 0 , 0 );
196- double m = org .apache .commons .statistics .descriptive .Mean .of (values ).getAsDouble ();
197- return evaluate (values , m , direction , biasCorrected , 0 , values .length );
103+ return compute (values , m , varianceDirection , biasCorrected , start , length );
198104 }
199105
200106 /**
@@ -211,33 +117,38 @@ public double evaluate(final double[] values, Direction direction)
211117 */
212118 public double evaluate (final double [] values , final double cutoff )
213119 throws MathIllegalArgumentException {
214- return evaluate (values , cutoff , varianceDirection , biasCorrected , 0 , values .length );
120+ if (values == null ) {
121+ throw new NullArgumentException (LocalizedFormats .INPUT_ARRAY );
122+ }
123+ return compute (values , cutoff , varianceDirection , biasCorrected , 0 , values .length );
215124 }
216125
217126 /**
218- * <p>Returns the {@link SemiVariance} of the designated values against the cutoff in the
219- * given direction, using the current value of the biasCorrection instance property .</p>
127+ * <p>Returns the {@link SemiVariance} of the designated values against the cutoff
128+ * in the given direction with the provided bias correction .</p>
220129 *
221130 * <p>Returns <code>NaN</code> if the array is empty and throws
222- * <code>MathIllegalArgumentException </code> if the array is null.</p>
131+ * <code>IllegalArgumentException </code> if the array is null.</p>
223132 *
224133 * @param values the input array
225134 * @param cutoff the reference point
226- * @param direction the {@link Direction} of the semivariance
135+ * @param start index of the first array element to include
136+ * @param length the number of elements to include
227137 * @return the SemiVariance
228- * @throws MathIllegalArgumentException if values is null
138+ * @throws MathIllegalArgumentException if the parameters are not valid
139+ *
229140 */
230- public double evaluate (final double [] values , final double cutoff , final Direction direction )
141+ public double evaluate (final double [] values , final double cutoff , final int start , final int length )
231142 throws MathIllegalArgumentException {
232- return evaluate (values , cutoff , direction , biasCorrected , 0 , values .length );
143+ MathArrays .verifyValues (values , start , length );
144+ return compute (values , cutoff , varianceDirection , biasCorrected , start , length );
233145 }
234146
235147 /**
236148 * <p>Returns the {@link SemiVariance} of the designated values against the cutoff
237149 * in the given direction with the provided bias correction.</p>
238150 *
239- * <p>Returns <code>NaN</code> if the array is empty and throws
240- * <code>IllegalArgumentException</code> if the array is null.</p>
151+ * <p>Returns <code>NaN</code> if the array is empty.</p>
241152 *
242153 * @param values the input array
243154 * @param cutoff the reference point
@@ -246,38 +157,33 @@ public double evaluate(final double[] values, final double cutoff, final Directi
246157 * @param start index of the first array element to include
247158 * @param length the number of elements to include
248159 * @return the SemiVariance
249- * @throws MathIllegalArgumentException if the parameters are not valid
250- *
251160 */
252- public double evaluate (final double [] values , final double cutoff , final Direction direction ,
253- final boolean corrected , final int start , final int length )
254- throws MathIllegalArgumentException {
255-
256- MathArrays .verifyValues (values , start , length );
257- if (values .length == 0 ) {
161+ private static double compute (double [] values , double cutoff , Direction direction ,
162+ boolean corrected , int start , int length ) {
163+ // Arguments must have been validated
164+ if (length == 0 ) {
258165 return Double .NaN ;
259- } else {
260- if (values .length == 1 ) {
261- return 0.0 ;
262- } else {
263- final boolean booleanDirection = direction .getDirection ();
264-
265- double dev = 0.0 ;
266- double sumsq = 0.0 ;
267- for (int i = start ; i < length ; i ++) {
268- if ((values [i ] > cutoff ) == booleanDirection ) {
269- dev = values [i ] - cutoff ;
270- sumsq += dev * dev ;
271- }
272- }
166+ }
167+ if (length == 1 ) {
168+ return 0.0 ;
169+ }
170+ final boolean booleanDirection = direction .getDirection ();
273171
274- if (corrected ) {
275- return sumsq / (length - 1.0 );
276- } else {
277- return sumsq / length ;
278- }
172+ double dev = 0.0 ;
173+ double sumsq = 0.0 ;
174+ final int end = start + length ;
175+ for (int i = start ; i < end ; i ++) {
176+ if ((values [i ] > cutoff ) == booleanDirection ) {
177+ dev = values [i ] - cutoff ;
178+ sumsq += dev * dev ;
279179 }
280180 }
181+
182+ if (corrected ) {
183+ return sumsq / (length - 1.0 );
184+ } else {
185+ return sumsq / length ;
186+ }
281187 }
282188
283189 /**
0 commit comments