Simple test for asyncio.library.
[AROS-Contrib.git] / gfx / povray / hcmplx.c
blobb55a0ebe046c7f9b1a95e13e787f6d96b6f174d2
1 /*****************************************************************************
2 * hcmplx.c
4 * This module implements hypercomplex Julia fractals.
6 * This file was written by Pascal Massimino.
8 * from Persistence of Vision(tm) Ray Tracer
9 * Copyright 1996,1999 Persistence of Vision Team
10 *---------------------------------------------------------------------------
11 * NOTICE: This source code file is provided so that users may experiment
12 * with enhancements to POV-Ray and to port the software to platforms other
13 * than those supported by the POV-Ray Team. There are strict rules under
14 * which you are permitted to use this file. The rules are in the file
15 * named POVLEGAL.DOC which should be distributed with this file.
16 * If POVLEGAL.DOC is not available or for more info please contact the POV-Ray
17 * Team Coordinator by email to team-coord@povray.org or visit us on the web at
18 * http://www.povray.org. The latest version of POV-Ray may be found at this site.
20 * This program is based on the popular DKB raytracer version 2.12.
21 * DKBTrace was originally written by David K. Buck.
22 * DKBTrace Ver 2.0-2.12 were written by David K. Buck & Aaron A. Collins.
24 *****************************************************************************/
26 #include "frame.h"
27 #include "povray.h"
28 #include "vector.h"
29 #include "povproto.h"
30 #include "fractal.h"
31 #include "spheres.h"
32 #include "hcmplx.h"
36 /*****************************************************************************
37 * Local preprocessor defines
38 ******************************************************************************/
40 #ifndef Fractal_Tolerance
41 #define Fractal_Tolerance 1e-8
42 #endif
45 #define HMult(xr,yr,zr,wr,x1,y1,z1,w1,x2,y2,z2,w2) \
46 (xr) = (x1) * (x2) - (y1) * (y2) - (z1) * (z2) + (w1) * (w2); \
47 (yr) = (y1) * (x2) + (x1) * (y2) - (w1) * (z2) - (z1) * (w2); \
48 (zr) = (z1) * (x2) - (w1) * (y2) + (x1) * (z2) - (y1) * (w2); \
49 (wr) = (w1) * (x2) + (z1) * (y2) + (y1) * (z2) + (x1) * (w2);
51 #define HSqr(xr,yr,zr,wr,x,y,z,w) \
52 (xr) = (x) * (x) - (y) * (y) - (z) * (z) + (w) * (w) ; \
53 (yr) = 2.0 * ( (x) * (y) - (z) * (w) ); \
54 (zr) = 2.0 * ( (z) * (x) - (w) * (y) ); \
55 (wr) = 2.0 * ( (w) * (x) + (z) * (y) );
59 /*****************************************************************************
60 * Local typedefs
61 ******************************************************************************/
65 /*****************************************************************************
66 * Static functions
67 ******************************************************************************/
69 static int HReciprocal (DBL * xr, DBL * yr, DBL * zr, DBL * wr, DBL x, DBL y, DBL z, DBL w);
70 static void HFunc (DBL * xr, DBL * yr, DBL * zr, DBL * wr, DBL x, DBL y, DBL z, DBL w, FRACTAL *f);
74 /*****************************************************************************
75 * Local variables
76 ******************************************************************************/
78 static CMPLX exponent = {0,0};
80 /******** Computations with Hypercomplexes **********/
84 /*****************************************************************************
86 * FUNCTION
88 * INPUT
90 * OUTPUT
92 * RETURNS
94 * AUTHOR
96 * Pascal Massimino
98 * DESCRIPTION
100 * CHANGES
102 ******************************************************************************/
104 static int HReciprocal(DBL *xr, DBL *yr, DBL *zr, DBL *wr, DBL x, DBL y, DBL z, DBL w)
106 DBL det, mod, xt_minus_yz;
108 det = ((x - w) * (x - w) + (y + z) * (y + z)) * ((x + w) * (x + w) + (y - z) * (y - z));
110 if (det == 0.0)
112 return (-1);
115 mod = (x * x + y * y + z * z + w * w);
117 xt_minus_yz = x * w - y * z;
119 *xr = (x * mod - 2 * w * xt_minus_yz) / det;
120 *yr = (-y * mod - 2 * z * xt_minus_yz) / det;
121 *zr = (-z * mod - 2 * y * xt_minus_yz) / det;
122 *wr = (w * mod - 2 * x * xt_minus_yz) / det;
124 return (0);
129 /*****************************************************************************
131 * FUNCTION Hfunc
133 * INPUT 4D Hypercomplex number, pointer to fractal object
135 * OUTPUT calculates the 4D generalization of fractal->Complex_Function
137 * RETURNS void
139 * AUTHOR
141 * Pascal Massimino
143 * DESCRIPTION
144 * Hypercomplex numbers allow generalization of any complex->complex
145 * function in a uniform way. This function implements a general
146 * unary 4D function based on the corresponding complex function.
148 * CHANGES
149 * Generalized to use Complex_Function() TW
151 ******************************************************************************/
153 static void HFunc(DBL *xr, DBL *yr, DBL *zr, DBL *wr, DBL x, DBL y, DBL z, DBL w, FRACTAL *f)
155 CMPLX a, b, ra, rb;
157 /* convert to duplex form */
158 a.x = x - w;
159 a.y = y + z;
160 b.x = x + w;
161 b.y = y - z;
163 if(f->Sub_Type == PWR_STYPE)
165 exponent = f->exponent;
168 /* apply function to each part */
169 Complex_Function(&ra, &a, f);
170 Complex_Function(&rb, &b, f);
172 /* convert back */
173 *xr = .5 * (ra.x + rb.x);
174 *yr = .5 * (ra.y + rb.y);
175 *zr = .5 * (ra.y - rb.y);
176 *wr = .5 * (rb.x - ra.x);
181 /*****************************************************************************
183 * FUNCTION
185 * INPUT
187 * OUTPUT
189 * RETURNS
191 * AUTHOR
193 * Pascal Massimino
195 * DESCRIPTION
197 * CHANGES
199 ******************************************************************************/
201 /*------------------ z2 Iteration method ------------------*/
203 int Iteration_HCompl(VECTOR IPoint, FRACTAL *HCompl)
205 int i;
206 DBL yz, xw;
207 DBL Exit_Value;
208 DBL x, y, z, w;
210 x = Sx[0] = IPoint[X];
211 y = Sy[0] = IPoint[Y];
212 z = Sz[0] = IPoint[Z];
213 w = Sw[0] = (HCompl->SliceDist
214 - HCompl->Slice[X]*x
215 - HCompl->Slice[Y]*y
216 - HCompl->Slice[Z]*z)/HCompl->Slice[T];
218 Exit_Value = HCompl->Exit_Value;
220 for (i = 1; i <= HCompl->n; ++i)
222 yz = y * y + z * z;
223 xw = x * x + w * w;
225 if ((xw + yz) > Exit_Value)
227 return (FALSE);
230 Sx[i] = xw - yz + HCompl->Julia_Parm[X];
231 Sy[i] = 2.0 * (x * y - z * w) + HCompl->Julia_Parm[Y];
232 Sz[i] = 2.0 * (x * z - w * y) + HCompl->Julia_Parm[Z];
233 Sw[i] = 2.0 * (x * w + y * z) + HCompl->Julia_Parm[T];
235 w = Sw[i];
236 x = Sx[i];
238 z = Sz[i];
239 y = Sy[i];
242 return (TRUE);
247 /*****************************************************************************
249 * FUNCTION
251 * INPUT
253 * OUTPUT
255 * RETURNS
257 * AUTHOR
259 * Pascal Massimino
261 * DESCRIPTION
263 * CHANGES
265 ******************************************************************************/
267 int D_Iteration_HCompl(VECTOR IPoint, FRACTAL *HCompl, DBL *Dist)
269 int i;
270 DBL yz, xw;
271 DBL Exit_Value, F_Value, Step;
272 DBL x, y, z, w;
273 VECTOR H_Normal;
275 x = Sx[0] = IPoint[X];
276 y = Sy[0] = IPoint[Y];
277 z = Sz[0] = IPoint[Z];
278 w = Sw[0] = (HCompl->SliceDist
279 - HCompl->Slice[X]*x
280 - HCompl->Slice[Y]*y
281 - HCompl->Slice[Z]*z)/HCompl->Slice[T];
283 Exit_Value = HCompl->Exit_Value;
285 for (i = 1; i <= HCompl->n; ++i)
287 yz = y * y + z * z;
288 xw = x * x + w * w;
290 if ((F_Value = xw + yz) > Exit_Value)
292 Normal_Calc_HCompl(H_Normal, i - 1, HCompl);
294 VDot(Step, H_Normal, Direction);
296 if (Step < -Fractal_Tolerance)
298 Step = -2.0 * Step;
300 if ((F_Value > Precision * Step) && (F_Value < 30 * Precision * Step))
302 *Dist = F_Value / Step;
304 return (FALSE);
308 *Dist = Precision;
310 return (FALSE);
313 Sx[i] = xw - yz + HCompl->Julia_Parm[X];
314 Sy[i] = 2.0 * (x * y - z * w) + HCompl->Julia_Parm[Y];
315 Sz[i] = 2.0 * (x * z - w * y) + HCompl->Julia_Parm[Z];
316 Sw[i] = 2.0 * (x * w + y * z) + HCompl->Julia_Parm[T];
318 w = Sw[i];
319 x = Sx[i];
321 z = Sz[i];
322 y = Sy[i];
325 *Dist = Precision;
327 return (TRUE);
332 /*****************************************************************************
334 * FUNCTION
336 * INPUT
338 * OUTPUT
340 * RETURNS
342 * AUTHOR
344 * Pascal Massimino
346 * DESCRIPTION
348 * CHANGES
350 ******************************************************************************/
352 void Normal_Calc_HCompl(VECTOR Result, int N_Max, FRACTAL *fractal)
354 DBL n1, n2, n3, n4;
355 int i;
356 DBL x, y, z, w;
357 DBL xx, yy, zz, ww;
358 DBL Pow;
361 * Algebraic properties of hypercomplexes allows simplifications in
362 * computations...
365 x = Sx[0];
366 y = Sy[0];
367 z = Sz[0];
368 w = Sw[0];
370 Pow = 2.0;
372 for (i = 1; i < N_Max; ++i)
376 * For a map z->f(z), f depending on c, one must perform here :
378 * (x,y,z,w) * df/dz(Sx[i],Sy[i],Sz[i],Sw[i]) -> (x,y,z,w) ,
380 * up to a constant.
383 /******************* Case z->z^2+c *****************/
385 /* the df/dz part needs no work */
387 HMult(xx, yy, zz, ww, Sx[i], Sy[i], Sz[i], Sw[i], x, y, z, w);
389 w = ww;
390 z = zz;
391 y = yy;
392 x = xx;
394 Pow *= 2.0;
397 n1 = Sx[N_Max] * Pow;
398 n2 = Sy[N_Max] * Pow;
399 n3 = Sz[N_Max] * Pow;
400 n4 = Sw[N_Max] * Pow;
402 Result[X] = x * n1 + y * n2 + z * n3 + w * n4;
403 Result[Y] = -y * n1 + x * n2 - w * n3 + z * n4;
404 Result[Z] = -z * n1 - w * n2 + x * n3 + y * n4;
409 /*****************************************************************************
411 * FUNCTION
413 * INPUT
415 * OUTPUT
417 * RETURNS
419 * AUTHOR
421 * Pascal Massimino
423 * DESCRIPTION
425 * CHANGES
427 ******************************************************************************/
429 int F_Bound_HCompl(RAY *Ray, FRACTAL *Fractal, DBL *Depth_Min, DBL *Depth_Max)
431 return (Intersect_Sphere(Ray, Fractal->Center, Fractal->Radius_Squared, Depth_Min, Depth_Max));
434 /****************************************************************/
435 /*--------------------------- z3 -------------------------------*/
436 /****************************************************************/
440 /*****************************************************************************
442 * FUNCTION
444 * INPUT
446 * OUTPUT
448 * RETURNS
450 * AUTHOR
452 * Pascal Massimino
454 * DESCRIPTION
456 * CHANGES
458 ******************************************************************************/
460 int Iteration_HCompl_z3(VECTOR IPoint, FRACTAL *HCompl)
462 int i;
463 DBL Norm, xx, yy, zz, ww;
464 DBL Exit_Value;
465 DBL x, y, z, w;
467 x = Sx[0] = IPoint[X];
468 y = Sy[0] = IPoint[Y];
469 z = Sz[0] = IPoint[Z];
470 w = Sw[0] = (HCompl->SliceDist
471 - HCompl->Slice[X]*x
472 - HCompl->Slice[Y]*y
473 - HCompl->Slice[Z]*z)/HCompl->Slice[T];
475 Exit_Value = HCompl->Exit_Value;
477 for (i = 1; i <= HCompl->n; ++i)
479 Norm = x * x + y * y + z * z + w * w;
481 /* is this test correct ? */
482 if (Norm > Exit_Value)
484 return (FALSE);
487 /*************** Case: z->z^2+c *********************/
488 HSqr(xx, yy, zz, ww, x, y, z, w);
490 x = Sx[i] = xx + HCompl->Julia_Parm[X];
491 y = Sy[i] = yy + HCompl->Julia_Parm[Y];
492 z = Sz[i] = zz + HCompl->Julia_Parm[Z];
493 w = Sw[i] = ww + HCompl->Julia_Parm[T];
497 return (TRUE);
502 /*****************************************************************************
504 * FUNCTION
506 * INPUT
508 * OUTPUT
510 * RETURNS
512 * AUTHOR
514 * Pascal Massimino
516 * DESCRIPTION
518 * CHANGES
520 ******************************************************************************/
522 int D_Iteration_HCompl_z3(VECTOR IPoint, FRACTAL *HCompl, DBL *Dist)
524 int i;
525 DBL xx, yy, zz, ww;
526 DBL Exit_Value, F_Value, Step;
527 DBL x, y, z, w;
528 VECTOR H_Normal;
530 x = Sx[0] = IPoint[X];
531 y = Sy[0] = IPoint[Y];
532 z = Sz[0] = IPoint[Z];
533 w = Sw[0] = (HCompl->SliceDist
534 - HCompl->Slice[X]*x
535 - HCompl->Slice[Y]*y
536 - HCompl->Slice[Z]*z)/HCompl->Slice[T];
538 Exit_Value = HCompl->Exit_Value;
540 for (i = 1; i <= HCompl->n; ++i)
542 F_Value = x * x + y * y + z * z + w * w;
544 if (F_Value > Exit_Value)
546 Normal_Calc_HCompl_z3(H_Normal, i - 1, HCompl);
548 VDot(Step, H_Normal, Direction);
550 if (Step < -Fractal_Tolerance)
552 Step = -2.0 * Step;
554 if ((F_Value > Precision * Step) && (F_Value < 30 * Precision * Step))
556 *Dist = F_Value / Step;
558 return (FALSE);
562 *Dist = Precision;
564 return (FALSE);
567 /*************** Case: z->z^2+c *********************/
569 HSqr(xx, yy, zz, ww, x, y, z, w);
571 x = Sx[i] = xx + HCompl->Julia_Parm[X];
572 y = Sy[i] = yy + HCompl->Julia_Parm[Y];
573 z = Sz[i] = zz + HCompl->Julia_Parm[Z];
574 w = Sw[i] = ww + HCompl->Julia_Parm[T];
577 *Dist = Precision;
579 return (TRUE);
584 /*****************************************************************************
586 * FUNCTION
588 * INPUT
590 * OUTPUT
592 * RETURNS
594 * AUTHOR
596 * Pascal Massimino
598 * DESCRIPTION
600 * CHANGES
602 ******************************************************************************/
604 void Normal_Calc_HCompl_z3(VECTOR Result, int N_Max, FRACTAL *fractal)
606 DBL n1, n2, n3, n4;
607 int i;
608 DBL x, y, z, w;
609 DBL xx, yy, zz, ww;
612 * Algebraic properties of hypercomplexes allows simplifications in
613 * computations...
616 x = Sx[0];
617 y = Sy[0];
618 z = Sz[0];
619 w = Sw[0];
621 for (i = 1; i < N_Max; ++i)
624 * For a map z->f(z), f depending on c, one must perform here :
626 * (x,y,z,w) * df/dz(Sx[i],Sy[i],Sz[i],Sw[i]) -> (x,y,z,w) ,
628 * up to a constant.
631 /******************* Case z->z^2+c *****************/
633 /* the df/dz part needs no work */
635 HMult(xx, yy, zz, ww, Sx[i], Sy[i], Sz[i], Sw[i], x, y, z, w);
637 x = xx;
638 y = yy;
639 z = zz;
640 w = ww;
643 n1 = Sx[N_Max];
644 n2 = Sy[N_Max];
645 n3 = Sz[N_Max];
646 n4 = Sw[N_Max];
648 Result[X] = x * n1 + y * n2 + z * n3 + w * n4;
649 Result[Y] = -y * n1 + x * n2 - w * n3 + z * n4;
650 Result[Z] = -z * n1 - w * n2 + x * n3 + y * n4;
655 /*****************************************************************************
657 * FUNCTION
659 * INPUT
661 * OUTPUT
663 * RETURNS
665 * AUTHOR
667 * Pascal Massimino
669 * DESCRIPTION
671 * CHANGES
673 ******************************************************************************/
675 int F_Bound_HCompl_z3(RAY *Ray, FRACTAL *Fractal, DBL *Depth_Min, DBL *Depth_Max)
677 return F_Bound_HCompl(Ray, Fractal, Depth_Min, Depth_Max);
680 /*--------------------------- Inv -------------------------------*/
683 /*****************************************************************************
685 * FUNCTION
687 * INPUT
689 * OUTPUT
691 * RETURNS
693 * AUTHOR
695 * Pascal Massimino
697 * DESCRIPTION
699 * CHANGES
701 ******************************************************************************/
703 int Iteration_HCompl_Reciprocal(VECTOR IPoint, FRACTAL *HCompl)
705 int i;
706 DBL Norm, xx, yy, zz, ww;
707 DBL Exit_Value;
708 DBL x, y, z, w;
710 x = Sx[0] = IPoint[X];
711 y = Sy[0] = IPoint[Y];
712 z = Sz[0] = IPoint[Z];
713 w = Sw[0] = (HCompl->SliceDist
714 - HCompl->Slice[X]*x
715 - HCompl->Slice[Y]*y
716 - HCompl->Slice[Z]*z)/HCompl->Slice[T];
718 Exit_Value = HCompl->Exit_Value;
720 for (i = 1; i <= HCompl->n; ++i)
722 Norm = x * x + y * y + z * z + w * w;
724 if (Norm > Exit_Value)
726 return (FALSE);
729 HReciprocal(&xx, &yy, &zz, &ww, x, y, z, w);
731 x = Sx[i] = xx + HCompl->Julia_Parm[X];
732 y = Sy[i] = yy + HCompl->Julia_Parm[Y];
733 z = Sz[i] = zz + HCompl->Julia_Parm[Z];
734 w = Sw[i] = ww + HCompl->Julia_Parm[T];
738 return (TRUE);
743 /*****************************************************************************
745 * FUNCTION
747 * INPUT
749 * OUTPUT
751 * RETURNS
753 * AUTHOR
755 * Pascal Massimino
757 * DESCRIPTION
759 * CHANGES
761 ******************************************************************************/
763 int D_Iteration_HCompl_Reciprocal(VECTOR IPoint, FRACTAL *HCompl, DBL *Dist)
765 int i;
766 DBL xx, yy, zz, ww;
767 DBL Exit_Value, F_Value, Step;
768 DBL x, y, z, w;
769 VECTOR H_Normal;
771 x = Sx[0] = IPoint[X];
772 y = Sy[0] = IPoint[Y];
773 z = Sz[0] = IPoint[Z];
774 w = Sw[0] = (HCompl->SliceDist
775 - HCompl->Slice[X]*x
776 - HCompl->Slice[Y]*y
777 - HCompl->Slice[Z]*z)/HCompl->Slice[T];
779 Exit_Value = HCompl->Exit_Value;
781 for (i = 1; i <= HCompl->n; ++i)
783 F_Value = x * x + y * y + z * z + w * w;
785 if (F_Value > Exit_Value)
787 Normal_Calc_HCompl_Reciprocal(H_Normal, i - 1, HCompl);
789 VDot(Step, H_Normal, Direction);
791 if (Step < -Fractal_Tolerance)
793 Step = -2.0 * Step;
795 if ((F_Value > Precision * Step) && F_Value < (30 * Precision * Step))
797 *Dist = F_Value / Step;
799 return (FALSE);
803 *Dist = Precision;
805 return (FALSE);
808 HReciprocal(&xx, &yy, &zz, &ww, x, y, z, w);
810 x = Sx[i] = xx + HCompl->Julia_Parm[X];
811 y = Sy[i] = yy + HCompl->Julia_Parm[Y];
812 z = Sz[i] = zz + HCompl->Julia_Parm[Z];
813 w = Sw[i] = ww + HCompl->Julia_Parm[T];
817 *Dist = Precision;
819 return (TRUE);
824 /*****************************************************************************
826 * FUNCTION
828 * INPUT
830 * OUTPUT
832 * RETURNS
834 * AUTHOR
836 * Pascal Massimino
838 * DESCRIPTION
840 * CHANGES
842 ******************************************************************************/
844 void Normal_Calc_HCompl_Reciprocal(VECTOR Result, int N_Max, FRACTAL *fractal)
846 DBL n1, n2, n3, n4;
847 int i;
848 DBL x, y, z, w;
849 DBL xx, yy, zz, ww;
850 DBL xxx, yyy, zzz, www;
853 * Algebraic properties of hypercomplexes allows simplifications in
854 * computations...
857 x = Sx[0];
858 y = Sy[0];
859 z = Sz[0];
860 w = Sw[0];
862 for (i = 1; i < N_Max; ++i)
864 /******************* Case: z->1/z+c *****************/
866 HReciprocal(&xx, &yy, &zz, &ww, Sx[i], Sy[i], Sz[i], Sw[i]);
868 HSqr(xxx, yyy, zzz, www, xx, yy, zz, ww);
870 HMult(xx, yy, zz, ww, x, y, z, w, -xxx, -yyy, -zzz, -www);
872 x = xx;
873 y = yy;
874 z = zz;
875 w = ww;
878 n1 = Sx[N_Max];
879 n2 = Sy[N_Max];
880 n3 = Sz[N_Max];
881 n4 = Sw[N_Max];
883 Result[X] = x * n1 + y * n2 + z * n3 + w * n4;
884 Result[Y] = -y * n1 + x * n2 - w * n3 + z * n4;
885 Result[Z] = -z * n1 - w * n2 + x * n3 + y * n4;
890 /*****************************************************************************
892 * FUNCTION
894 * INPUT
896 * OUTPUT
898 * RETURNS
900 * AUTHOR
902 * Pascal Massimino
904 * DESCRIPTION
906 * CHANGES
908 ******************************************************************************/
910 int F_Bound_HCompl_Reciprocal(RAY *Ray, FRACTAL *Fractal, DBL *Depth_Min, DBL *Depth_Max)
912 return F_Bound_HCompl(Ray, Fractal, Depth_Min, Depth_Max);
915 /*--------------------------- Func -------------------------------*/
918 /*****************************************************************************
920 * FUNCTION
922 * INPUT
924 * OUTPUT
926 * RETURNS
928 * AUTHOR
930 * Pascal Massimino
932 * DESCRIPTION
934 * CHANGES
936 ******************************************************************************/
938 int Iteration_HCompl_Func(VECTOR IPoint, FRACTAL *HCompl)
940 int i;
941 DBL Norm, xx, yy, zz, ww;
942 DBL Exit_Value;
943 DBL x, y, z, w;
945 x = Sx[0] = IPoint[X];
946 y = Sy[0] = IPoint[Y];
947 z = Sz[0] = IPoint[Y];
948 w = Sw[0] = (HCompl->SliceDist
949 - HCompl->Slice[X]*x
950 - HCompl->Slice[Y]*y
951 - HCompl->Slice[Z]*z)/HCompl->Slice[T];
953 Exit_Value = HCompl->Exit_Value;
955 for (i = 1; i <= HCompl->n; ++i)
957 Norm = x * x + y * y + z * z + w * w;
959 if (Norm > Exit_Value)
961 return (FALSE);
964 HFunc(&xx, &yy, &zz, &ww, x, y, z, w, HCompl);
966 x = Sx[i] = xx + HCompl->Julia_Parm[X];
967 y = Sy[i] = yy + HCompl->Julia_Parm[Y];
968 z = Sz[i] = zz + HCompl->Julia_Parm[Z];
969 w = Sw[i] = ww + HCompl->Julia_Parm[T];
973 return (TRUE);
978 /*****************************************************************************
980 * FUNCTION
982 * INPUT
984 * OUTPUT
986 * RETURNS
988 * AUTHOR
990 * Pascal Massimino
992 * DESCRIPTION
994 * CHANGES
996 ******************************************************************************/
998 int D_Iteration_HCompl_Func(VECTOR IPoint, FRACTAL *HCompl, DBL *Dist)
1000 int i;
1001 DBL xx, yy, zz, ww;
1002 DBL Exit_Value, F_Value, Step;
1003 DBL x, y, z, w;
1004 VECTOR H_Normal;
1006 x = Sx[0] = IPoint[X];
1007 y = Sy[0] = IPoint[Y];
1008 z = Sz[0] = IPoint[Z];
1009 w = Sw[0] = (HCompl->SliceDist
1010 - HCompl->Slice[X]*x
1011 - HCompl->Slice[Y]*y
1012 - HCompl->Slice[Z]*z)/HCompl->Slice[T];
1014 Exit_Value = HCompl->Exit_Value;
1016 for (i = 1; i <= HCompl->n; ++i)
1018 F_Value = x * x + y * y + z * z + w * w;
1020 if (F_Value > Exit_Value)
1022 Normal_Calc_HCompl_Func(H_Normal, i - 1, HCompl);
1024 VDot(Step, H_Normal, Direction);
1026 if (Step < -Fractal_Tolerance)
1028 Step = -2.0 * Step;
1030 if ((F_Value > Precision * Step) && F_Value < (30 * Precision * Step))
1032 *Dist = F_Value / Step;
1034 return (FALSE);
1038 *Dist = Precision;
1040 return (FALSE);
1043 HFunc(&xx, &yy, &zz, &ww, x, y, z, w, HCompl);
1045 x = Sx[i] = xx + HCompl->Julia_Parm[X];
1046 y = Sy[i] = yy + HCompl->Julia_Parm[Y];
1047 z = Sz[i] = zz + HCompl->Julia_Parm[Z];
1048 w = Sw[i] = ww + HCompl->Julia_Parm[T];
1052 *Dist = Precision;
1054 return (TRUE);
1059 /*****************************************************************************
1061 * FUNCTION
1063 * INPUT
1065 * OUTPUT
1067 * RETURNS
1069 * AUTHOR
1071 * Pascal Massimino
1073 * DESCRIPTION
1075 * CHANGES
1077 ******************************************************************************/
1079 void Normal_Calc_HCompl_Func(VECTOR Result, int N_Max, FRACTAL *fractal)
1081 DBL n1, n2, n3, n4;
1082 int i;
1083 DBL x, y, z, w;
1084 DBL xx, yy, zz, ww;
1085 DBL xxx, yyy, zzz, www;
1088 * Algebraic properties of hypercomplexes allows simplifications in
1089 * computations...
1092 x = Sx[0];
1093 y = Sy[0];
1094 z = Sz[0];
1095 w = Sw[0];
1097 for (i = 1; i < N_Max; ++i)
1099 /**************** Case: z-> f(z)+c ************************/
1101 HFunc(&xx, &yy, &zz, &ww, Sx[i], Sy[i], Sz[i], Sw[i], fractal);
1103 HMult(xxx, yyy, zzz, www, xx, yy, zz, ww, x, y, z, w);
1105 x = xxx;
1106 y = yyy;
1107 z = zzz;
1108 w = www;
1111 n1 = Sx[N_Max];
1112 n2 = Sy[N_Max];
1113 n3 = Sz[N_Max];
1114 n4 = Sw[N_Max];
1116 Result[X] = x * n1 + y * n2 + z * n3 + w * n4;
1117 Result[Y] = -y * n1 + x * n2 - w * n3 + z * n4;
1118 Result[Z] = -z * n1 - w * n2 + x * n3 + y * n4;
1123 /*****************************************************************************
1125 * FUNCTION
1127 * INPUT
1129 * OUTPUT
1131 * RETURNS
1133 * AUTHOR
1135 * Pascal Massimino
1137 * DESCRIPTION
1139 * CHANGES
1141 ******************************************************************************/
1143 int F_Bound_HCompl_Func(RAY *Ray, FRACTAL *Fractal, DBL *Depth_Min, DBL *Depth_Max)
1145 return F_Bound_HCompl(Ray, Fractal, Depth_Min, Depth_Max);
1148 /*****************************************************************************
1150 * FUNCTION Complex transcental functions
1152 * INPUT pointer to source complex number
1154 * OUTPUT fn(input)
1156 * RETURNS void
1158 * AUTHOR
1160 * Tim Wegner
1162 * DESCRIPTION Calculate common functions on complexes
1163 * Since our purpose is fractals, error checking is lax.
1165 * CHANGES
1167 ******************************************************************************/
1169 void Complex_Mult (CMPLX *target, CMPLX *source1, CMPLX *source2)
1171 DBL tmpx;
1172 tmpx = source1->x * source2->x - source1->y * source2->y;
1173 target->y = source1->x * source2->y + source1->y * source2->x;
1174 target->x = tmpx;
1177 void Complex_Div (CMPLX *target, CMPLX *source1, CMPLX *source2)
1179 DBL mod,tmpx,yxmod,yymod;
1180 mod = Sqr(source2->x) + Sqr(source2->y);
1181 if (mod==0)
1182 return;
1183 yxmod = source2->x/mod;
1184 yymod = - source2->y/mod;
1185 tmpx = source1->x * yxmod - source1->y * yymod;
1186 target->y = source1->x * yymod + source1->y * yxmod;
1187 target->x = tmpx;
1188 } /* End Complex_Mult() */
1190 void Complex_Exp (CMPLX *target, CMPLX *source)
1192 DBL expx;
1193 expx = exp(source->x);
1194 target->x = expx * cos(source->y);
1195 target->y = expx * sin(source->y);
1196 } /* End Complex_Exp() */
1198 void Complex_Sin (CMPLX *target, CMPLX *source)
1200 target->x = sin(source->x) * cosh(source->y);
1201 target->y = cos(source->x) * sinh(source->y);
1202 } /* End Complex_Sin() */
1204 void Complex_Sinh (CMPLX *target, CMPLX *source)
1206 target->x = sinh(source->x) * cos(source->y);
1207 target->y = cosh(source->x) * sin(source->y);
1208 } /* End Complex_Sinh() */
1211 void Complex_Cos (CMPLX *target, CMPLX *source)
1213 target->x = cos(source->x) * cosh(source->y);
1214 target->y = -sin(source->x) * sinh(source->y);
1215 } /* End Complex_Cos() */
1217 void Complex_Cosh (CMPLX *target, CMPLX *source)
1219 target->x = cosh(source->x) * cos(source->y);
1220 target->y = sinh(source->x) * sin(source->y);
1221 } /* End Complex_Cosh() */
1224 void Complex_Log (CMPLX *target, CMPLX *source)
1226 DBL mod,zx,zy;
1227 mod = sqrt(source->x * source->x + source->y * source->y);
1228 zx = log(mod);
1229 zy = atan2(source->y,source->x);
1231 target->x = zx;
1232 target->y = zy;
1233 } /* End Complex_Log() */
1235 void Complex_Sqrt(CMPLX *target, CMPLX *source)
1237 DBL mag;
1238 DBL theta;
1240 if(source->x == 0.0 && source->y == 0.0)
1242 target->x = target->y = 0.0;
1244 else
1246 mag = sqrt(sqrt(Sqr(source->x) + Sqr(source->y)));
1247 theta = atan2(source->y, source->x) / 2;
1248 target->y = mag * sin(theta);
1249 target->x = mag * cos(theta);
1251 } /* End Complex_Sqrt() */
1253 /* rz=Arcsin(z)=-i*Log{i*z+sqrt(1-z*z)} */
1254 void Complex_ASin(CMPLX *target, CMPLX *source)
1256 CMPLX tempz1,tempz2;
1258 Complex_Mult(&tempz1, source, source);
1259 tempz1.x = 1 - tempz1.x; tempz1.y = -tempz1.y;
1260 Complex_Sqrt( &tempz1, &tempz1);
1262 tempz2.x = -source->y; tempz2.y = source->x;
1263 tempz1.x += tempz2.x; tempz1.y += tempz2.y;
1265 Complex_Log( &tempz1, &tempz1);
1266 target->x = tempz1.y; target->y = -tempz1.x;
1267 } /* End Complex_ASin() */
1270 void Complex_ACos(CMPLX *target, CMPLX *source)
1272 CMPLX temp;
1274 Complex_Mult(&temp, source, source);
1275 temp.x -= 1;
1276 Complex_Sqrt(&temp, &temp);
1278 temp.x += source->x; temp.y += source->y;
1280 Complex_Log(&temp, &temp);
1281 target->x = temp.y; target->y = -temp.x;
1282 } /* End Complex_ACos() */
1284 void Complex_ASinh(CMPLX *target, CMPLX *source)
1286 CMPLX temp;
1288 Complex_Mult (&temp, source, source);
1289 temp.x += 1;
1290 Complex_Sqrt (&temp, &temp);
1291 temp.x += source->x; temp.y += source->y;
1292 Complex_Log(target, &temp);
1293 } /* End Complex_ASinh */
1295 /* rz=Arccosh(z)=Log(z+sqrt(z*z-1)} */
1296 void Complex_ACosh (CMPLX *target, CMPLX *source)
1298 CMPLX tempz;
1299 Complex_Mult(&tempz, source, source);
1300 tempz.x -= 1;
1301 Complex_Sqrt (&tempz, &tempz);
1302 tempz.x = source->x + tempz.x; tempz.y = source->y + tempz.y;
1303 Complex_Log (target, &tempz);
1304 } /* End Complex_ACosh() */
1306 /* rz=Arctanh(z)=1/2*Log{(1+z)/(1-z)} */
1307 void Complex_ATanh(CMPLX *target, CMPLX *source)
1309 CMPLX temp0,temp1,temp2;
1311 if( source->x == 0.0)
1313 target->x = 0;
1314 target->y = atan( source->y);
1315 return;
1317 else
1319 if( fabs(source->x) == 1.0 && source->y == 0.0)
1321 return;
1323 else if( fabs( source->x) < 1.0 && source->y == 0.0)
1325 target->x = log((1+source->x)/(1-source->x))/2;
1326 target->y = 0;
1327 return;
1329 else
1331 temp0.x = 1 + source->x; temp0.y = source->y;
1332 temp1.x = 1 - source->x; temp1.y = -source->y;
1333 Complex_Div(&temp2, &temp0, &temp1);
1334 Complex_Log(&temp2, &temp2);
1335 target->x = .5 * temp2.x; target->y = .5 * temp2.y;
1336 return;
1339 } /* End Complex_ATanh() */
1341 /* rz=Arctan(z)=i/2*Log{(1-i*z)/(1+i*z)} */
1342 void Complex_ATan(CMPLX *target, CMPLX *source)
1344 CMPLX temp0,temp1,temp2,temp3;
1345 if( source->x == 0.0 && source->y == 0.0)
1346 target->x = target->y = 0;
1347 else if( source->x != 0.0 && source->y == 0.0){
1348 target->x = atan(source->x);
1349 target->y = 0;
1351 else if( source->x == 0.0 && source->y != 0.0){
1352 temp0.x = source->y; temp0.y = 0.0;
1353 Complex_ATanh(&temp0, &temp0);
1354 target->x = -temp0.y; target->y = temp0.x;
1356 else if( source->x != 0.0 && source->y != 0.0)
1358 temp0.x = -source->y; temp0.y = source->x;
1359 temp1.x = 1 - temp0.x; temp1.y = -temp0.y;
1360 temp2.x = 1 + temp0.x; temp2.y = temp0.y;
1362 Complex_Div(&temp3, &temp1, &temp2);
1363 Complex_Log(&temp3, &temp3);
1364 target->x = -temp3.y * .5; target->y = .5 * temp3.x;
1366 } /* End Complex_ATanz() */
1368 void Complex_Tan(CMPLX *target, CMPLX *source)
1370 DBL x, y, sinx, cosx, sinhy, coshy, denom;
1371 x = 2 * source->x;
1372 y = 2 * source->y;
1373 sinx = sin(x); cosx = cos(x);
1374 sinhy = sinh(y); coshy = cosh(y);
1375 denom = cosx + coshy;
1376 if(denom == 0)
1377 return;
1378 target->x = sinx/denom;
1379 target->y = sinhy/denom;
1380 } /* End Complex_Tan() */
1382 void Complex_Tanh(CMPLX *target, CMPLX *source)
1384 DBL x, y, siny, cosy, sinhx, coshx, denom;
1385 x = 2 * source->x;
1386 y = 2 * source->y;
1387 siny = sin(y); cosy = cos(y);
1388 sinhx = sinh(x); coshx = cosh(x);
1389 denom = coshx + cosy;
1390 if(denom == 0)
1391 return;
1392 target->x = sinhx/denom;
1393 target->y = siny/denom;
1394 } /* End Complex_Tanh() */
1397 void Complex_Power (CMPLX *target, CMPLX *source1, CMPLX *source2)
1399 CMPLX cLog, t;
1400 DBL e2x;
1402 if(source1->x == 0 && source1->y == 0)
1404 target->x = target->y = 0.0;
1405 return;
1408 Complex_Log (&cLog, source1);
1409 Complex_Mult (&t, &cLog, source2);
1411 if(t.x < -690)
1412 e2x = 0;
1413 else
1414 e2x = exp(t.x);
1415 target->x = e2x * cos(t.y);
1416 target->y = e2x * sin(t.y);
1419 #if 1
1420 void Complex_Pwr (CMPLX *target, CMPLX *source)
1422 Complex_Power(target, source, &exponent);
1425 #else
1426 void Complex_Pwr (CMPLX *target, CMPLX *source)
1428 /* the sqr dunction for testing */
1429 Complex_Mult(target, source, source);
1431 #endif