| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431 |
- /*****************************************************************************
- * hcmplx.c
- *
- * This module implements hypercomplex Julia fractals.
- *
- * This file was written by Pascal Massimino.
- *
- * from Persistence of Vision(tm) Ray Tracer
- * Copyright 1996,1999 Persistence of Vision Team
- *---------------------------------------------------------------------------
- * NOTICE: This source code file is provided so that users may experiment
- * with enhancements to POV-Ray and to port the software to platforms other
- * than those supported by the POV-Ray Team. There are strict rules under
- * which you are permitted to use this file. The rules are in the file
- * named POVLEGAL.DOC which should be distributed with this file.
- * If POVLEGAL.DOC is not available or for more info please contact the POV-Ray
- * Team Coordinator by email to team-coord@povray.org or visit us on the web at
- * http://www.povray.org. The latest version of POV-Ray may be found at this site.
- *
- * This program is based on the popular DKB raytracer version 2.12.
- * DKBTrace was originally written by David K. Buck.
- * DKBTrace Ver 2.0-2.12 were written by David K. Buck & Aaron A. Collins.
- *
- *****************************************************************************/
- #include "frame.h"
- #include "povray.h"
- #include "vector.h"
- #include "povproto.h"
- #include "fractal.h"
- #include "spheres.h"
- #include "hcmplx.h"
- /*****************************************************************************
- * Local preprocessor defines
- ******************************************************************************/
- #ifndef Fractal_Tolerance
- #define Fractal_Tolerance 1e-8
- #endif
- #define HMult(xr,yr,zr,wr,x1,y1,z1,w1,x2,y2,z2,w2) \
- (xr) = (x1) * (x2) - (y1) * (y2) - (z1) * (z2) + (w1) * (w2); \
- (yr) = (y1) * (x2) + (x1) * (y2) - (w1) * (z2) - (z1) * (w2); \
- (zr) = (z1) * (x2) - (w1) * (y2) + (x1) * (z2) - (y1) * (w2); \
- (wr) = (w1) * (x2) + (z1) * (y2) + (y1) * (z2) + (x1) * (w2);
- #define HSqr(xr,yr,zr,wr,x,y,z,w) \
- (xr) = (x) * (x) - (y) * (y) - (z) * (z) + (w) * (w) ; \
- (yr) = 2.0 * ( (x) * (y) - (z) * (w) ); \
- (zr) = 2.0 * ( (z) * (x) - (w) * (y) ); \
- (wr) = 2.0 * ( (w) * (x) + (z) * (y) );
- /*****************************************************************************
- * Local typedefs
- ******************************************************************************/
- /*****************************************************************************
- * Static functions
- ******************************************************************************/
- static int HReciprocal (DBL * xr, DBL * yr, DBL * zr, DBL * wr, DBL x, DBL y, DBL z, DBL w);
- static void HFunc (DBL * xr, DBL * yr, DBL * zr, DBL * wr, DBL x, DBL y, DBL z, DBL w, FRACTAL *f);
- /*****************************************************************************
- * Local variables
- ******************************************************************************/
- static CMPLX exponent = {0,0};
- /******** Computations with Hypercomplexes **********/
- /*****************************************************************************
- *
- * FUNCTION
- *
- * INPUT
- *
- * OUTPUT
- *
- * RETURNS
- *
- * AUTHOR
- *
- * Pascal Massimino
- *
- * DESCRIPTION
- *
- * CHANGES
- *
- ******************************************************************************/
- static int HReciprocal(DBL *xr, DBL *yr, DBL *zr, DBL *wr, DBL x, DBL y, DBL z, DBL w)
- {
- DBL det, mod, xt_minus_yz;
- det = ((x - w) * (x - w) + (y + z) * (y + z)) * ((x + w) * (x + w) + (y - z) * (y - z));
- if (det == 0.0)
- {
- return (-1);
- }
- mod = (x * x + y * y + z * z + w * w);
- xt_minus_yz = x * w - y * z;
- *xr = (x * mod - 2 * w * xt_minus_yz) / det;
- *yr = (-y * mod - 2 * z * xt_minus_yz) / det;
- *zr = (-z * mod - 2 * y * xt_minus_yz) / det;
- *wr = (w * mod - 2 * x * xt_minus_yz) / det;
- return (0);
- }
- /*****************************************************************************
- *
- * FUNCTION Hfunc
- *
- * INPUT 4D Hypercomplex number, pointer to fractal object
- *
- * OUTPUT calculates the 4D generalization of fractal->Complex_Function
- *
- * RETURNS void
- *
- * AUTHOR
- *
- * Pascal Massimino
- *
- * DESCRIPTION
- * Hypercomplex numbers allow generalization of any complex->complex
- * function in a uniform way. This function implements a general
- * unary 4D function based on the corresponding complex function.
- *
- * CHANGES
- * Generalized to use Complex_Function() TW
- *
- ******************************************************************************/
- static void HFunc(DBL *xr, DBL *yr, DBL *zr, DBL *wr, DBL x, DBL y, DBL z, DBL w, FRACTAL *f)
- {
- CMPLX a, b, ra, rb;
-
- /* convert to duplex form */
- a.x = x - w;
- a.y = y + z;
- b.x = x + w;
- b.y = y - z;
-
- if(f->Sub_Type == PWR_STYPE)
- {
- exponent = f->exponent;
- }
-
- /* apply function to each part */
- Complex_Function(&ra, &a, f);
- Complex_Function(&rb, &b, f);
- /* convert back */
- *xr = .5 * (ra.x + rb.x);
- *yr = .5 * (ra.y + rb.y);
- *zr = .5 * (ra.y - rb.y);
- *wr = .5 * (rb.x - ra.x);
- }
- /*****************************************************************************
- *
- * FUNCTION
- *
- * INPUT
- *
- * OUTPUT
- *
- * RETURNS
- *
- * AUTHOR
- *
- * Pascal Massimino
- *
- * DESCRIPTION
- *
- * CHANGES
- *
- ******************************************************************************/
- /*------------------ z2 Iteration method ------------------*/
- int Iteration_HCompl(VECTOR IPoint, FRACTAL *HCompl)
- {
- int i;
- DBL yz, xw;
- DBL Exit_Value;
- DBL x, y, z, w;
- x = Sx[0] = IPoint[X];
- y = Sy[0] = IPoint[Y];
- z = Sz[0] = IPoint[Z];
- w = Sw[0] = (HCompl->SliceDist
- - HCompl->Slice[X]*x
- - HCompl->Slice[Y]*y
- - HCompl->Slice[Z]*z)/HCompl->Slice[T];
-
- Exit_Value = HCompl->Exit_Value;
- for (i = 1; i <= HCompl->n; ++i)
- {
- yz = y * y + z * z;
- xw = x * x + w * w;
- if ((xw + yz) > Exit_Value)
- {
- return (FALSE);
- }
- Sx[i] = xw - yz + HCompl->Julia_Parm[X];
- Sy[i] = 2.0 * (x * y - z * w) + HCompl->Julia_Parm[Y];
- Sz[i] = 2.0 * (x * z - w * y) + HCompl->Julia_Parm[Z];
- Sw[i] = 2.0 * (x * w + y * z) + HCompl->Julia_Parm[T];
- w = Sw[i];
- x = Sx[i];
- z = Sz[i];
- y = Sy[i];
- }
- return (TRUE);
- }
- /*****************************************************************************
- *
- * FUNCTION
- *
- * INPUT
- *
- * OUTPUT
- *
- * RETURNS
- *
- * AUTHOR
- *
- * Pascal Massimino
- *
- * DESCRIPTION
- *
- * CHANGES
- *
- ******************************************************************************/
- int D_Iteration_HCompl(VECTOR IPoint, FRACTAL *HCompl, DBL *Dist)
- {
- int i;
- DBL yz, xw;
- DBL Exit_Value, F_Value, Step;
- DBL x, y, z, w;
- VECTOR H_Normal;
- x = Sx[0] = IPoint[X];
- y = Sy[0] = IPoint[Y];
- z = Sz[0] = IPoint[Z];
- w = Sw[0] = (HCompl->SliceDist
- - HCompl->Slice[X]*x
- - HCompl->Slice[Y]*y
- - HCompl->Slice[Z]*z)/HCompl->Slice[T];
- Exit_Value = HCompl->Exit_Value;
- for (i = 1; i <= HCompl->n; ++i)
- {
- yz = y * y + z * z;
- xw = x * x + w * w;
- if ((F_Value = xw + yz) > Exit_Value)
- {
- Normal_Calc_HCompl(H_Normal, i - 1, HCompl);
- VDot(Step, H_Normal, Direction);
- if (Step < -Fractal_Tolerance)
- {
- Step = -2.0 * Step;
- if ((F_Value > Precision * Step) && (F_Value < 30 * Precision * Step))
- {
- *Dist = F_Value / Step;
- return (FALSE);
- }
- }
- *Dist = Precision;
- return (FALSE);
- }
- Sx[i] = xw - yz + HCompl->Julia_Parm[X];
- Sy[i] = 2.0 * (x * y - z * w) + HCompl->Julia_Parm[Y];
- Sz[i] = 2.0 * (x * z - w * y) + HCompl->Julia_Parm[Z];
- Sw[i] = 2.0 * (x * w + y * z) + HCompl->Julia_Parm[T];
- w = Sw[i];
- x = Sx[i];
- z = Sz[i];
- y = Sy[i];
- }
- *Dist = Precision;
- return (TRUE);
- }
- /*****************************************************************************
- *
- * FUNCTION
- *
- * INPUT
- *
- * OUTPUT
- *
- * RETURNS
- *
- * AUTHOR
- *
- * Pascal Massimino
- *
- * DESCRIPTION
- *
- * CHANGES
- *
- ******************************************************************************/
- void Normal_Calc_HCompl(VECTOR Result, int N_Max, FRACTAL *fractal)
- {
- DBL n1, n2, n3, n4;
- int i;
- DBL x, y, z, w;
- DBL xx, yy, zz, ww;
- DBL Pow;
- /*
- * Algebraic properties of hypercomplexes allows simplifications in
- * computations...
- */
- x = Sx[0];
- y = Sy[0];
- z = Sz[0];
- w = Sw[0];
- Pow = 2.0;
- for (i = 1; i < N_Max; ++i)
- {
- /*
- * For a map z->f(z), f depending on c, one must perform here :
- *
- * (x,y,z,w) * df/dz(Sx[i],Sy[i],Sz[i],Sw[i]) -> (x,y,z,w) ,
- *
- * up to a constant.
- */
- /******************* Case z->z^2+c *****************/
- /* the df/dz part needs no work */
- HMult(xx, yy, zz, ww, Sx[i], Sy[i], Sz[i], Sw[i], x, y, z, w);
- w = ww;
- z = zz;
- y = yy;
- x = xx;
- Pow *= 2.0;
- }
- n1 = Sx[N_Max] * Pow;
- n2 = Sy[N_Max] * Pow;
- n3 = Sz[N_Max] * Pow;
- n4 = Sw[N_Max] * Pow;
- Result[X] = x * n1 + y * n2 + z * n3 + w * n4;
- Result[Y] = -y * n1 + x * n2 - w * n3 + z * n4;
- Result[Z] = -z * n1 - w * n2 + x * n3 + y * n4;
- }
- /*****************************************************************************
- *
- * FUNCTION
- *
- * INPUT
- *
- * OUTPUT
- *
- * RETURNS
- *
- * AUTHOR
- *
- * Pascal Massimino
- *
- * DESCRIPTION
- *
- * CHANGES
- *
- ******************************************************************************/
- int F_Bound_HCompl(RAY *Ray, FRACTAL *Fractal, DBL *Depth_Min, DBL *Depth_Max)
- {
- return (Intersect_Sphere(Ray, Fractal->Center, Fractal->Radius_Squared, Depth_Min, Depth_Max));
- }
- /****************************************************************/
- /*--------------------------- z3 -------------------------------*/
- /****************************************************************/
- /*****************************************************************************
- *
- * FUNCTION
- *
- * INPUT
- *
- * OUTPUT
- *
- * RETURNS
- *
- * AUTHOR
- *
- * Pascal Massimino
- *
- * DESCRIPTION
- *
- * CHANGES
- *
- ******************************************************************************/
- int Iteration_HCompl_z3(VECTOR IPoint, FRACTAL *HCompl)
- {
- int i;
- DBL Norm, xx, yy, zz, ww;
- DBL Exit_Value;
- DBL x, y, z, w;
- x = Sx[0] = IPoint[X];
- y = Sy[0] = IPoint[Y];
- z = Sz[0] = IPoint[Z];
- w = Sw[0] = (HCompl->SliceDist
- - HCompl->Slice[X]*x
- - HCompl->Slice[Y]*y
- - HCompl->Slice[Z]*z)/HCompl->Slice[T];
- Exit_Value = HCompl->Exit_Value;
- for (i = 1; i <= HCompl->n; ++i)
- {
- Norm = x * x + y * y + z * z + w * w;
- /* is this test correct ? */
- if (Norm > Exit_Value)
- {
- return (FALSE);
- }
- /*************** Case: z->z^2+c *********************/
- HSqr(xx, yy, zz, ww, x, y, z, w);
- x = Sx[i] = xx + HCompl->Julia_Parm[X];
- y = Sy[i] = yy + HCompl->Julia_Parm[Y];
- z = Sz[i] = zz + HCompl->Julia_Parm[Z];
- w = Sw[i] = ww + HCompl->Julia_Parm[T];
- }
- return (TRUE);
- }
- /*****************************************************************************
- *
- * FUNCTION
- *
- * INPUT
- *
- * OUTPUT
- *
- * RETURNS
- *
- * AUTHOR
- *
- * Pascal Massimino
- *
- * DESCRIPTION
- *
- * CHANGES
- *
- ******************************************************************************/
- int D_Iteration_HCompl_z3(VECTOR IPoint, FRACTAL *HCompl, DBL *Dist)
- {
- int i;
- DBL xx, yy, zz, ww;
- DBL Exit_Value, F_Value, Step;
- DBL x, y, z, w;
- VECTOR H_Normal;
- x = Sx[0] = IPoint[X];
- y = Sy[0] = IPoint[Y];
- z = Sz[0] = IPoint[Z];
- w = Sw[0] = (HCompl->SliceDist
- - HCompl->Slice[X]*x
- - HCompl->Slice[Y]*y
- - HCompl->Slice[Z]*z)/HCompl->Slice[T];
- Exit_Value = HCompl->Exit_Value;
- for (i = 1; i <= HCompl->n; ++i)
- {
- F_Value = x * x + y * y + z * z + w * w;
- if (F_Value > Exit_Value)
- {
- Normal_Calc_HCompl_z3(H_Normal, i - 1, HCompl);
- VDot(Step, H_Normal, Direction);
- if (Step < -Fractal_Tolerance)
- {
- Step = -2.0 * Step;
- if ((F_Value > Precision * Step) && (F_Value < 30 * Precision * Step))
- {
- *Dist = F_Value / Step;
- return (FALSE);
- }
- }
- *Dist = Precision;
- return (FALSE);
- }
- /*************** Case: z->z^2+c *********************/
- HSqr(xx, yy, zz, ww, x, y, z, w);
- x = Sx[i] = xx + HCompl->Julia_Parm[X];
- y = Sy[i] = yy + HCompl->Julia_Parm[Y];
- z = Sz[i] = zz + HCompl->Julia_Parm[Z];
- w = Sw[i] = ww + HCompl->Julia_Parm[T];
- }
- *Dist = Precision;
- return (TRUE);
- }
- /*****************************************************************************
- *
- * FUNCTION
- *
- * INPUT
- *
- * OUTPUT
- *
- * RETURNS
- *
- * AUTHOR
- *
- * Pascal Massimino
- *
- * DESCRIPTION
- *
- * CHANGES
- *
- ******************************************************************************/
- void Normal_Calc_HCompl_z3(VECTOR Result, int N_Max, FRACTAL *fractal)
- {
- DBL n1, n2, n3, n4;
- int i;
- DBL x, y, z, w;
- DBL xx, yy, zz, ww;
- /*
- * Algebraic properties of hypercomplexes allows simplifications in
- * computations...
- */
- x = Sx[0];
- y = Sy[0];
- z = Sz[0];
- w = Sw[0];
- for (i = 1; i < N_Max; ++i)
- {
- /*
- * For a map z->f(z), f depending on c, one must perform here :
- *
- * (x,y,z,w) * df/dz(Sx[i],Sy[i],Sz[i],Sw[i]) -> (x,y,z,w) ,
- *
- * up to a constant.
- */
- /******************* Case z->z^2+c *****************/
- /* the df/dz part needs no work */
- HMult(xx, yy, zz, ww, Sx[i], Sy[i], Sz[i], Sw[i], x, y, z, w);
- x = xx;
- y = yy;
- z = zz;
- w = ww;
- }
- n1 = Sx[N_Max];
- n2 = Sy[N_Max];
- n3 = Sz[N_Max];
- n4 = Sw[N_Max];
- Result[X] = x * n1 + y * n2 + z * n3 + w * n4;
- Result[Y] = -y * n1 + x * n2 - w * n3 + z * n4;
- Result[Z] = -z * n1 - w * n2 + x * n3 + y * n4;
- }
- /*****************************************************************************
- *
- * FUNCTION
- *
- * INPUT
- *
- * OUTPUT
- *
- * RETURNS
- *
- * AUTHOR
- *
- * Pascal Massimino
- *
- * DESCRIPTION
- *
- * CHANGES
- *
- ******************************************************************************/
- int F_Bound_HCompl_z3(RAY *Ray, FRACTAL *Fractal, DBL *Depth_Min, DBL *Depth_Max)
- {
- return F_Bound_HCompl(Ray, Fractal, Depth_Min, Depth_Max);
- }
- /*--------------------------- Inv -------------------------------*/
- /*****************************************************************************
- *
- * FUNCTION
- *
- * INPUT
- *
- * OUTPUT
- *
- * RETURNS
- *
- * AUTHOR
- *
- * Pascal Massimino
- *
- * DESCRIPTION
- *
- * CHANGES
- *
- ******************************************************************************/
- int Iteration_HCompl_Reciprocal(VECTOR IPoint, FRACTAL *HCompl)
- {
- int i;
- DBL Norm, xx, yy, zz, ww;
- DBL Exit_Value;
- DBL x, y, z, w;
- x = Sx[0] = IPoint[X];
- y = Sy[0] = IPoint[Y];
- z = Sz[0] = IPoint[Z];
- w = Sw[0] = (HCompl->SliceDist
- - HCompl->Slice[X]*x
- - HCompl->Slice[Y]*y
- - HCompl->Slice[Z]*z)/HCompl->Slice[T];
- Exit_Value = HCompl->Exit_Value;
- for (i = 1; i <= HCompl->n; ++i)
- {
- Norm = x * x + y * y + z * z + w * w;
- if (Norm > Exit_Value)
- {
- return (FALSE);
- }
- HReciprocal(&xx, &yy, &zz, &ww, x, y, z, w);
- x = Sx[i] = xx + HCompl->Julia_Parm[X];
- y = Sy[i] = yy + HCompl->Julia_Parm[Y];
- z = Sz[i] = zz + HCompl->Julia_Parm[Z];
- w = Sw[i] = ww + HCompl->Julia_Parm[T];
- }
- return (TRUE);
- }
- /*****************************************************************************
- *
- * FUNCTION
- *
- * INPUT
- *
- * OUTPUT
- *
- * RETURNS
- *
- * AUTHOR
- *
- * Pascal Massimino
- *
- * DESCRIPTION
- *
- * CHANGES
- *
- ******************************************************************************/
- int D_Iteration_HCompl_Reciprocal(VECTOR IPoint, FRACTAL *HCompl, DBL *Dist)
- {
- int i;
- DBL xx, yy, zz, ww;
- DBL Exit_Value, F_Value, Step;
- DBL x, y, z, w;
- VECTOR H_Normal;
- x = Sx[0] = IPoint[X];
- y = Sy[0] = IPoint[Y];
- z = Sz[0] = IPoint[Z];
- w = Sw[0] = (HCompl->SliceDist
- - HCompl->Slice[X]*x
- - HCompl->Slice[Y]*y
- - HCompl->Slice[Z]*z)/HCompl->Slice[T];
- Exit_Value = HCompl->Exit_Value;
- for (i = 1; i <= HCompl->n; ++i)
- {
- F_Value = x * x + y * y + z * z + w * w;
- if (F_Value > Exit_Value)
- {
- Normal_Calc_HCompl_Reciprocal(H_Normal, i - 1, HCompl);
- VDot(Step, H_Normal, Direction);
- if (Step < -Fractal_Tolerance)
- {
- Step = -2.0 * Step;
- if ((F_Value > Precision * Step) && F_Value < (30 * Precision * Step))
- {
- *Dist = F_Value / Step;
- return (FALSE);
- }
- }
- *Dist = Precision;
- return (FALSE);
- }
- HReciprocal(&xx, &yy, &zz, &ww, x, y, z, w);
- x = Sx[i] = xx + HCompl->Julia_Parm[X];
- y = Sy[i] = yy + HCompl->Julia_Parm[Y];
- z = Sz[i] = zz + HCompl->Julia_Parm[Z];
- w = Sw[i] = ww + HCompl->Julia_Parm[T];
- }
- *Dist = Precision;
- return (TRUE);
- }
- /*****************************************************************************
- *
- * FUNCTION
- *
- * INPUT
- *
- * OUTPUT
- *
- * RETURNS
- *
- * AUTHOR
- *
- * Pascal Massimino
- *
- * DESCRIPTION
- *
- * CHANGES
- *
- ******************************************************************************/
- void Normal_Calc_HCompl_Reciprocal(VECTOR Result, int N_Max, FRACTAL *fractal)
- {
- DBL n1, n2, n3, n4;
- int i;
- DBL x, y, z, w;
- DBL xx, yy, zz, ww;
- DBL xxx, yyy, zzz, www;
- /*
- * Algebraic properties of hypercomplexes allows simplifications in
- * computations...
- */
- x = Sx[0];
- y = Sy[0];
- z = Sz[0];
- w = Sw[0];
- for (i = 1; i < N_Max; ++i)
- {
- /******************* Case: z->1/z+c *****************/
- HReciprocal(&xx, &yy, &zz, &ww, Sx[i], Sy[i], Sz[i], Sw[i]);
- HSqr(xxx, yyy, zzz, www, xx, yy, zz, ww);
- HMult(xx, yy, zz, ww, x, y, z, w, -xxx, -yyy, -zzz, -www);
- x = xx;
- y = yy;
- z = zz;
- w = ww;
- }
- n1 = Sx[N_Max];
- n2 = Sy[N_Max];
- n3 = Sz[N_Max];
- n4 = Sw[N_Max];
- Result[X] = x * n1 + y * n2 + z * n3 + w * n4;
- Result[Y] = -y * n1 + x * n2 - w * n3 + z * n4;
- Result[Z] = -z * n1 - w * n2 + x * n3 + y * n4;
- }
- /*****************************************************************************
- *
- * FUNCTION
- *
- * INPUT
- *
- * OUTPUT
- *
- * RETURNS
- *
- * AUTHOR
- *
- * Pascal Massimino
- *
- * DESCRIPTION
- *
- * CHANGES
- *
- ******************************************************************************/
- int F_Bound_HCompl_Reciprocal(RAY *Ray, FRACTAL *Fractal, DBL *Depth_Min, DBL *Depth_Max)
- {
- return F_Bound_HCompl(Ray, Fractal, Depth_Min, Depth_Max);
- }
- /*--------------------------- Func -------------------------------*/
- /*****************************************************************************
- *
- * FUNCTION
- *
- * INPUT
- *
- * OUTPUT
- *
- * RETURNS
- *
- * AUTHOR
- *
- * Pascal Massimino
- *
- * DESCRIPTION
- *
- * CHANGES
- *
- ******************************************************************************/
- int Iteration_HCompl_Func(VECTOR IPoint, FRACTAL *HCompl)
- {
- int i;
- DBL Norm, xx, yy, zz, ww;
- DBL Exit_Value;
- DBL x, y, z, w;
- x = Sx[0] = IPoint[X];
- y = Sy[0] = IPoint[Y];
- z = Sz[0] = IPoint[Y];
- w = Sw[0] = (HCompl->SliceDist
- - HCompl->Slice[X]*x
- - HCompl->Slice[Y]*y
- - HCompl->Slice[Z]*z)/HCompl->Slice[T];
- Exit_Value = HCompl->Exit_Value;
- for (i = 1; i <= HCompl->n; ++i)
- {
- Norm = x * x + y * y + z * z + w * w;
- if (Norm > Exit_Value)
- {
- return (FALSE);
- }
- HFunc(&xx, &yy, &zz, &ww, x, y, z, w, HCompl);
- x = Sx[i] = xx + HCompl->Julia_Parm[X];
- y = Sy[i] = yy + HCompl->Julia_Parm[Y];
- z = Sz[i] = zz + HCompl->Julia_Parm[Z];
- w = Sw[i] = ww + HCompl->Julia_Parm[T];
- }
- return (TRUE);
- }
- /*****************************************************************************
- *
- * FUNCTION
- *
- * INPUT
- *
- * OUTPUT
- *
- * RETURNS
- *
- * AUTHOR
- *
- * Pascal Massimino
- *
- * DESCRIPTION
- *
- * CHANGES
- *
- ******************************************************************************/
- int D_Iteration_HCompl_Func(VECTOR IPoint, FRACTAL *HCompl, DBL *Dist)
- {
- int i;
- DBL xx, yy, zz, ww;
- DBL Exit_Value, F_Value, Step;
- DBL x, y, z, w;
- VECTOR H_Normal;
- x = Sx[0] = IPoint[X];
- y = Sy[0] = IPoint[Y];
- z = Sz[0] = IPoint[Z];
- w = Sw[0] = (HCompl->SliceDist
- - HCompl->Slice[X]*x
- - HCompl->Slice[Y]*y
- - HCompl->Slice[Z]*z)/HCompl->Slice[T];
- Exit_Value = HCompl->Exit_Value;
- for (i = 1; i <= HCompl->n; ++i)
- {
- F_Value = x * x + y * y + z * z + w * w;
- if (F_Value > Exit_Value)
- {
- Normal_Calc_HCompl_Func(H_Normal, i - 1, HCompl);
- VDot(Step, H_Normal, Direction);
- if (Step < -Fractal_Tolerance)
- {
- Step = -2.0 * Step;
- if ((F_Value > Precision * Step) && F_Value < (30 * Precision * Step))
- {
- *Dist = F_Value / Step;
- return (FALSE);
- }
- }
- *Dist = Precision;
- return (FALSE);
- }
- HFunc(&xx, &yy, &zz, &ww, x, y, z, w, HCompl);
- x = Sx[i] = xx + HCompl->Julia_Parm[X];
- y = Sy[i] = yy + HCompl->Julia_Parm[Y];
- z = Sz[i] = zz + HCompl->Julia_Parm[Z];
- w = Sw[i] = ww + HCompl->Julia_Parm[T];
- }
- *Dist = Precision;
- return (TRUE);
- }
- /*****************************************************************************
- *
- * FUNCTION
- *
- * INPUT
- *
- * OUTPUT
- *
- * RETURNS
- *
- * AUTHOR
- *
- * Pascal Massimino
- *
- * DESCRIPTION
- *
- * CHANGES
- *
- ******************************************************************************/
- void Normal_Calc_HCompl_Func(VECTOR Result, int N_Max, FRACTAL *fractal)
- {
- DBL n1, n2, n3, n4;
- int i;
- DBL x, y, z, w;
- DBL xx, yy, zz, ww;
- DBL xxx, yyy, zzz, www;
- /*
- * Algebraic properties of hypercomplexes allows simplifications in
- * computations...
- */
- x = Sx[0];
- y = Sy[0];
- z = Sz[0];
- w = Sw[0];
- for (i = 1; i < N_Max; ++i)
- {
- /**************** Case: z-> f(z)+c ************************/
- HFunc(&xx, &yy, &zz, &ww, Sx[i], Sy[i], Sz[i], Sw[i], fractal);
- HMult(xxx, yyy, zzz, www, xx, yy, zz, ww, x, y, z, w);
- x = xxx;
- y = yyy;
- z = zzz;
- w = www;
- }
- n1 = Sx[N_Max];
- n2 = Sy[N_Max];
- n3 = Sz[N_Max];
- n4 = Sw[N_Max];
- Result[X] = x * n1 + y * n2 + z * n3 + w * n4;
- Result[Y] = -y * n1 + x * n2 - w * n3 + z * n4;
- Result[Z] = -z * n1 - w * n2 + x * n3 + y * n4;
- }
- /*****************************************************************************
- *
- * FUNCTION
- *
- * INPUT
- *
- * OUTPUT
- *
- * RETURNS
- *
- * AUTHOR
- *
- * Pascal Massimino
- *
- * DESCRIPTION
- *
- * CHANGES
- *
- ******************************************************************************/
- int F_Bound_HCompl_Func(RAY *Ray, FRACTAL *Fractal, DBL *Depth_Min, DBL *Depth_Max)
- {
- return F_Bound_HCompl(Ray, Fractal, Depth_Min, Depth_Max);
- }
- /*****************************************************************************
- *
- * FUNCTION Complex transcental functions
- *
- * INPUT pointer to source complex number
- *
- * OUTPUT fn(input)
- *
- * RETURNS void
- *
- * AUTHOR
- *
- * Tim Wegner
- *
- * DESCRIPTION Calculate common functions on complexes
- * Since our purpose is fractals, error checking is lax.
- *
- * CHANGES
- *
- ******************************************************************************/
- void Complex_Mult (CMPLX *target, CMPLX *source1, CMPLX *source2)
- {
- DBL tmpx;
- tmpx = source1->x * source2->x - source1->y * source2->y;
- target->y = source1->x * source2->y + source1->y * source2->x;
- target->x = tmpx;
- }
- void Complex_Div (CMPLX *target, CMPLX *source1, CMPLX *source2)
- {
- DBL mod,tmpx,yxmod,yymod;
- mod = Sqr(source2->x) + Sqr(source2->y);
- if (mod==0)
- return;
- yxmod = source2->x/mod;
- yymod = - source2->y/mod;
- tmpx = source1->x * yxmod - source1->y * yymod;
- target->y = source1->x * yymod + source1->y * yxmod;
- target->x = tmpx;
- } /* End Complex_Mult() */
- void Complex_Exp (CMPLX *target, CMPLX *source)
- {
- DBL expx;
- expx = exp(source->x);
- target->x = expx * cos(source->y);
- target->y = expx * sin(source->y);
- } /* End Complex_Exp() */
- void Complex_Sin (CMPLX *target, CMPLX *source)
- {
- target->x = sin(source->x) * cosh(source->y);
- target->y = cos(source->x) * sinh(source->y);
- } /* End Complex_Sin() */
- void Complex_Sinh (CMPLX *target, CMPLX *source)
- {
- target->x = sinh(source->x) * cos(source->y);
- target->y = cosh(source->x) * sin(source->y);
- } /* End Complex_Sinh() */
- void Complex_Cos (CMPLX *target, CMPLX *source)
- {
- target->x = cos(source->x) * cosh(source->y);
- target->y = -sin(source->x) * sinh(source->y);
- } /* End Complex_Cos() */
- void Complex_Cosh (CMPLX *target, CMPLX *source)
- {
- target->x = cosh(source->x) * cos(source->y);
- target->y = sinh(source->x) * sin(source->y);
- } /* End Complex_Cosh() */
- void Complex_Log (CMPLX *target, CMPLX *source)
- {
- DBL mod,zx,zy;
- mod = sqrt(source->x * source->x + source->y * source->y);
- zx = log(mod);
- zy = atan2(source->y,source->x);
- target->x = zx;
- target->y = zy;
- } /* End Complex_Log() */
- void Complex_Sqrt(CMPLX *target, CMPLX *source)
- {
- DBL mag;
- DBL theta;
- if(source->x == 0.0 && source->y == 0.0)
- {
- target->x = target->y = 0.0;
- }
- else
- {
- mag = sqrt(sqrt(Sqr(source->x) + Sqr(source->y)));
- theta = atan2(source->y, source->x) / 2;
- target->y = mag * sin(theta);
- target->x = mag * cos(theta);
- }
- } /* End Complex_Sqrt() */
- /* rz=Arcsin(z)=-i*Log{i*z+sqrt(1-z*z)} */
- void Complex_ASin(CMPLX *target, CMPLX *source)
- {
- CMPLX tempz1,tempz2;
- Complex_Mult(&tempz1, source, source);
- tempz1.x = 1 - tempz1.x; tempz1.y = -tempz1.y;
- Complex_Sqrt( &tempz1, &tempz1);
- tempz2.x = -source->y; tempz2.y = source->x;
- tempz1.x += tempz2.x; tempz1.y += tempz2.y;
- Complex_Log( &tempz1, &tempz1);
- target->x = tempz1.y; target->y = -tempz1.x;
- } /* End Complex_ASin() */
- void Complex_ACos(CMPLX *target, CMPLX *source)
- {
- CMPLX temp;
- Complex_Mult(&temp, source, source);
- temp.x -= 1;
- Complex_Sqrt(&temp, &temp);
- temp.x += source->x; temp.y += source->y;
-
- Complex_Log(&temp, &temp);
- target->x = temp.y; target->y = -temp.x;
- } /* End Complex_ACos() */
- void Complex_ASinh(CMPLX *target, CMPLX *source)
- {
- CMPLX temp;
- Complex_Mult (&temp, source, source);
- temp.x += 1;
- Complex_Sqrt (&temp, &temp);
- temp.x += source->x; temp.y += source->y;
- Complex_Log(target, &temp);
- } /* End Complex_ASinh */
- /* rz=Arccosh(z)=Log(z+sqrt(z*z-1)} */
- void Complex_ACosh (CMPLX *target, CMPLX *source)
- {
- CMPLX tempz;
- Complex_Mult(&tempz, source, source);
- tempz.x -= 1;
- Complex_Sqrt (&tempz, &tempz);
- tempz.x = source->x + tempz.x; tempz.y = source->y + tempz.y;
- Complex_Log (target, &tempz);
- } /* End Complex_ACosh() */
- /* rz=Arctanh(z)=1/2*Log{(1+z)/(1-z)} */
- void Complex_ATanh(CMPLX *target, CMPLX *source)
- {
- CMPLX temp0,temp1,temp2;
-
- if( source->x == 0.0)
- {
- target->x = 0;
- target->y = atan( source->y);
- return;
- }
- else
- {
- if( fabs(source->x) == 1.0 && source->y == 0.0)
- {
- return;
- }
- else if( fabs( source->x) < 1.0 && source->y == 0.0)
- {
- target->x = log((1+source->x)/(1-source->x))/2;
- target->y = 0;
- return;
- }
- else
- {
- temp0.x = 1 + source->x; temp0.y = source->y;
- temp1.x = 1 - source->x; temp1.y = -source->y;
- Complex_Div(&temp2, &temp0, &temp1);
- Complex_Log(&temp2, &temp2);
- target->x = .5 * temp2.x; target->y = .5 * temp2.y;
- return;
- }
- }
- } /* End Complex_ATanh() */
- /* rz=Arctan(z)=i/2*Log{(1-i*z)/(1+i*z)} */
- void Complex_ATan(CMPLX *target, CMPLX *source)
- {
- CMPLX temp0,temp1,temp2,temp3;
- if( source->x == 0.0 && source->y == 0.0)
- target->x = target->y = 0;
- else if( source->x != 0.0 && source->y == 0.0){
- target->x = atan(source->x);
- target->y = 0;
- }
- else if( source->x == 0.0 && source->y != 0.0){
- temp0.x = source->y; temp0.y = 0.0;
- Complex_ATanh(&temp0, &temp0);
- target->x = -temp0.y; target->y = temp0.x;
- }
- else if( source->x != 0.0 && source->y != 0.0)
- {
- temp0.x = -source->y; temp0.y = source->x;
- temp1.x = 1 - temp0.x; temp1.y = -temp0.y;
- temp2.x = 1 + temp0.x; temp2.y = temp0.y;
- Complex_Div(&temp3, &temp1, &temp2);
- Complex_Log(&temp3, &temp3);
- target->x = -temp3.y * .5; target->y = .5 * temp3.x;
- }
- } /* End Complex_ATanz() */
- void Complex_Tan(CMPLX *target, CMPLX *source)
- {
- DBL x, y, sinx, cosx, sinhy, coshy, denom;
- x = 2 * source->x;
- y = 2 * source->y;
- sinx = sin(x); cosx = cos(x);
- sinhy = sinh(y); coshy = cosh(y);
- denom = cosx + coshy;
- if(denom == 0)
- return;
- target->x = sinx/denom;
- target->y = sinhy/denom;
- } /* End Complex_Tan() */
- void Complex_Tanh(CMPLX *target, CMPLX *source)
- {
- DBL x, y, siny, cosy, sinhx, coshx, denom;
- x = 2 * source->x;
- y = 2 * source->y;
- siny = sin(y); cosy = cos(y);
- sinhx = sinh(x); coshx = cosh(x);
- denom = coshx + cosy;
- if(denom == 0)
- return;
- target->x = sinhx/denom;
- target->y = siny/denom;
- } /* End Complex_Tanh() */
- void Complex_Power (CMPLX *target, CMPLX *source1, CMPLX *source2)
- {
- CMPLX cLog, t;
- DBL e2x;
- if(source1->x == 0 && source1->y == 0)
- {
- target->x = target->y = 0.0;
- return;
- }
- Complex_Log (&cLog, source1);
- Complex_Mult (&t, &cLog, source2);
- if(t.x < -690)
- e2x = 0;
- else
- e2x = exp(t.x);
- target->x = e2x * cos(t.y);
- target->y = e2x * sin(t.y);
- }
- #if 1
- void Complex_Pwr (CMPLX *target, CMPLX *source)
- {
- Complex_Power(target, source, &exponent);
- }
- #else
- void Complex_Pwr (CMPLX *target, CMPLX *source)
- {
- /* the sqr dunction for testing */
- Complex_Mult(target, source, source);
- }
- #endif
|