/*
 * @author Ranides Atterwim <ranides@gmail.com>
 * @copyright Ranides Atterwim
 * @license WTFPL
 * @url http://ranides.net/projects/assira
 */
package net.ranides.assira.math;

import org.junit.Test;
import static org.junit.Assert.*;

/**
 *
 * @author Ranides Atterwim <ranides@gmail.com>
 */
public class MathUtilsTest {
    
    private final static float FP = 0.001f;
    
    private final static double DP = 0.001;
    

    @Test
    public void testInRange_byte() {
        byte rs = (byte)2;
        byte re = (byte)7;
        byte in = (byte)4;
        byte lo = (byte)1;
        byte hi = (byte)9;
        assertTrue( MathUtils.between(rs, rs, re));
        assertTrue( MathUtils.between(re, rs, re));
        assertTrue( MathUtils.between(in, rs, re));
        
        assertFalse( MathUtils.between(lo, rs, re));
        assertFalse( MathUtils.between(hi, rs, re));
    }

    @Test
    public void testInRange_int() {
        int rs = (int)2;
        int re = (int)7;
        int in = (int)4;
        int lo = (int)1;
        int hi = (int)9;
        assertTrue( MathUtils.between(rs, rs, re));
        assertTrue( MathUtils.between(re, rs, re));
        assertTrue( MathUtils.between(in, rs, re));
        
        assertFalse( MathUtils.between(lo, rs, re));
        assertFalse( MathUtils.between(hi, rs, re));
    }

    @Test
    public void testInRange_long() {
        long rs = (long)2;
        long re = (long)7;
        long in = (long)4;
        long lo = (long)1;
        byte hi = (byte)9;
        assertTrue( MathUtils.between(rs, rs, re));
        assertTrue( MathUtils.between(re, rs, re));
        assertTrue( MathUtils.between(in, rs, re));
        
        assertFalse( MathUtils.between(lo, rs, re));
        assertFalse( MathUtils.between(hi, rs, re));
    }

    @Test
    public void testClip_int() {
        int rs = (int)2;
        int re = (int)7;
        int in = (int)4;
        int lo = (int)1;
        int hi = (int)9;
        
        assertEquals(rs, MathUtils.clip(rs, rs, re));
        assertEquals(re, MathUtils.clip(re, rs, re));
        assertEquals(in, MathUtils.clip(in, rs, re));
        
        assertEquals(rs, MathUtils.clip(lo, rs, re));
        assertEquals(re, MathUtils.clip(hi, rs, re));
    }

    @Test
    public void testClip_float() {
        float rs = (float)2;
        float re = (float)7;
        float in = (float)4;
        float lo = (float)1;
        float hi = (float)9;
        
        assertEquals(rs, MathUtils.clip(rs, rs, re), FP);
        assertEquals(re, MathUtils.clip(re, rs, re), FP);
        assertEquals(in, MathUtils.clip(in, rs, re), FP);
        
        assertEquals(rs, MathUtils.clip(lo, rs, re), FP);
        assertEquals(re, MathUtils.clip(hi, rs, re), FP);
    }

    @Test
    public void testClip_double() {
        double rs = (double)2;
        double re = (double)7;
        double in = (double)4;
        double lo = (double)1;
        double hi = (double)9;
        
        assertEquals(rs, MathUtils.clip(rs, rs, re), DP);
        assertEquals(re, MathUtils.clip(re, rs, re), DP);
        assertEquals(in, MathUtils.clip(in, rs, re), DP);
        
        assertEquals(rs, MathUtils.clip(lo, rs, re), DP);
        assertEquals(re, MathUtils.clip(hi, rs, re), DP);
    }

    @Test
    public void testRound_int() {
        int rs = 2;
        int re = 7;
        
        assertEquals(2, MathUtils.round(1.0, rs, re));
        assertEquals(2, MathUtils.round(2.0, rs, re));
        assertEquals(2, MathUtils.round(2.1, rs, re));
        assertEquals(3, MathUtils.round(2.6, rs, re));
        
        assertEquals(6, MathUtils.round(6.0, rs, re));
        assertEquals(6, MathUtils.round(6.2, rs, re));
        assertEquals(7, MathUtils.round(6.8, rs, re));
        assertEquals(7, MathUtils.round(7.0, rs, re));
        assertEquals(7, MathUtils.round(7.1, rs, re));
        assertEquals(7, MathUtils.round(7.6, rs, re));
        assertEquals(7, MathUtils.round(8.0, rs, re));
        
        assertEquals(4, MathUtils.round(3.9, rs, re));
        assertEquals(4, MathUtils.round(4.0, rs, re));
        assertEquals(4, MathUtils.round(4.1, rs, re));
        assertEquals(5, MathUtils.round(4.6, rs, re));
    }

