content: /*******************************************************************************
   * Copyright 2011 See AUTHORS file.
   * 
   * Licensed 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 com.badlogic.gdx.math;
  
  import java.util.Random;
  
  import com.badlogic.gdx.utils.NumberUtils;
  
  /** Utility and fast math functions.<br>
   * <br>
   * Thanks to Riven on JavaGaming.org for sin/cos/atan2/floor/ceil.<br> */
  public class MathUtils {
  	static public final float PI = 3.1415927f;
  
  	static private final int SIN_BITS = 13; // Adjust for accuracy.
  	static private final int SIN_MASK = ~(-1 << SIN_BITS);
  	static private final int SIN_COUNT = SIN_MASK + 1;
  
  	static private final float radFull = PI * 2;
  	static private final float degFull = 360;
  	static private final float radToIndex = SIN_COUNT / radFull;
  	static private final float degToIndex = SIN_COUNT / degFull;
  
  	static public final float radiansToDegrees = 180f / PI;
  	static public final float degreesToRadians = PI / 180;
  
  	static public final float[] sin = new float[SIN_COUNT];
  	static public final float[] cos = new float[SIN_COUNT];
  
  	static {
  		for (int i = 0; i < SIN_COUNT; i++) {
  			float a = (i + 0.5f) / SIN_COUNT * radFull;
  			sin[i] = (float)Math.sin(a);
  			cos[i] = (float)Math.cos(a);
  		}
  		for (int i = 0; i < 360; i += 90) {
  			sin[(int)(i * degToIndex) & SIN_MASK] = (float)Math.sin(i * degreesToRadians);
  			cos[(int)(i * degToIndex) & SIN_MASK] = (float)Math.cos(i * degreesToRadians);
  		}
  	}
  
  	static public final float sin (float rad) {
  		return sin[(int)(rad * radToIndex) & SIN_MASK];
  	}
  
  	static public final float cos (float rad) {
  		return cos[(int)(rad * radToIndex) & SIN_MASK];
  	}
  
  	static public final float sinDeg (float deg) {
  		return sin[(int)(deg * degToIndex) & SIN_MASK];
  	}
  
  	static public final float cosDeg (float deg) {
  		return cos[(int)(deg * degToIndex) & SIN_MASK];
  	}
  
  	// ---
  
  	static private final int ATAN2_BITS = 7; // Adjust for accuracy.
  	static private final int ATAN2_BITS2 = ATAN2_BITS << 1;
  	static private final int ATAN2_MASK = ~(-1 << ATAN2_BITS2);
  	static private final int ATAN2_COUNT = ATAN2_MASK + 1;
  	static private final int ATAN2_DIM = (int)Math.sqrt(ATAN2_COUNT);
  	static private final float INV_ATAN2_DIM_MINUS_1 = 1.0f / (ATAN2_DIM - 1);
  	static private final float[] atan2 = new float[ATAN2_COUNT];
  	static {
  		for (int i = 0; i < ATAN2_DIM; i++) {
  			for (int j = 0; j < ATAN2_DIM; j++) {
  				float x0 = (float)i / ATAN2_DIM;
  				float y0 = (float)j / ATAN2_DIM;
  				atan2[j * ATAN2_DIM + i] = (float)Math.atan2(y0, x0);
  			}
  		}
  	}
  
  	static public final float atan2 (float y, float x) {
  		float add, mul;
  		if (x < 0) {
  			if (y < 0) {
  				y = -y;
  				mul = 1;
  			} else
  				mul = -1;
  			x = -x;
  			add = -3.141592653f;
  		} else {
  			if (y < 0) {
  				y = -y;
  				mul = -1;
  			} else
  				mul = 1;
  			add = 0;
  		}
  		float invDiv = 1 / ((x < y ? y : x) * INV_ATAN2_DIM_MINUS_1);
  		int xi = (int)(x * invDiv);
  		int yi = (int)(y * invDiv);
  		return (atan2[yi * ATAN2_DIM + xi] + add) * mul;
  	}
  
  	// ---
  
  	static public Random random = new Random();
  
  	/** Returns a random number between 0 (inclusive) and the specified value (inclusive). */
  	static public final int random (int range) {
  		return random.nextInt(range + 1);
  	}
  
  	static public final int random (int start, int end) {
  		return start + random.nextInt(end - start + 1);
  	}
  
  	static public final boolean randomBoolean () {
  		return random.nextBoolean();
  	}
  
  	static public final float random () {
  		return random.nextFloat();
  	}
  
  	static public final float random (float range) {
  		return random.nextFloat() * range;
  	}
  
  	static public final float random (float start, float end) {
  		return start + random.nextFloat() * (end - start);
  	}
  
  	// ---
  
  	static public int nextPowerOfTwo (int value) {
  		if (value == 0) return 1;
  		value--;
  		value |= value >> 1;
  		value |= value >> 2;
  		value |= value >> 4;
  		value |= value >> 8;
  		value |= value >> 16;
  		return value + 1;
  	}
  
  	static public boolean isPowerOfTwo (int value) {
  		return value != 0 && (value & value - 1) == 0;
  	}
  
  	// ---
  
  	static private final int BIG_ENOUGH_INT = 16 * 1024;
  	static private final double BIG_ENOUGH_FLOOR = BIG_ENOUGH_INT;
  	static private final double CEIL = 0.9999999;
  	static private final double BIG_ENOUGH_CEIL = NumberUtils
  		.longBitsToDouble(NumberUtils.doubleToLongBits(BIG_ENOUGH_INT + 1) - 1);
  	static private final double BIG_ENOUGH_ROUND = BIG_ENOUGH_INT + 0.5f;
  
  	/** Returns the largest integer less than or equal to the specified float. This method will only properly floor floats from
  	 * -(2^14) to (Float.MAX_VALUE - 2^14). */
  	static public int floor (float x) {
  		return (int)(x + BIG_ENOUGH_FLOOR) - BIG_ENOUGH_INT;
  	}
  
  	/** Returns the largest integer less than or equal to the specified float. This method will only properly floor floats that are
  	 * positive. Note this method simply casts the float to int. */
  	static public int floorPositive (float x) {
  		return (int)x;
  	}
  
  	/** Returns the smallest integer greater than or equal to the specified float. This method will only properly ceil floats from
  	 * -(2^14) to (Float.MAX_VALUE - 2^14). */
  	static public int ceil (float x) {
  		return (int)(x + BIG_ENOUGH_CEIL) - BIG_ENOUGH_INT;
  	}
  
  	/** Returns the smallest integer greater than or equal to the specified float. This method will only properly ceil floats that
  	 * are positive. */
  	static public int ceilPositive (float x) {
  		return (int)(x + CEIL);
  	}
  
  	/** Returns the closest integer to the specified float. This method will only properly round floats from -(2^14) to
  	 * (Float.MAX_VALUE - 2^14). */
  	static public int round (float x) {
  		return (int)(x + BIG_ENOUGH_ROUND) - BIG_ENOUGH_INT;
  	}
  
  	/** Returns the closest integer to the specified float. This method will only properly round floats that are positive. */
  	static public int roundPositive (float x) {
  		return (int)(x + 0.5f);
  	}
  }
  