package migl.lisp.operator;

import static org.junit.Assert.assertEquals;

import org.junit.Before;
import org.junit.Test;

import migl.lisp.Lisp;
import migl.lisp.LispElement;
import migl.lisp.LispError;
import migl.lisp.LispEval;
import migl.lisp.LispFactory;
import migl.util.ConsList;
import migl.util.ConsListFactory;

public class MathOperatorOwnTest {
	
	private Lisp interpreter;

	@Before
	public void init() {
		interpreter = LispFactory.makeIntepreter();
	}
	
	@Test(expected = LispError.class)
	public void testIncorrectNumberArgumentMathOperator() throws LispError {
		LispEval le = new LispEval(interpreter, interpreter.parse("(cbrt 8.0 8.0)"));
		le.evaluate();
	}
	
	@Test
	public void testMathOperator() throws LispError {
		assertEquals(LispElement.generate(2.0), interpreter.eval("(cbrt 8)"));
		assertEquals(LispElement.generate(2.0), interpreter.eval("(cbrt 8.0)"));
		assertEquals(LispElement.generate(2.0), interpreter.eval("(cbrt (/ 16 2.0))"));
		assertEquals(LispElement.generate(8.0), interpreter.eval("(ceil 8)"));
		assertEquals(LispElement.generate(9.0), interpreter.eval("(ceil 8.24)"));
		assertEquals(LispElement.generate(8.0), interpreter.eval("(floor 8)"));
		assertEquals(LispElement.generate(8.0), interpreter.eval("(floor 8.24)"));
		assertEquals(LispElement.generate(2.0), interpreter.eval("(log10 100)"));
		assertEquals(LispElement.generate(2.0), interpreter.eval("(log10 100.0)"));
		assertEquals(LispElement.generate(1.0), interpreter.eval("(cos 0)"));
		assertEquals(LispElement.generate(1.0), interpreter.eval("(cos 0.0)"));
		assertEquals(LispElement.generate(8.0), interpreter.eval("(rint 8)"));
		assertEquals(LispElement.generate(8.0), interpreter.eval("(rint 8.49)"));
		assertEquals(LispElement.generate(9.0), interpreter.eval("(rint 8.51)"));
		assertEquals(LispElement.generate(8), interpreter.eval("(round 8)"));
		assertEquals(LispElement.generate(8), interpreter.eval("(round 8.49)"));
		assertEquals(LispElement.generate(9), interpreter.eval("(round 8.51)"));
		assertEquals(LispElement.generate(1.0), interpreter.eval("(signum 5.9)"));
		assertEquals(LispElement.generate(-1.0), interpreter.eval("(signum -5.9)"));
		assertEquals(LispElement.generate(-1.0), interpreter.eval("(signum (- 5.9))"));
		assertEquals(LispElement.generate(0.0), interpreter.eval("(signum 0)"));
		assertEquals(LispElement.generate(0.0), interpreter.eval("(signum 0.0)"));
	}
	
	@Test(expected = LispError.class)
	public void testMathOperatorException() throws LispError {
		LispOperator math = new MathOperator();
		ConsList<Object> cl = ConsListFactory.nil();
		cl = cl.prepend(4.2);
		math.apply(new LispEval(interpreter), "_", cl);
	}

}
