/**
 * Mandelbulber v2, a 3D fractal generator  _%}}i*<.        ____                _______
 * Copyright (C) 2024 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%+++
 *
 * superformula Johan Gielis
 * https://bsapubs.onlinelibrary.wiley.com/doi/10.3732/ajb.90.3.333
 * http://paulbourke.net/geometry/supershape/

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

REAL4 TransfSupershapeIteration(REAL4 z, __constant sFractalCl *fractal, sExtendedAuxCl *aux)
{
	if (aux->i >= fractal->transformCommon.startIterationsP
			&& aux->i < fractal->transformCommon.stopIterationsP1)
	{
		if (fractal->transformCommon.functionEnabledBxFalse)
		{
			z.x = sign(z.x) * (fractal->transformCommon.offset000.x - fabs(z.x));
		}
		if (fractal->transformCommon.functionEnabledByFalse)
		{
			z.y = sign(z.y) * (fractal->transformCommon.offset000.y - fabs(z.y));
		}
		if (fractal->transformCommon.functionEnabledBzFalse)
		{
			z.z = sign(z.z) * (fractal->transformCommon.offset000.z - fabs(z.z));
		}
	}

	REAL r1 = native_sqrt(z.x * z.x + z.y * z.y);
	// REAL r2 = native_sqrt(z.x * z.x + z.y * z.y); // <<<<<<<<<<<<<<<<<<<<
	REAL phi;
	REAL tho = asin(z.z / r1);
	if (!fractal->transformCommon.functionEnabledAFalse)
		phi = atan2(z.y, z.x);
	else
		phi = atan2(z.x, z.y);

	REAL t1 = fabs(native_cos(fractal->transformCommon.constantMultiplierA111.x * phi)
								 * fractal->transformCommon.constantMultiplierA111.y);
	if (fractal->transformCommon.functionEnabledXFalse)
		t1 = pow(t1, fractal->transformCommon.constantMultiplierB111.x);

	REAL t2 = fabs(native_sin(fractal->transformCommon.constantMultiplierA111.x * phi)
								 * fractal->transformCommon.constantMultiplierA111.z);
	if (fractal->transformCommon.functionEnabledYFalse)
		t2 = pow(t2, fractal->transformCommon.constantMultiplierB111.y);

	if (!fractal->transformCommon.functionEnabledEFalse)
		r1 = (t1 + t2);
	else
		r1 = pow(t1 + t2, fractal->transformCommon.constantMultiplierB111.z);

	if (!fractal->transformCommon.functionEnabledFFalse) r1 = 1.0f / r1;

	r1 = r1 * fractal->transformCommon.radius1;

	if (fractal->transformCommon.functionEnabledGFalse)
		r1 = fabs(r1 - aux->r * fractal->transformCommon.scaleA0);
	// else
	//	r1 = fabs(r1 - r2 * fractal->transformCommon.scaleA1);

	// if (fractal->transformCommon.functionEnabledBFalse)
	//	aux->DE0 = r;

	if (fractal->transformCommon.functionEnabledxFalse)
	{
		if (!fractal->transformCommon.functionEnabledAxFalse)
			z.x = r1 * native_cos(phi);
		else
			z.x = r1 * native_sin(phi);
	}

	if (fractal->transformCommon.functionEnabledyFalse)
	{
		if (!fractal->transformCommon.functionEnabledAyFalse)
			z.y = r1 * native_sin(phi);
		else
			z.y = r1 * native_cos(phi);
	}

	if (fractal->transformCommon.functionEnabledzFalse)
	{
		if (!fractal->transformCommon.functionEnabledAzFalse)
			z.z = r1 * native_sin(phi);
		else
			z.z = r1 * native_cos(phi);
	}

	if (fractal->transformCommon.functionEnabledCFalse)
	{
		REAL cth = native_cos(tho);

		z.x = cth * native_cos(phi);
		z.y = cth * native_sin(phi);
		z.z = native_sin(tho);
		z *= r1;
	}

	if (fractal->analyticDE.enabledFalse)
		aux->DE = aux->DE * fractal->analyticDE.scale1 + fractal->analyticDE.offset0;

	if (fractal->transformCommon.functionEnabledKFalse)
	{
		REAL4 zc = z;

		REAL T1;
		if (!fractal->transformCommon.functionEnabledIFalse)
			T1 = length(zc);
		else
		{
			if (!fractal->transformCommon.functionEnabledJFalse) zc = fabs(zc);
			T1 = max(max(zc.x, zc.y), zc.z);
		}

		T1 = T1 / (aux->DE + fractal->transformCommon.offset0) - fractal->transformCommon.offset01;
		aux->dist = min(T1, aux->dist);

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