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 */ 017package org.apache.commons.math3.transform; 018 019import java.util.Arrays; 020 021import org.apache.commons.math3.complex.Complex; 022import org.apache.commons.math3.exception.DimensionMismatchException; 023import org.apache.commons.math3.exception.MathIllegalArgumentException; 024import org.apache.commons.math3.exception.util.LocalizedFormats; 025 026/** 027 * Useful functions for the implementation of various transforms. 028 * 029 * @since 3.0 030 */ 031public class TransformUtils { 032 /** 033 * Table of the powers of 2 to facilitate binary search lookup. 034 * 035 * @see #exactLog2(int) 036 */ 037 private static final int[] POWERS_OF_TWO = { 038 0x00000001, 0x00000002, 0x00000004, 0x00000008, 0x00000010, 0x00000020, 039 0x00000040, 0x00000080, 0x00000100, 0x00000200, 0x00000400, 0x00000800, 040 0x00001000, 0x00002000, 0x00004000, 0x00008000, 0x00010000, 0x00020000, 041 0x00040000, 0x00080000, 0x00100000, 0x00200000, 0x00400000, 0x00800000, 042 0x01000000, 0x02000000, 0x04000000, 0x08000000, 0x10000000, 0x20000000, 043 0x40000000 044 }; 045 046 /** Private constructor. */ 047 private TransformUtils() { 048 super(); 049 } 050 051 /** 052 * Multiply every component in the given real array by the 053 * given real number. The change is made in place. 054 * 055 * @param f the real array to be scaled 056 * @param d the real scaling coefficient 057 * @return a reference to the scaled array 058 */ 059 public static double[] scaleArray(double[] f, double d) { 060 061 for (int i = 0; i < f.length; i++) { 062 f[i] *= d; 063 } 064 return f; 065 } 066 067 /** 068 * Multiply every component in the given complex array by the 069 * given real number. The change is made in place. 070 * 071 * @param f the complex array to be scaled 072 * @param d the real scaling coefficient 073 * @return a reference to the scaled array 074 */ 075 public static Complex[] scaleArray(Complex[] f, double d) { 076 077 for (int i = 0; i < f.length; i++) { 078 f[i] = new Complex(d * f[i].getReal(), d * f[i].getImaginary()); 079 } 080 return f; 081 } 082 083 084 /** 085 * Builds a new two dimensional array of {@code double} filled with the real 086 * and imaginary parts of the specified {@link Complex} numbers. In the 087 * returned array {@code dataRI}, the data is laid out as follows 088 * <ul> 089 * <li>{@code dataRI[0][i] = dataC[i].getReal()},</li> 090 * <li>{@code dataRI[1][i] = dataC[i].getImaginary()}.</li> 091 * </ul> 092 * 093 * @param dataC the array of {@link Complex} data to be transformed 094 * @return a two dimensional array filled with the real and imaginary parts 095 * of the specified complex input 096 */ 097 public static double[][] createRealImaginaryArray(final Complex[] dataC) { 098 final double[][] dataRI = new double[2][dataC.length]; 099 final double[] dataR = dataRI[0]; 100 final double[] dataI = dataRI[1]; 101 for (int i = 0; i < dataC.length; i++) { 102 final Complex c = dataC[i]; 103 dataR[i] = c.getReal(); 104 dataI[i] = c.getImaginary(); 105 } 106 return dataRI; 107 } 108 109 /** 110 * Builds a new array of {@link Complex} from the specified two dimensional 111 * array of real and imaginary parts. In the returned array {@code dataC}, 112 * the data is laid out as follows 113 * <ul> 114 * <li>{@code dataC[i].getReal() = dataRI[0][i]},</li> 115 * <li>{@code dataC[i].getImaginary() = dataRI[1][i]}.</li> 116 * </ul> 117 * 118 * @param dataRI the array of real and imaginary parts to be transformed 119 * @return an array of {@link Complex} with specified real and imaginary parts. 120 * @throws DimensionMismatchException if the number of rows of the specified 121 * array is not two, or the array is not rectangular 122 */ 123 public static Complex[] createComplexArray(final double[][] dataRI) 124 throws DimensionMismatchException{ 125 126 if (dataRI.length != 2) { 127 throw new DimensionMismatchException(dataRI.length, 2); 128 } 129 final double[] dataR = dataRI[0]; 130 final double[] dataI = dataRI[1]; 131 if (dataR.length != dataI.length) { 132 throw new DimensionMismatchException(dataI.length, dataR.length); 133 } 134 135 final int n = dataR.length; 136 final Complex[] c = new Complex[n]; 137 for (int i = 0; i < n; i++) { 138 c[i] = new Complex(dataR[i], dataI[i]); 139 } 140 return c; 141 } 142 143 144 /** 145 * Returns the base-2 logarithm of the specified {@code int}. Throws an 146 * exception if {@code n} is not a power of two. 147 * 148 * @param n the {@code int} whose base-2 logarithm is to be evaluated 149 * @return the base-2 logarithm of {@code n} 150 * @throws MathIllegalArgumentException if {@code n} is not a power of two 151 */ 152 public static int exactLog2(final int n) 153 throws MathIllegalArgumentException { 154 155 int index = Arrays.binarySearch(TransformUtils.POWERS_OF_TWO, n); 156 if (index < 0) { 157 throw new MathIllegalArgumentException( 158 LocalizedFormats.NOT_POWER_OF_TWO_CONSIDER_PADDING, 159 Integer.valueOf(n)); 160 } 161 return index; 162 } 163}