module Data.Number.ER.RnToRm.BisectionTree.Integration
(
zipFromOrigin, zipOnSubdomain
)
where
import qualified Data.Number.ER.RnToRm.BisectionTree as BISTR
import qualified Data.Number.ER.Real.Approx as RA
import qualified Data.Number.ER.Real.DomainBox as DBox
import Data.Number.ER.Real.DomainBox (VariableID(..), DomainBox, DomainIntBox)
import Data.Number.ER.BasicTypes
import Data.Number.ER.Misc
import Data.Maybe
zipFromOrigin ::
(RA.ERIntApprox d, DomainIntBox box varid d, Show v1, Show v2, Show valPass) =>
BISTR.ValueSplitter box varid d v1 ->
BISTR.ValueCombiner box varid d v1 ->
EffortIndex ->
varid
->
d
->
(Maybe (box))
->
(Maybe valPass -> Maybe valPass -> [BISTR.BisectionTree box varid d v1] -> [BISTR.BisectionTree box varid d v2])
->
(EffortIndex -> BISTR.Depth -> (box) -> [v1] -> [v2] -> Bool)
->
(EffortIndex -> BISTR.Depth -> (box) -> [v1] -> (valPass,[v2],valPass))
->
(EffortIndex -> BISTR.Depth -> (box) -> valPass -> [v1] -> ([v2], valPass))
->
(EffortIndex -> BISTR.Depth -> (box) -> [v1] -> valPass -> (valPass, [v2]))
->
[BISTR.BisectionTree box varid d v1]
->
[BISTR.BisectionTree box varid d v2]
zipFromOrigin
valSplitter valCombiner ix
ivar origin maybeResultSupport outerValTransformer
decideShouldSplit integrLeafOH integrLeafOL integrLeafOR
bistrs =
resultBistrs
where
(_, resultBistrs, _) =
integrateBistrOriginHere $ BISTR.syncMany valSplitter ix bistrs
maybeSupport =
fmap extendToOrigin maybeResultSupport
where
extendToOrigin domB =
case DBox.member ivar domB of
True -> DBox.insertWith (RA.\/) ivar origin domB
False -> domB
integrateBistrOriginHere bistrs@((BISTR.Leaf depth dom _) : _)
| decideShouldSplit ix depth dom vals integrVals =
integrateBistrOriginHere $
map (BISTR.split valSplitter ix var pt dom) bistrs
| otherwise =
(Just lVal, map (\v -> BISTR.Leaf depth dom v) integrVals, Just rVal)
where
(var, pt) = DBox.bestSplit dom
vals = map BISTR.bistrVal bistrs
(lVal, integrVals, rVal) =
integrLeafOH ix depth dom vals
integrateBistrOriginHere bistrs@((BISTR.Node depth dom var pt lBounds rBounds):_)
| origin `RA.refines` rDom =
(lValHI, bistrsIntgHI, rValHI)
| origin `RA.refines` lDom =
(lValLO, bistrsIntgLO, rValLO)
| otherwise =
integrateBistrOriginHere $
map (\b -> BISTR.Leaf depth dom (valCombiner ix depth b)) bistrs
where
lDom = DBox.lookup "BTINTEG: zipFromOrigin: Here: L: " var (BISTR.bistrDom lBounds)
rDom = DBox.lookup "BTINTEG: zipFromOrigin: Here: R: " var (BISTR.bistrDom rBounds)
bistrsIntgHI =
zipWith
(\lo hi -> BISTR.Node depth dom var pt lo hi)
lBoundsIntgHI rBoundsIntgHI
(lValHIHI, rBoundsIntgHI, rValHI) =
integrateBistrOriginHere $
BISTR.syncMany valSplitter ix $ map BISTR.bistrHI bistrs
(lValHI, lBoundsIntgHI) =
integrateBistrOriginRight
(BISTR.syncMany valSplitter ix $ map BISTR.bistrLO bistrs)
lValHIHI
bistrsIntgLO =
zipWith
(\lo hi -> BISTR.Node depth dom var pt lo hi)
lBoundsIntgLO rBoundsIntgLO
(lValLO, lBoundsIntgLO, rValLOLO) =
integrateBistrOriginHere $
BISTR.syncMany valSplitter ix $ map BISTR.bistrLO bistrs
(rBoundsIntgLO, rValLO) =
integrateBistrOriginLeft
rValLOLO
(BISTR.syncMany valSplitter ix $ map BISTR.bistrHI bistrs)
integrateBistrOriginLeft Nothing bistrs =
(outerValTransformer Nothing Nothing bistrs, Nothing)
integrateBistrOriginLeft (Just lVal) bistrs@(bistr:_)
| (isJust maybeSupport) &&
(and $ Prelude.map snd $
DBox.zipWithDefaultSecond RA.bottomApprox RA.isInteriorDisjoint
(BISTR.bistrDom bistr)
(fromJust maybeSupport)) =
(outerValTransformer (Just lVal) Nothing bistrs, Nothing)
integrateBistrOriginLeft (Just lVal) bistrs@((BISTR.Leaf depth dom _) : _)
| decideShouldSplit ix depth dom vals integrVals =
integrateBistrOriginLeft (Just lVal) $
map (BISTR.split valSplitter ix var pt dom) bistrs
| otherwise =
(map (\v -> BISTR.Leaf depth dom v) integrVals,
Just rVal)
where
(var, pt) = DBox.bestSplit dom
vals = map BISTR.bistrVal bistrs
(integrVals, rVal) =
integrLeafOL ix depth dom lVal vals
integrateBistrOriginLeft mlVal bistrs@((BISTR.Node depth dom var pt _ _):_) =
(bistrsIntg, mrVal2)
where
bistrsIntg =
zipWith (\lo hi -> BISTR.Node depth dom var pt lo hi) lBoundsINT rBoundsINT
(lBoundsINT, mrVal1) =
integrateBistrOriginLeft mlVal $
BISTR.syncMany valSplitter ix $ map BISTR.bistrLO bistrs
(rBoundsINT, mrVal2) =
integrateBistrOriginLeft mrVal1 $
BISTR.syncMany valSplitter ix $ map BISTR.bistrHI bistrs
integrateBistrOriginRight bistrs Nothing =
(Nothing, outerValTransformer Nothing Nothing bistrs)
integrateBistrOriginRight bistrs@(bistr:_) (Just rVal)
| (isJust maybeSupport) &&
(and $ Prelude.map snd $
DBox.zipWithDefaultSecond RA.bottomApprox RA.isInteriorDisjoint
(BISTR.bistrDom bistr)
(fromJust maybeSupport)) =
(Nothing, outerValTransformer Nothing (Just rVal) bistrs)
integrateBistrOriginRight bistrs@((BISTR.Leaf depth dom _) : _) (Just rVal)
| decideShouldSplit ix depth dom vals integrVals =
integrateBistrOriginRight
(map (BISTR.split valSplitter ix var pt dom) bistrs)
(Just rVal)
| otherwise =
(Just lVal,
map (\v -> BISTR.Leaf depth dom v) integrVals)
where
(var, pt) = DBox.bestSplit dom
vals = map BISTR.bistrVal bistrs
(lVal, integrVals) =
integrLeafOR ix depth dom vals rVal
integrateBistrOriginRight bistrs@((BISTR.Node depth dom var pt _ _):_) mrVal =
(mlVal2, bistrsIntg)
where
bistrsIntg =
zipWith (\lo hi -> BISTR.Node depth dom var pt lo hi) lBoundsINT rBoundsINT
(mlVal2, lBoundsINT) =
integrateBistrOriginRight
(BISTR.syncMany valSplitter ix $ map BISTR.bistrLO bistrs) mlVal1
(mlVal1, rBoundsINT) =
integrateBistrOriginRight
(BISTR.syncMany valSplitter ix $ map BISTR.bistrHI bistrs) mrVal
zipOnSubdomain ::
(RA.ERIntApprox d, DomainIntBox box varid d) =>
BISTR.ValueSplitter box varid d v1 ->
EffortIndex ->
BISTR.Depth
->
box
->
(box -> [v1] -> [v2])
->
(box -> [v1] -> [v2])
->
(box -> [v1] -> [v2])
->
[BISTR.BisectionTree box varid d v1] ->
[BISTR.BisectionTree box varid d v2]
zipOnSubdomain valSplitter ix maxDepth sdom updateInside updateTouch updateAway bistrs =
resultBistrs
where
resultBistrs =
zz $ BISTR.syncMany valSplitter ix bistrs
zz bistrs@(BISTR.Leaf depth dom _ : _)
| intersect =
case depth < maxDepth of
True ->
zz $ map (BISTR.split valSplitter ix var pt dom) bistrs
False ->
error "BTINTEG: zipOnSubdomain: maxDepth reached but irregular splitting not implemented yet"
| away = lift updateAway
| touch = lift updateTouch
| inside = lift updateInside
where
(var, pt) = DBox.bestSplit dom
lift updateFn =
map (BISTR.Leaf depth dom) $
updateFn dom $
map BISTR.bistrVal bistrs
(away, touch, intersect, inside) =
DBox.classifyPosition dom sdom
zz bistrs@(BISTR.Node depth dom var pt _ _ : _) =
zipWith
(\bLO bHI -> BISTR.Node depth dom var pt bLO bHI)
(zz $ map BISTR.bistrLO bistrs)
(zz $ map BISTR.bistrHI bistrs)