package lpv;

import javax.vecmath.Point3i;
import javax.vecmath.Vector3f;
import javax.vecmath.Vector4f;

public class SH {
	public static Vector4f construct(float x, float y, float z) {
		return new Vector4f(
				 0.282094792f,
				-0.4886025119f * y,
				 0.4886025119f * z,
				-0.4886025119f * x
			);
	}
	
	public static Vector4f clampedCosineLobe(Point3i p) {
		return clampedCosineLobe(p.x, p.y, p.z);
	}

	public static Vector4f clampedCosineLobe(float x, float y, float z) {
		float fPI = (float)Math.PI;
		return new Vector4f(
				fPI * 0.282094792f,
				((2.0f*fPI)/3.0f) * -0.4886025119f * y, 
				((2.0f*fPI)/3.0f) *  0.4886025119f * z, 
				((2.0f*fPI)/3.0f) * -0.4886025119f * x
		);
		/*return new Vector4f(
				0.5f,
				-0.75f * y,
				0.75f * z,
				-0.75f * x
			);*/
	}

	public static Vector4f clampedCosineLobe(Vector3f dir) {
		return clampedCosineLobe(dir.x, dir.y, dir.z);
	}
	
	public static float infNorm(Vector4f v) {
		return Math.max(
				Math.max(
					Math.abs(v.x), 
					Math.abs(v.y)
				), 
				Math.max(
					Math.abs(v.z), 
					Math.abs(v.w)
				)
			);
	}
	
	public static float absoluteError(Vector4f approx, Vector4f real) {
		Vector4f diff = new Vector4f(approx);
		diff.sub(real);
		return infNorm(diff);
	}
	
	public static float relativeError(Vector4f approx, Vector4f real) {
		float in = infNorm(approx);
		return Math.abs(in) < 0.0001f ? 0.0f : absoluteError(approx, real) / in;
	}
}
