TransformUtils.java

  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.  *      http://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. package org.apache.commons.math3.transform;

  18. import java.util.Arrays;

  19. import org.apache.commons.math3.complex.Complex;
  20. import org.apache.commons.math3.exception.DimensionMismatchException;
  21. import org.apache.commons.math3.exception.MathIllegalArgumentException;
  22. import org.apache.commons.math3.exception.util.LocalizedFormats;

  23. /**
  24.  * Useful functions for the implementation of various transforms.
  25.  *
  26.  * @since 3.0
  27.  */
  28. public class TransformUtils {
  29.     /**
  30.      * Table of the powers of 2 to facilitate binary search lookup.
  31.      *
  32.      * @see #exactLog2(int)
  33.      */
  34.     private static final int[] POWERS_OF_TWO = {
  35.         0x00000001, 0x00000002, 0x00000004, 0x00000008, 0x00000010, 0x00000020,
  36.         0x00000040, 0x00000080, 0x00000100, 0x00000200, 0x00000400, 0x00000800,
  37.         0x00001000, 0x00002000, 0x00004000, 0x00008000, 0x00010000, 0x00020000,
  38.         0x00040000, 0x00080000, 0x00100000, 0x00200000, 0x00400000, 0x00800000,
  39.         0x01000000, 0x02000000, 0x04000000, 0x08000000, 0x10000000, 0x20000000,
  40.         0x40000000
  41.     };

  42.     /** Private constructor. */
  43.     private TransformUtils() {
  44.         super();
  45.     }

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

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

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

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


  74.     /**
  75.      * Builds a new two dimensional array of {@code double} filled with the real
  76.      * and imaginary parts of the specified {@link Complex} numbers. In the
  77.      * returned array {@code dataRI}, the data is laid out as follows
  78.      * <ul>
  79.      * <li>{@code dataRI[0][i] = dataC[i].getReal()},</li>
  80.      * <li>{@code dataRI[1][i] = dataC[i].getImaginary()}.</li>
  81.      * </ul>
  82.      *
  83.      * @param dataC the array of {@link Complex} data to be transformed
  84.      * @return a two dimensional array filled with the real and imaginary parts
  85.      *   of the specified complex input
  86.      */
  87.     public static double[][] createRealImaginaryArray(final Complex[] dataC) {
  88.         final double[][] dataRI = new double[2][dataC.length];
  89.         final double[] dataR = dataRI[0];
  90.         final double[] dataI = dataRI[1];
  91.         for (int i = 0; i < dataC.length; i++) {
  92.             final Complex c = dataC[i];
  93.             dataR[i] = c.getReal();
  94.             dataI[i] = c.getImaginary();
  95.         }
  96.         return dataRI;
  97.     }

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

  114.         if (dataRI.length != 2) {
  115.             throw new DimensionMismatchException(dataRI.length, 2);
  116.         }
  117.         final double[] dataR = dataRI[0];
  118.         final double[] dataI = dataRI[1];
  119.         if (dataR.length != dataI.length) {
  120.             throw new DimensionMismatchException(dataI.length, dataR.length);
  121.         }

  122.         final int n = dataR.length;
  123.         final Complex[] c = new Complex[n];
  124.         for (int i = 0; i < n; i++) {
  125.             c[i] = new Complex(dataR[i], dataI[i]);
  126.         }
  127.         return c;
  128.     }


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

  139.         int index = Arrays.binarySearch(TransformUtils.POWERS_OF_TWO, n);
  140.         if (index < 0) {
  141.             throw new MathIllegalArgumentException(
  142.                     LocalizedFormats.NOT_POWER_OF_TWO_CONSIDER_PADDING,
  143.                     Integer.valueOf(n));
  144.         }
  145.         return index;
  146.     }
  147. }