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.math4.transform;

  18. import java.util.function.DoubleUnaryOperator;

  19. import org.apache.commons.numbers.complex.Complex;

  20. /**
  21.  * Useful functions for the implementation of various transforms.
  22.  * Class is package-private (for internal use only).
  23.  */
  24. final class TransformUtils {
  25.     /** Number of array slots: 1 for "real" parts 1 for "imaginary" parts. */
  26.     private static final int NUM_PARTS = 2;

  27.     /** Utility class. */
  28.     private TransformUtils() {}

  29.     /**
  30.      * Multiply every component in the given real array by the
  31.      * given real number. The change is made in place.
  32.      *
  33.      * @param f Array to be scaled.
  34.      * @param d Scaling coefficient.
  35.      * @return a reference to the scaled array.
  36.      */
  37.     static double[] scaleInPlace(double[] f, double d) {
  38.         for (int i = 0; i < f.length; i++) {
  39.             f[i] *= d;
  40.         }
  41.         return f;
  42.     }

  43.     /**
  44.      * Multiply every component in the given complex array by the
  45.      * given real number. The change is made in place.
  46.      *
  47.      * @param f Array to be scaled.
  48.      * @param d Scaling coefficient.
  49.      * @return the scaled array.
  50.      */
  51.     static Complex[] scaleInPlace(Complex[] f, double d) {
  52.         for (int i = 0; i < f.length; i++) {
  53.             f[i] = Complex.ofCartesian(d * f[i].getReal(), d * f[i].getImaginary());
  54.         }
  55.         return f;
  56.     }


  57.     /**
  58.      * Builds a new two dimensional array of {@code double} filled with the real
  59.      * and imaginary parts of the specified {@link Complex} numbers. In the
  60.      * returned array {@code dataRI}, the data is laid out as follows
  61.      * <ul>
  62.      * <li>{@code dataRI[0][i] = dataC[i].getReal()},</li>
  63.      * <li>{@code dataRI[1][i] = dataC[i].getImaginary()}.</li>
  64.      * </ul>
  65.      *
  66.      * @param dataC Array of {@link Complex} data to be transformed.
  67.      * @return a two dimensional array filled with the real and imaginary parts
  68.      * of the specified complex input.
  69.      */
  70.     static double[][] createRealImaginary(final Complex[] dataC) {
  71.         final double[][] dataRI = new double[2][dataC.length];
  72.         final double[] dataR = dataRI[0];
  73.         final double[] dataI = dataRI[1];
  74.         for (int i = 0; i < dataC.length; i++) {
  75.             final Complex c = dataC[i];
  76.             dataR[i] = c.getReal();
  77.             dataI[i] = c.getImaginary();
  78.         }
  79.         return dataRI;
  80.     }

  81.     /**
  82.      * Builds a new array of {@link Complex} from the specified two dimensional
  83.      * array of real and imaginary parts. In the returned array {@code dataC},
  84.      * the data is laid out as follows
  85.      * <ul>
  86.      * <li>{@code dataC[i].getReal() = dataRI[0][i]},</li>
  87.      * <li>{@code dataC[i].getImaginary() = dataRI[1][i]}.</li>
  88.      * </ul>
  89.      *
  90.      * @param dataRI Array of real and imaginary parts to be transformed.
  91.      * @return a {@link Complex} array.
  92.      * @throws IllegalArgumentException if the number of rows of the specified
  93.      * array is not two, or the array is not rectangular.
  94.      */
  95.     static Complex[] createComplex(final double[][] dataRI) {
  96.         if (dataRI.length != NUM_PARTS) {
  97.             throw new TransformException(TransformException.SIZE_MISMATCH,
  98.                                          dataRI.length, NUM_PARTS);
  99.         }
  100.         final double[] dataR = dataRI[0];
  101.         final double[] dataI = dataRI[1];
  102.         if (dataR.length != dataI.length) {
  103.             throw new TransformException(TransformException.SIZE_MISMATCH,
  104.                                          dataI.length, dataR.length);
  105.         }

  106.         final int n = dataR.length;
  107.         final Complex[] c = new Complex[n];
  108.         for (int i = 0; i < n; i++) {
  109.             c[i] = Complex.ofCartesian(dataR[i], dataI[i]);
  110.         }
  111.         return c;
  112.     }

  113.     /**
  114.      * Samples the specified univariate real function on the specified interval.
  115.      * <p>
  116.      * The interval is divided equally into {@code n} sections and sample points
  117.      * are taken from {@code min} to {@code max - (max - min) / n}; therefore
  118.      * {@code f} is not sampled at the upper bound {@code max}.</p>
  119.      *
  120.      * @param f Function to be sampled
  121.      * @param min Lower bound of the interval (included).
  122.      * @param max Upper bound of the interval (excluded).
  123.      * @param n Number of sample points.
  124.      * @return the array of samples.
  125.      * @throws IllegalArgumentException if the lower bound {@code min} is
  126.      * greater than, or equal to the upper bound {@code max}, if the number
  127.      * of sample points {@code n} is negative.
  128.      */
  129.     static double[] sample(DoubleUnaryOperator f,
  130.                            double min,
  131.                            double max,
  132.                            int n) {
  133.         if (n <= 0) {
  134.             throw new TransformException(TransformException.NOT_STRICTLY_POSITIVE,
  135.                                          Integer.valueOf(n));
  136.         }
  137.         if (min >= max) {
  138.             throw new TransformException(TransformException.TOO_LARGE, min, max);
  139.         }

  140.         final double[] s = new double[n];
  141.         final double h = (max - min) / n;
  142.         for (int i = 0; i < n; i++) {
  143.             s[i] = f.applyAsDouble(min + i * h);
  144.         }
  145.         return s;
  146.     }
  147. }