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 }