1 /* 2 * Licensed to the Apache Software Foundation (ASF) under one or more 3 * contributor license agreements. See the NOTICE file distributed with 4 * this work for additional information regarding copyright ownership. 5 * The ASF licenses this file to You under the Apache License, Version 2.0 6 * (the "License"); you may not use this file except in compliance with 7 * the License. You may obtain a copy of the License at 8 * 9 * https://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * See the License for the specific language governing permissions and 15 * limitations under the License. 16 */ 17 18 /* 19 * This is not the original file distributed by the Apache Software Foundation 20 * It has been modified by the Hipparchus project 21 */ 22 package org.hipparchus.transform; 23 24 import java.util.Arrays; 25 26 import org.hipparchus.complex.Complex; 27 import org.hipparchus.exception.LocalizedCoreFormats; 28 import org.hipparchus.exception.MathIllegalArgumentException; 29 30 /** 31 * Useful functions for the implementation of various transforms. 32 * 33 */ 34 public class TransformUtils { 35 /** 36 * Table of the powers of 2 to facilitate binary search lookup. 37 * 38 * @see #exactLog2(int) 39 */ 40 private static final int[] POWERS_OF_TWO = { 41 0x00000001, 0x00000002, 0x00000004, 0x00000008, 0x00000010, 0x00000020, 42 0x00000040, 0x00000080, 0x00000100, 0x00000200, 0x00000400, 0x00000800, 43 0x00001000, 0x00002000, 0x00004000, 0x00008000, 0x00010000, 0x00020000, 44 0x00040000, 0x00080000, 0x00100000, 0x00200000, 0x00400000, 0x00800000, 45 0x01000000, 0x02000000, 0x04000000, 0x08000000, 0x10000000, 0x20000000, 46 0x40000000 47 }; 48 49 /** Private constructor. */ 50 private TransformUtils() { 51 super(); 52 } 53 54 /** 55 * Multiply every component in the given real array by the 56 * given real number. The change is made in place. 57 * 58 * @param f the real array to be scaled 59 * @param d the real scaling coefficient 60 * @return a reference to the scaled array 61 */ 62 public static double[] scaleArray(double[] f, double d) { 63 64 for (int i = 0; i < f.length; i++) { 65 f[i] *= d; 66 } 67 return f; 68 } 69 70 /** 71 * Multiply every component in the given complex array by the 72 * given real number. The change is made in place. 73 * 74 * @param f the complex array to be scaled 75 * @param d the real scaling coefficient 76 * @return a reference to the scaled array 77 */ 78 public static Complex[] scaleArray(Complex[] f, double d) { 79 80 for (int i = 0; i < f.length; i++) { 81 f[i] = new Complex(d * f[i].getReal(), d * f[i].getImaginary()); 82 } 83 return f; 84 } 85 86 87 /** 88 * Builds a new two dimensional array of {@code double} filled with the real 89 * and imaginary parts of the specified {@link Complex} numbers. In the 90 * returned array {@code dataRI}, the data is laid out as follows 91 * <ul> 92 * <li>{@code dataRI[0][i] = dataC[i].getReal()},</li> 93 * <li>{@code dataRI[1][i] = dataC[i].getImaginary()}.</li> 94 * </ul> 95 * 96 * @param dataC the array of {@link Complex} data to be transformed 97 * @return a two dimensional array filled with the real and imaginary parts 98 * of the specified complex input 99 */ 100 public static double[][] createRealImaginaryArray(final Complex[] dataC) { 101 final double[][] dataRI = new double[2][dataC.length]; 102 final double[] dataR = dataRI[0]; 103 final double[] dataI = dataRI[1]; 104 for (int i = 0; i < dataC.length; i++) { 105 final Complex c = dataC[i]; 106 dataR[i] = c.getReal(); 107 dataI[i] = c.getImaginary(); 108 } 109 return dataRI; 110 } 111 112 /** 113 * Builds a new array of {@link Complex} from the specified two dimensional 114 * array of real and imaginary parts. In the returned array {@code dataC}, 115 * the data is laid out as follows 116 * <ul> 117 * <li>{@code dataC[i].getReal() = dataRI[0][i]},</li> 118 * <li>{@code dataC[i].getImaginary() = dataRI[1][i]}.</li> 119 * </ul> 120 * 121 * @param dataRI the array of real and imaginary parts to be transformed 122 * @return an array of {@link Complex} with specified real and imaginary parts. 123 * @throws MathIllegalArgumentException if the number of rows of the specified 124 * array is not two, or the array is not rectangular 125 */ 126 public static Complex[] createComplexArray(final double[][] dataRI) 127 throws MathIllegalArgumentException { 128 129 if (dataRI.length != 2) { 130 throw new MathIllegalArgumentException(LocalizedCoreFormats.DIMENSIONS_MISMATCH, 131 dataRI.length, 2); 132 } 133 final double[] dataR = dataRI[0]; 134 final double[] dataI = dataRI[1]; 135 if (dataR.length != dataI.length) { 136 throw new MathIllegalArgumentException(LocalizedCoreFormats.DIMENSIONS_MISMATCH, 137 dataI.length, dataR.length); 138 } 139 140 final int n = dataR.length; 141 final Complex[] c = new Complex[n]; 142 for (int i = 0; i < n; i++) { 143 c[i] = new Complex(dataR[i], dataI[i]); 144 } 145 return c; 146 } 147 148 149 /** 150 * Returns the base-2 logarithm of the specified {@code int}. Throws an 151 * exception if {@code n} is not a power of two. 152 * 153 * @param n the {@code int} whose base-2 logarithm is to be evaluated 154 * @return the base-2 logarithm of {@code n} 155 * @throws MathIllegalArgumentException if {@code n} is not a power of two 156 */ 157 public static int exactLog2(final int n) 158 throws MathIllegalArgumentException { 159 160 int index = Arrays.binarySearch(TransformUtils.POWERS_OF_TWO, n); 161 if (index < 0) { 162 throw new MathIllegalArgumentException(LocalizedFFTFormats.NOT_POWER_OF_TWO_CONSIDER_PADDING, 163 Integer.valueOf(n)); 164 } 165 return index; 166 } 167 }