update for new variable-precision
[ruff:ruff.git] / Fractal / Mandelbrot / RayTraceForward4.hs
1 {-# LANGUAGE FlexibleContexts, Rank2Types #-}
2 {- |
3 Module      :  Fractal.Mandelbrot.RayTraceForward4
4 Copyright   :  (c) Claude Heiland-Allen 2012
5 License     :  BSD3
6
7 Maintainer  :  claudiusmaximus@goto10.org
8 Stability   :  unstable
9 Portability :  Rank2Types
10
11 Tracing four external rays simultaneously (one pair landing at the root
12 and the other at the 1/2 bond point) can be used to locate a particular
13 hyperbolic component.
14
15 Example:
16
17 > main :: IO ()
18 > main = do
19 >   let callback = RayTraceForward4Callback $ \continue zs@(z1, z2, z3, z4) ->
20 >          show zs : rayTraceForward4 continue callback
21 >       ray angle = rayTraceForward4 (rayTraceForwardStart4 (ol, oh, il, ih)) callback
22 >         where Just o@(ExternalAnglePair ol oh) = externalAngles =<< angledInternalAddress angle
23 >               ExternalAnglePair il ih = tunePair h o
24 >               h = ExternalAnglePair (1/3) (2/3)
25 >   putStrLn . unlines . take 256 . ray $ 1/71
26
27 -}
28 module Fractal.Mandelbrot.RayTraceForward4
29   ( RayTraceForward4Callback(RayTraceForward4Callback)
30   , RayTraceForward4(rayTraceForward4)
31   , rayTraceForwardStart4
32   ) where
33
34 import Numeric.VariablePrecision
35   ( NaturalNumber
36   , VComplex
37   )
38
39 import Fractal.Mandelbrot.ExternalAngle (ExternalAngle)
40 import Fractal.Mandelbrot.RayTraceForward (RayTraceForwardCallback(RayTraceForwardCallback), RayTraceForward(rayTraceForward), rayTraceForwardStart)
41
42 -- | For each four points on the rays, a callback gets passed the current
43 --   coordinates and aspect ratio, along with a continuation that can be
44 --   used to get more points.  The coordinates are all upconverted to the
45 --   same precision for convenience.
46 data RayTraceForward4Callback a =
47   RayTraceForward4Callback
48   { rayTraceForward4Callback
49       :: (NaturalNumber p, NaturalNumber q, NaturalNumber s, NaturalNumber t)
50       => RayTraceForward4 a
51       -> (VComplex p, VComplex q, VComplex s, VComplex t)
52       -> a
53   }
54
55 -- | Step along the four rays by one point each, calling the callback.
56 data RayTraceForward4  a =
57   RayTraceForward4
58   { rayTraceForward4  :: RayTraceForward4Callback a -> a }
59
60 -- | Initialize ray tracing for an quadruple of external angles.
61 --
62 --   Precondition:
63 --     @(ol, oh, il, ih)@ forms two ray pairs, with @(ol, oh)@ landing
64 --     at the root cusp and @(il, ih)@ landing at the 1/2 bond point
65 --     of the same hyperbolic component.
66 rayTraceForwardStart4
67   :: (ExternalAngle, ExternalAngle, ExternalAngle, ExternalAngle)
68   -> RayTraceForward4 a
69 rayTraceForwardStart4 (ol, oh, il, ih) =
70   RayTraceForward4
71   { rayTraceForward4 = rayTraceForwardStep4 
72       ( rayTraceForwardStart ol
73       , rayTraceForwardStart oh
74       , rayTraceForwardStart il
75       , rayTraceForwardStart ih
76       )
77   }
78
79 rayTraceForwardStep4
80   :: (RayTraceForward a, RayTraceForward a, RayTraceForward a, RayTraceForward a)
81   -> RayTraceForward4Callback a
82   -> a
83 rayTraceForwardStep4 (s4ol, s4oh, s4il, s4ih) callback =
84   rayTraceForward s4ol $ RayTraceForwardCallback $ \col zol _ ->
85   rayTraceForward s4oh $ RayTraceForwardCallback $ \coh zoh _ ->
86   rayTraceForward s4il $ RayTraceForwardCallback $ \cil zil _ ->
87   rayTraceForward s4ih $ RayTraceForwardCallback $ \cih zih _ ->
88   rayTraceForward4Callback callback RayTraceForward4
89     { rayTraceForward4 = rayTraceForwardStep4 (col, coh, cil, cih) }
90     (zol, zoh, zil, zih)