/**
 * Mandelbulber v2, a 3D fractal generator  _%}}i*<.        ____                _______
 * Copyright (C) 2021 Mandelbulber Team   _>]|=||i=i<,     / __ \___  ___ ___  / ___/ /
 *                                        \><||i|=>>%)    / /_/ / _ \/ -_) _ \/ /__/ /__
 * This file is part of Mandelbulber.     )<=i=]=|=i<>    \____/ .__/\__/_//_/\___/____/
 * The project is licensed under GPLv3,   -<>>=|><|||`        /_/
 * see also COPYING file in this folder.    ~+{i%+++
 *
 * TransfDifsGearV1Iteration based on example by Inigo Quilez,
 * https://www.iquilezles.org/

 * This file has been autogenerated by tools/populateUiInformation.php
 * from the file "fractal_transf_difs_gear_v1.cpp" in the folder formula/definition
 * D O    N O T    E D I T    T H I S    F I L E !
 */

REAL4 TransfDIFSGearV1Iteration(REAL4 z, __constant sFractalCl *fractal, sExtendedAuxCl *aux)
{
	if (fractal->transformCommon.rotation2EnabledFalse
			&& aux->i >= fractal->transformCommon.startIterationsT
			&& aux->i < fractal->transformCommon.stopIterationsT1)
	{
		z = Matrix33MulFloat4(fractal->transformCommon.rotationMatrix, z);
	}

	REAL angle = M_PI_2x_F / (fractal->transformCommon.int16);
	REAL sector = round(atan2(z.x, z.y) / angle) + fractal->transformCommon.intA * 1.0f;
	REAL4 zc = z;
	REAL an = sector * angle;
	REAL sinan = native_sin(an);
	REAL cosan = native_cos(an);
	REAL temp = zc.x;

	zc.x = zc.x * cosan - zc.y * sinan;
	zc.y = temp * sinan + zc.y * cosan;
	zc.y -= fractal->transformCommon.offset1;
	zc.z -= fractal->transformCommon.offset0;

	REAL widthX = fractal->transformCommon.offset01;
	REAL lengthY = fractal->transformCommon.offset02;
	REAL heightZ = fractal->transformCommon.offset05;

	// chevron
	if (fractal->transformCommon.functionEnabledFalse)
		zc.x -= fractal->transformCommon.scale0 * fabs(zc.y);

	// curve
	if (fractal->transformCommon.functionEnabledAFalse)
	{
		REAL absZZ = zc.z * zc.z;
		widthX += absZZ * fractal->transformCommon.constantMultiplier000.x;
		lengthY += absZZ * fractal->transformCommon.constantMultiplier000.y;
		widthX += zc.y * zc.y * fractal->transformCommon.constantMultiplier000.z;
	}

	// wedge
	if (fractal->transformCommon.functionEnabledBFalse)
	{
		widthX += zc.z * fractal->transformCommon.scale3D000.x;
		lengthY += zc.z * fractal->transformCommon.scale3D000.y;
		zc.y += zc.z * fractal->transformCommon.scale3D000.z;
	}

	// star
	if (fractal->transformCommon.functionEnabledCFalse)
		widthX -= zc.y * fractal->transformCommon.scaleC0;

	// saw
	if (fractal->transformCommon.functionEnabledDFalse)
		zc.x += zc.z * fractal->transformCommon.scaleA0;

	zc.x = fabs(zc.x) - widthX;
	zc.y = fabs(zc.y) - lengthY;
	zc.z = fabs(zc.z) - heightZ;

	// voids
	if (fractal->transformCommon.functionEnabledFFalse)
		zc.x *= -fractal->transformCommon.scaleE1 * zc.y;

	// track
	if (fractal->transformCommon.functionEnabledGFalse)
	{
		zc.x += zc.y * fractal->transformCommon.scale0000.x;
		zc.y += zc.x * fractal->transformCommon.scale0000.y;
		zc.y += zc.z * fractal->transformCommon.scale0000.z;
		zc.z += zc.y * fractal->transformCommon.scale0000.w;
	}

	zc.x = max(zc.x, 0.0f);
	zc.y = max(zc.y, 0.0f);
	zc.z = max(zc.z, 0.0f);
	REAL zcd = length(zc) + fractal->analyticDE.offset0;

	// cylinder
	REAL sdTor = 1000.0f;
	if (fractal->transformCommon.functionEnabled)
	{
		sdTor = fabs(native_sqrt(z.x * z.x + z.y * z.y) - fractal->transformCommon.offsetA1
								 + fractal->transformCommon.offsetR0)
						- fractal->transformCommon.offsetR0;
		sdTor = max(sdTor, fabs(z.z) - fractal->transformCommon.offsetA05);
	}

	REAL d = min(zcd, sdTor) - fractal->transformCommon.offset0005;

	// aux->color
	if (fractal->foldColor.auxColorEnabledFalse)
	{
		if (zcd > sdTor)
			aux->color = fractal->foldColor.difs0000.y;
		else
			aux->color = fractal->foldColor.difs0000.x;
	}

	aux->dist = min(aux->dist, d / (aux->DE + 1.0f));

	if (fractal->transformCommon.functionEnabledEFalse) z = zc;
	return z;
}