    @Test
    public void testRound_long() {
        long rs = 2L;
        long re = 7L;
        
        assertEquals(2, MathUtils.round(1.0, rs, re));
        assertEquals(2, MathUtils.round(2.0, rs, re));
        assertEquals(2, MathUtils.round(2.1, rs, re));
        assertEquals(3, MathUtils.round(2.6, rs, re));
        
        assertEquals(6, MathUtils.round(6.0, rs, re));
        assertEquals(6, MathUtils.round(6.2, rs, re));
        assertEquals(7, MathUtils.round(6.8, rs, re));
        assertEquals(7, MathUtils.round(7.0, rs, re));
        assertEquals(7, MathUtils.round(7.1, rs, re));
        assertEquals(7, MathUtils.round(7.6, rs, re));
        assertEquals(7, MathUtils.round(8.0, rs, re));
        
        assertEquals(4, MathUtils.round(3.9, rs, re));
        assertEquals(4, MathUtils.round(4.0, rs, re));
        assertEquals(4, MathUtils.round(4.1, rs, re));
        assertEquals(5, MathUtils.round(4.6, rs, re));
    }

    @Test
    public void testSignum() {
        assertTrue( MathUtils.signum(-100) < 0);
        assertTrue( MathUtils.signum(+100) > 0);
        assertTrue( MathUtils.signum(0) == 0);
    }

    @Test
    public void testLog2floor_int() {
        assertTrue( MathUtils.log2floor(0)< 0);
        assertEquals(0, MathUtils.log2floor(1));
        assertEquals(1, MathUtils.log2floor(2));
        assertEquals(2, MathUtils.log2floor(4));
        assertEquals(2, MathUtils.log2floor(5));
        assertEquals(2, MathUtils.log2floor(7));
        assertEquals(3, MathUtils.log2floor(8));
        assertEquals(3, MathUtils.log2floor(15));
        assertEquals(4, MathUtils.log2floor(16));
        assertEquals(4, MathUtils.log2floor(17));
    }

    @Test
    public void testLog2floor_long() {
        assertTrue( MathUtils.log2floor(0L)< 0);
        assertEquals(0, MathUtils.log2floor(1L));
        assertEquals(1, MathUtils.log2floor(2L));
        assertEquals(2, MathUtils.log2floor(4L));
        assertEquals(2, MathUtils.log2floor(5L));
        assertEquals(2, MathUtils.log2floor(7L));
        assertEquals(3, MathUtils.log2floor(8L));
        assertEquals(3, MathUtils.log2floor(15L));
        assertEquals(4, MathUtils.log2floor(16L));
        assertEquals(4, MathUtils.log2floor(17L));
    }

    @Test
    public void testLog2ceil_int() {
        assertTrue( MathUtils.log2ceil(0)<0 || MathUtils.log2ceil(0)>31 );
        assertEquals(0, MathUtils.log2ceil(1));
        assertEquals(1, MathUtils.log2ceil(2));
        assertEquals(2, MathUtils.log2ceil(4));
        assertEquals(3, MathUtils.log2ceil(5));
        assertEquals(3, MathUtils.log2ceil(7));
        assertEquals(3, MathUtils.log2ceil(8));
        assertEquals(4, MathUtils.log2ceil(15));
        assertEquals(4, MathUtils.log2ceil(16));
        assertEquals(5, MathUtils.log2ceil(17));
    }

