001 /*
002 * Licensed to the Apache Software Foundation (ASF) under one or more
003 * contributor license agreements. See the NOTICE file distributed with
004 * this work for additional information regarding copyright ownership.
005 * The ASF licenses this file to You under the Apache License, Version 2.0
006 * (the "License"); you may not use this file except in compliance with
007 * the License. You may obtain a copy of the License at
008 *
009 * http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 */
017 package org.apache.commons.math3.transform;
018
019 import java.util.Arrays;
020
021 import org.apache.commons.math3.complex.Complex;
022 import org.apache.commons.math3.exception.DimensionMismatchException;
023 import org.apache.commons.math3.exception.MathIllegalArgumentException;
024 import org.apache.commons.math3.exception.util.LocalizedFormats;
025
026 /**
027 * Useful functions for the implementation of various transforms.
028 *
029 * @version $Id: TransformUtils.java 1385310 2012-09-16 16:32:10Z tn $
030 * @since 3.0
031 */
032 public class TransformUtils {
033 /**
034 * Table of the powers of 2 to facilitate binary search lookup.
035 *
036 * @see #exactLog2(int)
037 */
038 private static final int[] POWERS_OF_TWO = {
039 0x00000001, 0x00000002, 0x00000004, 0x00000008, 0x00000010, 0x00000020,
040 0x00000040, 0x00000080, 0x00000100, 0x00000200, 0x00000400, 0x00000800,
041 0x00001000, 0x00002000, 0x00004000, 0x00008000, 0x00010000, 0x00020000,
042 0x00040000, 0x00080000, 0x00100000, 0x00200000, 0x00400000, 0x00800000,
043 0x01000000, 0x02000000, 0x04000000, 0x08000000, 0x10000000, 0x20000000,
044 0x40000000
045 };
046
047 /** Private constructor. */
048 private TransformUtils() {
049 super();
050 }
051
052 /**
053 * Multiply every component in the given real array by the
054 * given real number. The change is made in place.
055 *
056 * @param f the real array to be scaled
057 * @param d the real scaling coefficient
058 * @return a reference to the scaled array
059 */
060 public static double[] scaleArray(double[] f, double d) {
061
062 for (int i = 0; i < f.length; i++) {
063 f[i] *= d;
064 }
065 return f;
066 }
067
068 /**
069 * Multiply every component in the given complex array by the
070 * given real number. The change is made in place.
071 *
072 * @param f the complex array to be scaled
073 * @param d the real scaling coefficient
074 * @return a reference to the scaled array
075 */
076 public static Complex[] scaleArray(Complex[] f, double d) {
077
078 for (int i = 0; i < f.length; i++) {
079 f[i] = new Complex(d * f[i].getReal(), d * f[i].getImaginary());
080 }
081 return f;
082 }
083
084
085 /**
086 * Builds a new two dimensional array of {@code double} filled with the real
087 * and imaginary parts of the specified {@link Complex} numbers. In the
088 * returned array {@code dataRI}, the data is laid out as follows
089 * <ul>
090 * <li>{@code dataRI[0][i] = dataC[i].getReal()},</li>
091 * <li>{@code dataRI[1][i] = dataC[i].getImaginary()}.</li>
092 * </ul>
093 *
094 * @param dataC the array of {@link Complex} data to be transformed
095 * @return a two dimensional array filled with the real and imaginary parts
096 * of the specified complex input
097 */
098 public static double[][] createRealImaginaryArray(final Complex[] dataC) {
099 final double[][] dataRI = new double[2][dataC.length];
100 final double[] dataR = dataRI[0];
101 final double[] dataI = dataRI[1];
102 for (int i = 0; i < dataC.length; i++) {
103 final Complex c = dataC[i];
104 dataR[i] = c.getReal();
105 dataI[i] = c.getImaginary();
106 }
107 return dataRI;
108 }
109
110 /**
111 * Builds a new array of {@link Complex} from the specified two dimensional
112 * array of real and imaginary parts. In the returned array {@code dataC},
113 * the data is laid out as follows
114 * <ul>
115 * <li>{@code dataC[i].getReal() = dataRI[0][i]},</li>
116 * <li>{@code dataC[i].getImaginary() = dataRI[1][i]}.</li>
117 * </ul>
118 *
119 * @param dataRI the array of real and imaginary parts to be transformed
120 * @return an array of {@link Complex} with specified real and imaginary parts.
121 * @throws DimensionMismatchException if the number of rows of the specified
122 * array is not two, or the array is not rectangular
123 */
124 public static Complex[] createComplexArray(final double[][] dataRI)
125 throws DimensionMismatchException{
126
127 if (dataRI.length != 2) {
128 throw new DimensionMismatchException(dataRI.length, 2);
129 }
130 final double[] dataR = dataRI[0];
131 final double[] dataI = dataRI[1];
132 if (dataR.length != dataI.length) {
133 throw new DimensionMismatchException(dataI.length, dataR.length);
134 }
135
136 final int n = dataR.length;
137 final Complex[] c = new Complex[n];
138 for (int i = 0; i < n; i++) {
139 c[i] = new Complex(dataR[i], dataI[i]);
140 }
141 return c;
142 }
143
144
145 /**
146 * Returns the base-2 logarithm of the specified {@code int}. Throws an
147 * exception if {@code n} is not a power of two.
148 *
149 * @param n the {@code int} whose base-2 logarithm is to be evaluated
150 * @return the base-2 logarithm of {@code n}
151 * @throws MathIllegalArgumentException if {@code n} is not a power of two
152 */
153 public static int exactLog2(final int n)
154 throws MathIllegalArgumentException {
155
156 int index = Arrays.binarySearch(TransformUtils.POWERS_OF_TWO, n);
157 if (index < 0) {
158 throw new MathIllegalArgumentException(
159 LocalizedFormats.NOT_POWER_OF_TWO_CONSIDER_PADDING,
160 Integer.valueOf(n));
161 }
162 return index;
163 }
164 }