1/**
2 * Mandelbulber v2, a 3D fractal generator  _%}}i*<.        ____                _______
3 * Copyright (C) 2020 Mandelbulber Team   _>]|=||i=i<,     / __ \___  ___ ___  / ___/ /
4 *                                        \><||i|=>>%)    / /_/ / _ \/ -_) _ \/ /__/ /__
5 * This file is part of Mandelbulber.     )<=i=]=|=i<>    \____/ .__/\__/_//_/\___/____/
6 * The project is licensed under GPLv3,   -<>>=|><|||`        /_/
7 * see also COPYING file in this folder.    ~+{i%+++
8 *
9 * based on formula by kosalos
10 * https://fractalforums.org/fractal-mathematics-and-new-theories/28
11 * /julia-sets-and-altering-the-iterate-afterwards/2871/msg16342#msg16342
12 * This formula contains aux.const_c, and uses aux.c for oldZ
13
14 * This file has been autogenerated by tools/populateUiInformation.php
15 * from the file "fractal_mandelbulb_kosalos_v2.cpp" in the folder formula/definition
16 * D O    N O T    E D I T    T H I S    F I L E !
17 */
18
19REAL4 MandelbulbKosalosV2Iteration(REAL4 z, __constant sFractalCl *fractal, sExtendedAuxCl *aux)
20{
21	REAL4 c = aux->const_c;
22	REAL power = fractal->bulb.power;
23
24	REAL4 diffVec = (REAL4){0.001f, 0.001f, 0.001f, 0.0f} + aux->c - z;
25	aux->c = z;
26	REAL diffLen = length(diffVec); // > 3.16e-5f
27	REAL thetaTweak = fractal->transformCommon.scaleA1 * 0.01f
28										/ (diffLen + fractal->transformCommon.offsetA0 * 0.01f);
29
30	if (!fractal->transformCommon.functionEnabledxFalse)
31	{
32		thetaTweak = (1.0f - thetaTweak);
33	}
34	else // mode2
35	{
36		thetaTweak = thetaTweak + (1.0f - thetaTweak) * fractal->transformCommon.scaleB1;
37	}
38
39	REAL theta;
40	if (!fractal->transformCommon.functionEnabledAzFalse)
41	{
42		REAL xyL = native_sqrt(z.x * z.x + z.y * z.y);
43		theta = atan2(xyL * thetaTweak, z.z);
44	}
45	else
46	{
47		theta = asin(z.z / aux->r * thetaTweak);
48	}
49	theta = (theta + fractal->bulb.betaAngleOffset) * power;
50
51	REAL phi = atan2(z.y, z.x) * power;
52	REAL pwr = native_powr(aux->r, power);
53
54	if (!fractal->transformCommon.addCpixelEnabledFalse) // z = old z + new z
55	{
56		if (!fractal->transformCommon.functionEnabledzFalse)
57		{
58			REAL ss = native_sin(theta) * pwr;
59			z.x += ss * native_cos(phi);
60			z.y += ss * native_sin(phi);
61			z.z += pwr * native_cos(theta);
62		}
63		else
64		{
65			REAL cs = native_cos(theta) * pwr;
66			z.x += cs * native_sin(phi);
67			z.y += cs * native_cos(phi);
68			z.z += pwr * native_sin(theta);
69		}
70		aux->DE += (native_powr(aux->r, power - 1.0f) * power * aux->DE);
71		z.z += fractal->transformCommon.offset0;
72	}
73	else // z = f(z) + c
74	{
75		if (!fractal->transformCommon.functionEnabledzFalse)
76		{
77			REAL ss = native_sin(theta * power) * pwr;
78			z.x = ss * native_cos(phi);
79			z.y = ss * native_sin(phi);
80			z.z = pwr * native_cos(theta * power);
81		}
82		else
83		{
84			REAL cs = native_cos(theta * power) * pwr;
85			z.x += cs * native_sin(phi);
86			z.y += cs * native_cos(phi);
87			z.z += pwr * native_sin(theta * power);
88		}
89		aux->DE = (native_powr(aux->r, power - 1.0f) * power * aux->DE);
90		z.z += fractal->transformCommon.offset0;
91		c *= fractal->transformCommon.constantMultiplierC111;
92		if (!fractal->transformCommon.functionEnabledyFalse)
93			z += c;
94		else
95			z += (REAL4){c.y, c.x, c.z, 0.0f};
96	}
97	aux->DE = aux->DE * fractal->analyticDE.scale1 + fractal->analyticDE.offset1;
98	return z;
99}