summaryrefslogtreecommitdiff
path: root/src/main/java/org/apache/commons/math3/transform/TransformUtils.java
blob: 5cf83de416cbdffe74a5659be50a4fc27eb9e3f8 (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
/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You 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 org.apache.commons.math3.transform;

import org.apache.commons.math3.complex.Complex;
import org.apache.commons.math3.exception.DimensionMismatchException;
import org.apache.commons.math3.exception.MathIllegalArgumentException;
import org.apache.commons.math3.exception.util.LocalizedFormats;

import java.util.Arrays;

/**
 * Useful functions for the implementation of various transforms.
 *
 * @since 3.0
 */
public class TransformUtils {
    /**
     * Table of the powers of 2 to facilitate binary search lookup.
     *
     * @see #exactLog2(int)
     */
    private static final int[] POWERS_OF_TWO = {
        0x00000001, 0x00000002, 0x00000004, 0x00000008, 0x00000010, 0x00000020,
        0x00000040, 0x00000080, 0x00000100, 0x00000200, 0x00000400, 0x00000800,
        0x00001000, 0x00002000, 0x00004000, 0x00008000, 0x00010000, 0x00020000,
        0x00040000, 0x00080000, 0x00100000, 0x00200000, 0x00400000, 0x00800000,
        0x01000000, 0x02000000, 0x04000000, 0x08000000, 0x10000000, 0x20000000,
        0x40000000
    };

    /** Private constructor. */
    private TransformUtils() {
        super();
    }

    /**
     * Multiply every component in the given real array by the given real number. The change is made
     * in place.
     *
     * @param f the real array to be scaled
     * @param d the real scaling coefficient
     * @return a reference to the scaled array
     */
    public static double[] scaleArray(double[] f, double d) {

        for (int i = 0; i < f.length; i++) {
            f[i] *= d;
        }
        return f;
    }

    /**
     * Multiply every component in the given complex array by the given real number. The change is
     * made in place.
     *
     * @param f the complex array to be scaled
     * @param d the real scaling coefficient
     * @return a reference to the scaled array
     */
    public static Complex[] scaleArray(Complex[] f, double d) {

        for (int i = 0; i < f.length; i++) {
            f[i] = new Complex(d * f[i].getReal(), d * f[i].getImaginary());
        }
        return f;
    }

    /**
     * Builds a new two dimensional array of {@code double} filled with the real and imaginary parts
     * of the specified {@link Complex} numbers. In the returned array {@code dataRI}, the data is
     * laid out as follows
     *
     * <ul>
     *   <li>{@code dataRI[0][i] = dataC[i].getReal()},
     *   <li>{@code dataRI[1][i] = dataC[i].getImaginary()}.
     * </ul>
     *
     * @param dataC the array of {@link Complex} data to be transformed
     * @return a two dimensional array filled with the real and imaginary parts of the specified
     *     complex input
     */
    public static double[][] createRealImaginaryArray(final Complex[] dataC) {
        final double[][] dataRI = new double[2][dataC.length];
        final double[] dataR = dataRI[0];
        final double[] dataI = dataRI[1];
        for (int i = 0; i < dataC.length; i++) {
            final Complex c = dataC[i];
            dataR[i] = c.getReal();
            dataI[i] = c.getImaginary();
        }
        return dataRI;
    }

    /**
     * Builds a new array of {@link Complex} from the specified two dimensional array of real and
     * imaginary parts. In the returned array {@code dataC}, the data is laid out as follows
     *
     * <ul>
     *   <li>{@code dataC[i].getReal() = dataRI[0][i]},
     *   <li>{@code dataC[i].getImaginary() = dataRI[1][i]}.
     * </ul>
     *
     * @param dataRI the array of real and imaginary parts to be transformed
     * @return an array of {@link Complex} with specified real and imaginary parts.
     * @throws DimensionMismatchException if the number of rows of the specified array is not two,
     *     or the array is not rectangular
     */
    public static Complex[] createComplexArray(final double[][] dataRI)
            throws DimensionMismatchException {

        if (dataRI.length != 2) {
            throw new DimensionMismatchException(dataRI.length, 2);
        }
        final double[] dataR = dataRI[0];
        final double[] dataI = dataRI[1];
        if (dataR.length != dataI.length) {
            throw new DimensionMismatchException(dataI.length, dataR.length);
        }

        final int n = dataR.length;
        final Complex[] c = new Complex[n];
        for (int i = 0; i < n; i++) {
            c[i] = new Complex(dataR[i], dataI[i]);
        }
        return c;
    }

    /**
     * Returns the base-2 logarithm of the specified {@code int}. Throws an exception if {@code n}
     * is not a power of two.
     *
     * @param n the {@code int} whose base-2 logarithm is to be evaluated
     * @return the base-2 logarithm of {@code n}
     * @throws MathIllegalArgumentException if {@code n} is not a power of two
     */
    public static int exactLog2(final int n) throws MathIllegalArgumentException {

        int index = Arrays.binarySearch(TransformUtils.POWERS_OF_TWO, n);
        if (index < 0) {
            throw new MathIllegalArgumentException(
                    LocalizedFormats.NOT_POWER_OF_TWO_CONSIDER_PADDING, Integer.valueOf(n));
        }
        return index;
    }
}