mirror of
https://gitlab.com/sheaf/metabrush.git
synced 2024-11-05 14:53:37 +00:00
experiment: FMA backend for interval arithmetic
also includes the start of a way to observe which equations are being solved, which should help with improving the performance of the interval Newton method
This commit is contained in:
parent
cd6b7368f8
commit
52420a1169
|
@ -29,6 +29,11 @@ flag asserts
|
||||||
default: False
|
default: False
|
||||||
manual: True
|
manual: True
|
||||||
|
|
||||||
|
flag use-fma
|
||||||
|
description: Use fused-muliply add instructions to implement interval arithmetic.
|
||||||
|
default: False
|
||||||
|
manual: True
|
||||||
|
|
||||||
common common
|
common common
|
||||||
|
|
||||||
build-depends:
|
build-depends:
|
||||||
|
@ -53,7 +58,7 @@ common common
|
||||||
, rounded-hw
|
, rounded-hw
|
||||||
^>= 0.3
|
^>= 0.3
|
||||||
, transformers
|
, transformers
|
||||||
^>= 0.5.6.2
|
>= 0.5.6.2 && < 0.7
|
||||||
|
|
||||||
default-extensions:
|
default-extensions:
|
||||||
BangPatterns
|
BangPatterns
|
||||||
|
@ -109,6 +114,14 @@ common common
|
||||||
cpp-options:
|
cpp-options:
|
||||||
-DASSERTS
|
-DASSERTS
|
||||||
|
|
||||||
|
if flag(use-fma)
|
||||||
|
cpp-options:
|
||||||
|
-DUSE_FMA
|
||||||
|
ghc-options:
|
||||||
|
-mfma
|
||||||
|
if impl(ghc < 9.7)
|
||||||
|
buildable: False
|
||||||
|
|
||||||
autogen-modules:
|
autogen-modules:
|
||||||
Paths_MetaBrush
|
Paths_MetaBrush
|
||||||
|
|
||||||
|
@ -201,6 +214,10 @@ library splines
|
||||||
, Math.Module.Internal
|
, Math.Module.Internal
|
||||||
, TH.Utils
|
, TH.Utils
|
||||||
|
|
||||||
|
if flag(use-fma)
|
||||||
|
other-modules:
|
||||||
|
Math.Interval.FMA
|
||||||
|
|
||||||
build-depends:
|
build-depends:
|
||||||
bifunctors
|
bifunctors
|
||||||
>= 5.5.4 && < 5.6
|
>= 5.5.4 && < 5.6
|
||||||
|
@ -248,6 +265,19 @@ library metabrushes
|
||||||
, bytestring
|
, bytestring
|
||||||
>= 0.10.10.0 && < 0.12
|
>= 0.10.10.0 && < 0.12
|
||||||
|
|
||||||
|
executable test-cusp-isolation
|
||||||
|
|
||||||
|
import:
|
||||||
|
common
|
||||||
|
|
||||||
|
hs-source-dirs:
|
||||||
|
src/cusps
|
||||||
|
|
||||||
|
build-depends:
|
||||||
|
splines
|
||||||
|
|
||||||
|
main-is:
|
||||||
|
Main.hs
|
||||||
|
|
||||||
executable convert-metafont
|
executable convert-metafont
|
||||||
|
|
||||||
|
@ -261,8 +291,7 @@ executable convert-metafont
|
||||||
Haskell2010
|
Haskell2010
|
||||||
|
|
||||||
main-is:
|
main-is:
|
||||||
|
Main.hs
|
||||||
Main.hs
|
|
||||||
|
|
||||||
other-modules:
|
other-modules:
|
||||||
MetaBrush.MetaFont.Convert
|
MetaBrush.MetaFont.Convert
|
||||||
|
|
|
@ -11,6 +11,10 @@ source-repository-package
|
||||||
location: https://github.com/haskell-waargonaut/waargonaut
|
location: https://github.com/haskell-waargonaut/waargonaut
|
||||||
tag: 5f838582a8c5aae1a198ecd4958729e53a6b03cf
|
tag: 5f838582a8c5aae1a198ecd4958729e53a6b03cf
|
||||||
|
|
||||||
|
allow-newer:
|
||||||
|
*:base, *:ghc, *:ghc-prim, *:template-haskell,
|
||||||
|
*:text
|
||||||
|
|
||||||
-------------
|
-------------
|
||||||
-- GHC 9.2 --
|
-- GHC 9.2 --
|
||||||
-------------
|
-------------
|
||||||
|
@ -18,11 +22,8 @@ source-repository-package
|
||||||
allow-newer:
|
allow-newer:
|
||||||
digit:lens,
|
digit:lens,
|
||||||
hedgehog:resourcet,
|
hedgehog:resourcet,
|
||||||
hoist-error:base,
|
|
||||||
natural:lens,
|
natural:lens,
|
||||||
prim-instances:base,
|
waargonaut:lens,
|
||||||
records-sop:ghc-prim,
|
|
||||||
waargonaut:base, waargonaut:lens,
|
|
||||||
waargonaut:records-sop,
|
waargonaut:records-sop,
|
||||||
waargonaut:semigroups, waargonaut:text,
|
waargonaut:semigroups, waargonaut:text,
|
||||||
waargonaut:vector, waargonaut:witherable,
|
waargonaut:vector, waargonaut:witherable,
|
||||||
|
@ -54,9 +55,6 @@ source-repository-package
|
||||||
-- GHC 9.6 --
|
-- GHC 9.6 --
|
||||||
-------------
|
-------------
|
||||||
|
|
||||||
allow-newer:
|
-------------
|
||||||
attoparsec:ghc-prim,
|
-- GHC 9.8 --
|
||||||
generics-sop:base, generics-sop:ghc-prim,
|
-------------
|
||||||
hw-prim:ghc-prim,
|
|
||||||
integer-logarithms:ghc-prim,
|
|
||||||
vector-stream:base, vector-stream:ghc-prim,
|
|
||||||
|
|
|
@ -170,8 +170,8 @@ runApplication application = do
|
||||||
{ splineStart = mkPoint ( ℝ2 10 -20 ) 2 1 0
|
{ splineStart = mkPoint ( ℝ2 10 -20 ) 2 1 0
|
||||||
, splineCurves = OpenCurves $ Seq.fromList
|
, splineCurves = OpenCurves $ Seq.fromList
|
||||||
[ LineTo { curveEnd = NextPoint ( mkPoint ( ℝ2 10 10 ) 10 5 ( pi / 4 ) ), curveData = invalidateCache undefined }
|
[ LineTo { curveEnd = NextPoint ( mkPoint ( ℝ2 10 10 ) 10 5 ( pi / 4 ) ), curveData = invalidateCache undefined }
|
||||||
, LineTo { curveEnd = NextPoint ( mkPoint ( ℝ2 -10 10 ) 8 5 ( pi / 4 ) ), curveData = invalidateCache undefined }
|
--, LineTo { curveEnd = NextPoint ( mkPoint ( ℝ2 -10 10 ) 8 5 ( pi / 4 ) ), curveData = invalidateCache undefined }
|
||||||
, LineTo { curveEnd = NextPoint ( mkPoint ( ℝ2 -10 -20 ) 10 7 ( pi / 2 ) ), curveData = invalidateCache undefined }
|
--, LineTo { curveEnd = NextPoint ( mkPoint ( ℝ2 -10 -20 ) 10 7 ( pi / 2 ) ), curveData = invalidateCache undefined }
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -75,8 +75,6 @@ import Math.Bezier.Stroke
|
||||||
( Cusp(..), CachedStroke(..), invalidateCache
|
( Cusp(..), CachedStroke(..), invalidateCache
|
||||||
, computeStrokeOutline
|
, computeStrokeOutline
|
||||||
)
|
)
|
||||||
import Math.Interval
|
|
||||||
( Extent(Point) )
|
|
||||||
import Math.Linear
|
import Math.Linear
|
||||||
( ℝ(..), T(..) )
|
( ℝ(..), T(..) )
|
||||||
import Math.Module
|
import Math.Module
|
||||||
|
@ -310,7 +308,7 @@ strokeRenderData fitParams
|
||||||
StrokeWithOutlineRenderData
|
StrokeWithOutlineRenderData
|
||||||
{ strokeDataSpline = spline
|
{ strokeDataSpline = spline
|
||||||
, strokeOutlineData = ( outline, fitPts, cusps )
|
, strokeOutlineData = ( outline, fitPts, cusps )
|
||||||
, strokeBrushFunction = fun @Double ( brushFn @Point proxy# id )
|
, strokeBrushFunction = fun @Double ( brushFn @2 @() proxy# id )
|
||||||
. embedUsedParams
|
. embedUsedParams
|
||||||
. toUsedParams
|
. toUsedParams
|
||||||
}
|
}
|
||||||
|
|
209
src/cusps/Main.hs
Normal file
209
src/cusps/Main.hs
Normal file
|
@ -0,0 +1,209 @@
|
||||||
|
{-# LANGUAGE AllowAmbiguousTypes #-}
|
||||||
|
{-# LANGUAGE ScopedTypeVariables #-}
|
||||||
|
|
||||||
|
module Main where
|
||||||
|
|
||||||
|
-- base
|
||||||
|
import Prelude hiding ( Num(..), Fractional(..), Floating(..), (^) )
|
||||||
|
import qualified Prelude ( Num(..), Fractional(..) )
|
||||||
|
import Data.Coerce
|
||||||
|
( Coercible )
|
||||||
|
import GHC.Generics
|
||||||
|
( Generic )
|
||||||
|
|
||||||
|
-- acts
|
||||||
|
import Data.Act
|
||||||
|
( Torsor )
|
||||||
|
|
||||||
|
-- containers
|
||||||
|
import Data.Map
|
||||||
|
( Map )
|
||||||
|
import qualified Data.Map as Map
|
||||||
|
( (!) )
|
||||||
|
import qualified Data.Sequence as Seq
|
||||||
|
( index )
|
||||||
|
|
||||||
|
-- generic-lens
|
||||||
|
import Data.Generics.Product.Typed
|
||||||
|
( HasType )
|
||||||
|
|
||||||
|
-- MetaBrush
|
||||||
|
import Math.Algebra.Dual
|
||||||
|
import Math.Bezier.Spline
|
||||||
|
import Math.Bezier.Stroke
|
||||||
|
( brushStrokeData, pathAndUsedParams )
|
||||||
|
import Math.Bezier.Stroke.EnvelopeEquation
|
||||||
|
( StrokeDatum(..) )
|
||||||
|
import Math.Differentiable
|
||||||
|
( I )
|
||||||
|
import Math.Interval
|
||||||
|
import Math.Linear
|
||||||
|
( ℝ(..), T(..) )
|
||||||
|
import Math.Module
|
||||||
|
( Module, Cross )
|
||||||
|
import Math.Ring
|
||||||
|
( AbelianGroup(..), Ring(..), Field(..), Transcendental(..)
|
||||||
|
, ViaPrelude(..)
|
||||||
|
)
|
||||||
|
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
data PointData params
|
||||||
|
= PointData
|
||||||
|
{ pointCoords :: !( ℝ 2 )
|
||||||
|
, brushParams :: !params
|
||||||
|
}
|
||||||
|
deriving stock ( Show, Generic )
|
||||||
|
|
||||||
|
|
||||||
|
{-
|
||||||
|
|
||||||
|
newtype C k u v = D { runD :: u -> D k u v }
|
||||||
|
|
||||||
|
type instance D k ( ℝ n ) = Dk𝔸n
|
||||||
|
type instance D k ( 𝕀 v ) = D k v
|
||||||
|
|
||||||
|
e.g.
|
||||||
|
|
||||||
|
data D2𝔸2 v =
|
||||||
|
D22 { _D22_v :: !v
|
||||||
|
, _D22_dx, _D22_dy :: !( T v )
|
||||||
|
, _D22_dxdx, _D22_dxdy, _D22_dydy :: !( T v )
|
||||||
|
}
|
||||||
|
|
||||||
|
-}
|
||||||
|
|
||||||
|
|
||||||
|
outlineFunction
|
||||||
|
:: forall i brushParams
|
||||||
|
. ( Show brushParams
|
||||||
|
, D 1 ( I i ( ℝ 2 ) ) ~ D 1 ( ℝ 2 )
|
||||||
|
, D 2 ( I i ( ℝ 2 ) ) ~ D 2 ( ℝ 2 )
|
||||||
|
, D 3 ( I i ( ℝ 1 ) ) ~ D 3 ( ℝ 1 )
|
||||||
|
, D 3 ( I i ( ℝ 2 ) ) ~ D 3 ( ℝ 2 )
|
||||||
|
, Coercible ( I i ( ℝ 1 ) ) ( I i Double )
|
||||||
|
, HasType ( ℝ 2 ) ( PointData brushParams )
|
||||||
|
, Cross ( I i Double ) ( T ( I i ( ℝ 2 ) ) )
|
||||||
|
, Module ( I i Double ) ( T ( I i brushParams ) )
|
||||||
|
, Torsor ( T ( I i ( ℝ 2 ) ) ) ( I i ( ℝ 2 ) )
|
||||||
|
, Torsor ( T ( I i brushParams ) ) ( I i brushParams )
|
||||||
|
, HasChainRule ( I i Double ) 3 ( I i ( ℝ 1 ) )
|
||||||
|
, HasChainRule ( I i Double ) 3 ( I i brushParams )
|
||||||
|
, Traversable ( D 3 brushParams )
|
||||||
|
, Traversable ( D 3 ( I i brushParams ) )
|
||||||
|
)
|
||||||
|
=> ( forall a. a -> I i a )
|
||||||
|
-> C 3 ( I i brushParams ) ( Spline Closed () ( I i ( ℝ 2 ) ) )
|
||||||
|
-- ^ brush shape
|
||||||
|
-> Int -- ^ brush segment index to consider
|
||||||
|
-> PointData brushParams -> Curve Open () ( PointData brushParams )
|
||||||
|
-- ^ stroke path
|
||||||
|
-> ( I i ( ℝ 1 ) -> I i ( ℝ 1 ) -> StrokeDatum 3 i )
|
||||||
|
outlineFunction single brush brush_index sp0 crv = strokeData
|
||||||
|
|
||||||
|
where
|
||||||
|
path :: C 3 ( I i ( ℝ 1 ) ) ( I i ( ℝ 2 ) )
|
||||||
|
params :: C 3 ( I i ( ℝ 1 ) ) ( I i brushParams )
|
||||||
|
(path, params) =
|
||||||
|
pathAndUsedParams @3 @i single brushParams sp0 crv
|
||||||
|
|
||||||
|
strokeData :: I i ( ℝ 1 ) -> I i ( ℝ 1 ) -> StrokeDatum 3 i
|
||||||
|
strokeData =
|
||||||
|
fmap ( `Seq.index` brush_index ) $
|
||||||
|
brushStrokeData @3 @brushParams @i path params brush
|
||||||
|
|
||||||
|
main :: IO ()
|
||||||
|
main = return ()
|
||||||
|
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
-- EDSL for inspection
|
||||||
|
|
||||||
|
type instance I AA a = AA a
|
||||||
|
|
||||||
|
data AAVal a where
|
||||||
|
Val :: a -> AAVal a
|
||||||
|
Var :: String -> AAVal Double
|
||||||
|
|
||||||
|
instance Show a => Show ( AAVal a ) where
|
||||||
|
show (Val v) = show v
|
||||||
|
show (Var v) = show v
|
||||||
|
|
||||||
|
data AA a where
|
||||||
|
Pt :: AAVal a -> AA a
|
||||||
|
Ival :: AAVal a -> AAVal a -> AA a
|
||||||
|
(:+:) :: AA Double -> AA Double -> AA Double
|
||||||
|
(:-:) :: AA Double -> AA Double -> AA Double
|
||||||
|
Negate :: AA Double -> AA Double
|
||||||
|
(:*:) :: AA Double -> AA Double -> AA Double
|
||||||
|
(:^:) :: AA Double -> Word -> AA Double
|
||||||
|
Recip :: AA Double -> AA Double
|
||||||
|
Cos :: AA Double -> AA Double
|
||||||
|
Sin :: AA Double -> AA Double
|
||||||
|
Pi :: AA Double
|
||||||
|
|
||||||
|
instance Show a => Show (AA a) where
|
||||||
|
showsPrec prec = \case
|
||||||
|
Pt v -> showString "[" . showsPrec 0 v . showString "]"
|
||||||
|
Ival lo hi -> showString "[" . showsPrec 0 lo . showString "," . showsPrec 0 hi . showString "]"
|
||||||
|
iv1 :+: iv2 -> showParen (prec > 6) $ showsPrec 6 iv1 . showString " + " . showsPrec 7 iv2
|
||||||
|
iv1 :-: iv2 -> showParen (prec > 6) $ showsPrec 6 iv1 . showString " - " . showsPrec 7 iv2
|
||||||
|
iv1 :*: iv2 -> showParen (prec > 7) $ showsPrec 7 iv1 . showString " - " . showsPrec 8 iv2
|
||||||
|
iv :^: n -> showParen (prec > 8) $ showsPrec 9 iv . showString " ^ " . showsPrec 8 n
|
||||||
|
Negate iv -> showParen (prec > 10) $ showString "negate " . showsPrec 11 iv
|
||||||
|
Recip iv -> showParen (prec > 10) $ showString "recip " . showsPrec 11 iv
|
||||||
|
Cos iv -> showParen (prec > 10) $ showString "cos " . showsPrec 11 iv
|
||||||
|
Sin iv -> showParen (prec > 10) $ showString "sin " . showsPrec 11 iv
|
||||||
|
Pi -> showString "pi"
|
||||||
|
|
||||||
|
infixl 6 :+:
|
||||||
|
infixl 6 :-:
|
||||||
|
infixl 7 :*:
|
||||||
|
infixr 8 :^:
|
||||||
|
|
||||||
|
val :: Map String Double -> AAVal a -> a
|
||||||
|
val _ ( Val a ) = a
|
||||||
|
val vars ( Var v ) = vars Map.! v
|
||||||
|
|
||||||
|
eval :: Map String Double -> AA a -> 𝕀 a
|
||||||
|
eval vars = \ case
|
||||||
|
Pt v -> let f = val vars v in 𝕀 f f
|
||||||
|
Ival lo hi -> 𝕀 (val vars lo) (val vars hi)
|
||||||
|
iv1 :+: iv2 -> eval vars iv1 + eval vars iv2
|
||||||
|
iv1 :-: iv2 -> eval vars iv1 - eval vars iv2
|
||||||
|
Negate iv -> negate $ eval vars iv
|
||||||
|
iv1 :*: iv2 -> eval vars iv1 * eval vars iv2
|
||||||
|
iv :^: n -> eval vars iv ^ n
|
||||||
|
Recip iv -> recip $ eval vars iv
|
||||||
|
Cos iv -> cos $ eval vars iv
|
||||||
|
Sin iv -> sin $ eval vars iv
|
||||||
|
Pi -> pi
|
||||||
|
|
||||||
|
instance Prelude.Num ( AA Double ) where
|
||||||
|
(+) = (:+:)
|
||||||
|
(-) = (:-:)
|
||||||
|
negate = Negate
|
||||||
|
(*) = (:*:)
|
||||||
|
abs = error "No abs for abstract intervals"
|
||||||
|
signum = error "No signum for abstract intervals"
|
||||||
|
fromInteger = Pt . Val . fromInteger
|
||||||
|
|
||||||
|
instance Prelude.Fractional ( AA Double ) where
|
||||||
|
recip = Recip
|
||||||
|
(/) = error "No division for abstract intervals"
|
||||||
|
fromRational = Pt . Val . fromRational
|
||||||
|
|
||||||
|
instance Ring ( AA Double ) where
|
||||||
|
(*) = (:*:)
|
||||||
|
(^) = (:^:)
|
||||||
|
|
||||||
|
deriving via ViaPrelude ( AA Double )
|
||||||
|
instance AbelianGroup ( AA Double )
|
||||||
|
deriving via ViaPrelude ( AA Double )
|
||||||
|
instance AbelianGroup ( T ( AA Double ) )
|
||||||
|
deriving via ViaPrelude ( AA Double )
|
||||||
|
instance Field ( AA Double )
|
||||||
|
|
||||||
|
instance Transcendental ( AA Double ) where
|
||||||
|
pi = Pi
|
||||||
|
cos = Cos
|
||||||
|
sin = Sin
|
|
@ -1,5 +1,6 @@
|
||||||
{-# LANGUAGE AllowAmbiguousTypes #-}
|
{-# LANGUAGE AllowAmbiguousTypes #-}
|
||||||
{-# LANGUAGE OverloadedStrings #-}
|
{-# LANGUAGE OverloadedStrings #-}
|
||||||
|
{-# LANGUAGE PolyKinds #-}
|
||||||
{-# LANGUAGE ScopedTypeVariables #-}
|
{-# LANGUAGE ScopedTypeVariables #-}
|
||||||
|
|
||||||
module MetaBrush.Asset.Brushes
|
module MetaBrush.Asset.Brushes
|
||||||
|
@ -32,8 +33,8 @@ import qualified Data.HashMap.Strict as HashMap
|
||||||
-- MetaBrush
|
-- MetaBrush
|
||||||
import Math.Algebra.Dual
|
import Math.Algebra.Dual
|
||||||
import Math.Bezier.Spline
|
import Math.Bezier.Spline
|
||||||
import Math.Interval
|
import Math.Differentiable
|
||||||
|
( I )
|
||||||
import Math.Linear
|
import Math.Linear
|
||||||
import Math.Module
|
import Math.Module
|
||||||
( Module((^+^), (*^)) )
|
( Module((^+^), (*^)) )
|
||||||
|
@ -81,7 +82,7 @@ ellipse = BrushData "ellipse" ( WithParams deflts ellipseBrush )
|
||||||
--------------------------------------------------------------------------------
|
--------------------------------------------------------------------------------
|
||||||
-- Differentiable brushes.
|
-- Differentiable brushes.
|
||||||
|
|
||||||
circleSpline :: forall i k u v
|
circleSpline :: forall {t} (i :: t) k u v
|
||||||
. Applicative ( D k ( I i u ) )
|
. Applicative ( D k ( I i u ) )
|
||||||
=> ( Double -> Double -> D k ( I i u ) ( I i v ) )
|
=> ( Double -> Double -> D k ( I i u ) ( I i v ) )
|
||||||
-> D k ( I i u ) ( Spline 'Closed () ( I i v ) )
|
-> D k ( I i u ) ( Spline 'Closed () ( I i v ) )
|
||||||
|
@ -98,7 +99,7 @@ circleSpline p = sequenceA $
|
||||||
Bezier3To ( p κ -1 ) ( p 1 -κ ) BackToStart ()
|
Bezier3To ( p κ -1 ) ( p 1 -κ ) BackToStart ()
|
||||||
{-# INLINE circleSpline #-}
|
{-# INLINE circleSpline #-}
|
||||||
|
|
||||||
circleBrush :: forall i k irec
|
circleBrush :: forall {t} (i :: t) k irec
|
||||||
. ( irec ~ I i ( Record CircleBrushFields )
|
. ( irec ~ I i ( Record CircleBrushFields )
|
||||||
, Module
|
, Module
|
||||||
( D k irec ( I i Double ) )
|
( D k irec ( I i Double ) )
|
||||||
|
@ -113,7 +114,7 @@ circleBrush :: forall i k irec
|
||||||
-> C k irec ( Spline 'Closed () ( I i ( ℝ 2 ) ) )
|
-> C k irec ( Spline 'Closed () ( I i ( ℝ 2 ) ) )
|
||||||
circleBrush _ mkI =
|
circleBrush _ mkI =
|
||||||
D \ params ->
|
D \ params ->
|
||||||
let r :: D k irec( I i Double )
|
let r :: D k irec ( I i Double )
|
||||||
r = runD ( var @_ @k ( Fin 1 ) ) params
|
r = runD ( var @_ @k ( Fin 1 ) ) params
|
||||||
mkPt :: Double -> Double -> D k irec ( I i ( ℝ 2 ) )
|
mkPt :: Double -> Double -> D k irec ( I i ( ℝ 2 ) )
|
||||||
mkPt ( kon -> x ) ( kon -> y )
|
mkPt ( kon -> x ) ( kon -> y )
|
||||||
|
@ -128,7 +129,7 @@ circleBrush _ mkI =
|
||||||
kon = konst @( I i Double ) @k @irec . mkI
|
kon = konst @( I i Double ) @k @irec . mkI
|
||||||
{-# INLINEABLE circleBrush #-}
|
{-# INLINEABLE circleBrush #-}
|
||||||
|
|
||||||
ellipseBrush :: forall i k irec
|
ellipseBrush :: forall {t} (i :: t) k irec
|
||||||
. ( irec ~ I i ( Record EllipseBrushFields )
|
. ( irec ~ I i ( Record EllipseBrushFields )
|
||||||
, Module
|
, Module
|
||||||
( D k irec ( I i Double ) )
|
( D k irec ( I i Double ) )
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
{-# LANGUAGE AllowAmbiguousTypes #-}
|
{-# LANGUAGE AllowAmbiguousTypes #-}
|
||||||
|
{-# LANGUAGE PolyKinds #-}
|
||||||
{-# LANGUAGE QuantifiedConstraints #-}
|
{-# LANGUAGE QuantifiedConstraints #-}
|
||||||
{-# LANGUAGE ScopedTypeVariables #-}
|
{-# LANGUAGE ScopedTypeVariables #-}
|
||||||
{-# LANGUAGE UndecidableInstances #-}
|
{-# LANGUAGE UndecidableInstances #-}
|
||||||
|
@ -44,9 +45,9 @@ import Math.Algebra.Dual
|
||||||
import Math.Bezier.Spline
|
import Math.Bezier.Spline
|
||||||
( SplineType(Closed), Spline )
|
( SplineType(Closed), Spline )
|
||||||
import Math.Differentiable
|
import Math.Differentiable
|
||||||
( DiffInterp, ExtentOrder )
|
( DiffInterp, I )
|
||||||
import Math.Interval
|
import Math.Interval
|
||||||
( type I, Extent(Point, Interval) )
|
( 𝕀 )
|
||||||
import Math.Linear
|
import Math.Linear
|
||||||
import MetaBrush.Records
|
import MetaBrush.Records
|
||||||
( KnownSymbols, Length, Record )
|
( KnownSymbols, Length, Record )
|
||||||
|
@ -62,11 +63,11 @@ data WithParams params f =
|
||||||
WithParams
|
WithParams
|
||||||
{ defaultParams :: params
|
{ defaultParams :: params
|
||||||
, withParams
|
, withParams
|
||||||
:: forall i
|
:: forall {t} k (i :: t)
|
||||||
. ( DiffInterp i params )
|
. ( DiffInterp k i params )
|
||||||
=> Proxy# i
|
=> Proxy# i
|
||||||
-> ( forall a. a -> I i a )
|
-> ( forall a. a -> I i a )
|
||||||
-> C ( ExtentOrder i ) ( I i params ) ( f ( I i ( ℝ 2 ) ) )
|
-> C k ( I i params ) ( f ( I i ( ℝ 2 ) ) )
|
||||||
}
|
}
|
||||||
|
|
||||||
--------------------------------------------------------------------------------
|
--------------------------------------------------------------------------------
|
||||||
|
@ -82,8 +83,8 @@ data Brush brushFields where
|
||||||
:: forall brushFields
|
:: forall brushFields
|
||||||
. ( KnownSymbols brushFields, Typeable brushFields
|
. ( KnownSymbols brushFields, Typeable brushFields
|
||||||
, Representable Double ( ℝ ( Length brushFields ) )
|
, Representable Double ( ℝ ( Length brushFields ) )
|
||||||
, DiffInterp Point ( ℝ ( Length brushFields ) )
|
, DiffInterp 2 () ( ℝ ( Length brushFields ) )
|
||||||
, DiffInterp Interval ( ℝ ( Length brushFields ) )
|
, DiffInterp 3 𝕀 ( ℝ ( Length brushFields ) )
|
||||||
)
|
)
|
||||||
=> { brushName :: !Text
|
=> { brushName :: !Text
|
||||||
, brushFunction :: BrushFunction brushFields
|
, brushFunction :: BrushFunction brushFields
|
||||||
|
@ -118,8 +119,8 @@ class ( KnownSymbols pointFields, Typeable pointFields
|
||||||
, Show ( Record pointFields )
|
, Show ( Record pointFields )
|
||||||
, NFData ( Record pointFields )
|
, NFData ( Record pointFields )
|
||||||
, Representable Double ( ℝ ( Length pointFields ) )
|
, Representable Double ( ℝ ( Length pointFields ) )
|
||||||
, DiffInterp Point ( ℝ ( Length pointFields ) )
|
, DiffInterp 2 () ( ℝ ( Length pointFields ) )
|
||||||
, DiffInterp Interval ( ℝ ( Length pointFields ) )
|
, DiffInterp 3 𝕀 ( ℝ ( Length pointFields ) )
|
||||||
)
|
)
|
||||||
=> PointFields pointFields where { }
|
=> PointFields pointFields where { }
|
||||||
instance ( KnownSymbols pointFields, Typeable pointFields
|
instance ( KnownSymbols pointFields, Typeable pointFields
|
||||||
|
@ -127,8 +128,8 @@ instance ( KnownSymbols pointFields, Typeable pointFields
|
||||||
, Show ( Record pointFields )
|
, Show ( Record pointFields )
|
||||||
, NFData ( Record pointFields )
|
, NFData ( Record pointFields )
|
||||||
, Representable Double ( ℝ ( Length pointFields ) )
|
, Representable Double ( ℝ ( Length pointFields ) )
|
||||||
, DiffInterp Point ( ℝ ( Length pointFields ) )
|
, DiffInterp 2 () ( ℝ ( Length pointFields ) )
|
||||||
, DiffInterp Interval ( ℝ ( Length pointFields ) )
|
, DiffInterp 3 𝕀 ( ℝ ( Length pointFields ) )
|
||||||
)
|
)
|
||||||
=> PointFields pointFields where { }
|
=> PointFields pointFields where { }
|
||||||
|
|
||||||
|
|
|
@ -181,8 +181,8 @@ intersect :: forall r1 r2 l1 l2
|
||||||
, l1 ~ Length r1, l2 ~ Length r2
|
, l1 ~ Length r1, l2 ~ Length r2
|
||||||
, Representable Double ( ℝ l1 )
|
, Representable Double ( ℝ l1 )
|
||||||
, Representable Double ( ℝ l2 )
|
, Representable Double ( ℝ l2 )
|
||||||
, Differentiable 'Point ( ℝ l2 )
|
, Differentiable 2 () ( ℝ l2 )
|
||||||
, Differentiable 'Interval ( ℝ l2 )
|
, Differentiable 3 𝕀 ( ℝ l2 )
|
||||||
)
|
)
|
||||||
=> Intersection r1 r2
|
=> Intersection r1 r2
|
||||||
intersect
|
intersect
|
||||||
|
@ -206,8 +206,8 @@ data Intersection r1 r2 where
|
||||||
. ( l12 ~ Length r1r2
|
. ( l12 ~ Length r1r2
|
||||||
, KnownSymbols r1r2
|
, KnownSymbols r1r2
|
||||||
, Representable Double ( ℝ l12 )
|
, Representable Double ( ℝ l12 )
|
||||||
, Differentiable 'Point ( ℝ l12 )
|
, Differentiable 2 () ( ℝ l12 )
|
||||||
, Differentiable 'Interval ( ℝ l12 )
|
, Differentiable 3 𝕀 ( ℝ l12 )
|
||||||
)
|
)
|
||||||
=> { project :: Record r1 -> Record r1r2
|
=> { project :: Record r1 -> Record r1r2
|
||||||
-- ^ project out fields present in both rows
|
-- ^ project out fields present in both rows
|
||||||
|
@ -226,8 +226,8 @@ doIntersection
|
||||||
=> ( forall r1r2 l12.
|
=> ( forall r1r2 l12.
|
||||||
( r1r2 ~ Intersect r1 r2
|
( r1r2 ~ Intersect r1 r2
|
||||||
, KnownSymbols r1r2, l12 ~ Length r1r2
|
, KnownSymbols r1r2, l12 ~ Length r1r2
|
||||||
, Differentiable 'Point ( ℝ l12 )
|
, Differentiable 2 () ( ℝ l12 )
|
||||||
, Differentiable 'Interval ( ℝ l12 )
|
, Differentiable 3 𝕀 ( ℝ l12 )
|
||||||
, Representable Double ( ℝ l12 )
|
, Representable Double ( ℝ l12 )
|
||||||
)
|
)
|
||||||
=> Proxy# r1r2 -> Vec l12 ( Fin l1 ) -> Vec l12 ( Fin l2 ) -> kont )
|
=> Proxy# r1r2 -> Vec l12 ( Fin l1 ) -> Vec l12 ( Fin l2 ) -> kont )
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
|
|
||||||
{-# OPTIONS_GHC -Wno-orphans -O2 #-}
|
{-# OPTIONS_GHC -Wno-orphans -O2 #-}
|
||||||
|
|
||||||
{-# OPTIONS_GHC -ddump-splices -ddump-simpl -ddump-to-file -dno-typeable-binds
|
{-# OPTIONS_GHC -ddump-splices -ddump-simpl -ddump-cmm -ddump-to-file -dno-typeable-binds
|
||||||
-dsuppress-unfoldings -dsuppress-coercions #-}
|
-dsuppress-unfoldings -dsuppress-coercions #-}
|
||||||
|
|
||||||
module Math.Algebra.Dual
|
module Math.Algebra.Dual
|
||||||
|
|
|
@ -178,7 +178,7 @@ data D2𝔸4 v =
|
||||||
deriving Applicative
|
deriving Applicative
|
||||||
via Generically1 D2𝔸4
|
via Generically1 D2𝔸4
|
||||||
|
|
||||||
-- | \( \mathbb{Z}[x, y, z, w]/(x, y, z, w)^3 \).
|
-- | \( \mathbb{Z}[x, y, z, w]/(x, y, z, w)^4 \).
|
||||||
data D3𝔸4 v =
|
data D3𝔸4 v =
|
||||||
D34 { _D34_v :: !v
|
D34 { _D34_v :: !v
|
||||||
, _D34_dx, _D34_dy, _D34_dz, _D34_dw :: !( T v )
|
, _D34_dx, _D34_dy, _D34_dz, _D34_dw :: !( T v )
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
{-# LANGUAGE AllowAmbiguousTypes #-}
|
{-# LANGUAGE AllowAmbiguousTypes #-}
|
||||||
|
{-# LANGUAGE PolyKinds #-}
|
||||||
{-# LANGUAGE QuantifiedConstraints #-}
|
{-# LANGUAGE QuantifiedConstraints #-}
|
||||||
{-# LANGUAGE ScopedTypeVariables #-}
|
{-# LANGUAGE ScopedTypeVariables #-}
|
||||||
{-# LANGUAGE UndecidableInstances #-}
|
{-# LANGUAGE UndecidableInstances #-}
|
||||||
|
@ -13,6 +14,7 @@ module Math.Bezier.Stroke
|
||||||
|
|
||||||
, brushStroke, envelopeEquation
|
, brushStroke, envelopeEquation
|
||||||
, line, bezier2, bezier3
|
, line, bezier2, bezier3
|
||||||
|
, brushStrokeData, pathAndUsedParams
|
||||||
|
|
||||||
)
|
)
|
||||||
where
|
where
|
||||||
|
@ -45,9 +47,8 @@ import Data.Maybe
|
||||||
import Data.Semigroup
|
import Data.Semigroup
|
||||||
( sconcat )
|
( sconcat )
|
||||||
import GHC.Exts
|
import GHC.Exts
|
||||||
( newMutVar#, runRW#
|
( newMutVar#, runRW#, inline
|
||||||
, Proxy#, proxy#
|
, Proxy#, proxy#
|
||||||
, inline
|
|
||||||
)
|
)
|
||||||
import GHC.STRef
|
import GHC.STRef
|
||||||
( STRef(..), readSTRef, writeSTRef )
|
( STRef(..), readSTRef, writeSTRef )
|
||||||
|
@ -88,13 +89,6 @@ import Data.Generics.Internal.VL
|
||||||
import qualified Control.Parallel.Strategies as Strats
|
import qualified Control.Parallel.Strategies as Strats
|
||||||
( rdeepseq, parTuple2, using )
|
( rdeepseq, parTuple2, using )
|
||||||
|
|
||||||
-- rounded-hw
|
|
||||||
import Numeric.Rounded.Hardware
|
|
||||||
( Rounded(..) )
|
|
||||||
import Numeric.Rounded.Hardware.Interval.NonEmpty
|
|
||||||
( Interval(..) )
|
|
||||||
import qualified Numeric.Rounded.Hardware.Interval.NonEmpty as Interval
|
|
||||||
|
|
||||||
-- transformers
|
-- transformers
|
||||||
import Control.Monad.Trans.Class
|
import Control.Monad.Trans.Class
|
||||||
( lift )
|
( lift )
|
||||||
|
@ -123,9 +117,7 @@ import Math.Bezier.Spline
|
||||||
import qualified Math.Bezier.Quadratic as Quadratic
|
import qualified Math.Bezier.Quadratic as Quadratic
|
||||||
import Math.Bezier.Stroke.EnvelopeEquation
|
import Math.Bezier.Stroke.EnvelopeEquation
|
||||||
import Math.Differentiable
|
import Math.Differentiable
|
||||||
( Differentiable, DiffInterp
|
( Differentiable, DiffInterp, I )
|
||||||
, type ExtentOrder
|
|
||||||
)
|
|
||||||
import Math.Epsilon
|
import Math.Epsilon
|
||||||
( epsilon, nearZero )
|
( epsilon, nearZero )
|
||||||
import Math.Interval
|
import Math.Interval
|
||||||
|
@ -236,13 +228,13 @@ computeStrokeOutline ::
|
||||||
-- Differentiability.
|
-- Differentiability.
|
||||||
, Interpolatable Double usedParams
|
, Interpolatable Double usedParams
|
||||||
, Interpolatable ( 𝕀 Double ) ( 𝕀 usedParams )
|
, Interpolatable ( 𝕀 Double ) ( 𝕀 usedParams )
|
||||||
, DiffInterp 'Point brushParams
|
, DiffInterp 2 () brushParams
|
||||||
, DiffInterp 'Interval brushParams
|
, DiffInterp 3 𝕀 brushParams
|
||||||
, HasChainRule Double ( ExtentOrder 'Point ) usedParams
|
, HasChainRule Double 2 usedParams
|
||||||
, HasChainRule ( 𝕀 Double ) ( ExtentOrder 'Interval ) ( 𝕀 usedParams )
|
, HasChainRule ( 𝕀 Double ) 3 ( 𝕀 usedParams )
|
||||||
, HasChainRule Double ( ExtentOrder 'Point ) brushParams
|
, HasChainRule Double 2 brushParams
|
||||||
, HasChainRule ( 𝕀 Double ) ( ExtentOrder 'Interval ) ( 𝕀 brushParams )
|
, HasChainRule ( 𝕀 Double ) 3 ( 𝕀 brushParams )
|
||||||
, Traversable ( D ( ExtentOrder 'Point ) brushParams )
|
, Traversable ( D 2 brushParams )
|
||||||
|
|
||||||
-- Debugging.
|
-- Debugging.
|
||||||
, Show ptData, Show brushParams
|
, Show ptData, Show brushParams
|
||||||
|
@ -251,13 +243,12 @@ computeStrokeOutline ::
|
||||||
=> FitParameters
|
=> FitParameters
|
||||||
-> ( ptData -> usedParams )
|
-> ( ptData -> usedParams )
|
||||||
-> ( usedParams -> brushParams ) -- ^ assumed to be linear and non-decreasing
|
-> ( usedParams -> brushParams ) -- ^ assumed to be linear and non-decreasing
|
||||||
-> ( forall i
|
-> ( forall {t} k (i :: t)
|
||||||
. DiffInterp i brushParams
|
. DiffInterp k i brushParams
|
||||||
=> Proxy# i
|
=> Proxy# i
|
||||||
-> ( forall a. a -> I i a )
|
-> ( forall a. a -> I i a )
|
||||||
-> C ( ExtentOrder i )
|
-> C k ( I i brushParams )
|
||||||
( I i brushParams )
|
( Spline Closed () ( I i ( ℝ 2 ) ) )
|
||||||
( Spline Closed () ( I i ( ℝ 2 ) ) )
|
|
||||||
)
|
)
|
||||||
-> Spline clo crvData ptData
|
-> Spline clo crvData ptData
|
||||||
-> ST s
|
-> ST s
|
||||||
|
@ -381,7 +372,7 @@ computeStrokeOutline fitParams ptParams toBrushParams brushFn spline@( Spline {
|
||||||
outlineInfo p0 crv :<| go ( openCurveEnd crv ) crvs
|
outlineInfo p0 crv :<| go ( openCurveEnd crv ) crvs
|
||||||
|
|
||||||
brushShape :: ptData -> SplinePts Closed
|
brushShape :: ptData -> SplinePts Closed
|
||||||
brushShape pt = fun @Double ( brushFn @Point proxy# id ) $ toBrushParams $ ptParams pt
|
brushShape pt = fun @Double ( brushFn @2 @() proxy# id ) $ toBrushParams $ ptParams pt
|
||||||
|
|
||||||
updateSpline :: ( T ( ℝ 2 ), T ( ℝ 2 ), T ( ℝ 2 ) ) -> ST s OutlineData
|
updateSpline :: ( T ( ℝ 2 ), T ( ℝ 2 ), T ( ℝ 2 ) ) -> ST s OutlineData
|
||||||
updateSpline ( lastTgt, lastTgtFwd, lastTgtBwd )
|
updateSpline ( lastTgt, lastTgtFwd, lastTgtBwd )
|
||||||
|
@ -514,87 +505,61 @@ outlineFunction
|
||||||
-- Differentiability.
|
-- Differentiability.
|
||||||
, Interpolatable Double usedParams
|
, Interpolatable Double usedParams
|
||||||
, Interpolatable ( 𝕀 Double ) ( 𝕀 usedParams )
|
, Interpolatable ( 𝕀 Double ) ( 𝕀 usedParams )
|
||||||
, DiffInterp 'Point brushParams
|
, DiffInterp 2 () brushParams
|
||||||
, DiffInterp 'Interval brushParams
|
, DiffInterp 3 𝕀 brushParams
|
||||||
, HasChainRule Double ( ExtentOrder 'Point ) usedParams
|
, HasChainRule Double 2 usedParams
|
||||||
, HasChainRule ( 𝕀 Double ) ( ExtentOrder 'Interval ) ( 𝕀 usedParams )
|
, HasChainRule ( 𝕀 Double ) 3 ( 𝕀 usedParams )
|
||||||
, HasChainRule Double ( ExtentOrder 'Point ) brushParams
|
, HasChainRule Double 2 brushParams
|
||||||
, HasChainRule ( 𝕀 Double ) ( ExtentOrder 'Interval ) ( 𝕀 brushParams )
|
, HasChainRule ( 𝕀 Double ) 3 ( 𝕀 brushParams )
|
||||||
, Traversable ( D ( ExtentOrder 'Point ) brushParams )
|
, Traversable ( D 2 brushParams )
|
||||||
|
|
||||||
-- Debugging.
|
-- Debugging.
|
||||||
, Show ptData, Show brushParams
|
, Show ptData, Show brushParams
|
||||||
)
|
)
|
||||||
=> ( ptData -> usedParams )
|
=> ( ptData -> usedParams )
|
||||||
-> ( usedParams -> brushParams ) -- ^ assumed to be linear and non-decreasing
|
-> ( usedParams -> brushParams ) -- ^ assumed to be linear and non-decreasing
|
||||||
-> ( forall i
|
-> ( forall {t} k (i :: t)
|
||||||
. DiffInterp i brushParams
|
. DiffInterp k i brushParams
|
||||||
=> Proxy# i
|
=> Proxy# i
|
||||||
-> ( forall a. a -> I i a )
|
-> ( forall a. a -> I i a )
|
||||||
-> C ( ExtentOrder i )
|
-> C k ( I i brushParams )
|
||||||
( I i brushParams )
|
( Spline Closed () ( I i ( ℝ 2 ) ) )
|
||||||
( Spline Closed () ( I i ( ℝ 2 ) ) )
|
|
||||||
)
|
)
|
||||||
-> ptData
|
-> ptData
|
||||||
-> Curve Open crvData ptData
|
-> Curve Open crvData ptData
|
||||||
-> OutlineInfo
|
-> OutlineInfo
|
||||||
outlineFunction ptParams toBrushParams brushFromParams = \ sp0 crv ->
|
outlineFunction ptParams toBrushParams brushFromParams = \ sp0 crv ->
|
||||||
let
|
let
|
||||||
pathAndUsedParams :: forall i k arr
|
|
||||||
. ( k ~ ExtentOrder i, CurveOrder k
|
|
||||||
, arr ~ C k
|
|
||||||
, D k ( I i ( ℝ 1 ) ) ~ D k ( ℝ 1 )
|
|
||||||
, Coercible ( I i ( ℝ 1 ) ) ( I i Double )
|
|
||||||
, Module ( I i Double ) ( T ( I i ( ℝ 2 ) ) )
|
|
||||||
, Torsor ( T ( I i ( ℝ 2 ) ) ) ( I i ( ℝ 2 ) )
|
|
||||||
, Module ( I i Double ) ( T ( I i usedParams ) )
|
|
||||||
, Torsor ( T ( I i usedParams ) ) ( I i usedParams )
|
|
||||||
)
|
|
||||||
=> ( forall a. a -> I i a )
|
|
||||||
-> ( I i ( ℝ 1 ) `arr` I i ( ℝ 2 ), I i ( ℝ 1 ) `arr` I i usedParams )
|
|
||||||
pathAndUsedParams toI =
|
|
||||||
case crv of
|
|
||||||
LineTo { curveEnd = NextPoint sp1 }
|
|
||||||
| let seg = Segment sp0 sp1
|
|
||||||
-> ( line @k @i ( fmap ( toI . coords ) seg )
|
|
||||||
, line @k @i ( fmap ( toI . ptParams ) seg ) )
|
|
||||||
Bezier2To { controlPoint = sp1, curveEnd = NextPoint sp2 }
|
|
||||||
| let bez2 = Quadratic.Bezier sp0 sp1 sp2
|
|
||||||
-> ( bezier2 @k @i ( fmap ( toI . coords ) bez2 )
|
|
||||||
, bezier2 @k @i ( fmap ( toI . ptParams ) bez2 ) )
|
|
||||||
Bezier3To { controlPoint1 = sp1, controlPoint2 = sp2, curveEnd = NextPoint sp3 }
|
|
||||||
| let bez3 = Cubic.Bezier sp0 sp1 sp2 sp3
|
|
||||||
-> ( bezier3 @k @i ( fmap ( toI . coords ) bez3 )
|
|
||||||
, bezier3 @k @i ( fmap ( toI . ptParams ) bez3 ) )
|
|
||||||
|
|
||||||
usedParams :: C ( ExtentOrder 'Point ) ( ℝ 1 ) usedParams
|
usedParams :: C 2 ( ℝ 1 ) usedParams
|
||||||
path :: C ( ExtentOrder 'Point ) ( ℝ 1 ) ( ℝ 2 )
|
path :: C 2 ( ℝ 1 ) ( ℝ 2 )
|
||||||
( path, usedParams ) = pathAndUsedParams @Point id
|
( path, usedParams )
|
||||||
|
= pathAndUsedParams @2 @() id ptParams sp0 crv
|
||||||
|
|
||||||
curves :: ℝ 1 -- t
|
curves :: ℝ 1 -- t
|
||||||
-> Seq ( ℝ 1 {- s -} -> StrokeDatum Point )
|
-> Seq ( ℝ 1 {- s -} -> StrokeDatum 2 () )
|
||||||
curves =
|
curves =
|
||||||
brushStrokeData @Point @( ExtentOrder 'Point ) @brushParams
|
brushStrokeData @2 @brushParams
|
||||||
path
|
path
|
||||||
( chainRule @Double @( ExtentOrder 'Point )
|
( chainRule @Double @2
|
||||||
usedParams
|
usedParams
|
||||||
( linear toBrushParams )
|
( linear toBrushParams )
|
||||||
)
|
)
|
||||||
( brushFromParams @Point proxy# id )
|
( brushFromParams @2 @() proxy# id )
|
||||||
|
|
||||||
curvesI :: 𝕀ℝ 1 -- t
|
curvesI :: 𝕀ℝ 1 -- t
|
||||||
-> Seq ( 𝕀ℝ 1 {- s -} -> StrokeDatum 'Interval )
|
-> Seq ( 𝕀ℝ 1 {- s -} -> StrokeDatum 3 𝕀 )
|
||||||
curvesI = brushStrokeData @'Interval @( ExtentOrder 'Interval ) @brushParams
|
curvesI = brushStrokeData @3 @brushParams
|
||||||
pathI
|
pathI
|
||||||
( chainRule @( 𝕀 Double ) @( ExtentOrder 'Interval )
|
( chainRule @( 𝕀 Double ) @3
|
||||||
usedParamsI
|
usedParamsI
|
||||||
( linear ( nonDecreasing toBrushParams ) )
|
( linear ( nonDecreasing toBrushParams ) )
|
||||||
)
|
)
|
||||||
( brushFromParams @'Interval proxy# singleton )
|
( brushFromParams @3 @𝕀 proxy# singleton )
|
||||||
|
|
||||||
usedParamsI :: C ( ExtentOrder 'Interval ) ( 𝕀ℝ 1 ) ( 𝕀 usedParams )
|
usedParamsI :: C 3 ( 𝕀ℝ 1 ) ( 𝕀 usedParams )
|
||||||
pathI :: C ( ExtentOrder 'Interval ) ( 𝕀ℝ 1 ) ( 𝕀ℝ 2 )
|
pathI :: C 3 ( 𝕀ℝ 1 ) ( 𝕀ℝ 2 )
|
||||||
( pathI, usedParamsI ) = pathAndUsedParams @'Interval singleton
|
( pathI, usedParamsI ) = pathAndUsedParams @3 @𝕀 singleton ptParams sp0 crv
|
||||||
|
|
||||||
fwdBwd :: OutlineFn
|
fwdBwd :: OutlineFn
|
||||||
fwdBwd t
|
fwdBwd t
|
||||||
|
@ -608,10 +573,10 @@ outlineFunction ptParams toBrushParams brushFromParams = \ sp0 crv ->
|
||||||
D21 path_t path'_t _ = runD path t
|
D21 path_t path'_t _ = runD path t
|
||||||
D21 params_t _ _ = runD usedParams t
|
D21 params_t _ _ = runD usedParams t
|
||||||
brush_t = value @Double @2 @brushParams
|
brush_t = value @Double @2 @brushParams
|
||||||
$ runD ( brushFromParams @Point proxy# id )
|
$ runD ( brushFromParams @2 @() proxy# id )
|
||||||
$ toBrushParams params_t
|
$ toBrushParams params_t
|
||||||
|
|
||||||
( newtDunno, newtSols ) = intervalNewtonGS InverseMidJacobian 0.0001 curvesI
|
( newtDunno, newtSols ) = intervalNewtonGS InverseMidJacobian 1e-7 curvesI
|
||||||
|
|
||||||
in --trace
|
in --trace
|
||||||
-- ( unlines $
|
-- ( unlines $
|
||||||
|
@ -631,6 +596,37 @@ outlineFunction ptParams toBrushParams brushFromParams = \ sp0 crv ->
|
||||||
}
|
}
|
||||||
{-# INLINEABLE outlineFunction #-}
|
{-# INLINEABLE outlineFunction #-}
|
||||||
|
|
||||||
|
pathAndUsedParams :: forall k i arr crvData ptData usedParams
|
||||||
|
. ( HasType ( ℝ 2 ) ptData
|
||||||
|
, CurveOrder k
|
||||||
|
, arr ~ C k
|
||||||
|
, D k ( I i ( ℝ 1 ) ) ~ D k ( ℝ 1 )
|
||||||
|
, Coercible ( I i ( ℝ 1 ) ) ( I i Double )
|
||||||
|
, Module ( I i Double ) ( T ( I i ( ℝ 2 ) ) )
|
||||||
|
, Torsor ( T ( I i ( ℝ 2 ) ) ) ( I i ( ℝ 2 ) )
|
||||||
|
, Module ( I i Double ) ( T ( I i usedParams ) )
|
||||||
|
, Torsor ( T ( I i usedParams ) ) ( I i usedParams )
|
||||||
|
)
|
||||||
|
=> ( forall a. a -> I i a )
|
||||||
|
-> ( ptData -> usedParams )
|
||||||
|
-> ptData
|
||||||
|
-> Curve Open crvData ptData
|
||||||
|
-> ( I i ( ℝ 1 ) `arr` I i ( ℝ 2 ), I i ( ℝ 1 ) `arr` I i usedParams )
|
||||||
|
pathAndUsedParams toI ptParams sp0 crv =
|
||||||
|
case crv of
|
||||||
|
LineTo { curveEnd = NextPoint sp1 }
|
||||||
|
| let seg = Segment sp0 sp1
|
||||||
|
-> ( line @k @i ( fmap ( toI . coords ) seg )
|
||||||
|
, line @k @i ( fmap ( toI . ptParams ) seg ) )
|
||||||
|
Bezier2To { controlPoint = sp1, curveEnd = NextPoint sp2 }
|
||||||
|
| let bez2 = Quadratic.Bezier sp0 sp1 sp2
|
||||||
|
-> ( bezier2 @k @i ( fmap ( toI . coords ) bez2 )
|
||||||
|
, bezier2 @k @i ( fmap ( toI . ptParams ) bez2 ) )
|
||||||
|
Bezier3To { controlPoint1 = sp1, controlPoint2 = sp2, curveEnd = NextPoint sp3 }
|
||||||
|
| let bez3 = Cubic.Bezier sp0 sp1 sp2 sp3
|
||||||
|
-> ( bezier3 @k @i ( fmap ( toI . coords ) bez3 )
|
||||||
|
, bezier3 @k @i ( fmap ( toI . ptParams ) bez3 ) )
|
||||||
|
|
||||||
-----------------------------------
|
-----------------------------------
|
||||||
-- Various utility functions
|
-- Various utility functions
|
||||||
-- used in the "stroke" function.
|
-- used in the "stroke" function.
|
||||||
|
@ -924,10 +920,8 @@ withTangent tgt_wanted spline@( Spline { splineStart } )
|
||||||
, offset = T $ Cubic.bezier @( T ( ℝ 2 ) ) bez t
|
, offset = T $ Cubic.bezier @( T ( ℝ 2 ) ) bez t
|
||||||
}
|
}
|
||||||
|
|
||||||
|
splineCurveFns :: forall k i
|
||||||
|
. ( CurveOrder k
|
||||||
splineCurveFns :: forall i k
|
|
||||||
. ( k ~ ExtentOrder i, CurveOrder k
|
|
||||||
, D k ( I i ( ℝ 1 ) ) ~ D k ( ℝ 1 )
|
, D k ( I i ( ℝ 1 ) ) ~ D k ( ℝ 1 )
|
||||||
, Module ( I i Double ) ( T ( I i ( ℝ 2 ) ) )
|
, Module ( I i Double ) ( T ( I i ( ℝ 2 ) ) )
|
||||||
, Torsor ( T ( I i ( ℝ 2 ) ) ) ( I i ( ℝ 2 ) )
|
, Torsor ( T ( I i ( ℝ 2 ) ) ) ( I i ( ℝ 2 ) )
|
||||||
|
@ -958,7 +952,7 @@ solveEnvelopeEquations :: ℝ 1 -- ^ @t@ (for debugging only)
|
||||||
-> ℝ 2
|
-> ℝ 2
|
||||||
-> T ( ℝ 2 )
|
-> T ( ℝ 2 )
|
||||||
-> ( Offset, Offset )
|
-> ( Offset, Offset )
|
||||||
-> Seq ( ℝ 1 -> StrokeDatum Point )
|
-> Seq ( ℝ 1 -> StrokeDatum 2 () )
|
||||||
-> ( ( ℝ 2, T ( ℝ 2 ) ), ( ℝ 2, T ( ℝ 2 ) ) )
|
-> ( ( ℝ 2, T ( ℝ 2 ) ), ( ℝ 2, T ( ℝ 2 ) ) )
|
||||||
solveEnvelopeEquations _t path_t path'_t ( fwdOffset, bwdOffset ) strokeData
|
solveEnvelopeEquations _t path_t path'_t ( fwdOffset, bwdOffset ) strokeData
|
||||||
= ( fwdSol, ( bwdPt, -1 *^ bwdTgt ) )
|
= ( fwdSol, ( bwdPt, -1 *^ bwdTgt ) )
|
||||||
|
@ -1020,7 +1014,7 @@ solveEnvelopeEquations _t path_t path'_t ( fwdOffset, bwdOffset ) strokeData
|
||||||
| otherwise
|
| otherwise
|
||||||
= i + 1
|
= i + 1
|
||||||
|
|
||||||
sol :: Double -> ( ℝ 1 -> StrokeDatum Point ) -> ( Bool, ℝ 1, ℝ 2, T ( ℝ 2 ) )
|
sol :: Double -> ( ℝ 1 -> StrokeDatum 2 () ) -> ( Bool, ℝ 1, ℝ 2, T ( ℝ 2 ) )
|
||||||
sol initialGuess f =
|
sol initialGuess f =
|
||||||
let (good, s) = case newtonRaphson maxIters precision domain ( eqn f ) initialGuess of
|
let (good, s) = case newtonRaphson maxIters precision domain ( eqn f ) initialGuess of
|
||||||
Nothing -> ( False, initialGuess )
|
Nothing -> ( False, initialGuess )
|
||||||
|
@ -1052,13 +1046,13 @@ solveEnvelopeEquations _t path_t path'_t ( fwdOffset, bwdOffset ) strokeData
|
||||||
-- , " ∂E/∂s = " ++ show ee_s
|
-- , " ∂E/∂s = " ++ show ee_s
|
||||||
-- , " dc/dt = " ++ show dcdt
|
-- , " dc/dt = " ++ show dcdt
|
||||||
-- ] )
|
-- ] )
|
||||||
( good, ℝ1 s, value @Double @2 @( ℝ 2 ) dstroke, dcdt )
|
( good, ℝ1 s, value @Double @2 @( ℝ 2 ) dstroke, dcdt )
|
||||||
|
|
||||||
eqn :: ( ℝ 1 -> StrokeDatum Point ) -> ( Double -> ( Double, Double ) )
|
eqn :: ( ℝ 1 -> StrokeDatum 2 () ) -> ( Double -> ( Double, Double ) )
|
||||||
eqn f s =
|
eqn f s =
|
||||||
case f ( ℝ1 s ) of
|
case f ( ℝ1 s ) of
|
||||||
StrokeDatum { ee = D12 ( ℝ1 ee ) _ ( T ( ℝ1 ee_s ) ) } ->
|
StrokeDatum { ee = D12 ee _ ee_s } ->
|
||||||
( ee, ee_s )
|
coerce ( ee, ee_s )
|
||||||
|
|
||||||
maxIters :: Word
|
maxIters :: Word
|
||||||
maxIters = 5 --30
|
maxIters = 5 --30
|
||||||
|
@ -1074,10 +1068,9 @@ instance Applicative ZipSeq where
|
||||||
liftA2 f ( ZipSeq xs ) ( ZipSeq ys ) = ZipSeq ( Seq.zipWith f xs ys )
|
liftA2 f ( ZipSeq xs ) ( ZipSeq ys ) = ZipSeq ( Seq.zipWith f xs ys )
|
||||||
{-# INLINE liftA2 #-}
|
{-# INLINE liftA2 #-}
|
||||||
|
|
||||||
brushStrokeData :: forall i k brushParams arr
|
brushStrokeData :: forall k brushParams i arr
|
||||||
. ( k ~ ExtentOrder i, CurveOrder k, arr ~ C k
|
. ( CurveOrder k, arr ~ C k
|
||||||
, Differentiable i brushParams
|
, Differentiable k i brushParams
|
||||||
, Fractional ( I i Double )
|
|
||||||
, HasChainRule ( I i Double ) k ( I i ( ℝ 1 ) )
|
, HasChainRule ( I i Double ) k ( I i ( ℝ 1 ) )
|
||||||
, Applicative ( D k ( ℝ 1 ) )
|
, Applicative ( D k ( ℝ 1 ) )
|
||||||
|
|
||||||
|
@ -1097,7 +1090,7 @@ brushStrokeData :: forall i k brushParams arr
|
||||||
-- ^ brush parameters
|
-- ^ brush parameters
|
||||||
-> ( I i brushParams `arr` Spline Closed () ( I i ( ℝ 2 ) ) )
|
-> ( I i brushParams `arr` Spline Closed () ( I i ( ℝ 2 ) ) )
|
||||||
-- ^ brush from parameters
|
-- ^ brush from parameters
|
||||||
-> ( I i ( ℝ 1 ) -> Seq ( I i ( ℝ 1 ) -> StrokeDatum i ) )
|
-> ( I i ( ℝ 1 ) -> Seq ( I i ( ℝ 1 ) -> StrokeDatum k i ) )
|
||||||
brushStrokeData path params brush =
|
brushStrokeData path params brush =
|
||||||
\ t ->
|
\ t ->
|
||||||
let
|
let
|
||||||
|
@ -1108,7 +1101,7 @@ brushStrokeData path params brush =
|
||||||
dbrush_params :: D k ( I i brushParams ) ( Spline Closed () ( I i ( ℝ 2 ) ) )
|
dbrush_params :: D k ( I i brushParams ) ( Spline Closed () ( I i ( ℝ 2 ) ) )
|
||||||
!dbrush_params = runD brush $ value @( I i Double ) @k @( I i ( ℝ 1 ) ) dparams_t
|
!dbrush_params = runD brush $ value @( I i Double ) @k @( I i ( ℝ 1 ) ) dparams_t
|
||||||
splines :: Seq ( D k ( I i brushParams ) ( I i ( ℝ 1 ) `arr` I i ( ℝ 2 ) ) )
|
splines :: Seq ( D k ( I i brushParams ) ( I i ( ℝ 1 ) `arr` I i ( ℝ 2 ) ) )
|
||||||
!splines = getZipSeq $ traverse ( ZipSeq . splineCurveFns @i @k ) dbrush_params
|
!splines = getZipSeq $ traverse ( ZipSeq . splineCurveFns @k @i ) dbrush_params
|
||||||
dbrushes_t :: Seq ( I i ( ℝ 1 ) -> D k ( I i ( ℝ 2 ) ) ( I i ( ℝ 2 ) ) )
|
dbrushes_t :: Seq ( I i ( ℝ 1 ) -> D k ( I i ( ℝ 2 ) ) ( I i ( ℝ 2 ) ) )
|
||||||
!dbrushes_t = force $ fmap ( uncurryD @k . ( chain @(I i Double) @k dparams_t ) ) splines
|
!dbrushes_t = force $ fmap ( uncurryD @k . ( chain @(I i Double) @k dparams_t ) ) splines
|
||||||
-- This is the crucial use of the chain rule.
|
-- This is the crucial use of the chain rule.
|
||||||
|
@ -1118,7 +1111,7 @@ brushStrokeData path params brush =
|
||||||
|
|
||||||
mkStrokeDatum :: D k ( I i ( ℝ 1 ) ) ( I i ( ℝ 2 ) )
|
mkStrokeDatum :: D k ( I i ( ℝ 1 ) ) ( I i ( ℝ 2 ) )
|
||||||
-> ( I i ( ℝ 1 ) -> D k ( I i ( ℝ 2 ) ) ( I i ( ℝ 2 ) ) )
|
-> ( I i ( ℝ 1 ) -> D k ( I i ( ℝ 2 ) ) ( I i ( ℝ 2 ) ) )
|
||||||
-> ( I i ( ℝ 1 ) -> StrokeDatum i )
|
-> ( I i ( ℝ 1 ) -> StrokeDatum k i )
|
||||||
mkStrokeDatum dpath_t dbrush_t s =
|
mkStrokeDatum dpath_t dbrush_t s =
|
||||||
let dbrush_t_s = dbrush_t s
|
let dbrush_t_s = dbrush_t s
|
||||||
dstroke = brushStroke @k dpath_t dbrush_t_s
|
dstroke = brushStroke @k dpath_t dbrush_t_s
|
||||||
|
@ -1200,7 +1193,7 @@ extendedRecip x@( 𝕀 lo hi )
|
||||||
|
|
||||||
-- | Computes the brush stroke coordinates of a cusp from
|
-- | Computes the brush stroke coordinates of a cusp from
|
||||||
-- the @(t,s)@ parameter values.
|
-- the @(t,s)@ parameter values.
|
||||||
cuspCoords :: ( ℝ 1 -> Seq ( ℝ 1 -> StrokeDatum 'Point ) )
|
cuspCoords :: ( ℝ 1 -> Seq ( ℝ 1 -> StrokeDatum 2 () ) )
|
||||||
-> ( 𝕀ℝ 1, Int, 𝕀ℝ 1 )
|
-> ( 𝕀ℝ 1, Int, 𝕀ℝ 1 )
|
||||||
-> Cusp
|
-> Cusp
|
||||||
cuspCoords eqs ( 𝕀 ( ℝ1 t_lo ) ( ℝ1 t_hi ), i, 𝕀 ( ℝ1 s_lo ) ( ℝ1 s_hi ) )
|
cuspCoords eqs ( 𝕀 ( ℝ1 t_lo ) ( ℝ1 t_hi ), i, 𝕀 ( ℝ1 s_lo ) ( ℝ1 s_hi ) )
|
||||||
|
@ -1210,8 +1203,8 @@ cuspCoords eqs ( 𝕀 ( ℝ1 t_lo ) ( ℝ1 t_hi ), i, 𝕀 ( ℝ1 s_lo ) ( ℝ1
|
||||||
<- ( eqs ( ℝ1 t_mid ) `Seq.index` i ) ( ℝ1 s_mid )
|
<- ( eqs ( ℝ1 t_mid ) `Seq.index` i ) ( ℝ1 s_mid )
|
||||||
= Cusp
|
= Cusp
|
||||||
{ cuspParameters = ℝ2 t_mid s_mid
|
{ cuspParameters = ℝ2 t_mid s_mid
|
||||||
, cuspPathCoords = dpath
|
, cuspPathCoords = coerce dpath
|
||||||
, cuspStrokeCoords = stroke
|
, cuspStrokeCoords = coerce stroke
|
||||||
}
|
}
|
||||||
where
|
where
|
||||||
t_mid = 0.5 * ( t_lo + t_hi )
|
t_mid = 0.5 * ( t_lo + t_hi )
|
||||||
|
@ -1228,33 +1221,41 @@ data Preconditioner
|
||||||
--
|
--
|
||||||
-- Returns @(dunno, sols)@ where @sols@ are boxes that contain a unique solution
|
-- Returns @(dunno, sols)@ where @sols@ are boxes that contain a unique solution
|
||||||
-- (and to which Newton's method will converge starting from anywhere inside
|
-- (and to which Newton's method will converge starting from anywhere inside
|
||||||
-- the box), and @dunno@ which are small boxes which might or might not
|
-- the box), and @dunno@ are small boxes which might or might not
|
||||||
-- contain solutions.
|
-- contain solutions.
|
||||||
intervalNewtonGS :: Preconditioner
|
intervalNewtonGS :: Preconditioner
|
||||||
-> Double
|
-> Double
|
||||||
-> ( 𝕀ℝ 1 -> Seq ( 𝕀ℝ 1 -> StrokeDatum 'Interval ) )
|
-> ( 𝕀ℝ 1 -> Seq ( 𝕀ℝ 1 -> StrokeDatum 3 𝕀 ) )
|
||||||
-> ( [ ( 𝕀ℝ 1, Int, 𝕀ℝ 1 ) ], [ ( 𝕀ℝ 1, Int, 𝕀ℝ 1 ) ] )
|
-> ( [ ( 𝕀ℝ 1, Int, 𝕀ℝ 1 ) ], [ ( 𝕀ℝ 1, Int, 𝕀ℝ 1 ) ] )
|
||||||
intervalNewtonGS precondMethod minWidth eqs =
|
intervalNewtonGS precondMethod minWidth eqs =
|
||||||
go [ ( 𝕀 ( ℝ1 0 ) ( ℝ1 1 ), i, 𝕀 ( ℝ1 0 ) ( ℝ1 1 ) )
|
go (0,0)
|
||||||
| i <- [ 0 .. length ( eqs ( 𝕀 ( ℝ1 0 ) ( ℝ1 1 ) ) ) - 1 ]
|
[ ( 𝕀 ( ℝ1 0 ) ( ℝ1 1 ), i, 𝕀 ( ℝ1 0 ) ( ℝ1 1 ) )
|
||||||
]
|
| i <- [ 0 .. length ( eqs ( 𝕀 ( ℝ1 0 ) ( ℝ1 1 ) ) ) - 1 ]
|
||||||
[]
|
]
|
||||||
[]
|
[]
|
||||||
|
[]
|
||||||
|
|
||||||
where
|
where
|
||||||
|
|
||||||
go :: [ ( 𝕀ℝ 1, Int, 𝕀ℝ 1 ) ] -- boxes to work on
|
go :: ( Int, Int ) -- step counts (for debugging)
|
||||||
|
-> [ ( 𝕀ℝ 1, Int, 𝕀ℝ 1 ) ] -- boxes to work on
|
||||||
-> [ ( 𝕀ℝ 1, Int, 𝕀ℝ 1 ) ] -- too small: don't shrink further
|
-> [ ( 𝕀ℝ 1, Int, 𝕀ℝ 1 ) ] -- too small: don't shrink further
|
||||||
-> [ ( 𝕀ℝ 1, Int, 𝕀ℝ 1 ) ] -- found solutions
|
-> [ ( 𝕀ℝ 1, Int, 𝕀ℝ 1 ) ] -- found solutions
|
||||||
-> ( [ ( 𝕀ℝ 1, Int, 𝕀ℝ 1 ) ], [ ( 𝕀ℝ 1, Int, 𝕀ℝ 1 ) ] )
|
-> ( [ ( 𝕀ℝ 1, Int, 𝕀ℝ 1 ) ], [ ( 𝕀ℝ 1, Int, 𝕀ℝ 1 ) ] )
|
||||||
go [] giveUp sols = ( giveUp, sols )
|
go ( bis, newt ) [] giveUp sols =
|
||||||
go ( cand@( t@( 𝕀 ( ℝ1 t_lo ) ( ℝ1 t_hi ) )
|
trace ( unlines [ "intervalNewtonGS done"
|
||||||
, i
|
, " #bisections: " ++ show bis
|
||||||
, s@( 𝕀 ( ℝ1 s_lo ) ( ℝ1 s_hi ) )
|
, " #newtonSteps: " ++ show newt
|
||||||
) : cands ) giveUp sols
|
, " #sols: " ++ show ( length sols )
|
||||||
|
, " #dunno: " ++ show ( length giveUp ) ] )
|
||||||
|
( giveUp, sols )
|
||||||
|
go ( bis, newt ) ( cand@( t@( 𝕀 ( ℝ1 t_lo ) ( ℝ1 t_hi ) )
|
||||||
|
, i
|
||||||
|
, s@( 𝕀 ( ℝ1 s_lo ) ( ℝ1 s_hi ) )
|
||||||
|
) : cands ) giveUp sols
|
||||||
-- Box is small: stop processing it.
|
-- Box is small: stop processing it.
|
||||||
| t_hi - t_lo < minWidth && s_hi - s_lo < minWidth
|
| t_hi - t_lo < minWidth && s_hi - s_lo < minWidth
|
||||||
= go cands ( cand : giveUp ) sols
|
= go ( bis, newt ) cands ( cand : giveUp ) sols
|
||||||
|
|
||||||
| StrokeDatum { ee = D22 ee _ _ _ _ _
|
| StrokeDatum { ee = D22 ee _ _ _ _ _
|
||||||
, 𝛿E𝛿sdcdt = D12 ( T f ) ( T ( T f_t ) ) ( T ( T f_s ) ) }
|
, 𝛿E𝛿sdcdt = D12 ( T f ) ( T ( T f_t ) ) ( T ( T f_s ) ) }
|
||||||
|
@ -1262,14 +1263,14 @@ intervalNewtonGS precondMethod minWidth eqs =
|
||||||
|
|
||||||
, StrokeDatum { 𝛿E𝛿sdcdt = D12 ( T f_mid ) ( T ( T f_t_mid ) ) ( T ( T f_s_mid ) ) }
|
, StrokeDatum { 𝛿E𝛿sdcdt = D12 ( T f_mid ) ( T ( T f_t_mid ) ) ( T ( T f_s_mid ) ) }
|
||||||
<- ( eqs i_t_mid `Seq.index` i ) i_s_mid
|
<- ( eqs i_t_mid `Seq.index` i ) i_s_mid
|
||||||
= if | Interval.inf ( ival ee ) < Rounded ( ℝ1 0 )
|
= if | inf ee < ℝ1 0
|
||||||
, Interval.sup ( ival ee ) > Rounded ( ℝ1 0 )
|
, sup ee > ℝ1 0
|
||||||
, cmpℝ2 (<) ( getRounded ( Interval.inf $ ival f ) ) ( ℝ2 0 0 )
|
, cmpℝ2 (<) ( inf f ) ( ℝ2 0 0 )
|
||||||
, cmpℝ2 (>) ( getRounded ( Interval.sup $ ival f ) ) ( ℝ2 0 0 )
|
, cmpℝ2 (>) ( sup f ) ( ℝ2 0 0 )
|
||||||
-> let -- Interval Newton method: take one Gauss–Seidel step
|
-> let -- Interval Newton method: take one Gauss–Seidel step
|
||||||
-- for the equation f'(X) v = - f(x_mid).
|
-- for the equation f'(X) v = - f(x_mid).
|
||||||
!( a, b ) = precondition precondMethod
|
!( a, b ) = precondition precondMethod
|
||||||
( f_t_mid, f_s_mid )
|
( f_t, f_s )
|
||||||
( f_t, f_s ) ( neg f_mid )
|
( f_t, f_s ) ( neg f_mid )
|
||||||
|
|
||||||
!gsGuesses = gaussSeidel a b
|
!gsGuesses = gaussSeidel a b
|
||||||
|
@ -1284,7 +1285,7 @@ intervalNewtonGS precondMethod minWidth eqs =
|
||||||
-- Newton's method is guaranteed to converge to the unique solution.
|
-- Newton's method is guaranteed to converge to the unique solution.
|
||||||
let !(done, todo) = bimap ( map ( mkGuess . fst ) ) ( map ( mkGuess . fst ) )
|
let !(done, todo) = bimap ( map ( mkGuess . fst ) ) ( map ( mkGuess . fst ) )
|
||||||
$ partition snd gsGuesses
|
$ partition snd gsGuesses
|
||||||
in go ( todo ++ cands ) giveUp ( done ++ sols )
|
in go ( bis, newt + 1 ) ( todo ++ cands ) giveUp ( done ++ sols )
|
||||||
else
|
else
|
||||||
-- Gauss–Seidel failed to shrink the boxes.
|
-- Gauss–Seidel failed to shrink the boxes.
|
||||||
-- Bisect along the widest dimension instead.
|
-- Bisect along the widest dimension instead.
|
||||||
|
@ -1295,11 +1296,11 @@ intervalNewtonGS precondMethod minWidth eqs =
|
||||||
| otherwise
|
| otherwise
|
||||||
= [ ( t, i, 𝕀 ( ℝ1 s_lo ) ( ℝ1 s_mid ) )
|
= [ ( t, i, 𝕀 ( ℝ1 s_lo ) ( ℝ1 s_mid ) )
|
||||||
, ( t, i, 𝕀 ( ℝ1 s_mid ) ( ℝ1 s_hi ) ) ]
|
, ( t, i, 𝕀 ( ℝ1 s_mid ) ( ℝ1 s_hi ) ) ]
|
||||||
in go ( bisGuesses ++ cands ) giveUp sols
|
in go ( bis + 1, newt ) ( bisGuesses ++ cands ) giveUp sols
|
||||||
|
|
||||||
-- Box doesn't contain a solution: discard it.
|
-- Box doesn't contain a solution: discard it.
|
||||||
| otherwise
|
| otherwise
|
||||||
-> go cands giveUp sols
|
-> go ( bis, newt ) cands giveUp sols
|
||||||
where
|
where
|
||||||
t_mid = 0.5 * ( t_lo + t_hi )
|
t_mid = 0.5 * ( t_lo + t_hi )
|
||||||
s_mid = 0.5 * ( s_lo + s_hi )
|
s_mid = 0.5 * ( s_lo + s_hi )
|
||||||
|
@ -1336,7 +1337,7 @@ precondition meth jac_mid a@( a1, a2 ) b =
|
||||||
!a22 = 0.5 * ( a22_lo + a22_hi )
|
!a22 = 0.5 * ( a22_lo + a22_hi )
|
||||||
!d = a11 * a22 - a12 * a21
|
!d = a11 * a22 - a12 * a21
|
||||||
, not ( nearZero d )
|
, not ( nearZero d )
|
||||||
, let !precond = ( ℝ2 a22 -a21, ℝ2 -a12 a11 )
|
, let !precond = ( ℝ2 a22 -a12, ℝ2 -a21 a11 )
|
||||||
!inv = recip d
|
!inv = recip d
|
||||||
f x = scale inv $ matMulVec precond x
|
f x = scale inv $ matMulVec precond x
|
||||||
-> ( ( f a1, f a2 ), f b )
|
-> ( ( f a1, f a2 ), f b )
|
||||||
|
@ -1345,21 +1346,19 @@ precondition meth jac_mid a@( a1, a2 ) b =
|
||||||
|
|
||||||
scale :: Double -> 𝕀ℝ 2 -> 𝕀ℝ 2
|
scale :: Double -> 𝕀ℝ 2 -> 𝕀ℝ 2
|
||||||
scale s ( 𝕀 ( ℝ2 a1_lo a2_lo ) ( ℝ2 a1_hi a2_hi ) )
|
scale s ( 𝕀 ( ℝ2 a1_lo a2_lo ) ( ℝ2 a1_hi a2_hi ) )
|
||||||
| I ( Rounded b1_lo ) ( Rounded b1_hi )
|
| 𝕀 b1_lo b1_hi <- scaleInterval s ( 𝕀 a1_lo a1_hi )
|
||||||
<- I ( Rounded s ) ( Rounded s ) * I ( Rounded a1_lo ) ( Rounded a1_hi )
|
, 𝕀 b2_lo b2_hi <- scaleInterval s ( 𝕀 a2_lo a2_hi )
|
||||||
, I ( Rounded b2_lo ) ( Rounded b2_hi )
|
|
||||||
<- I ( Rounded s ) ( Rounded s ) * I ( Rounded a2_lo ) ( Rounded a2_hi )
|
|
||||||
= 𝕀 ( ℝ2 b1_lo b2_lo ) ( ℝ2 b1_hi b2_hi )
|
= 𝕀 ( ℝ2 b1_lo b2_lo ) ( ℝ2 b1_hi b2_hi )
|
||||||
|
|
||||||
matMulVec :: ( ℝ 2, ℝ 2 ) -> 𝕀ℝ 2 -> 𝕀ℝ 2
|
matMulVec :: ( ℝ 2, ℝ 2 ) -> 𝕀ℝ 2 -> 𝕀ℝ 2
|
||||||
matMulVec ( ℝ2 a11 a21, ℝ2 a12 a22 ) ( 𝕀 ( ℝ2 u_lo v_lo ) ( ℝ2 u_hi v_hi ) ) =
|
matMulVec ( ℝ2 a11 a21, ℝ2 a12 a22 ) ( 𝕀 ( ℝ2 u_lo v_lo ) ( ℝ2 u_hi v_hi ) )
|
||||||
let !( I ( Rounded u'_lo ) ( Rounded u'_hi ) ) =
|
| 𝕀 u'_lo u'_hi <-
|
||||||
I ( Rounded a11 ) ( Rounded a11 ) * I ( Rounded u_lo ) ( Rounded u_hi )
|
𝕀 a11 a11 * 𝕀 u_lo u_hi
|
||||||
+ I ( Rounded a12 ) ( Rounded a12 ) * I ( Rounded v_lo ) ( Rounded v_hi )
|
+ 𝕀 a12 a12 * 𝕀 v_lo v_hi
|
||||||
!( I ( Rounded v'_lo ) ( Rounded v'_hi ) ) =
|
, 𝕀 v'_lo v'_hi <-
|
||||||
I ( Rounded a21 ) ( Rounded a21 ) * I ( Rounded u_lo ) ( Rounded u_hi )
|
𝕀 a21 a21 * 𝕀 u_lo u_hi
|
||||||
+ I ( Rounded a22 ) ( Rounded a22 ) * I ( Rounded v_lo ) ( Rounded v_hi )
|
+ 𝕀 a22 a22 * 𝕀 v_lo v_hi
|
||||||
in 𝕀 ( ℝ2 u'_lo v'_lo ) ( ℝ2 u'_hi v'_hi )
|
= 𝕀 ( ℝ2 u'_lo v'_lo ) ( ℝ2 u'_hi v'_hi )
|
||||||
|
|
||||||
|
|
||||||
cmpℝ2 :: ( Double -> Double -> Bool ) -> ℝ 2 -> ℝ 2 -> Bool
|
cmpℝ2 :: ( Double -> Double -> Bool ) -> ℝ 2 -> ℝ 2 -> Bool
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
{-# LANGUAGE AllowAmbiguousTypes #-}
|
{-# LANGUAGE AllowAmbiguousTypes #-}
|
||||||
|
{-# LANGUAGE PolyKinds #-}
|
||||||
{-# LANGUAGE RebindableSyntax #-}
|
{-# LANGUAGE RebindableSyntax #-}
|
||||||
{-# LANGUAGE ScopedTypeVariables #-}
|
{-# LANGUAGE ScopedTypeVariables #-}
|
||||||
|
|
||||||
|
@ -11,8 +12,10 @@ module Math.Bezier.Stroke.EnvelopeEquation
|
||||||
import Prelude hiding ( Num(..), (^) )
|
import Prelude hiding ( Num(..), (^) )
|
||||||
import Data.Coerce
|
import Data.Coerce
|
||||||
( Coercible, coerce )
|
( Coercible, coerce )
|
||||||
|
import Data.Functor.Identity
|
||||||
|
( Identity(..) )
|
||||||
import Data.Kind
|
import Data.Kind
|
||||||
( Constraint )
|
( Type, Constraint )
|
||||||
import GHC.TypeNats
|
import GHC.TypeNats
|
||||||
( Nat, type (-) )
|
( Nat, type (-) )
|
||||||
|
|
||||||
|
@ -25,7 +28,7 @@ import Math.Algebra.Dual
|
||||||
import qualified Math.Bezier.Cubic as Cubic
|
import qualified Math.Bezier.Cubic as Cubic
|
||||||
import qualified Math.Bezier.Quadratic as Quadratic
|
import qualified Math.Bezier.Quadratic as Quadratic
|
||||||
import Math.Differentiable
|
import Math.Differentiable
|
||||||
( type ExtentOrder )
|
( type I )
|
||||||
import Math.Interval
|
import Math.Interval
|
||||||
import Math.Linear
|
import Math.Linear
|
||||||
import Math.Module
|
import Math.Module
|
||||||
|
@ -37,34 +40,35 @@ import Math.Ring
|
||||||
-- | The value and derivative of a brush stroke at a given coordinate
|
-- | The value and derivative of a brush stroke at a given coordinate
|
||||||
-- \( (t_0, s_0) \), together with the value of the envelope equation at that
|
-- \( (t_0, s_0) \), together with the value of the envelope equation at that
|
||||||
-- point.
|
-- point.
|
||||||
data StrokeDatum i
|
type StrokeDatum :: Nat -> k -> Type
|
||||||
|
data StrokeDatum k i
|
||||||
= StrokeDatum
|
= StrokeDatum
|
||||||
{ -- | Path \( p(t_0) \).
|
{ -- | Path \( p(t_0) \).
|
||||||
dpath :: D ( ExtentOrder i ) ( I i ( ℝ 1 ) ) ( I i ( ℝ 2 ) )
|
dpath :: D k ( I i ( ℝ 1 ) ) ( I i ( ℝ 2 ) )
|
||||||
-- | Brush shape \( b(t_0, s_0) \).
|
-- | Brush shape \( b(t_0, s_0) \).
|
||||||
, dbrush :: D ( ExtentOrder i ) ( I i ( ℝ 2 ) ) ( I i ( ℝ 2 ) )
|
, dbrush :: D k ( I i ( ℝ 2 ) ) ( I i ( ℝ 2 ) )
|
||||||
|
|
||||||
-- Everything below can be computed in terms of the first two fields.
|
-- Everything below can be computed in terms of the first two fields.
|
||||||
|
|
||||||
-- | Stroke \( c(t_0,s_0) = p(t_0) + b(t_0,s_0) \).
|
-- | Stroke \( c(t_0,s_0) = p(t_0) + b(t_0,s_0) \).
|
||||||
, dstroke :: D ( ExtentOrder i ) ( I i ( ℝ 2 ) ) ( I i ( ℝ 2 ) )
|
, dstroke :: D k ( I i ( ℝ 2 ) ) ( I i ( ℝ 2 ) )
|
||||||
|
|
||||||
-- | Envelope function
|
-- | Envelope function
|
||||||
--
|
--
|
||||||
-- \[ E(t_0,s_0) = \left ( \frac{\partial c}{\partial t} \times \frac{\partial c}{\partial s} \right )_{(t_0,s_0)}. \]
|
-- \[ E(t_0,s_0) = \left ( \frac{\partial c}{\partial t} \times \frac{\partial c}{\partial s} \right )_{(t_0,s_0)}. \]
|
||||||
, ee :: D ( ExtentOrder i - 1 ) ( I i ( ℝ 2 ) ) ( I i ( ℝ 1 ) )
|
, ee :: D ( k - 1 ) ( I i ( ℝ 2 ) ) ( I i ( ℝ 1 ) )
|
||||||
|
|
||||||
-- \[ \frac{\partial E}{\partial s} \frac{\mathrm{d} c}{\mathrm{d} t}, \]
|
-- \[ \frac{\partial E}{\partial s} \frac{\mathrm{d} c}{\mathrm{d} t}, \]
|
||||||
--
|
--
|
||||||
-- where \( \frac{\mathrm{d} c}{\mathrm{d} t} \)
|
-- where \( \frac{\mathrm{d} c}{\mathrm{d} t} \)
|
||||||
--
|
--
|
||||||
-- denotes a total derivative.
|
-- denotes a total derivative.
|
||||||
, 𝛿E𝛿sdcdt :: D ( ExtentOrder i - 2 ) ( I i ( ℝ 2 ) ) ( T ( I i ( ℝ 2 ) ) )
|
, 𝛿E𝛿sdcdt :: D ( k - 2 ) ( I i ( ℝ 2 ) ) ( T ( I i ( ℝ 2 ) ) )
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
deriving stock instance Show ( StrokeDatum 'Point )
|
deriving stock instance Show ( StrokeDatum 2 () )
|
||||||
deriving stock instance Show ( StrokeDatum 'Interval )
|
deriving stock instance Show ( StrokeDatum 3 𝕀 )
|
||||||
|
|
||||||
--------------------------------------------------------------------------------
|
--------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
@ -123,8 +127,7 @@ class CurveOrder k where
|
||||||
--
|
--
|
||||||
-- denotes a total derivative.
|
-- denotes a total derivative.
|
||||||
envelopeEquation :: forall i
|
envelopeEquation :: forall i
|
||||||
. ( k ~ ExtentOrder i
|
. ( D ( k - 2 ) ( I i ( ℝ 2 ) ) ~ D ( k - 2 ) ( ℝ 2 )
|
||||||
, D ( k - 2 ) ( I i ( ℝ 2 ) ) ~ D ( k - 2 ) ( ℝ 2 )
|
|
||||||
, D ( k - 1 ) ( I i ( ℝ 2 ) ) ~ D ( k - 1 ) ( ℝ 2 )
|
, D ( k - 1 ) ( I i ( ℝ 2 ) ) ~ D ( k - 1 ) ( ℝ 2 )
|
||||||
, D k ( I i ( ℝ 2 ) ) ~ D k ( ℝ 2 )
|
, D k ( I i ( ℝ 2 ) ) ~ D k ( ℝ 2 )
|
||||||
, Cross ( I i Double ) ( T ( I i ( ℝ 2 ) ) )
|
, Cross ( I i Double ) ( T ( I i ( ℝ 2 ) ) )
|
||||||
|
@ -134,7 +137,6 @@ class CurveOrder k where
|
||||||
-> ( D ( k - 1 ) ( I i ( ℝ 2 ) ) ( I i ( ℝ 1 ) )
|
-> ( D ( k - 1 ) ( I i ( ℝ 2 ) ) ( I i ( ℝ 1 ) )
|
||||||
, D ( k - 2 ) ( I i ( ℝ 2 ) ) ( T ( I i ( ℝ 2 ) ) ) )
|
, D ( k - 2 ) ( I i ( ℝ 2 ) ) ( T ( I i ( ℝ 2 ) ) ) )
|
||||||
|
|
||||||
|
|
||||||
instance CurveOrder 2 where
|
instance CurveOrder 2 where
|
||||||
line ( Segment a b :: Segment b ) =
|
line ( Segment a b :: Segment b ) =
|
||||||
D \ ( coerce -> t ) ->
|
D \ ( coerce -> t ) ->
|
||||||
|
|
|
@ -1,7 +1,8 @@
|
||||||
|
{-# LANGUAGE PolyKinds #-}
|
||||||
{-# LANGUAGE UndecidableInstances #-}
|
{-# LANGUAGE UndecidableInstances #-}
|
||||||
|
|
||||||
module Math.Differentiable
|
module Math.Differentiable
|
||||||
( ExtentOrder, Differentiable, DiffInterp )
|
( I, Differentiable, DiffInterp )
|
||||||
where
|
where
|
||||||
|
|
||||||
-- base
|
-- base
|
||||||
|
@ -13,52 +14,53 @@ import GHC.TypeNats
|
||||||
-- MetaBrush
|
-- MetaBrush
|
||||||
import Math.Algebra.Dual
|
import Math.Algebra.Dual
|
||||||
( D, HasChainRule )
|
( D, HasChainRule )
|
||||||
|
import Math.Interval
|
||||||
|
( 𝕀 )
|
||||||
import Math.Linear
|
import Math.Linear
|
||||||
import Math.Module
|
import Math.Module
|
||||||
import Math.Interval
|
|
||||||
( Extent(..), type I )
|
|
||||||
import Math.Ring
|
import Math.Ring
|
||||||
( Transcendental )
|
( Transcendental )
|
||||||
|
|
||||||
--------------------------------------------------------------------------------
|
--------------------------------------------------------------------------------
|
||||||
|
|
||||||
type ExtentOrder :: Extent -> Nat
|
-- | Type family to parametrise over both pointwise and interval computations.
|
||||||
type family ExtentOrder e where
|
--
|
||||||
ExtentOrder 'Point = 2
|
-- Use '()' parameter for points, and '𝕀' parameter for intervals.
|
||||||
ExtentOrder 'Interval = 3
|
type I :: k -> Type -> Type
|
||||||
-- Currently we're doing order 2 derivatives for the brush stroke fitting,
|
type family I i a
|
||||||
-- but order 3 derivatives for the interval Newton method to find cusps.
|
type instance I () a = a
|
||||||
|
type instance I 𝕀 a = 𝕀 a
|
||||||
|
|
||||||
type Differentiable :: Extent -> Type -> Constraint
|
type Differentiable :: Nat -> k -> Type -> Constraint
|
||||||
class
|
class
|
||||||
( Module ( I i Double ) ( T ( I i u ) )
|
( Module ( I i Double ) ( T ( I i u ) )
|
||||||
, HasChainRule ( I i Double ) ( ExtentOrder i ) ( I i u )
|
, HasChainRule ( I i Double ) k ( I i u )
|
||||||
, Traversable ( D ( ExtentOrder i ) ( I i u ) )
|
, Traversable ( D k ( I i u ) )
|
||||||
) => Differentiable i u
|
) => Differentiable k i u
|
||||||
instance
|
instance
|
||||||
( Module ( I i Double ) ( T ( I i u ) )
|
( Module ( I i Double ) ( T ( I i u ) )
|
||||||
, HasChainRule ( I i Double ) ( ExtentOrder i ) ( I i u )
|
, HasChainRule ( I i Double ) k ( I i u )
|
||||||
, Traversable ( D ( ExtentOrder i ) ( I i u ) )
|
, Traversable ( D k ( I i u ) )
|
||||||
) => Differentiable i u
|
) => Differentiable k i u
|
||||||
|
|
||||||
type DiffInterp :: Extent -> Type -> Constraint
|
type DiffInterp :: Nat -> k -> Type -> Constraint
|
||||||
class
|
class
|
||||||
( Differentiable i u
|
( Differentiable k i u
|
||||||
, Interpolatable ( I i Double ) ( I i u )
|
, Interpolatable ( I i Double ) ( I i u )
|
||||||
, Module ( I i Double ) ( T ( I i Double ) )
|
, Module ( I i Double ) ( T ( I i Double ) )
|
||||||
, Module ( D ( ExtentOrder i ) ( I i u ) ( I i Double ) )
|
, Module ( D k ( I i u ) ( I i Double ) )
|
||||||
( D ( ExtentOrder i ) ( I i u ) ( I i ( ℝ 2 ) ) )
|
( D k ( I i u ) ( I i ( ℝ 2 ) ) )
|
||||||
, Transcendental ( D ( ExtentOrder i ) ( I i u ) ( I i Double ) )
|
, Transcendental ( D k ( I i u ) ( I i Double ) )
|
||||||
, Applicative ( D ( ExtentOrder i ) ( I i u ) )
|
, Applicative ( D k ( I i u ) )
|
||||||
, Representable ( I i Double ) ( I i u )
|
, Representable ( I i Double ) ( I i u )
|
||||||
) => DiffInterp i u
|
) => DiffInterp k i u
|
||||||
instance
|
instance
|
||||||
( Differentiable i u
|
( Differentiable k i u
|
||||||
, Interpolatable ( I i Double ) ( I i u )
|
, Interpolatable ( I i Double ) ( I i u )
|
||||||
, Module ( I i Double ) ( T ( I i Double ) )
|
, Module ( I i Double ) ( T ( I i Double ) )
|
||||||
, Module ( D ( ExtentOrder i ) ( I i u ) ( I i Double ) )
|
, Module ( D k ( I i u ) ( I i Double ) )
|
||||||
( D ( ExtentOrder i ) ( I i u ) ( I i ( ℝ 2 ) ) )
|
( D k ( I i u ) ( I i ( ℝ 2 ) ) )
|
||||||
, Transcendental ( D ( ExtentOrder i ) ( I i u ) ( I i Double ) )
|
, Transcendental ( D k ( I i u ) ( I i Double ) )
|
||||||
, Applicative ( D ( ExtentOrder i ) ( I i u ) )
|
, Applicative ( D k ( I i u ) )
|
||||||
, Representable ( I i Double ) ( I i u )
|
, Representable ( I i Double ) ( I i u )
|
||||||
) => DiffInterp i u
|
) => DiffInterp k i u
|
||||||
|
|
|
@ -4,21 +4,19 @@
|
||||||
|
|
||||||
{-# OPTIONS_GHC -Wno-orphans #-}
|
{-# OPTIONS_GHC -Wno-orphans #-}
|
||||||
|
|
||||||
|
{-# OPTIONS_GHC -ddump-splices -ddump-simpl -ddump-cmm -ddump-to-file -dno-typeable-binds
|
||||||
|
-dsuppress-unfoldings -dsuppress-coercions #-}
|
||||||
|
|
||||||
module Math.Interval
|
module Math.Interval
|
||||||
( 𝕀(..), 𝕀ℝ
|
( 𝕀(𝕀), inf, sup
|
||||||
, Extent(..), type I
|
, scaleInterval
|
||||||
|
, 𝕀ℝ
|
||||||
, singleton, nonDecreasing
|
, singleton, nonDecreasing
|
||||||
)
|
)
|
||||||
where
|
where
|
||||||
|
|
||||||
-- base
|
-- base
|
||||||
import Prelude hiding ( Num(..) )
|
import Prelude hiding ( Num(..) )
|
||||||
import Data.Coerce
|
|
||||||
( coerce )
|
|
||||||
import Data.Kind
|
|
||||||
( Type )
|
|
||||||
import Data.Monoid
|
|
||||||
( Sum(..) )
|
|
||||||
|
|
||||||
-- acts
|
-- acts
|
||||||
import Data.Act
|
import Data.Act
|
||||||
|
@ -37,7 +35,7 @@ import Math.Algebra.Dual
|
||||||
import Math.Algebra.Dual.Internal
|
import Math.Algebra.Dual.Internal
|
||||||
( chainRule1NQ )
|
( chainRule1NQ )
|
||||||
import Math.Interval.Internal
|
import Math.Interval.Internal
|
||||||
( 𝕀(..) )
|
( 𝕀(𝕀), inf, sup, scaleInterval )
|
||||||
import Math.Linear
|
import Math.Linear
|
||||||
( ℝ(..), T(..)
|
( ℝ(..), T(..)
|
||||||
, RepresentableQ(..)
|
, RepresentableQ(..)
|
||||||
|
@ -52,14 +50,6 @@ import Math.Ring
|
||||||
type 𝕀ℝ n = 𝕀 ( ℝ n )
|
type 𝕀ℝ n = 𝕀 ( ℝ n )
|
||||||
type instance D k ( 𝕀 v ) = D k v
|
type instance D k ( 𝕀 v ) = D k v
|
||||||
|
|
||||||
-- Handling points and intervals uniformly.
|
|
||||||
data Extent = Point | Interval
|
|
||||||
|
|
||||||
type I :: Extent -> Type -> Type
|
|
||||||
type family I i a where
|
|
||||||
I 'Point a = a
|
|
||||||
I 'Interval a = 𝕀 a
|
|
||||||
|
|
||||||
singleton :: a -> 𝕀 a
|
singleton :: a -> 𝕀 a
|
||||||
singleton a = 𝕀 a a
|
singleton a = 𝕀 a a
|
||||||
|
|
||||||
|
@ -76,9 +66,9 @@ deriving via ViaAbelianGroup ( T ( 𝕀 Double ) )
|
||||||
instance Group ( T ( 𝕀 Double ) )
|
instance Group ( T ( 𝕀 Double ) )
|
||||||
|
|
||||||
instance Act ( T ( 𝕀 Double ) ) ( 𝕀 Double ) where
|
instance Act ( T ( 𝕀 Double ) ) ( 𝕀 Double ) where
|
||||||
T g • a = coerce ( Sum g • a )
|
T g • a = g + a
|
||||||
instance Torsor ( T ( 𝕀 Double ) ) ( 𝕀 Double ) where
|
instance Torsor ( T ( 𝕀 Double ) ) ( 𝕀 Double ) where
|
||||||
a --> b = T $ getSum ( a --> b )
|
a --> b = T $ b - a
|
||||||
|
|
||||||
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
@ -171,9 +161,9 @@ instance HasChainRule ( 𝕀 Double ) 2 ( 𝕀ℝ 1 ) where
|
||||||
| Just i <- isLinear mon
|
| Just i <- isLinear mon
|
||||||
-> [|| f $$( tabulateQ \ j ->
|
-> [|| f $$( tabulateQ \ j ->
|
||||||
if | j == i
|
if | j == i
|
||||||
-> [|| 1 ||]
|
-> [|| 𝕀 1 1 ||]
|
||||||
| otherwise
|
| otherwise
|
||||||
-> [|| 0 ||]
|
-> [|| 𝕀 0 0 ||]
|
||||||
) ||]
|
) ||]
|
||||||
| otherwise
|
| otherwise
|
||||||
-> [|| unT o ||]
|
-> [|| unT o ||]
|
||||||
|
@ -206,9 +196,9 @@ instance HasChainRule ( 𝕀 Double ) 3 ( 𝕀ℝ 1 ) where
|
||||||
| Just i <- isLinear mon
|
| Just i <- isLinear mon
|
||||||
-> [|| f $$( tabulateQ \ j ->
|
-> [|| f $$( tabulateQ \ j ->
|
||||||
if | j == i
|
if | j == i
|
||||||
-> [|| 1 ||]
|
-> [|| 𝕀 1 1 ||]
|
||||||
| otherwise
|
| otherwise
|
||||||
-> [|| 0 ||]
|
-> [|| 𝕀 0 0 ||]
|
||||||
) ||]
|
) ||]
|
||||||
| otherwise
|
| otherwise
|
||||||
-> [|| unT o ||]
|
-> [|| unT o ||]
|
||||||
|
@ -241,9 +231,9 @@ instance HasChainRule ( 𝕀 Double ) 2 ( 𝕀ℝ 2 ) where
|
||||||
| Just i <- isLinear mon
|
| Just i <- isLinear mon
|
||||||
-> [|| f $$( tabulateQ \ j ->
|
-> [|| f $$( tabulateQ \ j ->
|
||||||
if | j == i
|
if | j == i
|
||||||
-> [|| 1 ||]
|
-> [|| 𝕀 1 1 ||]
|
||||||
| otherwise
|
| otherwise
|
||||||
-> [|| 0 ||]
|
-> [|| 𝕀 0 0 ||]
|
||||||
) ||]
|
) ||]
|
||||||
| otherwise
|
| otherwise
|
||||||
-> [|| unT o ||]
|
-> [|| unT o ||]
|
||||||
|
@ -276,9 +266,9 @@ instance HasChainRule ( 𝕀 Double ) 3 ( 𝕀ℝ 2 ) where
|
||||||
| Just i <- isLinear mon
|
| Just i <- isLinear mon
|
||||||
-> [|| f $$( tabulateQ \ j ->
|
-> [|| f $$( tabulateQ \ j ->
|
||||||
if | j == i
|
if | j == i
|
||||||
-> [|| 1 ||]
|
-> [|| 𝕀 1 1 ||]
|
||||||
| otherwise
|
| otherwise
|
||||||
-> [|| 0 ||]
|
-> [|| 𝕀 0 0 ||]
|
||||||
) ||]
|
) ||]
|
||||||
| otherwise
|
| otherwise
|
||||||
-> [|| unT o ||]
|
-> [|| unT o ||]
|
||||||
|
@ -311,9 +301,9 @@ instance HasChainRule ( 𝕀 Double ) 2 ( 𝕀ℝ 3 ) where
|
||||||
| Just i <- isLinear mon
|
| Just i <- isLinear mon
|
||||||
-> [|| f $$( tabulateQ \ j ->
|
-> [|| f $$( tabulateQ \ j ->
|
||||||
if | j == i
|
if | j == i
|
||||||
-> [|| 1 ||]
|
-> [|| 𝕀 1 1 ||]
|
||||||
| otherwise
|
| otherwise
|
||||||
-> [|| 0 ||]
|
-> [|| 𝕀 0 0 ||]
|
||||||
) ||]
|
) ||]
|
||||||
| otherwise
|
| otherwise
|
||||||
-> [|| unT o ||]
|
-> [|| unT o ||]
|
||||||
|
@ -346,9 +336,9 @@ instance HasChainRule ( 𝕀 Double ) 3 ( 𝕀ℝ 3 ) where
|
||||||
| Just i <- isLinear mon
|
| Just i <- isLinear mon
|
||||||
-> [|| f $$( tabulateQ \ j ->
|
-> [|| f $$( tabulateQ \ j ->
|
||||||
if | j == i
|
if | j == i
|
||||||
-> [|| 1 ||]
|
-> [|| 𝕀 1 1 ||]
|
||||||
| otherwise
|
| otherwise
|
||||||
-> [|| 0 ||]
|
-> [|| 𝕀 0 0 ||]
|
||||||
) ||]
|
) ||]
|
||||||
| otherwise
|
| otherwise
|
||||||
-> [|| unT o ||]
|
-> [|| unT o ||]
|
||||||
|
@ -381,9 +371,9 @@ instance HasChainRule ( 𝕀 Double ) 2 ( 𝕀ℝ 4 ) where
|
||||||
| Just i <- isLinear mon
|
| Just i <- isLinear mon
|
||||||
-> [|| f $$( tabulateQ \ j ->
|
-> [|| f $$( tabulateQ \ j ->
|
||||||
if | j == i
|
if | j == i
|
||||||
-> [|| 1 ||]
|
-> [|| 𝕀 1 1 ||]
|
||||||
| otherwise
|
| otherwise
|
||||||
-> [|| 0 ||]
|
-> [|| 𝕀 0 0 ||]
|
||||||
) ||]
|
) ||]
|
||||||
| otherwise
|
| otherwise
|
||||||
-> [|| unT o ||]
|
-> [|| unT o ||]
|
||||||
|
@ -416,9 +406,9 @@ instance HasChainRule ( 𝕀 Double ) 3 ( 𝕀ℝ 4 ) where
|
||||||
| Just i <- isLinear mon
|
| Just i <- isLinear mon
|
||||||
-> [|| f $$( tabulateQ \ j ->
|
-> [|| f $$( tabulateQ \ j ->
|
||||||
if | j == i
|
if | j == i
|
||||||
-> [|| 1 ||]
|
-> [|| 𝕀 1 1 ||]
|
||||||
| otherwise
|
| otherwise
|
||||||
-> [|| 0 ||]
|
-> [|| 𝕀 0 0 ||]
|
||||||
) ||]
|
) ||]
|
||||||
| otherwise
|
| otherwise
|
||||||
-> [|| unT o ||]
|
-> [|| unT o ||]
|
||||||
|
|
152
src/splines/Math/Interval/FMA.hs
Normal file
152
src/splines/Math/Interval/FMA.hs
Normal file
|
@ -0,0 +1,152 @@
|
||||||
|
{-# LANGUAGE AllowAmbiguousTypes #-}
|
||||||
|
{-# LANGUAGE ScopedTypeVariables #-}
|
||||||
|
|
||||||
|
module Math.Interval.FMA ( addI, subI, prodI, divI, posPowI ) where
|
||||||
|
|
||||||
|
-- base
|
||||||
|
import Data.Bits
|
||||||
|
( Bits((.&.), shiftL) )
|
||||||
|
import Data.Word
|
||||||
|
( Word32, Word64 )
|
||||||
|
import GHC.Exts
|
||||||
|
( Double(D#), fmsubDouble#, fnmaddDouble# )
|
||||||
|
import GHC.Float
|
||||||
|
( castFloatToWord32 , castWord32ToFloat
|
||||||
|
, castDoubleToWord64, castWord64ToDouble
|
||||||
|
)
|
||||||
|
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
class ( RealFloat f, Num b, Bits b ) => FPBits f b | f -> b, b -> f where
|
||||||
|
toBits :: f -> b
|
||||||
|
fromBits :: b -> f
|
||||||
|
-- | Size in bytes.
|
||||||
|
sizeOf :: Int
|
||||||
|
|
||||||
|
instance FPBits Float Word32 where
|
||||||
|
toBits = castFloatToWord32
|
||||||
|
fromBits = castWord32ToFloat
|
||||||
|
sizeOf = 4
|
||||||
|
|
||||||
|
instance FPBits Double Word64 where
|
||||||
|
toBits = castDoubleToWord64
|
||||||
|
fromBits = castWord64ToDouble
|
||||||
|
sizeOf = 8
|
||||||
|
|
||||||
|
|
||||||
|
{-# SPECIALISE nextAfter :: Float -> Float -> Float #-}
|
||||||
|
{-# SPECIALISE nextAfter :: Double -> Double -> Double #-}
|
||||||
|
{-# INLINEABLE nextAfter #-}
|
||||||
|
-- | @nextAfter a b@ computes the next floating-point value after @a@
|
||||||
|
-- in the direction of @b@.
|
||||||
|
nextAfter :: forall f b. FPBits f b => f -> f -> f
|
||||||
|
nextAfter a b
|
||||||
|
| isNaN a
|
||||||
|
= a
|
||||||
|
| isNaN b
|
||||||
|
= b
|
||||||
|
| a == b
|
||||||
|
= b
|
||||||
|
| otherwise
|
||||||
|
= let !res_bits
|
||||||
|
| a == 0
|
||||||
|
, let !sgn_mask = 1 `shiftL` ( sizeOf @f * 8 - 1 )
|
||||||
|
= ( toBits b .&. sgn_mask ) + 1
|
||||||
|
| ( a < b ) == ( a > 0 )
|
||||||
|
= toBits a + 1
|
||||||
|
| otherwise
|
||||||
|
= toBits a - 1
|
||||||
|
in fromBits res_bits
|
||||||
|
|
||||||
|
{-# SPECIALISE succFP :: Float -> Float #-}
|
||||||
|
{-# SPECIALISE succFP :: Double -> Double #-}
|
||||||
|
{-# INLINEABLE succFP #-}
|
||||||
|
-- | The next floating-point number.
|
||||||
|
succFP :: forall f b. FPBits f b => f -> f
|
||||||
|
succFP x = nextAfter x (1/0)
|
||||||
|
|
||||||
|
|
||||||
|
{-# SPECIALISE prevFP :: Float -> Float #-}
|
||||||
|
{-# SPECIALISE prevFP :: Double -> Double #-}
|
||||||
|
{-# INLINEABLE prevFP #-}
|
||||||
|
-- | The previous floating-point number.
|
||||||
|
prevFP :: forall f b. FPBits f b => f -> f
|
||||||
|
prevFP x = nextAfter x (-1/0)
|
||||||
|
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
{-# INLINE withError #-}
|
||||||
|
withError :: Double -> Double -> ( Double, Double )
|
||||||
|
withError f e =
|
||||||
|
case compare e 0 of
|
||||||
|
LT -> ( prevFP f, f )
|
||||||
|
EQ -> ( f, f )
|
||||||
|
GT -> ( f, succFP f )
|
||||||
|
|
||||||
|
addI :: Double -> Double -> ( Double, Double )
|
||||||
|
addI a b =
|
||||||
|
let !s = a + b
|
||||||
|
!a' = s - b
|
||||||
|
!b' = s - a'
|
||||||
|
!da = a - a'
|
||||||
|
!db = b - b'
|
||||||
|
!e = da + db
|
||||||
|
in s `withError` e
|
||||||
|
|
||||||
|
subI :: Double -> Double -> ( Double, Double )
|
||||||
|
subI a b =
|
||||||
|
let !s = a - b
|
||||||
|
!a' = s - b
|
||||||
|
!b' = s - a'
|
||||||
|
!da = a - a'
|
||||||
|
!db = b - b'
|
||||||
|
!e = da + db
|
||||||
|
in s `withError` e
|
||||||
|
|
||||||
|
{-# INLINE fmsubDouble #-}
|
||||||
|
fmsubDouble :: Double -> Double -> Double -> Double
|
||||||
|
fmsubDouble ( D# x ) ( D# y ) ( D# z ) = D# ( fmsubDouble# x y z )
|
||||||
|
{-# INLINE fnmaddDouble #-}
|
||||||
|
fnmaddDouble :: Double -> Double -> Double -> Double
|
||||||
|
fnmaddDouble ( D# x ) ( D# y ) ( D# z ) = D# ( fnmaddDouble# x y z )
|
||||||
|
|
||||||
|
prodI :: Double -> Double -> ( Double, Double )
|
||||||
|
prodI a b =
|
||||||
|
let !p = a * b
|
||||||
|
!e = fmsubDouble a b p
|
||||||
|
in p `withError` e
|
||||||
|
|
||||||
|
divI :: Double -> Double -> ( Double, Double )
|
||||||
|
divI a b =
|
||||||
|
let !r = a / b
|
||||||
|
!e = fnmaddDouble r b a
|
||||||
|
in r `withError` e
|
||||||
|
|
||||||
|
-- | Power of a **non-negative** number to a natural power.
|
||||||
|
posPowI :: Double -- ^ Assumed to be non-negative!
|
||||||
|
-> Word -> ( Double, Double )
|
||||||
|
posPowI _ 0 = ( 1, 1 )
|
||||||
|
posPowI f 1 = ( f, f )
|
||||||
|
posPowI f 2 = prodI f f
|
||||||
|
posPowI f n
|
||||||
|
| even n
|
||||||
|
, let m = n `quot` 2
|
||||||
|
( f²_lo, f²_hi ) = prodI f f
|
||||||
|
= ( fst $ posPowI f²_lo m, snd $ posPowI f²_hi m )
|
||||||
|
| otherwise
|
||||||
|
, let m = n `quot` 2
|
||||||
|
( f²_lo, f²_hi ) = prodI f f
|
||||||
|
= ( fst $ posPowAcc f²_lo m f, snd $ posPowAcc f²_hi m f )
|
||||||
|
|
||||||
|
posPowAcc :: Double -> Word -> Double -> ( Double, Double )
|
||||||
|
posPowAcc f 1 x = prodI f x
|
||||||
|
posPowAcc f n x
|
||||||
|
| even n
|
||||||
|
, let m = n `quot` 2
|
||||||
|
( f²_lo, f²_hi ) = prodI f f
|
||||||
|
= ( fst $ posPowAcc f²_lo m x, snd $ posPowAcc f²_hi m x )
|
||||||
|
| otherwise
|
||||||
|
, let m = n `quot` 2
|
||||||
|
( f²_lo, f²_hi ) = prodI f f
|
||||||
|
( y_lo, y_hi ) = prodI f x
|
||||||
|
= ( fst $ posPowAcc f²_lo m y_lo, snd $ posPowAcc f²_hi m y_hi )
|
|
@ -1,11 +1,12 @@
|
||||||
{-# LANGUAGE ScopedTypeVariables #-}
|
{-# LANGUAGE CPP #-}
|
||||||
|
{-# LANGUAGE ScopedTypeVariables #-}
|
||||||
{-# LANGUAGE TemplateHaskell #-}
|
{-# LANGUAGE TemplateHaskell #-}
|
||||||
{-# LANGUAGE UndecidableInstances #-}
|
{-# LANGUAGE UndecidableInstances #-}
|
||||||
|
|
||||||
{-# OPTIONS_GHC -Wno-orphans #-}
|
{-# OPTIONS_GHC -Wno-orphans #-}
|
||||||
|
|
||||||
module Math.Interval.Internal
|
module Math.Interval.Internal
|
||||||
( 𝕀(.., 𝕀) )
|
( 𝕀(𝕀), inf, sup, scaleInterval )
|
||||||
where
|
where
|
||||||
|
|
||||||
-- base
|
-- base
|
||||||
|
@ -18,17 +19,24 @@ import GHC.Show
|
||||||
|
|
||||||
-- deepseq
|
-- deepseq
|
||||||
import Control.DeepSeq
|
import Control.DeepSeq
|
||||||
( NFData )
|
( NFData(..) )
|
||||||
|
|
||||||
-- rounded-hw
|
-- rounded-hw
|
||||||
import Numeric.Rounded.Hardware
|
import Numeric.Rounded.Hardware
|
||||||
( Rounded(..) )
|
( Rounded(..) )
|
||||||
import Numeric.Rounded.Hardware.Interval.NonEmpty
|
|
||||||
( Interval )
|
|
||||||
import qualified Numeric.Rounded.Hardware.Interval.NonEmpty as Interval
|
import qualified Numeric.Rounded.Hardware.Interval.NonEmpty as Interval
|
||||||
( Interval(..) )
|
( Interval(..) )
|
||||||
|
|
||||||
|
#ifdef USE_FMA
|
||||||
|
-- MetaBrush
|
||||||
|
import Math.Interval.FMA
|
||||||
|
( addI, subI, prodI, divI, posPowI )
|
||||||
|
|
||||||
|
#else
|
||||||
|
-- rounded-hw
|
||||||
import qualified Numeric.Rounded.Hardware.Interval.NonEmpty as Interval
|
import qualified Numeric.Rounded.Hardware.Interval.NonEmpty as Interval
|
||||||
( sup, inf, powInt )
|
( powInt )
|
||||||
|
#endif
|
||||||
|
|
||||||
-- MetaBrush
|
-- MetaBrush
|
||||||
import Math.Linear
|
import Math.Linear
|
||||||
|
@ -42,29 +50,104 @@ import Math.Ring
|
||||||
--------------------------------------------------------------------------------
|
--------------------------------------------------------------------------------
|
||||||
-- Intervals.
|
-- Intervals.
|
||||||
|
|
||||||
newtype 𝕀 a = MkI { ival :: Interval a }
|
#ifdef USE_FMA
|
||||||
|
data 𝕀 a = 𝕀 { inf, sup :: !a }
|
||||||
|
|
||||||
|
instance NFData a => NFData ( 𝕀 a ) where
|
||||||
|
rnf ( 𝕀 lo hi ) = rnf lo `seq` rnf hi
|
||||||
|
|
||||||
|
instance Prelude.Num ( 𝕀 Double ) where
|
||||||
|
𝕀 x_lo x_hi + 𝕀 y_lo y_hi
|
||||||
|
| let !z_lo = fst $ addI x_lo y_lo
|
||||||
|
!z_hi = snd $ addI x_hi y_hi
|
||||||
|
= 𝕀 z_lo z_hi
|
||||||
|
𝕀 x_lo x_hi - 𝕀 y_lo y_hi
|
||||||
|
| let !z_lo = fst $ subI x_lo y_hi
|
||||||
|
!z_hi = snd $ subI x_hi y_lo
|
||||||
|
= 𝕀 z_lo z_hi
|
||||||
|
negate (𝕀 lo hi) = 𝕀 (Prelude.negate hi) (Prelude.negate lo)
|
||||||
|
(*) = (*)
|
||||||
|
fromInteger i =
|
||||||
|
let !j = Prelude.fromInteger i
|
||||||
|
in 𝕀 j j
|
||||||
|
abs (𝕀 lo hi)
|
||||||
|
| 0 <= lo
|
||||||
|
= 𝕀 lo hi
|
||||||
|
| hi <= 0
|
||||||
|
= 𝕀 (Prelude.negate hi) (Prelude.negate lo)
|
||||||
|
| otherwise
|
||||||
|
= 𝕀 0 (max (Prelude.negate lo) hi)
|
||||||
|
signum _ = error "No implementation of signum for intervals"
|
||||||
|
|
||||||
|
instance Ring ( 𝕀 Double ) where
|
||||||
|
𝕀 lo1 hi1 * 𝕀 lo2 hi2
|
||||||
|
| let !( x_min, x_max ) = prodI lo1 lo2
|
||||||
|
!( y_min, y_max ) = prodI lo1 hi2
|
||||||
|
!( z_min, z_max ) = prodI hi1 lo2
|
||||||
|
!( w_min, w_max ) = prodI hi1 hi2
|
||||||
|
= 𝕀 ( min ( min x_min y_min ) ( min z_min w_min ) )
|
||||||
|
( max ( max x_max y_max ) ( max z_max w_max ) )
|
||||||
|
_ ^ 0 = 𝕀 1 1
|
||||||
|
iv ^ 1 = iv
|
||||||
|
𝕀 lo hi ^ n
|
||||||
|
| odd n || 0 <= lo
|
||||||
|
, let !lo' = fst $ posPowI lo n
|
||||||
|
!hi' = snd $ posPowI hi n
|
||||||
|
= 𝕀 lo' hi'
|
||||||
|
| hi <= 0
|
||||||
|
, let !lo' = fst $ posPowI (negate hi) n
|
||||||
|
!hi' = snd $ posPowI (negate lo) n
|
||||||
|
= 𝕀 lo' hi'
|
||||||
|
| otherwise
|
||||||
|
, let !hi1 = snd $ posPowI (negate lo) n
|
||||||
|
, let !hi2 = snd $ posPowI hi n
|
||||||
|
= 𝕀 0 ( max hi1 hi2 )
|
||||||
|
|
||||||
|
instance Prelude.Fractional ( 𝕀 Double ) where
|
||||||
|
fromRational r =
|
||||||
|
let q = Prelude.fromRational r
|
||||||
|
in 𝕀 q q
|
||||||
|
recip (𝕀 lo hi)
|
||||||
|
-- #ifdef ASSERTS
|
||||||
|
| lo >= 0 || hi <= 0
|
||||||
|
-- #endif
|
||||||
|
= 𝕀 ( fst $ divI 1 hi ) ( snd $ divI 1 lo )
|
||||||
|
-- #ifdef ASSERTS
|
||||||
|
| otherwise
|
||||||
|
= error "BAD interval recip; should use extendedRecip instead"
|
||||||
|
-- #endif
|
||||||
|
_ / _ = error "TODO: interval division is not implemented"
|
||||||
|
|
||||||
|
instance Transcendental ( 𝕀 Double ) where
|
||||||
|
pi = 𝕀 3.141592653589793 3.1415926535897936
|
||||||
|
cos = withHW Prelude.cos
|
||||||
|
sin = withHW Prelude.sin
|
||||||
|
|
||||||
|
{-# INLINE withHW #-}
|
||||||
|
withHW :: (Interval.Interval a -> Interval.Interval b) -> 𝕀 a -> 𝕀 b
|
||||||
|
withHW f = \ ( 𝕀 lo hi ) ->
|
||||||
|
case f ( Interval.I ( Rounded lo ) ( Rounded hi ) ) of
|
||||||
|
Interval.I ( Rounded x ) ( Rounded y ) -> 𝕀 x y
|
||||||
|
|
||||||
|
scaleInterval :: Double -> 𝕀 Double -> 𝕀 Double
|
||||||
|
scaleInterval s ( 𝕀 lo hi ) =
|
||||||
|
case compare s 0 of
|
||||||
|
LT -> 𝕀 ( fst $ prodI s hi ) ( snd $ prodI s lo )
|
||||||
|
EQ -> 𝕀 0 0
|
||||||
|
GT -> 𝕀 ( fst $ prodI s lo ) ( snd $ prodI s hi )
|
||||||
|
#else
|
||||||
|
|
||||||
|
newtype 𝕀 a = MkI { ival :: Interval.Interval a }
|
||||||
deriving newtype ( Prelude.Num, Prelude.Fractional, Prelude.Floating )
|
deriving newtype ( Prelude.Num, Prelude.Fractional, Prelude.Floating )
|
||||||
deriving newtype NFData
|
deriving newtype NFData
|
||||||
|
|
||||||
instance Eq a => Eq ( 𝕀 a ) where
|
|
||||||
𝕀 a b == 𝕀 c d =
|
|
||||||
a == c && b == d
|
|
||||||
|
|
||||||
{-# COMPLETE 𝕀 #-}
|
{-# COMPLETE 𝕀 #-}
|
||||||
pattern 𝕀 :: a -> a -> 𝕀 a
|
pattern 𝕀 :: a -> a -> 𝕀 a
|
||||||
pattern 𝕀 x y = MkI ( Interval.I ( Rounded x ) ( Rounded y ) )
|
pattern 𝕀 x y = MkI ( Interval.I ( Rounded x ) ( Rounded y ) )
|
||||||
instance Show a => Show ( 𝕀 a ) where
|
|
||||||
showsPrec _ ( 𝕀 x y )
|
|
||||||
= showString "["
|
|
||||||
. showsPrec 0 x
|
|
||||||
. showCommaSpace
|
|
||||||
. showsPrec 0 y
|
|
||||||
. showString "]"
|
|
||||||
|
|
||||||
deriving via ViaPrelude ( 𝕀 Double )
|
inf, sup :: 𝕀 a -> a
|
||||||
instance AbelianGroup ( 𝕀 Double )
|
inf (𝕀 a _) = a
|
||||||
deriving via ViaPrelude ( 𝕀 Double )
|
sup (𝕀 _ b) = b
|
||||||
instance AbelianGroup ( T ( 𝕀 Double ) )
|
|
||||||
|
|
||||||
instance Ring ( 𝕀 Double ) where
|
instance Ring ( 𝕀 Double ) where
|
||||||
MkI i1 * MkI i2 = MkI $ i1 Prelude.* i2
|
MkI i1 * MkI i2 = MkI $ i1 Prelude.* i2
|
||||||
|
@ -74,16 +157,40 @@ instance Ring ( 𝕀 Double ) where
|
||||||
-- accidentally use (^) from Prelude.
|
-- accidentally use (^) from Prelude.
|
||||||
|
|
||||||
deriving via ViaPrelude ( 𝕀 Double )
|
deriving via ViaPrelude ( 𝕀 Double )
|
||||||
instance Field ( 𝕀 Double )
|
instance Transcendental ( 𝕀 Double )
|
||||||
|
|
||||||
|
scaleInterval :: Double -> 𝕀 Double -> 𝕀 Double
|
||||||
|
scaleInterval s iv = 𝕀 s s * iv -- TODO: could be better
|
||||||
|
#endif
|
||||||
|
|
||||||
deriving via ViaPrelude ( 𝕀 Double )
|
deriving via ViaPrelude ( 𝕀 Double )
|
||||||
instance Transcendental ( 𝕀 Double )
|
instance AbelianGroup ( 𝕀 Double )
|
||||||
|
deriving via ViaPrelude ( 𝕀 Double )
|
||||||
|
instance AbelianGroup ( T ( 𝕀 Double ) )
|
||||||
|
deriving via ViaPrelude ( 𝕀 Double )
|
||||||
|
instance Field ( 𝕀 Double )
|
||||||
|
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
instance Eq a => Eq ( 𝕀 a ) where
|
||||||
|
𝕀 a b == 𝕀 c d =
|
||||||
|
a == c && b == d
|
||||||
|
|
||||||
|
instance Show a => Show ( 𝕀 a ) where
|
||||||
|
showsPrec _ ( 𝕀 x y )
|
||||||
|
= showString "["
|
||||||
|
. showsPrec 0 x
|
||||||
|
. showCommaSpace
|
||||||
|
. showsPrec 0 y
|
||||||
|
. showString "]"
|
||||||
|
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
|
||||||
type instance RepDim ( 𝕀 u ) = RepDim u
|
type instance RepDim ( 𝕀 u ) = RepDim u
|
||||||
instance RepresentableQ r u => RepresentableQ ( 𝕀 r ) ( 𝕀 u ) where
|
instance RepresentableQ r u => RepresentableQ ( 𝕀 r ) ( 𝕀 u ) where
|
||||||
tabulateQ f =
|
tabulateQ f =
|
||||||
let !lo = tabulateQ @r @u ( \ i -> [|| getRounded $ Interval.inf $ ival $$( f i ) ||] )
|
let !lo = tabulateQ @r @u ( \ i -> [|| inf $ $$( f i ) ||] )
|
||||||
!hi = tabulateQ @r @u ( \ i -> [|| getRounded $ Interval.sup $ ival $$( f i ) ||] )
|
!hi = tabulateQ @r @u ( \ i -> [|| sup $ $$( f i ) ||] )
|
||||||
in [|| 𝕀 $$lo $$hi ||]
|
in [|| 𝕀 $$lo $$hi ||]
|
||||||
|
|
||||||
indexQ d i =
|
indexQ d i =
|
||||||
|
@ -95,8 +202,8 @@ instance RepresentableQ r u => RepresentableQ ( 𝕀 r ) ( 𝕀 u ) where
|
||||||
||]
|
||]
|
||||||
instance Representable r u => Representable ( 𝕀 r ) ( 𝕀 u ) where
|
instance Representable r u => Representable ( 𝕀 r ) ( 𝕀 u ) where
|
||||||
tabulate f =
|
tabulate f =
|
||||||
let !lo = tabulate @r @u ( \ i -> getRounded $ Interval.inf $ ival ( f i ) )
|
let !lo = tabulate @r @u ( \ i -> inf $ f i )
|
||||||
!hi = tabulate @r @u ( \ i -> getRounded $ Interval.sup $ ival ( f i ) )
|
!hi = tabulate @r @u ( \ i -> sup $ f i )
|
||||||
in 𝕀 lo hi
|
in 𝕀 lo hi
|
||||||
|
|
||||||
index d i =
|
index d i =
|
||||||
|
|
Loading…
Reference in a new issue