moonlight-planar-1.1.0.0: bench/curve/Moonlight/Planar/AuthoringBench.hs
-- | Matched attachment fixture. Admission is outside the timed action;
-- ordered world curves and every requested port are fully forced inside it.
module Moonlight.Planar.AuthoringBench (benchmarks) where
import BenchMeasure (timedProjection)
import Control.DeepSeq (force)
import Control.Exception (evaluate)
import Data.Foldable (toList, traverse_)
import Data.List.NonEmpty (NonEmpty (..))
import qualified Data.Sequence as Seq
import Moonlight.Planar.Affine
import Moonlight.Planar.Curve
import Moonlight.Planar.Exact
import Moonlight.Planar.Illustration
import Moonlight.Planar.Illustration.Motif
import Moonlight.Planar.Illustration.Layout
data Port = Root | Tip
type Observation = ([Path], [AffineIso2])
type Instance = Motif Port ()
benchmarks :: IO ()
benchmarks = do
source <- admitted (affine2 (ExactVector 2 1) (ExactVector 1 2) (ExactVector 7 (-3)))
tip <- admitted (affine2 (ExactVector 1 0) (ExactVector 1 1) (ExactVector 8 12))
targets <- traverse (admitted . target) [1 .. 4096]
inputs <- evaluate (force (source, tip, targets))
instances <- timedProjection "attachment-authoring-n4096" observe
(evaluate (assemble inputs))
let (curves, ports) = observe instances
checksum = sum (pathChecksum <$> curves) + sum (frameChecksum <$> ports)
putStrLn ("attachment-authoring-receipt: instances=4096 paths=" <> show (length curves)
<> " ports=" <> show (length ports) <> " exact-checksum=" <> show checksum)
putStrLn "attachment-authoring-contract: admitted-inputs-outside; full-world-path-and-port-NF-inside"
traverse_ (benchmarkLayout source tip) [1024,2048]
admitted :: Affine2 -> IO AffineIso2
admitted = maybe (fail "benchmark frame is singular") pure . affineIso2
target :: Integer -> Affine2
target index =
let n = fromInteger index
in affine2 (ExactVector 1 (n * exactThird)) (ExactVector 0 2) (ExactVector (25 * n) (3 * n))
assemble :: (AffineIso2, AffineIso2, [AffineIso2]) -> [Instance]
assemble (source, tip, targets) = fmap instantiate targets
where
ports :: Port -> AffineIso2
ports Root = source
ports Tip = tip
instantiate :: AffineIso2 -> Instance
instantiate destination = attachMotif Root destination (motif artwork ports)
{-# NOINLINE assemble #-}
artwork :: Picture ()
artwork = fill NonZero (Solid (RGB 80 150 110))
(ellipse (ExactVector 8 2) (ExactVector (-1) 12) :| [])
observe :: [Instance] -> Observation
observe instances =
(concatMap (worldPaths . motifPicture) instances, concatMap (\value -> fmap (motifPort value) [Root,Tip]) instances)
-- New capability costs, not comparisons with a reference envelope/layout engine.
benchmarkLayout :: AffineIso2 -> AffineIso2 -> Int -> IO ()
benchmarkLayout source tip count = do
targets <- traverse (admitted . target) [1 .. fromIntegral count]
inputs <- evaluate (force (source, tip, targets))
let instances = assemble inputs
_ <- evaluate (force (observe instances))
envelope <- timedProjection ("geometry-envelope-n" <> show count) observeEnvelope
(evaluate (foldMap (geometryEnvelope . motifPicture) instances))
putStrLn ("geometry-envelope-receipt: instances=" <> show count <> " observations=" <> show (observeEnvelope envelope))
arranged <- timedProjection ("motif-layout-n" <> show count) (observe . toList)
(evaluate (arrangeMotifs Horizontal 3 (Seq.fromList instances)))
let (curves,ports) = observe (toList arranged)
putStrLn ("motif-layout-receipt: instances=" <> show count
<> " paths=" <> show (length curves) <> " ports=" <> show (length ports)
<> " exact-checksum=" <> show (sum (pathChecksum <$> curves) + sum (frameChecksum <$> ports)))
putStrLn "envelope-layout-contract: new-capability; prepared-inputs-outside; envelope-support-or-full-world-path-and-port-NF-inside"
observeEnvelope
:: GeometryEnvelope
-> (Maybe (ExactRational, ExactRational, ExactRational, ExactRational), [Maybe ExactRational])
observeEnvelope envelope =
(fmap (\bounds -> (boundsMinimumX bounds, boundsMinimumY bounds, boundsMaximumX bounds, boundsMaximumY bounds))
(geometryBounds envelope), fmap (`geometrySupport` envelope)
[ExactVector 1 0, ExactVector 0 1, ExactVector (-1) 0, ExactVector 0 (-1), ExactVector 2 3])
worldPaths :: Picture part -> [Path]
worldPaths picture = foldPicture algebra picture identityAffine2
where
algebra :: PictureAlgebra part (Affine2 -> [Path])
algebra = PictureAlgebra
{ paintSequence = \children frame -> concatMap ($ frame) (toList children)
, paintFill = \_ _ contours frame -> [transformPath frame (path (Seq.fromList (ClosedSubpath <$> toList contours)))]
, paintStroke = \_ curve frame -> [transformPath frame curve]
, paintClip = \_ contours child frame ->
transformPath frame (path (Seq.fromList (ClosedSubpath <$> toList contours))) : child frame
, paintPlace = \placement child frame -> child (composeAffine2 frame placement)
, paintOpacity = \_ child -> child
, paintAnnotation = \_ child -> child
}
pathChecksum :: Path -> ExactRational
pathChecksum = sum . fmap subpathChecksum . toList . pathSubpaths
where
subpathChecksum :: Subpath -> ExactRational
subpathChecksum (OpenSubpath value) = trailChecksum (location value) (toList (trailSteps (locatedValue value)))
subpathChecksum (ClosedSubpath value) = trailChecksum (location value) (toList (closedTrailSteps (locatedValue value)))
trailChecksum :: ExactPoint -> [CurveStep] -> ExactRational
trailChecksum origin steps =
let (x,y) = exactPointCoordinates origin
in x + y + sum (fmap (sum . fmap vectorChecksum . toList . stepControlPoints) steps)
frameChecksum :: AffineIso2 -> ExactRational
frameChecksum frame =
let (x,y,offset) = affineColumns (affineIsoMap frame)
in vectorChecksum x + vectorChecksum y + vectorChecksum offset
vectorChecksum :: ExactVector -> ExactRational
vectorChecksum (ExactVector x y) = x + y