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.algebra;
17
18 /**
19 * Class in charge of computing norms of arrays and matrices.
20 * Norms can be computed in different ways depending on the desired norm
21 * measure. For that purpose subclass implementations of this class attempt to
22 * work on different norm types.
23 * By default, Frobenius norm is used for arrays and matrices, which consists
24 * on computing the square root of summation of all the squared elements within
25 * a given matrix or array.
26 */
27 public abstract class NormComputer {
28 /**
29 * Constant defining default norm type to be used.
30 */
31 public static final NormType DEFAULT_NORM_TYPE = NormType.FROBENIUS_NORM;
32
33 /**
34 * Constructor of this class.
35 */
36 protected NormComputer() {
37 }
38
39 /**
40 * Returns norm type being used by this class.
41 *
42 * @return Norm type being used by this class.
43 */
44 public abstract NormType getNormType();
45
46 /**
47 * Computes norm of provided matrix.
48 *
49 * @param m Matrix being used for norm computation.
50 * @return Norm of provided matrix.
51 */
52 public abstract double getNorm(final Matrix m);
53
54 /**
55 * Computes norm of provided array.
56 *
57 * @param array Array being used for norm computation.
58 * @return Norm of provided vector.
59 */
60 public abstract double getNorm(final double[] array);
61
62 /**
63 * Computes norm of provided array and stores the jacobian into provided
64 * instance.
65 *
66 * @param array array being used for norm computation.
67 * @param jacobian instance where jacobian will be stored. Must be 1xN,
68 * where N is length of array.
69 * @return norm of provided vector.
70 * @throws WrongSizeException if provided jacobian is not 1xN, where N is
71 * length of array.
72 */
73 public double getNorm(final double[] array, final Matrix jacobian) throws WrongSizeException {
74 if (jacobian != null && (jacobian.getRows() != 1 || jacobian.getColumns() != array.length)) {
75 throw new WrongSizeException("jacobian must be 1xN, where N is length of array");
76 }
77
78 final var norm = getNorm(array);
79
80 if (jacobian != null) {
81 jacobian.fromArray(array);
82 jacobian.multiplyByScalar(1.0 / norm);
83 }
84
85 return norm;
86 }
87
88 /**
89 * Factory method. Returns a new instance of NormComputer prepared to
90 * compute norms using provided NormType.
91 *
92 * @param normType Norm type to be used by returned instance.
93 * @return New instance of NormComputer.
94 */
95 public static NormComputer create(final NormType normType) {
96 return switch (normType) {
97 case INFINITY_NORM -> new InfinityNormComputer();
98 case ONE_NORM -> new OneNormComputer();
99 default -> new FrobeniusNormComputer();
100 };
101 }
102
103 /**
104 * Factory method. Returns a new instance of NormComputer prepared to
105 * compute norms using provided NormType.
106 *
107 * @return New instance of NormComputer.
108 */
109 public static NormComputer create() {
110 return create(DEFAULT_NORM_TYPE);
111 }
112 }