/*-------------------------------------------------------------------------
 * drawElements Quality Program Tester Core
 * ----------------------------------------
 *
 * Copyright 2014 The Android Open Source Project
 *
 * 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.
 *
 *//*!
 * \file
 * \brief Internal utilities shared between TexLookup and TexCompare verifiers.
 *//*--------------------------------------------------------------------*/

#include "tcuTexVerifierUtil.hpp"
#include "tcuFloat.hpp"

namespace tcu
{
namespace TexVerifierUtil
{

float computeFloatingPointError (const float value, const int numAccurateBits)
{
	DE_ASSERT(numAccurateBits >= 0);
	DE_ASSERT(numAccurateBits <= 23);

	const int		numGarbageBits	= 23-numAccurateBits;
	const deUint32	mask			= (1u<<numGarbageBits)-1u;
	const int		exp				= tcu::Float32(value).exponent();

	return Float32::construct(+1, exp, (1u<<23) | mask).asFloat() - Float32::construct(+1, exp, 1u<<23).asFloat();
}

float computeFixedPointError (const int numAccurateBits)
{
	return computeFloatingPointError(1.0f, numAccurateBits);
}

Vec2 computeNonNormalizedCoordBounds (const bool normalizedCoords, const int dim, const float coord, const int coordBits, const int uvBits)
{
	const float		coordErr		= computeFloatingPointError(coord, coordBits);
	const float		minN			= coord - coordErr;
	const float		maxN			= coord + coordErr;
	const float		minA			= normalizedCoords ? minN*float(dim) : minN;
	const float		maxA			= normalizedCoords ? maxN*float(dim) : maxN;
	const float		minC			= minA - computeFixedPointError(uvBits);
	const float		maxC			= maxA + computeFixedPointError(uvBits);

	DE_ASSERT(minC <= maxC);

	return Vec2(minC, maxC);
}

void getPossibleCubeFaces (const Vec3& coord, const IVec3& bits, CubeFace* faces, int& numFaces)
{
	const float	x	= coord.x();
	const float	y	= coord.y();
	const float	z	= coord.z();
	const float ax	= de::abs(x);
	const float ay	= de::abs(y);
	const float az	= de::abs(z);
	const float ex	= computeFloatingPointError(x, bits.x());
	const float	ey	= computeFloatingPointError(y, bits.y());
	const float ez	= computeFloatingPointError(z, bits.z());

	numFaces = 0;

	if (ay+ey < ax-ex && az+ez < ax-ex)
	{
		if (x >= ex) faces[numFaces++] = CUBEFACE_POSITIVE_X;
		if (x <= ex) faces[numFaces++] = CUBEFACE_NEGATIVE_X;
	}
	else if (ax+ex < ay-ey && az+ez < ay-ey)
	{
		if (y >= ey) faces[numFaces++] = CUBEFACE_POSITIVE_Y;
		if (y <= ey) faces[numFaces++] = CUBEFACE_NEGATIVE_Y;
	}
	else if (ax+ex < az-ez && ay+ey < az-ez)
	{
		if (z >= ez) faces[numFaces++] = CUBEFACE_POSITIVE_Z;
		if (z <= ez) faces[numFaces++] = CUBEFACE_NEGATIVE_Z;
	}
	else
	{
		// One or more components are equal (or within error bounds). Allow all faces where major axis is not zero.
		if (ax > ex)
		{
			faces[numFaces++] = CUBEFACE_NEGATIVE_X;
			faces[numFaces++] = CUBEFACE_POSITIVE_X;
		}

		if (ay > ey)
		{
			faces[numFaces++] = CUBEFACE_NEGATIVE_Y;
			faces[numFaces++] = CUBEFACE_POSITIVE_Y;
		}

		if (az > ez)
		{
			faces[numFaces++] = CUBEFACE_NEGATIVE_Z;
			faces[numFaces++] = CUBEFACE_POSITIVE_Z;
		}
	}
}

Sampler getUnnormalizedCoordSampler (const Sampler& sampler)
{
	Sampler copy = sampler;
	copy.normalizedCoords = false;
	return copy;
}

static inline int imod (int a, int b)
{
	int m = a % b;
	return m < 0 ? m + b : m;
}

static inline int mirror (int a)
{
	return a >= 0 ? a : -(1 + a);
}

int wrap (Sampler::WrapMode mode, int c, int size)
{
	switch (mode)
	{
		// \note CL and GL modes are handled identically here, as verification process accounts for
		//		 accuracy differences caused by different methods (wrapping vs. denormalizing first).
		case tcu::Sampler::CLAMP_TO_BORDER:
			return deClamp32(c, -1, size);

		case tcu::Sampler::CLAMP_TO_EDGE:
			return deClamp32(c, 0, size-1);

		case tcu::Sampler::REPEAT_GL:
		case tcu::Sampler::REPEAT_CL:
			return imod(c, size);

		case tcu::Sampler::MIRRORED_ONCE:
			c = deClamp32(c, -size, size);
			// Fall-through

		case tcu::Sampler::MIRRORED_REPEAT_GL:
		case tcu::Sampler::MIRRORED_REPEAT_CL:
			return (size - 1) - mirror(imod(c, 2*size) - size);

		default:
			DE_ASSERT(DE_FALSE);
			return 0;
	}
}
} // TexVerifierUtil
} // tcu
