\begin{code}
module Algebra.Polynomials.Bernstein (Bernsteinp(..),solve,Bernstein(..),
derivate,reorient) where
import Control.Monad.ST
import Algebra.Polynomials.Numerical
import qualified Data.Vector.Unboxed as UV
import qualified Data.Vector.Unboxed.Mutable as MUV
import qualified Data.Vector as V
import Data.Vector.Generic as GV hiding ((++))
data Bernsteinp a b=Bernsteinp { bounds::a, coefs::UV.Vector b } deriving (Eq,Show)
type family Param a b
type instance Param Int a=a
type instance Param (Int,Int) a=(a,a)
type instance Param (Int,Int,Int) a=(a,a,a)
type instance Param (Int,Int,Int,Int) a=(a,a,a,a)
type family Inter a b
type instance Inter Int a=(a,a)
type instance Inter (Int,Int) a=(a,a,a,a)
type instance Inter (Int,Int,Int) a=(a,a,a,a,a,a)
type instance Inter (Int,Int,Int,Int) a=(a,a,a,a,a,a,a,a)
class Bernstein a where
(?)::UV.Unbox b=>Bernsteinp a b->a->b
constant::(UV.Unbox b,Num b, Fractional b)=>b->Bernsteinp a b
scale::(Num b, Fractional b,UV.Unbox b)=>b->Bernsteinp a b->Bernsteinp a b
scale a (Bernsteinp i b)=Bernsteinp i $ UV.map (*a) b
promote::(UV.Unbox b,Num b, Fractional b)=>Int->Bernsteinp Int b->Bernsteinp a b
elevate::(UV.Unbox b,Num b, Fractional b)=>a->Bernsteinp a b->Bernsteinp a b
eval::(UV.Unbox b,Num b,Fractional b)=>Bernsteinp a b->Param a b->b
restriction::(UV.Unbox b,Fractional b,Num b)=>Bernsteinp a b->Param a b->Param a b->Bernsteinp a b
instance Num (Bernsteinp a Interval)=>Intervalize (Bernsteinp a) where
intervalize (Bernsteinp i x)=Bernsteinp i $! UV.map interval x
intersects bxf bxg=
let (Bernsteinp _ xx)=bxfbxg in
UV.all (\(Interval a b)->a<=0 && b>=0) xx
binomials::(Num a, MUV.Unbox a)=>Int->UV.Vector a
binomials m=
UV.create $ do
v<-MUV.replicate ((m+1)*(m+1)) 0
MUV.write v 0 1
let fill i
| i>=(m+1)*(m+1) = return v
| i`mod`(m+1) == 0 = do
MUV.write v i 1
fill (i+1)
| otherwise = do
a<-MUV.read v (im1)
b<-MUV.read v (im2)
MUV.write v i (a+b)
fill (i+1)
fill (m+1)
instance Bernstein Int where
(?) (Bernsteinp _ a) b=a!b
constant x=Bernsteinp 1 $ GV.singleton x
promote _=id
elevate r (Bernsteinp n f)=
if r<=0 then Bernsteinp n f else
let coef j=
let sumAll i result
| (i>j) || (i>=n) = result
| otherwise =
sumAll (i+1) $ result+(f!i)*((bin i (n1))*((bin (ji) r))/(bin j (n+r1)))
in
(sumAll 0 0)
binomial=binomials $ n+r1
bin a b=binomial!(b*(n+r)+a)
in
Bernsteinp (n+r) $ UV.generate (n+r) coef
eval (Bernsteinp n points) t=
if n==0 then 0 else runST $ do
arr<-thaw points
let fill i s
| s>=n = MUV.read arr 0
| i>=ns = fill 0 (s+1)
| otherwise = do
a<-MUV.read arr i
b<-MUV.read arr (i+1)
MUV.write arr i $ a*(1t)+b*t
fill (i+1) s
fill 0 1
restriction (Bernsteinp n0 points) a b=
runST $ do
pf<-thaw points
let casteljau bef aft nv u v i k s j
| i>=bef = return ()
| k>=aft= casteljau bef aft nv u v (i+1) 0 1 0
| s>=nv = casteljau bef aft nv u v i (k+1) 1 0
| j>=nv = casteljau bef aft nv u v i k (s+1) 0
| otherwise=
let idx i_ j_ k_=(i_*nv+j_)*aft + k_
v'=(vu)/(1u)
in
if s+j<nv then do
pfi0<-MUV.read pf (idx i j k)
pfi1<-MUV.read pf (idx i (j+1) k)
MUV.write pf (idx i j k) $ (1u)*pfi0+u*pfi1
casteljau bef aft nv u v i k s (j+1)
else do
pfi0<-MUV.read pf (idx i (j1) k)
pfi1<-MUV.read pf (idx i j k)
MUV.write pf (idx i j k) $ (1v')*pfi0+v'*pfi1
casteljau bef aft nv u v i k s (j+1)
casteljau 1 1 n0 a b 0 0 1 0
pff<-unsafeFreeze pf
return $ Bernsteinp n0 pff
instance Bernstein (Int,Int) where
(?) (Bernsteinp (_,b) c) (i,j)=c!(i*b+j)
constant x=Bernsteinp (1,1) $ UV.singleton x
promote 1 (Bernsteinp i x)=Bernsteinp (i,1) x
promote _ (Bernsteinp i x)=Bernsteinp (1,i) x
elevate (ra_,rb_) (Bernsteinp (a,b) f)=
let ra
| ra_>0 = ra_
| otherwise = 0
rb
| rb_>0 = rb_
| otherwise = 0
in
if a<=0 || b<=0 then Bernsteinp (a+ra,b+rb) $ GV.replicate ((a+ra)*(b+rb)) 0 else
let idx i j=(i*b)+j
idx' i j=(i*(b+rb))+j
vect=create $ do
v<-MUV.new ((a+ra)*(b+rb))
let coef i j
| i>=(a+ra) = return v
| j>=(b+rb) = coef (i+1) 0
| otherwise=do
let sumAll i' j' !result
| i'>=a || i'>i = result
| j'>=b || j'>j = sumAll (i'+1) 0 result
| otherwise =
let x0=(bin i' (a1))*((bin (ii') ra)/(bin i (a+ra1)))
x1=(bin j' (b1))*((bin (jj') rb)/(bin j (b+rb1)))
in
sumAll i' (j'+1) $! result+x0*x1*(f!(idx i' j'))
MUV.write v (idx' i j) $ sumAll 0 0 0
coef i (j+1)
coef 0 0
m=max (a+ra1) (b+rb1)
bin i j=binomial!(j*(m+1)+i)
binomial=binomials m
in
Bernsteinp (a+ra,b+rb) vect
eval (Bernsteinp (n0,n1) points) (a,b)=
if n0<=0 || n1<=0 then 0 else
runST $ do
pf<-thaw points
let casteljau p0 p1 u i j s
| i>=p0 = return ()
| s>=p1 = casteljau p0 p1 u (i+1) 0 1
| j>=(p1s) = casteljau p0 p1 u i 0 (s+1)
| otherwise = do
x0<-MUV.read pf $ i+p0*j
x1<-MUV.read pf $ i+p0*(j+1)
MUV.write pf (i+p0*j) $ (1u)*x0+u*x1
casteljau p0 p1 u i (j+1) s
casteljau n1 n0 a 0 0 1
casteljau 1 n1 b 0 0 1
MUV.read pf 0
restriction (Bernsteinp (n0,n1) points) (a,c) (b,d)=
runST $ do
pf<-thaw points
let casteljau bef aft nv u v i k s j
| i>=bef = return ()
| k>=aft= casteljau bef aft nv u v (i+1) 0 1 0
| s>=nv = casteljau bef aft nv u v i (k+1) 1 0
| j>=nv = casteljau bef aft nv u v i k (s+1) 0
| otherwise=
let idx i_ j_ k_=(i_*nv+j_)*aft + k_
v'=(vu)/(1u)
in
if s+j<nv then do
pfi0<-MUV.read pf (idx i j k)
pfi1<-MUV.read pf (idx i (j+1) k)
MUV.write pf (idx i j k) $ (1u)*pfi0+u*pfi1
casteljau bef aft nv u v i k s (j+1)
else do
pfi0<-MUV.read pf (idx i (j1) k)
pfi1<-MUV.read pf (idx i j k)
MUV.write pf (idx i j k) $ (1v')*pfi0+v'*pfi1
casteljau bef aft nv u v i k s (j+1)
casteljau 1 n1 n0 a b 0 0 1 0
casteljau n0 1 n1 c d 0 0 1 0
pff<-unsafeFreeze pf
return $ Bernsteinp (n0,n1) pff
instance Bernstein (Int,Int,Int) where
(?) (Bernsteinp (_,b,c) d) (i,j,k)=d!(((i*b+j)*c)+k)
constant x=Bernsteinp (1,1,1) $ UV.singleton x
promote 1 (Bernsteinp i x)=Bernsteinp (i,1,1) x
promote 2 (Bernsteinp i x)=Bernsteinp (1,i,1) x
promote _ (Bernsteinp i x)=Bernsteinp (1,1,i) x
elevate (ra_,rb_,rc_) (Bernsteinp (a,b,c) f)=
let ra
| ra_>0 = ra_
| otherwise = 0
rb
| rb_>0 = rb_
| otherwise = 0
rc
| rc_>0 = rc_
| otherwise = 0
in
if a<=0 || b<=0 || c<=0 then
Bernsteinp (a+ra,b+rb,c+rc) $ GV.replicate ((a+ra)*(b+rb)*(c+rc)) 0
else
let idx i j k=((i*b)+j)*c+k
idx' i j k=((i*(b+rb))+j)*(c+rc)+k
vect=create $ do
v<-MUV.new ((a+ra)*(b+rb)*(c+rc))
let coef i j k
| i>=a+ra = return v
| j>=b+rb = coef (i+1) 0 0
| k>=c+rc = coef i (j+1) 0
| otherwise=do
let sumAll i' j' k' !result
| i'>=a || i'>i = result
| j'>=b || j'>j = sumAll (i'+1) 0 0 result
| k'>=c || k'>k = sumAll i' (j'+1) 0 result
| otherwise =
let x0=(bin i' (a1))*((bin (ii') ra)/(bin i (a+ra1)))
x1=(bin j' (b1))*((bin (jj') rb)/(bin j (b+rb1)))
x2=(bin k' (c1))*((bin (kk') rc)/(bin k (c+rc1)))
in
sumAll i' j' (k'+1) $! result+x0*x1*x2*(f!(idx i' j' k'))
MUV.write v (idx' i j k) $ sumAll 0 0 0 0
coef i j (k+1)
coef 0 0 0
m=max (max (a+ra1) (b+rb1)) (c+rc1)
bin i j=binomial!(j*(m+1)+i)
binomial=binomials m
in
Bernsteinp (a+ra,b+rb,c+rc) vect
eval (Bernsteinp (n0,n1,n2) points) (a,b,c)=
if n0<=0 || n1<=0 || n2<=0 then 0 else
runST $ do
pf<-thaw points
let casteljau p0 p1 u i j s
| i>=p0 = return ()
| s>=p1 = casteljau p0 p1 u (i+1) 0 1
| j>=(p1s) = casteljau p0 p1 u i 0 (s+1)
| otherwise = do
x0<-MUV.read pf $ i+p0*j
x1<-MUV.read pf $ i+p0*(j+1)
MUV.write pf (i+p0*j) $ (1u)*x0+u*x1
casteljau p0 p1 u i (j+1) s
casteljau (n1*n2) n0 a 0 0 1
casteljau n2 n1 b 0 0 1
casteljau 1 n2 c 0 0 1
MUV.read pf 0
restriction (Bernsteinp (n0,n1,n2) points) (a,c,e) (b,d,f)=
runST $ do
pf<-thaw points
let casteljau bef aft nv u v i k s j
| i>=bef = return ()
| k>=aft= casteljau bef aft nv u v (i+1) 0 1 0
| s>=nv = casteljau bef aft nv u v i (k+1) 1 0
| j>=nv = casteljau bef aft nv u v i k (s+1) 0
| otherwise=
let idx i_ j_ k_=(i_*nv+j_)*aft + k_
v'=(vu)/(1u)
in
if s+j<nv then do
pfi0<-MUV.read pf (idx i j k)
pfi1<-MUV.read pf (idx i (j+1) k)
MUV.write pf (idx i j k) $ (1u)*pfi0+u*pfi1
casteljau bef aft nv u v i k s (j+1)
else do
pfi0<-MUV.read pf (idx i (j1) k)
pfi1<-MUV.read pf (idx i j k)
MUV.write pf (idx i j k) $ (1v')*pfi0+v'*pfi1
casteljau bef aft nv u v i k s (j+1)
casteljau 1 (n1*n2) n0 a b 0 0 1 0
casteljau n0 n2 n1 c d 0 0 1 0
casteljau (n0*n1) 1 n2 e f 0 0 1 0
pff<-unsafeFreeze pf
return $ Bernsteinp (n0,n1,n2) pff
instance Bernstein (Int,Int,Int,Int) where
(?) (Bernsteinp (_,b,c,d) e) (i,j,k,l)=e!((((i*b+j)*c)+k)*d+l)
constant x=Bernsteinp (1,1,1,1) $ UV.singleton x
promote 1 (Bernsteinp i x)=Bernsteinp (i,1,1,1) x
promote 2 (Bernsteinp i x)=Bernsteinp (1,i,1,1) x
promote 3 (Bernsteinp i x)=Bernsteinp (1,1,i,1) x
promote _ (Bernsteinp i x)=Bernsteinp (1,1,1,i) x
elevate (ra_,rb_,rc_,rd_) (Bernsteinp (a,b,c,d) f)=
let ra
| ra_>0 = ra_
| otherwise = 0
rb
| rb_>0 = rb_
| otherwise = 0
rc
| rc_>0 = rc_
| otherwise = 0
rd
| rd_>0 = rd_
| otherwise = 0
in
if a<=0 || b<=0 || c<=0 || d<=0 then
Bernsteinp (a+ra,b+rb,c+rc,d+rd) $ GV.replicate ((a+ra)*(b+rb)*(c+rc)*(d+rd)) 0
else
let idx i j k l=(((i*b)+j)*c+k)*d+l
idx' i j k l=(((i*(b+rb))+j)*(c+rc)+k)*(d+rd)+l
vect=create $ do
v<-MUV.new ((a+ra)*(b+rb)*(c+rc)*(d+rd))
let coef i j k l
| i>=a+ra = return v
| j>=b+rb = coef (i+1) 0 0 0
| k>=c+rc = coef i (j+1) 0 0
| l>=d+rd = coef i j (k+1) 0
| otherwise=do
let sumAll i' j' k' l' !result
| i'>=a || i'>i = result
| j'>=b || j'>j = sumAll (i'+1) 0 0 0 result
| k'>=c || k'>k = sumAll i' (j'+1) 0 0 result
| l'>=d || l'>l = sumAll i' j' (k'+1) 0 result
| otherwise =
let x0=(bin i' (a1))*((bin (ii') ra)/(bin i (a+ra1)))
x1=(bin j' (b1))*((bin (jj') rb)/(bin j (b+rb1)))
x2=(bin k' (c1))*((bin (kk') rc)/(bin k (c+rc1)))
x3=(bin l' (d1))*((bin (ll') rd)/(bin l (d+rd1)))
in
sumAll i' j' k' (l'+1) $! result+x0*x1*x2*x3*(f!(idx i' j' k' l'))
MUV.write v (idx' i j k l) $ sumAll 0 0 0 0 0
coef i j k (l+1)
coef 0 0 0 0
m=max (max (a+ra) (b+rb)) (max (c+rc) (d+rd))
bin i j=binomial!(j*(m+1)+i)
binomial=binomials m
in
Bernsteinp (a+ra,b+rb,c+rc,d+rd) vect
eval (Bernsteinp (n0,n1,n2,n3) points) (a,b,c,d)=
if n0<=0 || n1<=0 || n2<=0 || n3<=0 then 0 else
runST $ do
pf<-thaw points
let casteljau p0 p1 u i j s
| i>=p0 = return ()
| s>=p1 = casteljau p0 p1 u (i+1) 0 1
| j>=(p1s) = casteljau p0 p1 u i 0 (s+1)
| otherwise = do
x0<-MUV.read pf $ i+p0*j
x1<-MUV.read pf $ i+p0*(j+1)
MUV.write pf (i+p0*j) $ (1u)*x0+u*x1
casteljau p0 p1 u i (j+1) s
casteljau (n1*n2*n3) n0 a 0 0 1
casteljau (n2*n3) n1 b 0 0 1
casteljau n3 n2 c 0 0 1
casteljau 1 n3 d 0 0 1
MUV.read pf 0
restriction (Bernsteinp (n0,n1,n2,n3) points) (a,c,e,g) (b,d,f,h)=
runST $ do
pf<-thaw points
let casteljau bef aft nv u v i k s j
| i>=bef = return ()
| k>=aft= casteljau bef aft nv u v (i+1) 0 1 0
| s>=nv = casteljau bef aft nv u v i (k+1) 1 0
| j>=nv = casteljau bef aft nv u v i k (s+1) 0
| otherwise=
let idx i_ j_ k_=(i_*nv+j_)*aft + k_
v'=(vu)/(1u)
in
if s+j<nv then do
pfi0<-MUV.read pf (idx i j k)
pfi1<-MUV.read pf (idx i (j+1) k)
MUV.write pf (idx i j k) $ (1u)*pfi0+u*pfi1
casteljau bef aft nv u v i k s (j+1)
else do
pfi0<-MUV.read pf (idx i (j1) k)
pfi1<-MUV.read pf (idx i j k)
MUV.write pf (idx i j k) $ (1v')*pfi0+v'*pfi1
casteljau bef aft nv u v i k s (j+1)
casteljau 1 (n1*n2*n3) n0 a b 0 0 1 0
casteljau n0 (n2*n3) n1 c d 0 0 1 0
casteljau (n0*n1) n3 n2 e f 0 0 1 0
casteljau (n0*n1*n2) 1 n3 g h 0 0 1 0
pff<-unsafeFreeze pf
return $ Bernsteinp (n0,n1,n2,n3) pff
instance (Num a,Fractional a,MUV.Unbox a)=>Num (Bernsteinp Int a) where
(+) bf@(Bernsteinp m _) bg@(Bernsteinp n _)=
let (Bernsteinp m' f')=elevate (nm) bf
(Bernsteinp _ g')=elevate (mn) bg
in
Bernsteinp m' $ UV.generate m' $ \i->f'!i+g'!i
(*) ff@(Bernsteinp (af) _) gg@(Bernsteinp (ag) _)=
if af<=0 || ag<=0 then
Bernsteinp 0 UV.empty
else
let mm=(af+ag)2
binomial=binomials mm
bin a b=binomial!(b*(mm+1)+a)
in
Bernsteinp (af+ag1) $ create $ do
v<-MUV.new $ af+ag1
let fill i
| i>=af+ag1 = return v
| otherwise = do
let mCoef' i' result
| i'>i || i'>=af =
result
| otherwise =
let a=((bin i' (af1))*(bin (ii') (ag1)))/(bin i (af+ag2)) in
mCoef' (i'+1) $
result+a*(ff?i')*(gg?(ii'))
MUV.write v i $! mCoef' (max 0 (iag+1)) 0
fill (i+1)
fill 0
() bf (Bernsteinp i g)= bf+(Bernsteinp i $ UV.map negate g)
signum _=error "No signum operation for Bernstein1"
abs _=error "No abs operation for Bernstein1"
fromInteger x=Bernsteinp 1 $ UV.singleton $ fromIntegral x
instance (Fractional a, Num a,UV.Unbox a)=>Num (Bernsteinp (Int,Int) a) where
(+) bff@(Bernsteinp (af,bf) _) bgg@(Bernsteinp (ag,bg) _)=
let (Bernsteinp (a,b) f')=elevate (agaf,bgbf) bff
(Bernsteinp _ g')=elevate (afag,bfbg) bgg
in
Bernsteinp (a,b) $ UV.generate (a*b) $ \i->f'!i+g'!i
(*) ff@(Bernsteinp (af,bf) _) gg@(Bernsteinp (ag,bg) _)=
if af<=0 || bf<=0 || ag<=0 || bg<=0 then
Bernsteinp (0,0) UV.empty
else
let mm=max (af+ag) (bf+bg)2
binomial=binomials mm
bin a b=binomial!(b*(mm+1)+a)
in
Bernsteinp (af+ag1,bf+bg1) $ create $ do
v<-MUV.new $ (af+ag1)*(bf+bg1)
let idx i j=i*(bf+bg1)+j
fill i j
| i>=af+ag1 = return v
| j>=bf+bg1 = fill (i+1) 0
| otherwise =
do
let mCoef' i' j' result
| i'>i || i'>=af =
let b=(bin i (af+ag2))*(bin j (bf+bg2)) in
result/b
| j'>j || j'>=bf = mCoef' (i'+1) (max 0 (jbg+1)) result
| otherwise =
let a=(bin i' (af1))*(bin (ii') (ag1))*
(bin j' (bf1))*(bin (jj') (bg1))
in
mCoef' i' (j'+1) $
result+a*(ff?(i',j'))*(gg?(ii',jj'))
MUV.write v (idx i j) $!
mCoef' (max 0 (iag+1)) (max 0 (jbg+1)) 0
fill i (j+1)
fill 0 0
() bf bg=bf+(bg { coefs=UV.map negate $ coefs bg })
signum _=error "No signum operation for Bernstein1"
abs _=error "No abs operation for Bernstein1"
fromInteger x=Bernsteinp (1,1) $ UV.singleton $ fromIntegral x
instance (Fractional a, Num a, UV.Unbox a)=>Num (Bernsteinp (Int,Int,Int) a) where
(+) bff@(Bernsteinp (af,bf,cf) _) bgg@(Bernsteinp (ag,bg,cg) _)=
let (Bernsteinp (a,b,c) f')=elevate (agaf,bgbf,cgcf) bff
(Bernsteinp _ g')=elevate (afag,bfbg,cfcg) bgg
in
Bernsteinp (a,b,c) $ UV.generate (a*b*c) $ \i->f'!i+g'!i
(*) ff@(Bernsteinp (af,bf,cf) _) gg@(Bernsteinp (ag,bg,cg) _)=
if af<=0 || bf<=0 || cf<=0 || ag<=0 || bg<=0 || cg<=0 then
Bernsteinp (0,0,0) UV.empty
else
let mm=(max (max (af+ag) (bf+bg)) (cf+cg))2
binomial=binomials mm
bin a b=binomial!(b*(mm+1)+a)
in
Bernsteinp (af+ag1,bf+bg1,cf+cg1) $ create $ do
v<-MUV.new $ (af+ag1)*(bf+bg1)*(cf+cg1)
let idx i j k=(i*(bf+bg1)+j)*(cf+cg1)+k
fill i j k
| i>=af+ag1 = return v
| j>=bf+bg1 = fill (i+1) 0 0
| k>=cf+cg1 = fill i (j+1) 0
| otherwise =
do
let mCoef' i' j' k' result
| i'>i || i'>=af =
let b=(bin i (af+ag2))*(bin j (bf+bg2))*
(bin k (cf+cg2))
in
result/b
| j'>j || j'>=bf = mCoef' (i'+1) (max 0 (jbg+1)) (max 0 (kcg+1)) result
| k'>k || k'>=cf = mCoef' i' (j'+1) (max 0 (kcg+1)) result
| otherwise =
let a=(bin i' (af1))*(bin (ii') (ag1))*
(bin j' (bf1))*(bin (jj') (bg1))*
(bin k' (cf1))*(bin (kk') (cg1))
in
mCoef' i' j' (k'+1) $
result+a*(ff?(i',j',k'))*(gg?(ii',jj',kk'))
MUV.write v (idx i j k) $!
mCoef' (max 0 (iag+1)) (max 0 (jbg+1)) (max 0 (kcg+1)) 0
fill i j (k+1)
fill 0 0 0
() bf bg=bf+(bg { coefs=UV.map negate $ coefs bg })
signum _=error "No signum operation for Bernstein1"
abs _=error "No abs operation for Bernstein1"
fromInteger x=Bernsteinp (1,1,1) $ UV.singleton $ fromIntegral x
instance (Fractional a, Num a,UV.Unbox a)=>Num (Bernsteinp (Int,Int,Int,Int) a) where
(+) bff@(Bernsteinp (af,bf,cf,df) _) bgg@(Bernsteinp (ag,bg,cg,dg) _)=
let (Bernsteinp (a,b,c,d) f')=elevate (agaf,bgbf,cgcf,dgdf) bff
(Bernsteinp _ g')=elevate (afag,bfbg,cfcg,dfdg) bgg
in
Bernsteinp (a,b,c,d) $ UV.generate (a*b*c*d) $ \i->f'!i+g'!i
(*) ff@(Bernsteinp (af,bf,cf,df) _) gg@(Bernsteinp (ag,bg,cg,dg) _)=
if af<=0 || bf<=0 || cf<=0 || df<=0 || ag<=0 || bg<=0 || cg<=0 || dg<=0 then
Bernsteinp (0,0,0,0) UV.empty
else
let mm=(max (max (af+ag) (bf+bg)) (max (cf+cg) (df+dg)))2
binomial=binomials mm
bin a b=binomial!(b*(mm+1)+a)
in
Bernsteinp (af+ag1,bf+bg1,cf+cg1,df+dg1) $ create $ do
v<-MUV.new $ (af+ag1)*(bf+bg1)*(cf+cg1)*(df+dg1)
let idx i j k l=((i*(bf+bg1)+j)*(cf+cg1)+k)*(df+dg1)+l
fill i j k l
| i>=af+ag1 = return v
| j>=bf+bg1 = fill (i+1) 0 0 0
| k>=cf+cg1 = fill i (j+1) 0 0
| l>=df+dg1 = fill i j (k+1) 0
| otherwise =
do
let mCoef' i' j' k' l' result
| i'>i || i'>=af =
let b=(bin i (af+ag2))*(bin j (bf+bg2))*
(bin k (cf+cg2))*(bin l (df+dg2))
in
result/b
| j'>j || j'>=bf = mCoef' (i'+1) (max 0 (jbg+1)) (max 0 (kcg+1)) (max 0 (ldg+1)) result
| k'>k || k'>=cf = mCoef' i' (j'+1) (max 0 (kcg+1)) (max 0 (ldg+1)) result
| l'>l || l'>=df = mCoef' i' j' (k'+1) (max 0 (ldg+1)) result
| otherwise =
let a=(bin i' (af1))*(bin (ii') (ag1))*
(bin j' (bf1))*(bin (jj') (bg1))*
(bin k' (cf1))*(bin (kk') (cg1))*
(bin l' (df1))*(bin (ll') (dg1))
in
mCoef' i' j' k' (l'+1) $
result+a*(ff?(i',j',k',l'))*(gg?(ii',jj',kk',ll'))
MUV.write v (idx i j k l) $!
mCoef' (max 0 (iag+1)) (max 0 (jbg+1)) (max 0 (kcg+1)) (max 0 (ldg+1)) 0
fill i j k (l+1)
fill 0 0 0 0
() bf bg=bf+(bg { coefs=UV.map negate $ coefs bg })
signum _=error "No signum operation for Bernstein1"
abs _=error "No abs operation for Bernstein1"
fromInteger x=Bernsteinp (1,1,1,1) $ UV.singleton $ fromIntegral x
derivate::(UV.Unbox a,Num a)=>Bernsteinp Int a->Bernsteinp Int a
derivate (Bernsteinp n f)
| n<=1 = Bernsteinp 0 $ UV.empty
| otherwise=Bernsteinp (n1) $ UV.generate (n1) (\i->(f!(i+1)f!i)*(fromIntegral $ n1))
reorient::(UV.Unbox a)=>Bernsteinp Int a->Bernsteinp Int a
reorient (Bernsteinp n f)=Bernsteinp n (UV.reverse f)
\end{code}
\begin{code}
convexHull::Int->Int->Int->Bernsteinp i Interval->Double->Double->(Bool,Double,Double)
convexHull bef aft nv (Bernsteinp _ points) a b=
let (allzero,pointsl,pointsu)=runST $ do
let idx i j k=(i*nv+j)*aft + k
pl<-MUV.replicate nv (1/0)
pu<-MUV.replicate nv (1/0)
let fill i j k allzero_
| i>=bef = return allzero_
| j>=nv = fill (i+1) 0 0 allzero_
| k>=aft = fill i (j+1) 0 allzero_
| otherwise = do
pl0<-MUV.read pl j
pu0<-MUV.read pu j
MUV.write pl j (min pl0 $ ilow $ points!(idx i j k))
MUV.write pu j (max pu0 $ iup $ points!(idx i j k))
fill i j (k+1) (allzero_ && pl0<=0 && pu0>=0)
allzero_<-fill 0 0 0 True
pl'<-UV.unsafeFreeze pl
pu'<-UV.unsafeFreeze pu
return (allzero_,pl',pu')
inter::Int->Int->(Double,Double)
inter i j
| i>j = inter j i
| otherwise =
let yli=pointsl!i
yui=pointsu!i
ylj=pointsl!j
yuj=pointsu!j
fi=fromIntegral i
fj=fromIntegral j
inter0 yi yj=
let k=fromIntegral $ ij in
Interval fi fi +
(Interval yi yi)*(Interval k k)/
(Interval yj yjInterval yi yi)
in
if yli<=0 then
if yui>=0 then
if ylj<=0 then
if yuj>=0 then
(fi,fj)
else
(fi, iup $ inter0 yui yuj)
else
(fi,iup $ inter0 yli ylj)
else
if ylj<=0 then
if yuj>=0 then
(ilow $ inter0 yui yuj, fj)
else
(1/0,1/0)
else
(ilow $ inter0 yui yuj, iup $ inter0 yli ylj)
else
if ylj<=0 then
if yuj>=0 then
(ilow $ inter0 yli ylj,fj)
else
(ilow $ inter0 yli ylj, iup $ inter0 yui yuj)
else
(1/0,1/0)
testAll i j m0 m1
| i>=nv =
let fn=fromIntegral (nv1)
(# a0,b0 #)=over m0 m0 fn fn
(# a1,b1 #)=minus b b a a
(# a2,b2 #)=times a0 b0 a1 b1
(# a3,_ #)=plus a a a2 b2
(# c0,d0 #)=over m1 m1 fn fn
(# c2,d2 #)=times c0 d0 a1 b1
(# _,d3 #)=plus a a c2 d2
in
(False,a3,d3)
| j>=nv = testAll (i+1) (i+1) m0 m1
| otherwise =
let (m0',m1')=inter i j in
testAll i (j+1)
(min m0 m0') (max m1 m1')
in
if allzero then (True,a,b) else
testAll 0 0 (1/0) (1/0)
class Box a i | a->i where
cut::Int->a->[a]
size::Int->a->Double
restriction#::a->Bernsteinp i Interval->a
variables::a->Int
instance Box (Double,Double) Int where
cut _ (a,b)=
let m=(a+b)/2 in
if a<m && m<b then
[(a,m),(m,b)]
else
[(a,b)]
size _ (a,b)=ba
restriction# (a,b) points@(Bernsteinp n0 _)=
let restr=restriction points (Interval a a) (Interval b b)
(allz,a',b')=convexHull 1 1 n0 restr a b
in
(max a a', min b b')
variables _ = 1
instance Box (Double,Double,Double,Double) (Int,Int) where
cut 0 x@(a,b,c,d)=
let m=(a+b)/2 in
if a<m && m<b then
[(a,m,c,d),(m,b,c,d)]
else
[x]
cut _ x@(a,b,c,d)=
let m=(c+d)/2 in
if c<m && m<d then
[(a,b,c,m),(a,b,m,d)]
else
[x]
size 0 (a,b,_,_)=ba
size _ (_,_,a,b)=ba
restriction# (a,b,c,d) points@(Bernsteinp (n0,n1) _)=
let restr=restriction points (Interval a a,Interval c c) (Interval b b,Interval d d)
(allz0,a',b')
| n0>1 = convexHull 1 n1 n0 restr a b
| otherwise = (False,a,b)
(allz1,c',d')
| n1>1 = convexHull n0 1 n1 restr c d
| otherwise = (False,c,d)
in
(max a a', min b b', max c c', min d d')
variables _=2
instance Box (Double,Double,Double,Double,Double,Double) (Int,Int,Int) where
cut 0 x@(a,b,c,d,e,f)=
let m=(a+b)/2 in
if a<m && m<b then
[(a,m,c,d,e,f),(m,b,c,d,e,f)]
else
[x]
cut 1 x@(a,b,c,d,e,f)=
let m=(c+d)/2 in
if c<m && m<d then
[(a,b,c,m,e,f),(a,b,m,d,e,f)]
else
[x]
cut _ x@(a,b,c,d,e,f)=
let m=(e+f)/2 in
if e<m && m<f then
[(a,b,c,d,e,m),(a,b,c,d,m,f)]
else
[x]
size 0 (a,b,_,_,_,_)=ba
size 1 (_,_,a,b,_,_)=ba
size _ (_,_,_,_,a,b)=ba
restriction# (a,b,c,d,e,f) points@(Bernsteinp (n0,n1,n2) _)=
let restr=restriction points (Interval a a,Interval c c,Interval e e)
(Interval b b,Interval d d,Interval f f)
(allz0,a',b')
| n0>1 = convexHull 1 (n1*n2) n0 restr a b
| otherwise = (False,a,b)
(allz1,c',d')
| n1>1 = convexHull n0 n2 n1 restr c d
| otherwise = (False,c,d)
(allz2,e',f')
| n2>1 = convexHull (n0*n1) 1 n2 restr e f
| otherwise = (False,e,f)
in
(max a a', min b b', max c c', min d d', max e e', min f f')
variables _=3
instance Box (Double,Double,Double,Double,Double,Double,Double,Double) (Int,Int,Int,Int) where
cut 0 x@(a,b,c,d,e,f,g,h)=
let m=(a+b)/2 in
if a<m && m<b then
[(a,m,c,d,e,f,g,h),(m,b,c,d,e,f,g,h)]
else
[x]
cut 1 x@(a,b,c,d,e,f,g,h)=
let m=(c+d)/2 in
if c<m && m<d then
[(a,b,c,m,e,f,g,h),(a,b,m,d,e,f,g,h)]
else
[x]
cut 2 x@(a,b,c,d,e,f,g,h)=
let m=(e+f)/2 in
if e<m && m<f then
[(a,b,c,d,e,m,g,h),(a,b,c,d,m,f,g,h)]
else
[x]
cut _ x@(a,b,c,d,e,f,g,h)=
let m=(g+h)/2 in
if g<m && m<h then
[(a,b,c,d,e,f,g,m),(a,b,c,d,e,f,m,h)]
else
[x]
size 0 (a,b,_,_,_,_,_,_)=ba
size 1 (_,_,a,b,_,_,_,_)=ba
size 2 (_,_,_,_,a,b,_,_)=ba
size _ (_,_,_,_,_,_,a,b)=ba
restriction# (a,b,c,d,e,f,g,h) points@(Bernsteinp (n0,n1,n2,n3) _)=
let restr=restriction points (Interval a a,Interval c c,Interval e e,Interval g g)
(Interval b b,Interval d d,Interval f f,Interval h h)
(allz0,a',b')
| n0>1 = convexHull 1 (n1*n2*n3) n0 restr a b
| otherwise = (False,a,b)
(allz1,c',d')
| n1>1 = convexHull n0 (n2*n3) n1 restr c d
| otherwise = (False,c,d)
(allz2,e',f')
| n2>1 = convexHull (n0*n1) n3 n2 restr e f
| otherwise = (False,e,f)
(allz3,g',h')
| n3>1 = convexHull (n0*n1*n2) 1 n3 restr g h
| otherwise = (False,g,h)
in
(max a a', min b b', max c c', min d d',
max e e', min f f', max g g', min h h')
variables _=4
solve::(Show a,Show i,Eq a,Box a i)=>Double->V.Vector (Bernsteinp i Interval)->a->[a]
solve sizeThreshold equations h=
let splitThreshold=0.95
restrictAll neq box
| neq>=V.length equations = box
| not (check 0 box) = box
| otherwise =
let next=restriction# box (equations!neq) in
restrictAll (neq+1) next
check v box=
(v>=(variables box)) ||
(let s=size v box in
0<=s && s<(1/0) && check (v+1) box)
h'=restrictAll 0 h
isSmall v box=
(v>=variables box) ||
((size v box <= sizeThreshold) && (isSmall (v+1) box))
in
if isSmall 0 h' then
if check 0 (restrictAll 0 h') then
[h']
else
[]
else
if check 0 h' then
let cutAll v boxes
| v>=(variables h) = boxes
| otherwise =
cutAll (v+1) $
Prelude.concatMap (\b->if (size v b)>=splitThreshold*(size v h)
&& (size v b)>sizeThreshold
then
cut v b
else [b]) boxes
cc=cutAll 0 [h']
in
case cc of
[h'']
| h''==h ->
[h]
| otherwise -> Prelude.concatMap (solve sizeThreshold equations) cc
_->
Prelude.concatMap (solve sizeThreshold equations) cc
else
[]
\end{code}