    @Test
    public void testLog2ceil_long() {
        assertTrue( MathUtils.log2ceil(0L)<0 || MathUtils.log2ceil(0L)>31 );
        assertEquals(0, MathUtils.log2ceil(1L));
        assertEquals(1, MathUtils.log2ceil(2L));
        assertEquals(2, MathUtils.log2ceil(4L));
        assertEquals(3, MathUtils.log2ceil(5L));
        assertEquals(3, MathUtils.log2ceil(7L));
        assertEquals(3, MathUtils.log2ceil(8L));
        assertEquals(4, MathUtils.log2ceil(15L));
        assertEquals(4, MathUtils.log2ceil(16L));
        assertEquals(5, MathUtils.log2ceil(17L));
    }

    @Test
    public void testPow2next_int() {
        assertEquals(1, MathUtils.pow2next(0));
        assertEquals(1, MathUtils.pow2next(1));
        assertEquals(2, MathUtils.pow2next(2));
        assertEquals(8, MathUtils.pow2next(5));
        assertEquals(8, MathUtils.pow2next(7));
        assertEquals(8, MathUtils.pow2next(8));
        assertEquals(16, MathUtils.pow2next(15));
        assertEquals(16, MathUtils.pow2next(16));
        assertEquals(32, MathUtils.pow2next(17));
    }

    @Test
    public void testPow2next_long() {
        assertEquals(1L, MathUtils.pow2next(0L));
        assertEquals(1L, MathUtils.pow2next(1L));
        assertEquals(2L, MathUtils.pow2next(2L));
        assertEquals(8L, MathUtils.pow2next(5L));
        assertEquals(8L, MathUtils.pow2next(7L));
        assertEquals(8L, MathUtils.pow2next(8L));
        assertEquals(16L, MathUtils.pow2next(15L));
        assertEquals(16L, MathUtils.pow2next(16L));
        assertEquals(32L, MathUtils.pow2next(17L));
    }

    @Test
    public void testGcd_int() {
        assertEquals(1, MathUtils.gcd(1, 35));
        assertEquals(1, MathUtils.gcd(2, 3));
        assertEquals(3, MathUtils.gcd(3, 3));
        assertEquals(7, MathUtils.gcd(14, 35));
        assertEquals(7, MathUtils.gcd(35, 14));
        
        assertEquals(7, MathUtils.gcd(14, 28, 63));
        assertEquals(14, MathUtils.gcd(14, 28, 70));
        assertEquals(2, MathUtils.gcd(14, 28, 70, 2));
        assertEquals(1, MathUtils.gcd(14, 28, 70, 3));
    }

    @Test
    public void testGcd_long() {
        assertEquals(1L, MathUtils.gcd(1L, 35L));
        assertEquals(1L, MathUtils.gcd(2L, 3L));
        assertEquals(3L, MathUtils.gcd(3L, 3L));
        assertEquals(7L, MathUtils.gcd(14L, 35L));
        assertEquals(7L, MathUtils.gcd(35L, 14L));
        
        assertEquals(7L, MathUtils.gcd(14L, 28L, 63L));
        assertEquals(14L, MathUtils.gcd(14L, 28L, 70L));
        assertEquals(2L, MathUtils.gcd(14L, 28L, 70L, 2L));
        assertEquals(1L, MathUtils.gcd(14L, 28L, 70L, 3L));
    }

    @Test
    public void testLcm_int() {
        assertEquals(1, MathUtils.lcm(1,1));
        assertEquals(4, MathUtils.lcm(1,4));
        assertEquals(28, MathUtils.lcm(7,4));
        
        assertEquals(28, MathUtils.lcm(14,4));
        assertEquals(105, MathUtils.lcm(21,35));
        
        assertEquals(110, MathUtils.lcm(2,5,11));
        assertEquals(30, MathUtils.lcm(6,15,30));
        assertEquals(60, MathUtils.lcm(6,15,20));
    }

    @Test
    public void testLcm_long() {
        assertEquals(1L, MathUtils.lcm(1L,1L));
        assertEquals(4L, MathUtils.lcm(1L,4L));
        assertEquals(28L, MathUtils.lcm(7L,4L));
        
        assertEquals(28L, MathUtils.lcm(14L,4L));
        assertEquals(105L, MathUtils.lcm(21L,35L));
        
        assertEquals(110L, MathUtils.lcm(2L,5L,11L));
        assertEquals(30L, MathUtils.lcm(6L,15L,30L));
        assertEquals(60L, MathUtils.lcm(6L,15L,20L));
    }

    
}
