    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    }