HCMPLX.C 30 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431
  1. /*****************************************************************************
  2. * hcmplx.c
  3. *
  4. * This module implements hypercomplex Julia fractals.
  5. *
  6. * This file was written by Pascal Massimino.
  7. *
  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.
  19. *
  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.
  23. *
  24. *****************************************************************************/
  25. #include "frame.h"
  26. #include "povray.h"
  27. #include "vector.h"
  28. #include "povproto.h"
  29. #include "fractal.h"
  30. #include "spheres.h"
  31. #include "hcmplx.h"
  32. /*****************************************************************************
  33. * Local preprocessor defines
  34. ******************************************************************************/
  35. #ifndef Fractal_Tolerance
  36. #define Fractal_Tolerance 1e-8
  37. #endif
  38. #define HMult(xr,yr,zr,wr,x1,y1,z1,w1,x2,y2,z2,w2) \
  39. (xr) = (x1) * (x2) - (y1) * (y2) - (z1) * (z2) + (w1) * (w2); \
  40. (yr) = (y1) * (x2) + (x1) * (y2) - (w1) * (z2) - (z1) * (w2); \
  41. (zr) = (z1) * (x2) - (w1) * (y2) + (x1) * (z2) - (y1) * (w2); \
  42. (wr) = (w1) * (x2) + (z1) * (y2) + (y1) * (z2) + (x1) * (w2);
  43. #define HSqr(xr,yr,zr,wr,x,y,z,w) \
  44. (xr) = (x) * (x) - (y) * (y) - (z) * (z) + (w) * (w) ; \
  45. (yr) = 2.0 * ( (x) * (y) - (z) * (w) ); \
  46. (zr) = 2.0 * ( (z) * (x) - (w) * (y) ); \
  47. (wr) = 2.0 * ( (w) * (x) + (z) * (y) );
  48. /*****************************************************************************
  49. * Local typedefs
  50. ******************************************************************************/
  51. /*****************************************************************************
  52. * Static functions
  53. ******************************************************************************/
  54. static int HReciprocal (DBL * xr, DBL * yr, DBL * zr, DBL * wr, DBL x, DBL y, DBL z, DBL w);
  55. static void HFunc (DBL * xr, DBL * yr, DBL * zr, DBL * wr, DBL x, DBL y, DBL z, DBL w, FRACTAL *f);
  56. /*****************************************************************************
  57. * Local variables
  58. ******************************************************************************/
  59. static CMPLX exponent = {0,0};
  60. /******** Computations with Hypercomplexes **********/
  61. /*****************************************************************************
  62. *
  63. * FUNCTION
  64. *
  65. * INPUT
  66. *
  67. * OUTPUT
  68. *
  69. * RETURNS
  70. *
  71. * AUTHOR
  72. *
  73. * Pascal Massimino
  74. *
  75. * DESCRIPTION
  76. *
  77. * CHANGES
  78. *
  79. ******************************************************************************/
  80. static int HReciprocal(DBL *xr, DBL *yr, DBL *zr, DBL *wr, DBL x, DBL y, DBL z, DBL w)
  81. {
  82. DBL det, mod, xt_minus_yz;
  83. det = ((x - w) * (x - w) + (y + z) * (y + z)) * ((x + w) * (x + w) + (y - z) * (y - z));
  84. if (det == 0.0)
  85. {
  86. return (-1);
  87. }
  88. mod = (x * x + y * y + z * z + w * w);
  89. xt_minus_yz = x * w - y * z;
  90. *xr = (x * mod - 2 * w * xt_minus_yz) / det;
  91. *yr = (-y * mod - 2 * z * xt_minus_yz) / det;
  92. *zr = (-z * mod - 2 * y * xt_minus_yz) / det;
  93. *wr = (w * mod - 2 * x * xt_minus_yz) / det;
  94. return (0);
  95. }
  96. /*****************************************************************************
  97. *
  98. * FUNCTION Hfunc
  99. *
  100. * INPUT 4D Hypercomplex number, pointer to fractal object
  101. *
  102. * OUTPUT calculates the 4D generalization of fractal->Complex_Function
  103. *
  104. * RETURNS void
  105. *
  106. * AUTHOR
  107. *
  108. * Pascal Massimino
  109. *
  110. * DESCRIPTION
  111. * Hypercomplex numbers allow generalization of any complex->complex
  112. * function in a uniform way. This function implements a general
  113. * unary 4D function based on the corresponding complex function.
  114. *
  115. * CHANGES
  116. * Generalized to use Complex_Function() TW
  117. *
  118. ******************************************************************************/
  119. static void HFunc(DBL *xr, DBL *yr, DBL *zr, DBL *wr, DBL x, DBL y, DBL z, DBL w, FRACTAL *f)
  120. {
  121. CMPLX a, b, ra, rb;
  122. /* convert to duplex form */
  123. a.x = x - w;
  124. a.y = y + z;
  125. b.x = x + w;
  126. b.y = y - z;
  127. if(f->Sub_Type == PWR_STYPE)
  128. {
  129. exponent = f->exponent;
  130. }
  131. /* apply function to each part */
  132. Complex_Function(&ra, &a, f);
  133. Complex_Function(&rb, &b, f);
  134. /* convert back */
  135. *xr = .5 * (ra.x + rb.x);
  136. *yr = .5 * (ra.y + rb.y);
  137. *zr = .5 * (ra.y - rb.y);
  138. *wr = .5 * (rb.x - ra.x);
  139. }
  140. /*****************************************************************************
  141. *
  142. * FUNCTION
  143. *
  144. * INPUT
  145. *
  146. * OUTPUT
  147. *
  148. * RETURNS
  149. *
  150. * AUTHOR
  151. *
  152. * Pascal Massimino
  153. *
  154. * DESCRIPTION
  155. *
  156. * CHANGES
  157. *
  158. ******************************************************************************/
  159. /*------------------ z2 Iteration method ------------------*/
  160. int Iteration_HCompl(VECTOR IPoint, FRACTAL *HCompl)
  161. {
  162. int i;
  163. DBL yz, xw;
  164. DBL Exit_Value;
  165. DBL x, y, z, w;
  166. x = Sx[0] = IPoint[X];
  167. y = Sy[0] = IPoint[Y];
  168. z = Sz[0] = IPoint[Z];
  169. w = Sw[0] = (HCompl->SliceDist
  170. - HCompl->Slice[X]*x
  171. - HCompl->Slice[Y]*y
  172. - HCompl->Slice[Z]*z)/HCompl->Slice[T];
  173. Exit_Value = HCompl->Exit_Value;
  174. for (i = 1; i <= HCompl->n; ++i)
  175. {
  176. yz = y * y + z * z;
  177. xw = x * x + w * w;
  178. if ((xw + yz) > Exit_Value)
  179. {
  180. return (FALSE);
  181. }
  182. Sx[i] = xw - yz + HCompl->Julia_Parm[X];
  183. Sy[i] = 2.0 * (x * y - z * w) + HCompl->Julia_Parm[Y];
  184. Sz[i] = 2.0 * (x * z - w * y) + HCompl->Julia_Parm[Z];
  185. Sw[i] = 2.0 * (x * w + y * z) + HCompl->Julia_Parm[T];
  186. w = Sw[i];
  187. x = Sx[i];
  188. z = Sz[i];
  189. y = Sy[i];
  190. }
  191. return (TRUE);
  192. }
  193. /*****************************************************************************
  194. *
  195. * FUNCTION
  196. *
  197. * INPUT
  198. *
  199. * OUTPUT
  200. *
  201. * RETURNS
  202. *
  203. * AUTHOR
  204. *
  205. * Pascal Massimino
  206. *
  207. * DESCRIPTION
  208. *
  209. * CHANGES
  210. *
  211. ******************************************************************************/
  212. int D_Iteration_HCompl(VECTOR IPoint, FRACTAL *HCompl, DBL *Dist)
  213. {
  214. int i;
  215. DBL yz, xw;
  216. DBL Exit_Value, F_Value, Step;
  217. DBL x, y, z, w;
  218. VECTOR H_Normal;
  219. x = Sx[0] = IPoint[X];
  220. y = Sy[0] = IPoint[Y];
  221. z = Sz[0] = IPoint[Z];
  222. w = Sw[0] = (HCompl->SliceDist
  223. - HCompl->Slice[X]*x
  224. - HCompl->Slice[Y]*y
  225. - HCompl->Slice[Z]*z)/HCompl->Slice[T];
  226. Exit_Value = HCompl->Exit_Value;
  227. for (i = 1; i <= HCompl->n; ++i)
  228. {
  229. yz = y * y + z * z;
  230. xw = x * x + w * w;
  231. if ((F_Value = xw + yz) > Exit_Value)
  232. {
  233. Normal_Calc_HCompl(H_Normal, i - 1, HCompl);
  234. VDot(Step, H_Normal, Direction);
  235. if (Step < -Fractal_Tolerance)
  236. {
  237. Step = -2.0 * Step;
  238. if ((F_Value > Precision * Step) && (F_Value < 30 * Precision * Step))
  239. {
  240. *Dist = F_Value / Step;
  241. return (FALSE);
  242. }
  243. }
  244. *Dist = Precision;
  245. return (FALSE);
  246. }
  247. Sx[i] = xw - yz + HCompl->Julia_Parm[X];
  248. Sy[i] = 2.0 * (x * y - z * w) + HCompl->Julia_Parm[Y];
  249. Sz[i] = 2.0 * (x * z - w * y) + HCompl->Julia_Parm[Z];
  250. Sw[i] = 2.0 * (x * w + y * z) + HCompl->Julia_Parm[T];
  251. w = Sw[i];
  252. x = Sx[i];
  253. z = Sz[i];
  254. y = Sy[i];
  255. }
  256. *Dist = Precision;
  257. return (TRUE);
  258. }
  259. /*****************************************************************************
  260. *
  261. * FUNCTION
  262. *
  263. * INPUT
  264. *
  265. * OUTPUT
  266. *
  267. * RETURNS
  268. *
  269. * AUTHOR
  270. *
  271. * Pascal Massimino
  272. *
  273. * DESCRIPTION
  274. *
  275. * CHANGES
  276. *
  277. ******************************************************************************/
  278. void Normal_Calc_HCompl(VECTOR Result, int N_Max, FRACTAL *fractal)
  279. {
  280. DBL n1, n2, n3, n4;
  281. int i;
  282. DBL x, y, z, w;
  283. DBL xx, yy, zz, ww;
  284. DBL Pow;
  285. /*
  286. * Algebraic properties of hypercomplexes allows simplifications in
  287. * computations...
  288. */
  289. x = Sx[0];
  290. y = Sy[0];
  291. z = Sz[0];
  292. w = Sw[0];
  293. Pow = 2.0;
  294. for (i = 1; i < N_Max; ++i)
  295. {
  296. /*
  297. * For a map z->f(z), f depending on c, one must perform here :
  298. *
  299. * (x,y,z,w) * df/dz(Sx[i],Sy[i],Sz[i],Sw[i]) -> (x,y,z,w) ,
  300. *
  301. * up to a constant.
  302. */
  303. /******************* Case z->z^2+c *****************/
  304. /* the df/dz part needs no work */
  305. HMult(xx, yy, zz, ww, Sx[i], Sy[i], Sz[i], Sw[i], x, y, z, w);
  306. w = ww;
  307. z = zz;
  308. y = yy;
  309. x = xx;
  310. Pow *= 2.0;
  311. }
  312. n1 = Sx[N_Max] * Pow;
  313. n2 = Sy[N_Max] * Pow;
  314. n3 = Sz[N_Max] * Pow;
  315. n4 = Sw[N_Max] * Pow;
  316. Result[X] = x * n1 + y * n2 + z * n3 + w * n4;
  317. Result[Y] = -y * n1 + x * n2 - w * n3 + z * n4;
  318. Result[Z] = -z * n1 - w * n2 + x * n3 + y * n4;
  319. }
  320. /*****************************************************************************
  321. *
  322. * FUNCTION
  323. *
  324. * INPUT
  325. *
  326. * OUTPUT
  327. *
  328. * RETURNS
  329. *
  330. * AUTHOR
  331. *
  332. * Pascal Massimino
  333. *
  334. * DESCRIPTION
  335. *
  336. * CHANGES
  337. *
  338. ******************************************************************************/
  339. int F_Bound_HCompl(RAY *Ray, FRACTAL *Fractal, DBL *Depth_Min, DBL *Depth_Max)
  340. {
  341. return (Intersect_Sphere(Ray, Fractal->Center, Fractal->Radius_Squared, Depth_Min, Depth_Max));
  342. }
  343. /****************************************************************/
  344. /*--------------------------- z3 -------------------------------*/
  345. /****************************************************************/
  346. /*****************************************************************************
  347. *
  348. * FUNCTION
  349. *
  350. * INPUT
  351. *
  352. * OUTPUT
  353. *
  354. * RETURNS
  355. *
  356. * AUTHOR
  357. *
  358. * Pascal Massimino
  359. *
  360. * DESCRIPTION
  361. *
  362. * CHANGES
  363. *
  364. ******************************************************************************/
  365. int Iteration_HCompl_z3(VECTOR IPoint, FRACTAL *HCompl)
  366. {
  367. int i;
  368. DBL Norm, xx, yy, zz, ww;
  369. DBL Exit_Value;
  370. DBL x, y, z, w;
  371. x = Sx[0] = IPoint[X];
  372. y = Sy[0] = IPoint[Y];
  373. z = Sz[0] = IPoint[Z];
  374. w = Sw[0] = (HCompl->SliceDist
  375. - HCompl->Slice[X]*x
  376. - HCompl->Slice[Y]*y
  377. - HCompl->Slice[Z]*z)/HCompl->Slice[T];
  378. Exit_Value = HCompl->Exit_Value;
  379. for (i = 1; i <= HCompl->n; ++i)
  380. {
  381. Norm = x * x + y * y + z * z + w * w;
  382. /* is this test correct ? */
  383. if (Norm > Exit_Value)
  384. {
  385. return (FALSE);
  386. }
  387. /*************** Case: z->z^2+c *********************/
  388. HSqr(xx, yy, zz, ww, x, y, z, w);
  389. x = Sx[i] = xx + HCompl->Julia_Parm[X];
  390. y = Sy[i] = yy + HCompl->Julia_Parm[Y];
  391. z = Sz[i] = zz + HCompl->Julia_Parm[Z];
  392. w = Sw[i] = ww + HCompl->Julia_Parm[T];
  393. }
  394. return (TRUE);
  395. }
  396. /*****************************************************************************
  397. *
  398. * FUNCTION
  399. *
  400. * INPUT
  401. *
  402. * OUTPUT
  403. *
  404. * RETURNS
  405. *
  406. * AUTHOR
  407. *
  408. * Pascal Massimino
  409. *
  410. * DESCRIPTION
  411. *
  412. * CHANGES
  413. *
  414. ******************************************************************************/
  415. int D_Iteration_HCompl_z3(VECTOR IPoint, FRACTAL *HCompl, DBL *Dist)
  416. {
  417. int i;
  418. DBL xx, yy, zz, ww;
  419. DBL Exit_Value, F_Value, Step;
  420. DBL x, y, z, w;
  421. VECTOR H_Normal;
  422. x = Sx[0] = IPoint[X];
  423. y = Sy[0] = IPoint[Y];
  424. z = Sz[0] = IPoint[Z];
  425. w = Sw[0] = (HCompl->SliceDist
  426. - HCompl->Slice[X]*x
  427. - HCompl->Slice[Y]*y
  428. - HCompl->Slice[Z]*z)/HCompl->Slice[T];
  429. Exit_Value = HCompl->Exit_Value;
  430. for (i = 1; i <= HCompl->n; ++i)
  431. {
  432. F_Value = x * x + y * y + z * z + w * w;
  433. if (F_Value > Exit_Value)
  434. {
  435. Normal_Calc_HCompl_z3(H_Normal, i - 1, HCompl);
  436. VDot(Step, H_Normal, Direction);
  437. if (Step < -Fractal_Tolerance)
  438. {
  439. Step = -2.0 * Step;
  440. if ((F_Value > Precision * Step) && (F_Value < 30 * Precision * Step))
  441. {
  442. *Dist = F_Value / Step;
  443. return (FALSE);
  444. }
  445. }
  446. *Dist = Precision;
  447. return (FALSE);
  448. }
  449. /*************** Case: z->z^2+c *********************/
  450. HSqr(xx, yy, zz, ww, x, y, z, w);
  451. x = Sx[i] = xx + HCompl->Julia_Parm[X];
  452. y = Sy[i] = yy + HCompl->Julia_Parm[Y];
  453. z = Sz[i] = zz + HCompl->Julia_Parm[Z];
  454. w = Sw[i] = ww + HCompl->Julia_Parm[T];
  455. }
  456. *Dist = Precision;
  457. return (TRUE);
  458. }
  459. /*****************************************************************************
  460. *
  461. * FUNCTION
  462. *
  463. * INPUT
  464. *
  465. * OUTPUT
  466. *
  467. * RETURNS
  468. *
  469. * AUTHOR
  470. *
  471. * Pascal Massimino
  472. *
  473. * DESCRIPTION
  474. *
  475. * CHANGES
  476. *
  477. ******************************************************************************/
  478. void Normal_Calc_HCompl_z3(VECTOR Result, int N_Max, FRACTAL *fractal)
  479. {
  480. DBL n1, n2, n3, n4;
  481. int i;
  482. DBL x, y, z, w;
  483. DBL xx, yy, zz, ww;
  484. /*
  485. * Algebraic properties of hypercomplexes allows simplifications in
  486. * computations...
  487. */
  488. x = Sx[0];
  489. y = Sy[0];
  490. z = Sz[0];
  491. w = Sw[0];
  492. for (i = 1; i < N_Max; ++i)
  493. {
  494. /*
  495. * For a map z->f(z), f depending on c, one must perform here :
  496. *
  497. * (x,y,z,w) * df/dz(Sx[i],Sy[i],Sz[i],Sw[i]) -> (x,y,z,w) ,
  498. *
  499. * up to a constant.
  500. */
  501. /******************* Case z->z^2+c *****************/
  502. /* the df/dz part needs no work */
  503. HMult(xx, yy, zz, ww, Sx[i], Sy[i], Sz[i], Sw[i], x, y, z, w);
  504. x = xx;
  505. y = yy;
  506. z = zz;
  507. w = ww;
  508. }
  509. n1 = Sx[N_Max];
  510. n2 = Sy[N_Max];
  511. n3 = Sz[N_Max];
  512. n4 = Sw[N_Max];
  513. Result[X] = x * n1 + y * n2 + z * n3 + w * n4;
  514. Result[Y] = -y * n1 + x * n2 - w * n3 + z * n4;
  515. Result[Z] = -z * n1 - w * n2 + x * n3 + y * n4;
  516. }
  517. /*****************************************************************************
  518. *
  519. * FUNCTION
  520. *
  521. * INPUT
  522. *
  523. * OUTPUT
  524. *
  525. * RETURNS
  526. *
  527. * AUTHOR
  528. *
  529. * Pascal Massimino
  530. *
  531. * DESCRIPTION
  532. *
  533. * CHANGES
  534. *
  535. ******************************************************************************/
  536. int F_Bound_HCompl_z3(RAY *Ray, FRACTAL *Fractal, DBL *Depth_Min, DBL *Depth_Max)
  537. {
  538. return F_Bound_HCompl(Ray, Fractal, Depth_Min, Depth_Max);
  539. }
  540. /*--------------------------- Inv -------------------------------*/
  541. /*****************************************************************************
  542. *
  543. * FUNCTION
  544. *
  545. * INPUT
  546. *
  547. * OUTPUT
  548. *
  549. * RETURNS
  550. *
  551. * AUTHOR
  552. *
  553. * Pascal Massimino
  554. *
  555. * DESCRIPTION
  556. *
  557. * CHANGES
  558. *
  559. ******************************************************************************/
  560. int Iteration_HCompl_Reciprocal(VECTOR IPoint, FRACTAL *HCompl)
  561. {
  562. int i;
  563. DBL Norm, xx, yy, zz, ww;
  564. DBL Exit_Value;
  565. DBL x, y, z, w;
  566. x = Sx[0] = IPoint[X];
  567. y = Sy[0] = IPoint[Y];
  568. z = Sz[0] = IPoint[Z];
  569. w = Sw[0] = (HCompl->SliceDist
  570. - HCompl->Slice[X]*x
  571. - HCompl->Slice[Y]*y
  572. - HCompl->Slice[Z]*z)/HCompl->Slice[T];
  573. Exit_Value = HCompl->Exit_Value;
  574. for (i = 1; i <= HCompl->n; ++i)
  575. {
  576. Norm = x * x + y * y + z * z + w * w;
  577. if (Norm > Exit_Value)
  578. {
  579. return (FALSE);
  580. }
  581. HReciprocal(&xx, &yy, &zz, &ww, x, y, z, w);
  582. x = Sx[i] = xx + HCompl->Julia_Parm[X];
  583. y = Sy[i] = yy + HCompl->Julia_Parm[Y];
  584. z = Sz[i] = zz + HCompl->Julia_Parm[Z];
  585. w = Sw[i] = ww + HCompl->Julia_Parm[T];
  586. }
  587. return (TRUE);
  588. }
  589. /*****************************************************************************
  590. *
  591. * FUNCTION
  592. *
  593. * INPUT
  594. *
  595. * OUTPUT
  596. *
  597. * RETURNS
  598. *
  599. * AUTHOR
  600. *
  601. * Pascal Massimino
  602. *
  603. * DESCRIPTION
  604. *
  605. * CHANGES
  606. *
  607. ******************************************************************************/
  608. int D_Iteration_HCompl_Reciprocal(VECTOR IPoint, FRACTAL *HCompl, DBL *Dist)
  609. {
  610. int i;
  611. DBL xx, yy, zz, ww;
  612. DBL Exit_Value, F_Value, Step;
  613. DBL x, y, z, w;
  614. VECTOR H_Normal;
  615. x = Sx[0] = IPoint[X];
  616. y = Sy[0] = IPoint[Y];
  617. z = Sz[0] = IPoint[Z];
  618. w = Sw[0] = (HCompl->SliceDist
  619. - HCompl->Slice[X]*x
  620. - HCompl->Slice[Y]*y
  621. - HCompl->Slice[Z]*z)/HCompl->Slice[T];
  622. Exit_Value = HCompl->Exit_Value;
  623. for (i = 1; i <= HCompl->n; ++i)
  624. {
  625. F_Value = x * x + y * y + z * z + w * w;
  626. if (F_Value > Exit_Value)
  627. {
  628. Normal_Calc_HCompl_Reciprocal(H_Normal, i - 1, HCompl);
  629. VDot(Step, H_Normal, Direction);
  630. if (Step < -Fractal_Tolerance)
  631. {
  632. Step = -2.0 * Step;
  633. if ((F_Value > Precision * Step) && F_Value < (30 * Precision * Step))
  634. {
  635. *Dist = F_Value / Step;
  636. return (FALSE);
  637. }
  638. }
  639. *Dist = Precision;
  640. return (FALSE);
  641. }
  642. HReciprocal(&xx, &yy, &zz, &ww, x, y, z, w);
  643. x = Sx[i] = xx + HCompl->Julia_Parm[X];
  644. y = Sy[i] = yy + HCompl->Julia_Parm[Y];
  645. z = Sz[i] = zz + HCompl->Julia_Parm[Z];
  646. w = Sw[i] = ww + HCompl->Julia_Parm[T];
  647. }
  648. *Dist = Precision;
  649. return (TRUE);
  650. }
  651. /*****************************************************************************
  652. *
  653. * FUNCTION
  654. *
  655. * INPUT
  656. *
  657. * OUTPUT
  658. *
  659. * RETURNS
  660. *
  661. * AUTHOR
  662. *
  663. * Pascal Massimino
  664. *
  665. * DESCRIPTION
  666. *
  667. * CHANGES
  668. *
  669. ******************************************************************************/
  670. void Normal_Calc_HCompl_Reciprocal(VECTOR Result, int N_Max, FRACTAL *fractal)
  671. {
  672. DBL n1, n2, n3, n4;
  673. int i;
  674. DBL x, y, z, w;
  675. DBL xx, yy, zz, ww;
  676. DBL xxx, yyy, zzz, www;
  677. /*
  678. * Algebraic properties of hypercomplexes allows simplifications in
  679. * computations...
  680. */
  681. x = Sx[0];
  682. y = Sy[0];
  683. z = Sz[0];
  684. w = Sw[0];
  685. for (i = 1; i < N_Max; ++i)
  686. {
  687. /******************* Case: z->1/z+c *****************/
  688. HReciprocal(&xx, &yy, &zz, &ww, Sx[i], Sy[i], Sz[i], Sw[i]);
  689. HSqr(xxx, yyy, zzz, www, xx, yy, zz, ww);
  690. HMult(xx, yy, zz, ww, x, y, z, w, -xxx, -yyy, -zzz, -www);
  691. x = xx;
  692. y = yy;
  693. z = zz;
  694. w = ww;
  695. }
  696. n1 = Sx[N_Max];
  697. n2 = Sy[N_Max];
  698. n3 = Sz[N_Max];
  699. n4 = Sw[N_Max];
  700. Result[X] = x * n1 + y * n2 + z * n3 + w * n4;
  701. Result[Y] = -y * n1 + x * n2 - w * n3 + z * n4;
  702. Result[Z] = -z * n1 - w * n2 + x * n3 + y * n4;
  703. }
  704. /*****************************************************************************
  705. *
  706. * FUNCTION
  707. *
  708. * INPUT
  709. *
  710. * OUTPUT
  711. *
  712. * RETURNS
  713. *
  714. * AUTHOR
  715. *
  716. * Pascal Massimino
  717. *
  718. * DESCRIPTION
  719. *
  720. * CHANGES
  721. *
  722. ******************************************************************************/
  723. int F_Bound_HCompl_Reciprocal(RAY *Ray, FRACTAL *Fractal, DBL *Depth_Min, DBL *Depth_Max)
  724. {
  725. return F_Bound_HCompl(Ray, Fractal, Depth_Min, Depth_Max);
  726. }
  727. /*--------------------------- Func -------------------------------*/
  728. /*****************************************************************************
  729. *
  730. * FUNCTION
  731. *
  732. * INPUT
  733. *
  734. * OUTPUT
  735. *
  736. * RETURNS
  737. *
  738. * AUTHOR
  739. *
  740. * Pascal Massimino
  741. *
  742. * DESCRIPTION
  743. *
  744. * CHANGES
  745. *
  746. ******************************************************************************/
  747. int Iteration_HCompl_Func(VECTOR IPoint, FRACTAL *HCompl)
  748. {
  749. int i;
  750. DBL Norm, xx, yy, zz, ww;
  751. DBL Exit_Value;
  752. DBL x, y, z, w;
  753. x = Sx[0] = IPoint[X];
  754. y = Sy[0] = IPoint[Y];
  755. z = Sz[0] = IPoint[Y];
  756. w = Sw[0] = (HCompl->SliceDist
  757. - HCompl->Slice[X]*x
  758. - HCompl->Slice[Y]*y
  759. - HCompl->Slice[Z]*z)/HCompl->Slice[T];
  760. Exit_Value = HCompl->Exit_Value;
  761. for (i = 1; i <= HCompl->n; ++i)
  762. {
  763. Norm = x * x + y * y + z * z + w * w;
  764. if (Norm > Exit_Value)
  765. {
  766. return (FALSE);
  767. }
  768. HFunc(&xx, &yy, &zz, &ww, x, y, z, w, HCompl);
  769. x = Sx[i] = xx + HCompl->Julia_Parm[X];
  770. y = Sy[i] = yy + HCompl->Julia_Parm[Y];
  771. z = Sz[i] = zz + HCompl->Julia_Parm[Z];
  772. w = Sw[i] = ww + HCompl->Julia_Parm[T];
  773. }
  774. return (TRUE);
  775. }
  776. /*****************************************************************************
  777. *
  778. * FUNCTION
  779. *
  780. * INPUT
  781. *
  782. * OUTPUT
  783. *
  784. * RETURNS
  785. *
  786. * AUTHOR
  787. *
  788. * Pascal Massimino
  789. *
  790. * DESCRIPTION
  791. *
  792. * CHANGES
  793. *
  794. ******************************************************************************/
  795. int D_Iteration_HCompl_Func(VECTOR IPoint, FRACTAL *HCompl, DBL *Dist)
  796. {
  797. int i;
  798. DBL xx, yy, zz, ww;
  799. DBL Exit_Value, F_Value, Step;
  800. DBL x, y, z, w;
  801. VECTOR H_Normal;
  802. x = Sx[0] = IPoint[X];
  803. y = Sy[0] = IPoint[Y];
  804. z = Sz[0] = IPoint[Z];
  805. w = Sw[0] = (HCompl->SliceDist
  806. - HCompl->Slice[X]*x
  807. - HCompl->Slice[Y]*y
  808. - HCompl->Slice[Z]*z)/HCompl->Slice[T];
  809. Exit_Value = HCompl->Exit_Value;
  810. for (i = 1; i <= HCompl->n; ++i)
  811. {
  812. F_Value = x * x + y * y + z * z + w * w;
  813. if (F_Value > Exit_Value)
  814. {
  815. Normal_Calc_HCompl_Func(H_Normal, i - 1, HCompl);
  816. VDot(Step, H_Normal, Direction);
  817. if (Step < -Fractal_Tolerance)
  818. {
  819. Step = -2.0 * Step;
  820. if ((F_Value > Precision * Step) && F_Value < (30 * Precision * Step))
  821. {
  822. *Dist = F_Value / Step;
  823. return (FALSE);
  824. }
  825. }
  826. *Dist = Precision;
  827. return (FALSE);
  828. }
  829. HFunc(&xx, &yy, &zz, &ww, x, y, z, w, HCompl);
  830. x = Sx[i] = xx + HCompl->Julia_Parm[X];
  831. y = Sy[i] = yy + HCompl->Julia_Parm[Y];
  832. z = Sz[i] = zz + HCompl->Julia_Parm[Z];
  833. w = Sw[i] = ww + HCompl->Julia_Parm[T];
  834. }
  835. *Dist = Precision;
  836. return (TRUE);
  837. }
  838. /*****************************************************************************
  839. *
  840. * FUNCTION
  841. *
  842. * INPUT
  843. *
  844. * OUTPUT
  845. *
  846. * RETURNS
  847. *
  848. * AUTHOR
  849. *
  850. * Pascal Massimino
  851. *
  852. * DESCRIPTION
  853. *
  854. * CHANGES
  855. *
  856. ******************************************************************************/
  857. void Normal_Calc_HCompl_Func(VECTOR Result, int N_Max, FRACTAL *fractal)
  858. {
  859. DBL n1, n2, n3, n4;
  860. int i;
  861. DBL x, y, z, w;
  862. DBL xx, yy, zz, ww;
  863. DBL xxx, yyy, zzz, www;
  864. /*
  865. * Algebraic properties of hypercomplexes allows simplifications in
  866. * computations...
  867. */
  868. x = Sx[0];
  869. y = Sy[0];
  870. z = Sz[0];
  871. w = Sw[0];
  872. for (i = 1; i < N_Max; ++i)
  873. {
  874. /**************** Case: z-> f(z)+c ************************/
  875. HFunc(&xx, &yy, &zz, &ww, Sx[i], Sy[i], Sz[i], Sw[i], fractal);
  876. HMult(xxx, yyy, zzz, www, xx, yy, zz, ww, x, y, z, w);
  877. x = xxx;
  878. y = yyy;
  879. z = zzz;
  880. w = www;
  881. }
  882. n1 = Sx[N_Max];
  883. n2 = Sy[N_Max];
  884. n3 = Sz[N_Max];
  885. n4 = Sw[N_Max];
  886. Result[X] = x * n1 + y * n2 + z * n3 + w * n4;
  887. Result[Y] = -y * n1 + x * n2 - w * n3 + z * n4;
  888. Result[Z] = -z * n1 - w * n2 + x * n3 + y * n4;
  889. }
  890. /*****************************************************************************
  891. *
  892. * FUNCTION
  893. *
  894. * INPUT
  895. *
  896. * OUTPUT
  897. *
  898. * RETURNS
  899. *
  900. * AUTHOR
  901. *
  902. * Pascal Massimino
  903. *
  904. * DESCRIPTION
  905. *
  906. * CHANGES
  907. *
  908. ******************************************************************************/
  909. int F_Bound_HCompl_Func(RAY *Ray, FRACTAL *Fractal, DBL *Depth_Min, DBL *Depth_Max)
  910. {
  911. return F_Bound_HCompl(Ray, Fractal, Depth_Min, Depth_Max);
  912. }
  913. /*****************************************************************************
  914. *
  915. * FUNCTION Complex transcental functions
  916. *
  917. * INPUT pointer to source complex number
  918. *
  919. * OUTPUT fn(input)
  920. *
  921. * RETURNS void
  922. *
  923. * AUTHOR
  924. *
  925. * Tim Wegner
  926. *
  927. * DESCRIPTION Calculate common functions on complexes
  928. * Since our purpose is fractals, error checking is lax.
  929. *
  930. * CHANGES
  931. *
  932. ******************************************************************************/
  933. void Complex_Mult (CMPLX *target, CMPLX *source1, CMPLX *source2)
  934. {
  935. DBL tmpx;
  936. tmpx = source1->x * source2->x - source1->y * source2->y;
  937. target->y = source1->x * source2->y + source1->y * source2->x;
  938. target->x = tmpx;
  939. }
  940. void Complex_Div (CMPLX *target, CMPLX *source1, CMPLX *source2)
  941. {
  942. DBL mod,tmpx,yxmod,yymod;
  943. mod = Sqr(source2->x) + Sqr(source2->y);
  944. if (mod==0)
  945. return;
  946. yxmod = source2->x/mod;
  947. yymod = - source2->y/mod;
  948. tmpx = source1->x * yxmod - source1->y * yymod;
  949. target->y = source1->x * yymod + source1->y * yxmod;
  950. target->x = tmpx;
  951. } /* End Complex_Mult() */
  952. void Complex_Exp (CMPLX *target, CMPLX *source)
  953. {
  954. DBL expx;
  955. expx = exp(source->x);
  956. target->x = expx * cos(source->y);
  957. target->y = expx * sin(source->y);
  958. } /* End Complex_Exp() */
  959. void Complex_Sin (CMPLX *target, CMPLX *source)
  960. {
  961. target->x = sin(source->x) * cosh(source->y);
  962. target->y = cos(source->x) * sinh(source->y);
  963. } /* End Complex_Sin() */
  964. void Complex_Sinh (CMPLX *target, CMPLX *source)
  965. {
  966. target->x = sinh(source->x) * cos(source->y);
  967. target->y = cosh(source->x) * sin(source->y);
  968. } /* End Complex_Sinh() */
  969. void Complex_Cos (CMPLX *target, CMPLX *source)
  970. {
  971. target->x = cos(source->x) * cosh(source->y);
  972. target->y = -sin(source->x) * sinh(source->y);
  973. } /* End Complex_Cos() */
  974. void Complex_Cosh (CMPLX *target, CMPLX *source)
  975. {
  976. target->x = cosh(source->x) * cos(source->y);
  977. target->y = sinh(source->x) * sin(source->y);
  978. } /* End Complex_Cosh() */
  979. void Complex_Log (CMPLX *target, CMPLX *source)
  980. {
  981. DBL mod,zx,zy;
  982. mod = sqrt(source->x * source->x + source->y * source->y);
  983. zx = log(mod);
  984. zy = atan2(source->y,source->x);
  985. target->x = zx;
  986. target->y = zy;
  987. } /* End Complex_Log() */
  988. void Complex_Sqrt(CMPLX *target, CMPLX *source)
  989. {
  990. DBL mag;
  991. DBL theta;
  992. if(source->x == 0.0 && source->y == 0.0)
  993. {
  994. target->x = target->y = 0.0;
  995. }
  996. else
  997. {
  998. mag = sqrt(sqrt(Sqr(source->x) + Sqr(source->y)));
  999. theta = atan2(source->y, source->x) / 2;
  1000. target->y = mag * sin(theta);
  1001. target->x = mag * cos(theta);
  1002. }
  1003. } /* End Complex_Sqrt() */
  1004. /* rz=Arcsin(z)=-i*Log{i*z+sqrt(1-z*z)} */
  1005. void Complex_ASin(CMPLX *target, CMPLX *source)
  1006. {
  1007. CMPLX tempz1,tempz2;
  1008. Complex_Mult(&tempz1, source, source);
  1009. tempz1.x = 1 - tempz1.x; tempz1.y = -tempz1.y;
  1010. Complex_Sqrt( &tempz1, &tempz1);
  1011. tempz2.x = -source->y; tempz2.y = source->x;
  1012. tempz1.x += tempz2.x; tempz1.y += tempz2.y;
  1013. Complex_Log( &tempz1, &tempz1);
  1014. target->x = tempz1.y; target->y = -tempz1.x;
  1015. } /* End Complex_ASin() */
  1016. void Complex_ACos(CMPLX *target, CMPLX *source)
  1017. {
  1018. CMPLX temp;
  1019. Complex_Mult(&temp, source, source);
  1020. temp.x -= 1;
  1021. Complex_Sqrt(&temp, &temp);
  1022. temp.x += source->x; temp.y += source->y;
  1023. Complex_Log(&temp, &temp);
  1024. target->x = temp.y; target->y = -temp.x;
  1025. } /* End Complex_ACos() */
  1026. void Complex_ASinh(CMPLX *target, CMPLX *source)
  1027. {
  1028. CMPLX temp;
  1029. Complex_Mult (&temp, source, source);
  1030. temp.x += 1;
  1031. Complex_Sqrt (&temp, &temp);
  1032. temp.x += source->x; temp.y += source->y;
  1033. Complex_Log(target, &temp);
  1034. } /* End Complex_ASinh */
  1035. /* rz=Arccosh(z)=Log(z+sqrt(z*z-1)} */
  1036. void Complex_ACosh (CMPLX *target, CMPLX *source)
  1037. {
  1038. CMPLX tempz;
  1039. Complex_Mult(&tempz, source, source);
  1040. tempz.x -= 1;
  1041. Complex_Sqrt (&tempz, &tempz);
  1042. tempz.x = source->x + tempz.x; tempz.y = source->y + tempz.y;
  1043. Complex_Log (target, &tempz);
  1044. } /* End Complex_ACosh() */
  1045. /* rz=Arctanh(z)=1/2*Log{(1+z)/(1-z)} */
  1046. void Complex_ATanh(CMPLX *target, CMPLX *source)
  1047. {
  1048. CMPLX temp0,temp1,temp2;
  1049. if( source->x == 0.0)
  1050. {
  1051. target->x = 0;
  1052. target->y = atan( source->y);
  1053. return;
  1054. }
  1055. else
  1056. {
  1057. if( fabs(source->x) == 1.0 && source->y == 0.0)
  1058. {
  1059. return;
  1060. }
  1061. else if( fabs( source->x) < 1.0 && source->y == 0.0)
  1062. {
  1063. target->x = log((1+source->x)/(1-source->x))/2;
  1064. target->y = 0;
  1065. return;
  1066. }
  1067. else
  1068. {
  1069. temp0.x = 1 + source->x; temp0.y = source->y;
  1070. temp1.x = 1 - source->x; temp1.y = -source->y;
  1071. Complex_Div(&temp2, &temp0, &temp1);
  1072. Complex_Log(&temp2, &temp2);
  1073. target->x = .5 * temp2.x; target->y = .5 * temp2.y;
  1074. return;
  1075. }
  1076. }
  1077. } /* End Complex_ATanh() */
  1078. /* rz=Arctan(z)=i/2*Log{(1-i*z)/(1+i*z)} */
  1079. void Complex_ATan(CMPLX *target, CMPLX *source)
  1080. {
  1081. CMPLX temp0,temp1,temp2,temp3;
  1082. if( source->x == 0.0 && source->y == 0.0)
  1083. target->x = target->y = 0;
  1084. else if( source->x != 0.0 && source->y == 0.0){
  1085. target->x = atan(source->x);
  1086. target->y = 0;
  1087. }
  1088. else if( source->x == 0.0 && source->y != 0.0){
  1089. temp0.x = source->y; temp0.y = 0.0;
  1090. Complex_ATanh(&temp0, &temp0);
  1091. target->x = -temp0.y; target->y = temp0.x;
  1092. }
  1093. else if( source->x != 0.0 && source->y != 0.0)
  1094. {
  1095. temp0.x = -source->y; temp0.y = source->x;
  1096. temp1.x = 1 - temp0.x; temp1.y = -temp0.y;
  1097. temp2.x = 1 + temp0.x; temp2.y = temp0.y;
  1098. Complex_Div(&temp3, &temp1, &temp2);
  1099. Complex_Log(&temp3, &temp3);
  1100. target->x = -temp3.y * .5; target->y = .5 * temp3.x;
  1101. }
  1102. } /* End Complex_ATanz() */
  1103. void Complex_Tan(CMPLX *target, CMPLX *source)
  1104. {
  1105. DBL x, y, sinx, cosx, sinhy, coshy, denom;
  1106. x = 2 * source->x;
  1107. y = 2 * source->y;
  1108. sinx = sin(x); cosx = cos(x);
  1109. sinhy = sinh(y); coshy = cosh(y);
  1110. denom = cosx + coshy;
  1111. if(denom == 0)
  1112. return;
  1113. target->x = sinx/denom;
  1114. target->y = sinhy/denom;
  1115. } /* End Complex_Tan() */
  1116. void Complex_Tanh(CMPLX *target, CMPLX *source)
  1117. {
  1118. DBL x, y, siny, cosy, sinhx, coshx, denom;
  1119. x = 2 * source->x;
  1120. y = 2 * source->y;
  1121. siny = sin(y); cosy = cos(y);
  1122. sinhx = sinh(x); coshx = cosh(x);
  1123. denom = coshx + cosy;
  1124. if(denom == 0)
  1125. return;
  1126. target->x = sinhx/denom;
  1127. target->y = siny/denom;
  1128. } /* End Complex_Tanh() */
  1129. void Complex_Power (CMPLX *target, CMPLX *source1, CMPLX *source2)
  1130. {
  1131. CMPLX cLog, t;
  1132. DBL e2x;
  1133. if(source1->x == 0 && source1->y == 0)
  1134. {
  1135. target->x = target->y = 0.0;
  1136. return;
  1137. }
  1138. Complex_Log (&cLog, source1);
  1139. Complex_Mult (&t, &cLog, source2);
  1140. if(t.x < -690)
  1141. e2x = 0;
  1142. else
  1143. e2x = exp(t.x);
  1144. target->x = e2x * cos(t.y);
  1145. target->y = e2x * sin(t.y);
  1146. }
  1147. #if 1
  1148. void Complex_Pwr (CMPLX *target, CMPLX *source)
  1149. {
  1150. Complex_Power(target, source, &exponent);
  1151. }
  1152. #else
  1153. void Complex_Pwr (CMPLX *target, CMPLX *source)
  1154. {
  1155. /* the sqr dunction for testing */
  1156. Complex_Mult(target, source, source);
  1157. }
  1158. #endif