| /* |
| * Licensed to the Apache Software Foundation (ASF) under one or more |
| * contributor license agreements. See the NOTICE file distributed with |
| * this work for additional information regarding copyright ownership. |
| * The ASF licenses this file to You under the Apache License, Version 2.0 |
| * (the "License"); you may not use this file except in compliance with |
| * the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| package org.apache.commons.numbers.complex; |
| |
| /** |
| * Computation of the {@code n}-th roots of unity. |
| */ |
| public class RootsOfUnity { |
| /** 2 * π */ |
| private static final double TWO_PI = 2 * Math.PI; |
| /** Number of roots of unity. */ |
| private final int omegaCount; |
| /** The roots. */ |
| private final Complex[] omega; |
| /** |
| * {@code true} if the constructor was called with a positive |
| * value of its argument {@code n}. |
| */ |
| private final boolean isCounterClockwise; |
| |
| /** |
| * Computes the {@code n}-th roots of unity. |
| * |
| * The roots are stored in an array |
| * {@code omega[]}, such that {@code omega[k] = w ^ k}, where |
| * {@code k = 0, ..., n - 1}, {@code w = exp(2 * pi * i / n)} and |
| * {@code i = sqrt(-1)}. |
| * |
| * <p>{@code n} can be positive of negative ({@code abs(n)} is always |
| * the number of roots of unity):</p> |
| * <ul> |
| * <li>If {@code n > 0}, then the roots are stored in counter-clockwise order.</li> |
| * <li>If {@code n < 0}, then the roots are stored in clockwise order.</li> |
| * </ul> |
| * |
| * @param n The (signed) number of roots of unity to be computed. |
| * @throws IllegalArgumentException if {@code n == 0}? |
| */ |
| public RootsOfUnity(int n) { |
| if (n == 0) { |
| throw new IllegalArgumentException("Zero-th root"); |
| } |
| |
| omegaCount = Math.abs(n); |
| isCounterClockwise = n > 0; |
| |
| omega = new Complex[omegaCount]; |
| final double t = TWO_PI / omegaCount; |
| final double cosT = Math.cos(t); |
| final double sinT = Math.sin(t); |
| |
| double previousReal = 1; |
| double previousImag = 0; |
| omega[0] = new Complex(previousReal, previousImag); |
| for (int i = 1; i < omegaCount; i++) { |
| final double real = previousReal * cosT - previousImag * sinT; |
| final double imag = previousReal * sinT + previousImag * cosT; |
| |
| omega[i] = isCounterClockwise ? |
| new Complex(real, imag) : |
| new Complex(real, -imag); |
| |
| previousReal = real; |
| previousImag = imag; |
| } |
| } |
| |
| /** |
| * Returns {@code true} if {@link #RootsOfUnity(int)} was called with a |
| * positive value of its argument {@code n}. |
| * If {@code true}, then the imaginary parts of the successive roots are |
| * {@link #getRoot(int) returned} in counter-clockwise order. |
| * |
| * @return {@code true} if the roots of unity are stored in |
| * counter-clockwise order. |
| */ |
| public boolean isCounterClockwise() { |
| return isCounterClockwise; |
| } |
| |
| /** |
| * Gets the {@code k}-th among the computed roots of unity. |
| * |
| * @param k Index of the requested value. |
| * @return the {@code k}-th among the {@code N}-th root of unity |
| * where {@code N} is the absolute value of the argument passed |
| * to the constructor. |
| * @throws IndexOutOfBoundsException if {@code k} is out of range. |
| */ |
| public Complex getRoot(int k) { |
| return omega[k]; |
| } |
| |
| /** |
| * Gets the number of roots of unity. |
| * |
| * @return the number of roots of unity. |
| */ |
| public int getNumberOfRoots() { |
| return omegaCount; |
| } |
| } |