// 
// Decompiled by Procyon v0.6.0
// 

package com.hypixel.hytale.math.util;

import javax.annotation.Nonnull;

public class TrigMathUtil
{
    public static final float PI = 3.1415927f;
    public static final float PI_HALF = 1.5707964f;
    public static final float PI_QUARTER = 0.7853982f;
    public static final float PI2 = 6.2831855f;
    public static final float PI4 = 12.566371f;
    public static final float radToDeg = 57.295776f;
    public static final float degToRad = 0.017453292f;
    
    public static float sin(final float radians) {
        return Riven.sin(radians);
    }
    
    public static float cos(final float radians) {
        return Riven.cos(radians);
    }
    
    public static float sin(final double radians) {
        return Riven.sin((float)radians);
    }
    
    public static float cos(final double radians) {
        return Riven.cos((float)radians);
    }
    
    public static float atan2(final float y, final float x) {
        return Icecore.atan2(y, x);
    }
    
    public static float atan2(final double y, final double x) {
        return Icecore.atan2((float)y, (float)x);
    }
    
    public static float atan(final double d) {
        return (float)Math.atan(d);
    }
    
    public static float asin(final double d) {
        return (float)Math.asin(d);
    }
    
    private TrigMathUtil() {
    }
    
    private static final class Riven
    {
        private static final int SIN_BITS;
        private static final int SIN_MASK;
        private static final int SIN_COUNT;
        private static final float radFull;
        private static final float radToIndex;
        private static final float degFull;
        private static final float degToIndex;
        @Nonnull
        private static final float[] SIN;
        @Nonnull
        private static final float[] COS;
        
        public static float sin(final float rad) {
            return Riven.SIN[(int)(rad * Riven.radToIndex) & Riven.SIN_MASK];
        }
        
        public static float cos(final float rad) {
            return Riven.COS[(int)(rad * Riven.radToIndex) & Riven.SIN_MASK];
        }
        
        static {
            SIN_BITS = 12;
            SIN_MASK = ~(-1 << Riven.SIN_BITS);
            SIN_COUNT = Riven.SIN_MASK + 1;
            radFull = 6.2831855f;
            degFull = 360.0f;
            radToIndex = Riven.SIN_COUNT / Riven.radFull;
            degToIndex = Riven.SIN_COUNT / Riven.degFull;
            SIN = new float[Riven.SIN_COUNT];
            COS = new float[Riven.SIN_COUNT];
            for (int i = 0; i < Riven.SIN_COUNT; ++i) {
                Riven.SIN[i] = (float)Math.sin((i + 0.5f) / Riven.SIN_COUNT * Riven.radFull);
                Riven.COS[i] = (float)Math.cos((i + 0.5f) / Riven.SIN_COUNT * Riven.radFull);
            }
            for (int i = 0; i < 360; i += 90) {
                Riven.SIN[(int)(i * Riven.degToIndex) & Riven.SIN_MASK] = (float)Math.sin(i * 3.141592653589793 / 180.0);
                Riven.COS[(int)(i * Riven.degToIndex) & Riven.SIN_MASK] = (float)Math.cos(i * 3.141592653589793 / 180.0);
            }
        }
    }
    
    private static final class Icecore
    {
        private static final int SIZE_AC = 100000;
        private static final int SIZE_AR = 100001;
        private static final float[] ATAN2;
        
        public static float atan2(float y, float x) {
            if (y < 0.0f) {
                if (x < 0.0f) {
                    if (y < x) {
                        return -Icecore.ATAN2[(int)(x / y * 100000.0f)] - 1.5707964f;
                    }
                    return Icecore.ATAN2[(int)(y / x * 100000.0f)] - 3.1415927f;
                }
                else {
                    y = -y;
                    if (y > x) {
                        return Icecore.ATAN2[(int)(x / y * 100000.0f)] - 1.5707964f;
                    }
                    return -Icecore.ATAN2[(int)(y / x * 100000.0f)];
                }
            }
            else if (x < 0.0f) {
                x = -x;
                if (y > x) {
                    return Icecore.ATAN2[(int)(x / y * 100000.0f)] + 1.5707964f;
                }
                return -Icecore.ATAN2[(int)(y / x * 100000.0f)] + 3.1415927f;
            }
            else {
                if (y > x) {
                    return -Icecore.ATAN2[(int)(x / y * 100000.0f)] + 1.5707964f;
                }
                return Icecore.ATAN2[(int)(y / x * 100000.0f)];
            }
        }
        
        static {
            ATAN2 = new float[100001];
            for (int i = 0; i <= 100000; ++i) {
                final double d = i / 100000.0;
                final double x = 1.0;
                final double y = x * d;
                final float v = (float)Math.atan2(y, x);
                Icecore.ATAN2[i] = v;
            }
        }
    }
}
