/**
 * Mandelbulber v2, a 3D fractal generator  _%}}i*<.        ____                _______
 * Copyright (C) 2018 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%+++
 *
 * quadratic iteration in real or imaginary scator algebra
 * using r = length
 * @reference
 * http://www.fractalforums.com/new-theories-and-research/
 * ix-possibly-the-holy-grail-fractal-%28in-fff-lore%29
 * https://luz.izt.uam.mx/drupal/en/fractals/ix
 * @author Manuel Fernandez-Guasti
 * This formula contains aux.DE

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

REAL4 ScatorPower2StdRIteration(REAL4 z, __constant sFractalCl *fractal, sExtendedAuxCl *aux)
{
	REAL4 oldZ = z;

	// Scator real enabled
	REAL4 zz = z * z;
	REAL4 newZ = z;
	if (fractal->transformCommon.functionEnabledFalse)
	{ // scator imaginary
		newZ.x = zz.x - zz.y - zz.z;
		newZ.y = z.x * z.y;
		newZ.z = z.x * z.z;
		newZ *= fractal->transformCommon.constantMultiplier122;
		newZ.x += native_divide((zz.y * zz.z), zz.x);
		newZ.y *= (1.0f - native_divide(zz.z, zz.x));
		newZ.z *= (1.0f - native_divide(zz.y, zz.x));
	}
	else
	{ // scator real
		newZ.x = zz.x + zz.y + zz.z;
		newZ.y = z.x * z.y;
		newZ.z = z.x * z.z;
		newZ *= fractal->transformCommon.constantMultiplier122;
		newZ.x += native_divide((zz.y * zz.z), zz.x);
		newZ.y *= (1.0f + native_divide(zz.z, zz.x));
		newZ.z *= (1.0f + native_divide(zz.y, zz.x));
	}
	z = newZ;

	if (fractal->analyticDE.enabled)
	{
		REAL r = aux->r; // r = length;
		REAL vecDE = 0.0f;
		if (!fractal->analyticDE.enabledFalse)
		{
			if (fractal->transformCommon.functionEnabledXFalse)
			{
				r = native_sqrt(zz.x + zz.y + zz.z + native_divide((zz.y * zz.z), zz.x));
			}
			aux->DE = mad(r * aux->DE * 2.0f, fractal->analyticDE.scale1, fractal->analyticDE.offset1);
		}
		else
		{
			vecDE = fractal->transformCommon.scaleA1 * native_divide(length(z), length(oldZ));
			aux->DE = mad(
				max(r, vecDE) * aux->DE * 2.0f, fractal->analyticDE.scale1, fractal->analyticDE.offset1);
		}
	}
	return z;
}