/*
 * 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.math.transform;

import org.apache.commons.math.analysis.*;
import org.apache.commons.math.MathException;
import junit.framework.TestCase;

/**
 * Testcase for fast sine transformer.
 * <p>
 * FST algorithm is exact, the small tolerance number is used only to account
 * for round-off errors.
 * 
 * @version $Revision$ $Date$
 */
public final class FastSineTransformerTest extends TestCase {

	/**
	 * Test of transformer for the ad hoc data.
	 */
	public void testAdHocData() {
		FastSineTransformer transformer = new FastSineTransformer();
		double result[], tolerance = 1E-12;

		double x[] = { 0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0 };
		double y[] = { 0.0, 20.1093579685034, -9.65685424949238, 5.98642305066196, -4.0, 2.67271455167720,
				-1.65685424949238, 0.795649469518633 };

		result = transformer.transform(x);
		for (int i = 0; i < result.length; i++) {
			assertEquals(y[i], result[i], tolerance);
		}

		result = transformer.inversetransform(y);
		for (int i = 0; i < result.length; i++) {
			assertEquals(x[i], result[i], tolerance);
		}

		FastFourierTransformer.scaleArray(x, Math.sqrt(x.length / 2.0));

		result = transformer.transform2(y);
		for (int i = 0; i < result.length; i++) {
			assertEquals(x[i], result[i], tolerance);
		}

		result = transformer.inversetransform2(x);
		for (int i = 0; i < result.length; i++) {
			assertEquals(y[i], result[i], tolerance);
		}
	}

	/**
	 * Test of transformer for the sine function.
	 */
	public void testSinFunction() throws MathException {
		UnivariateRealFunction f = new SinFunction();
		FastSineTransformer transformer = new FastSineTransformer();
		double min, max, result[], tolerance = 1E-12;
		int N = 1 << 8;

		min = 0.0;
		max = 2.0 * Math.PI;
		result = transformer.transform(f, min, max, N);
		assertEquals(N >> 1, result[2], tolerance);
		for (int i = 0; i < N; i += (i == 1 ? 2 : 1)) {
			assertEquals(0.0, result[i], tolerance);
		}

		min = -Math.PI;
		max = Math.PI;
		result = transformer.transform(f, min, max, N);
		assertEquals(-(N >> 1), result[2], tolerance);
		for (int i = 0; i < N; i += (i == 1 ? 2 : 1)) {
			assertEquals(0.0, result[i], tolerance);
		}
	}

	/**
	 * Test of parameters for the transformer.
	 */
	public void testParameters() throws Exception {
		UnivariateRealFunction f = new SinFunction();
		FastSineTransformer transformer = new FastSineTransformer();

		try {
			// bad interval
			transformer.transform(f, 1, -1, 64);
			fail("Expecting IllegalArgumentException - bad interval");
		} catch (IllegalArgumentException ex) {
			// expected
		}
		try {
			// bad samples number
			transformer.transform(f, -1, 1, 0);
			fail("Expecting IllegalArgumentException - bad samples number");
		} catch (IllegalArgumentException ex) {
			// expected
		}
		try {
			// bad samples number
			transformer.transform(f, -1, 1, 100);
			fail("Expecting IllegalArgumentException - bad samples number");
		} catch (IllegalArgumentException ex) {
			// expected
		}
	}
}
