diff --git a/Algebra/Polynomials/Bernstein.lhs b/Algebra/Polynomials/Bernstein.lhs
new file mode 100644
--- /dev/null
+++ b/Algebra/Polynomials/Bernstein.lhs
@@ -0,0 +1,1009 @@
+\begin{code}
+{-# OPTIONS -XUnboxedTuples -XScopedTypeVariables -XFlexibleContexts -XBangPatterns -XUndecidableInstances -XMultiParamTypeClasses -XFunctionalDependencies -XFlexibleInstances -XMagicHash -XTypeFamilies #-}
+-- | Various functions for manipulating polynomials, essentially when
+-- represented in the Bernstein basis, in one or two variables.
+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 ((++))
+  
+-- | The type for Bernstein polynomials with an arbitrary number of variables
+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
+  -- Constructeurs
+  (?)::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)=bxf-bxg 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 (i-m-1)
+            b<-MUV.read v (i-m-2)
+            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 (n-1))*((bin (j-i) r))/(bin j (n+r-1)))
+            in
+             (sumAll 0 0)
+          binomial=binomials $ n+r-1
+          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>=n-s = fill 0 (s+1)
+            | otherwise = do
+              a<-MUV.read arr i
+              b<-MUV.read arr (i+1)
+              MUV.write arr i $ a*(1-t)+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'=(v-u)/(1-u)
+              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) $ (1-u)*pfi0+u*pfi1
+                 casteljau bef aft nv u v i k s (j+1)
+               else do
+                 pfi0<-MUV.read pf (idx i (j-1) k)
+                 pfi1<-MUV.read pf (idx i j k)
+                 MUV.write pf (idx i j k) $ (1-v')*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' (a-1))*((bin (i-i') ra)/(bin i (a+ra-1)))
+                                 x1=(bin j' (b-1))*((bin (j-j') rb)/(bin j (b+rb-1)))
+                             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+ra-1) (b+rb-1)
+           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>=(p1-s) = 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) $ (1-u)*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'=(v-u)/(1-u)
+              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) $ (1-u)*pfi0+u*pfi1
+                 casteljau bef aft nv u v i k s (j+1)
+               else do
+                 pfi0<-MUV.read pf (idx i (j-1) k)
+                 pfi1<-MUV.read pf (idx i j k)
+                 MUV.write pf (idx i j k) $ (1-v')*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' (a-1))*((bin (i-i') ra)/(bin i (a+ra-1)))
+                                 x1=(bin j' (b-1))*((bin (j-j') rb)/(bin j (b+rb-1)))
+                                 x2=(bin k' (c-1))*((bin (k-k') rc)/(bin k (c+rc-1)))
+                             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+ra-1) (b+rb-1)) (c+rc-1)
+           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>=(p1-s) = 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) $ (1-u)*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'=(v-u)/(1-u)
+              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) $ (1-u)*pfi0+u*pfi1
+                 casteljau bef aft nv u v i k s (j+1)
+               else do
+                 pfi0<-MUV.read pf (idx i (j-1) k)
+                 pfi1<-MUV.read pf (idx i j k)
+                 MUV.write pf (idx i j k) $ (1-v')*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' (a-1))*((bin (i-i') ra)/(bin i (a+ra-1)))
+                                 x1=(bin j' (b-1))*((bin (j-j') rb)/(bin j (b+rb-1)))
+                                 x2=(bin k' (c-1))*((bin (k-k') rc)/(bin k (c+rc-1)))
+                                 x3=(bin l' (d-1))*((bin (l-l') rd)/(bin l (d+rd-1)))
+                             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>=(p1-s) = 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) $ (1-u)*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'=(v-u)/(1-u)
+              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) $ (1-u)*pfi0+u*pfi1
+                 casteljau bef aft nv u v i k s (j+1)
+               else do
+                 pfi0<-MUV.read pf (idx i (j-1) k)
+                 pfi1<-MUV.read pf (idx i j k)
+                 MUV.write pf (idx i j k) $ (1-v')*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 (n-m) bf
+        (Bernsteinp _ g')=elevate (m-n) 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+ag-1) $ create $ do
+       v<-MUV.new $ af+ag-1
+       let fill i
+             | i>=af+ag-1 = return v
+             | otherwise = do
+               let mCoef' i' result
+                     | i'>i || i'>=af = 
+                       result
+                     | otherwise =
+                       let a=((bin i' (af-1))*(bin (i-i') (ag-1)))/(bin i (af+ag-2)) in
+                       mCoef' (i'+1) $
+                       result+a*(ff?i')*(gg?(i-i'))
+               
+               MUV.write v i $! mCoef' (max 0 (i-ag+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 (ag-af,bg-bf) bff
+        (Bernsteinp _ g')=elevate (af-ag,bf-bg) 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+ag-1,bf+bg-1) $ create $ do
+       v<-MUV.new $ (af+ag-1)*(bf+bg-1)
+       let idx i j=i*(bf+bg-1)+j
+           fill i j
+             | i>=af+ag-1 = return v
+             | j>=bf+bg-1 = fill (i+1) 0
+             | otherwise =
+               do
+               let mCoef' i' j' result
+                     | i'>i || i'>=af = 
+                       let b=(bin i (af+ag-2))*(bin j (bf+bg-2)) in
+                       result/b
+                     | j'>j || j'>=bf = mCoef' (i'+1) (max 0 (j-bg+1)) result
+                     | otherwise =
+                       let a=(bin i' (af-1))*(bin (i-i') (ag-1))*
+                             (bin j' (bf-1))*(bin (j-j') (bg-1))
+                       in
+                        mCoef' i' (j'+1) $
+                        result+a*(ff?(i',j'))*(gg?(i-i',j-j'))
+               
+               MUV.write v (idx i j) $!
+                 mCoef' (max 0 (i-ag+1)) (max 0 (j-bg+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 (ag-af,bg-bf,cg-cf) bff
+        (Bernsteinp _ g')=elevate (af-ag,bf-bg,cf-cg) 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+ag-1,bf+bg-1,cf+cg-1) $ create $ do
+       v<-MUV.new $ (af+ag-1)*(bf+bg-1)*(cf+cg-1)
+       let idx i j k=(i*(bf+bg-1)+j)*(cf+cg-1)+k
+           fill i j k
+             | i>=af+ag-1 = return v
+             | j>=bf+bg-1 = fill (i+1) 0 0
+             | k>=cf+cg-1 = fill i (j+1) 0
+             | otherwise =
+               do
+               let mCoef' i' j' k' result
+                     | i'>i || i'>=af = 
+                       let b=(bin i (af+ag-2))*(bin j (bf+bg-2))*
+                             (bin k (cf+cg-2))
+                       in
+                        result/b
+                     | j'>j || j'>=bf = mCoef' (i'+1) (max 0 (j-bg+1)) (max 0 (k-cg+1)) result
+                     | k'>k || k'>=cf = mCoef' i' (j'+1) (max 0 (k-cg+1)) result
+                     | otherwise =
+                       let a=(bin i' (af-1))*(bin (i-i') (ag-1))*
+                             (bin j' (bf-1))*(bin (j-j') (bg-1))*
+                             (bin k' (cf-1))*(bin (k-k') (cg-1))
+                       in
+                        mCoef' i' j' (k'+1) $
+                        result+a*(ff?(i',j',k'))*(gg?(i-i',j-j',k-k'))
+               
+               MUV.write v (idx i j k) $!
+                 mCoef' (max 0 (i-ag+1)) (max 0 (j-bg+1)) (max 0 (k-cg+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 (ag-af,bg-bf,cg-cf,dg-df) bff
+        (Bernsteinp _ g')=elevate (af-ag,bf-bg,cf-cg,df-dg) 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+ag-1,bf+bg-1,cf+cg-1,df+dg-1) $ create $ do
+       v<-MUV.new $ (af+ag-1)*(bf+bg-1)*(cf+cg-1)*(df+dg-1)
+       let idx i j k l=((i*(bf+bg-1)+j)*(cf+cg-1)+k)*(df+dg-1)+l
+           fill i j k l
+             | i>=af+ag-1 = return v
+             | j>=bf+bg-1 = fill (i+1) 0 0 0
+             | k>=cf+cg-1 = fill i (j+1) 0 0
+             | l>=df+dg-1 = fill i j (k+1) 0
+             | otherwise =
+               do
+               let mCoef' i' j' k' l' result
+                     | i'>i || i'>=af = 
+                       let b=(bin i (af+ag-2))*(bin j (bf+bg-2))*
+                             (bin k (cf+cg-2))*(bin l (df+dg-2))
+                       in
+                        result/b
+                     | j'>j || j'>=bf = mCoef' (i'+1) (max 0 (j-bg+1)) (max 0 (k-cg+1)) (max 0 (l-dg+1)) result
+                     | k'>k || k'>=cf = mCoef' i' (j'+1) (max 0 (k-cg+1)) (max 0 (l-dg+1)) result
+                     | l'>l || l'>=df = mCoef' i' j' (k'+1) (max 0 (l-dg+1)) result
+                     | otherwise =
+                       let a=(bin i' (af-1))*(bin (i-i') (ag-1))*
+                             (bin j' (bf-1))*(bin (j-j') (bg-1))*
+                             (bin k' (cf-1))*(bin (k-k') (cg-1))*
+                             (bin l' (df-1))*(bin (l-l') (dg-1))
+                       in
+                        mCoef' i' j' k' (l'+1) $
+                        result+a*(ff?(i',j',k',l'))*(gg?(i-i',j-j',k-k',l-l'))
+               
+               MUV.write v (idx i j k l) $!
+                 mCoef' (max 0 (i-ag+1)) (max 0 (j-bg+1)) (max 0 (k-cg+1)) (max 0 (l-dg+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
+
+-- | Computes the derivative of a univariate Bernstein polynomial.
+derivate::(UV.Unbox a,Num a)=>Bernsteinp Int a->Bernsteinp Int a
+derivate (Bernsteinp n f)
+  | n<=1 = Bernsteinp 0 $ UV.empty
+  | otherwise=Bernsteinp (n-1) $ UV.generate (n-1) (\i->(f!(i+1)-f!i)*(fromIntegral $ n-1))
+
+-- | Computes @f(1-x)@ (useful when used with Bezier curves).
+reorient::(UV.Unbox a)=>Bernsteinp Int a->Bernsteinp Int a
+reorient (Bernsteinp n f)=Bernsteinp n (UV.reverse f)
+
+\end{code}
+
+\begin{code}
+{-
+restrict::Int->Int->Int->Bernsteinp i Interval->Double->Double->Bernsteinp i Interval
+restrict bef aft nv (Bernsteinp ix poly) a b=
+  --traceShow "Restrict" $   
+  runST $ do
+    poly'<-thaw poly :: ST s (MUV.STVector s Interval)
+    casteljau poly' 0 0 1 0
+    unsafeFreeze poly' >>= return.(Bernsteinp ix)
+  
+  where
+    
+    
+    (# bl,bu #)=
+      let (# b0,b1 #)=minus b b a a
+          (# b2,b3 #)=minus 1 1 a a
+      in
+       over b0 b1 b2 b3
+
+    idx i j k= --traceShow (i,j,k,d) $
+      (i*nv+j)*aft + k
+      
+    casteljau::MUV.STVector s Interval->
+               Int->Int->Int->Int->ST s ()
+                                  
+    casteljau pf i k s j
+      | i>=bef = return ()
+      | k>=aft= casteljau pf (i+1) 0 1 0
+      | s>=nv = casteljau pf i (k+1) 1 0
+      | j>=nv = casteljau pf i k (s+1) 0
+        
+    -- Au boulot
+      | s+j<nv = do
+        (Interval l1 u1)<-MUV.read pf (idx i j k)
+        (Interval l3 u3)<-MUV.read pf (idx i (j+1) k)
+        let (# l0,u0 #)=minus 1 1 a a
+            (# l2,u2 #)=times l0 u0 l1 u1
+            (# l4,u4 #)=times a a l3 u3
+            (# l5,u5 #)=plus l2 u2 l4 u4
+        MUV.write pf (idx i j k) (Interval l5 u5)
+        casteljau pf i k s (j+1)
+                  
+      | otherwise = do
+        (Interval l1 u1)<-MUV.read pf (idx i (j-1) k)
+        (Interval l3 u3)<-MUV.read pf (idx i j k)
+        let (# l0,u0 #)=minus 1 1 bl bu
+            (# l2,u2 #)=times l0 u0 l1 u1
+            (# l4,u4 #)=times bl bu l3 u3
+            (# l5,u5 #)=plus l2 u2 l4 u4
+        MUV.write pf (idx i j k) (Interval l5 u5)
+        casteljau pf i k s (j+1)
+-}
+{-
+restrict::Int->Int->Int->Bernsteinp i a->a->a->Bernsteinp i a
+restrict bef aft nv (Bernsteinp ix poly) a b=
+  --traceShow "Restrict" $   
+  runST $ do
+    poly'<-thaw poly
+    casteljau poly' 0 0 1 0
+    unsafeFreeze poly' >>= return.(Bernsteinp ix)
+  
+  where
+    
+    
+    casteljau pf bef aft nv a b i k s j
+      | i>=bef = return ()
+      | k>=aft= casteljau pf bef aft nv a b (i+1) 0 1 0
+      | s>=nv = casteljau pf bef aft nv a b i (k+1) 1 0
+      | j>=nv = casteljau pf bef aft nv a b i k (s+1) 0
+      | otherwise=
+        let idx i j k=(i*nv+j)*aft + k 
+            b'=(b-a)/(1-a)
+        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) $ (1-a)*pfi0+a*pfi1
+           casteljau pf bef aft nv a b i k s (j+1)
+         else do
+           pfi0<-MUV.read pf (idx i (j-1) k)
+           pfi1<-MUV.read pf (idx i j k)
+           MUV.write pf (idx i j k) $ (1-b')*pfi0+b*pfi1
+           casteljau pf bef aft nv a b i k s (j+1)
+-}
+
+-- Le booleen veut dire "tous les coefs sont nuls"
+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_ -- a avant, b courant, c apres
+              | 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 $ i-j in
+                Interval fi fi + 
+                (Interval yi yi)*(Interval k k)/
+                (Interval yj yj-Interval yi yi)
+          in
+           if yli<=0 then
+             if yui>=0 then
+               if ylj<=0 then
+                 if yuj>=0 then
+                   -- 1 les deux sont sur la ligne
+                   --traceShow "1" $
+                   (fi,fj)
+                 else
+                   -- 2 M est sur la ligne, M' est en-dessous
+                   --traceShow "2" $
+                   (fi, iup $ inter0 yui yuj)
+               else
+                 -- 3 M est sur la ligne, M' est au-dessus
+                 --traceShow "3" $
+                 (fi,iup $ inter0 yli ylj)
+             else
+               -- M est en-dessous de la ligne 
+               if ylj<=0 then
+                 if yuj>=0 then
+                   -- 4 M' est sur la ligne
+                   --traceShow "4" $
+                   (ilow $ inter0 yui yuj, fj)
+                 else
+                   -- 5 M' est en-dessous (comme M)
+                   --traceShow "5" $
+                   (1/0,-1/0)
+               else
+                 -- 6 M' est au-dessus
+                 --traceShow "6" $
+                 (ilow $ inter0 yui yuj, iup $ inter0 yli ylj)
+           else
+               -- M est au-dessus de la ligne
+               if ylj<=0 then
+                 if yuj>=0 then
+                   -- 7 M' est sur la ligne
+                   --traceShow "7" $
+                   (ilow $ inter0 yli ylj,fj)
+                 else
+                   -- 8 M' est en-dessous (comme M)
+                   --traceShow "8" $
+                   (ilow $ inter0 yli ylj, iup $ inter0 yui yuj)
+               else
+                 -- 9 M' est au-dessus
+                 --traceShow "9" $
+                 (1/0,-1/0)
+                 
+      testAll i j m0 m1
+        | i>=nv = 
+          let fn=fromIntegral (nv-1)
+              (# 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
+   --traceShow allzero $
+   if allzero then (True,a,b) else
+     testAll 0 0 (1/0) (-1/0)
+--traceShow ("convexHull",pointsl,pointsu,m) $ m
+
+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)=b-a
+  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,_,_)=b-a
+  size _ (_,_,a,b)=b-a
+                   
+  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,_,_,_,_)=b-a
+  size 1 (_,_,a,b,_,_)=b-a
+  size _ (_,_,_,_,a,b)=b-a
+    
+  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,_,_,_,_,_,_)=b-a
+  size 1 (_,_,a,b,_,_,_,_)=b-a
+  size 2 (_,_,_,_,a,b,_,_)=b-a
+  size _ (_,_,_,_,_,_,a,b)=b-a
+    
+  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
+     --traceShow restr $
+    (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
+
+-- | Computes the intersection of a given Bezier hypersurface, given
+-- by its graph, with plane @z=0@.
+solve::(Show a,Show i,Eq a,Box a i)=>Double->V.Vector (Bernsteinp i Interval)->a->[a]
+solve sizeThreshold equations h= -- traceShow 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}
diff --git a/Algebra/Polynomials/Numerical.hs b/Algebra/Polynomials/Numerical.hs
new file mode 100644
--- /dev/null
+++ b/Algebra/Polynomials/Numerical.hs
@@ -0,0 +1,263 @@
+{-# CFILES cnumerical.c #-}
+{-# OPTIONS -XUnboxedTuples -XMagicHash -XScopedTypeVariables -XBangPatterns -cpp -XTypeFamilies -XMultiParamTypeClasses #-}
+{-# LANGUAGE ForeignFunctionInterface #-}
+-- | This module contains the definition of the main arithmetic tools
+-- used in Metafont'.
+module Algebra.Polynomials.Numerical(
+  -- * Raw operations
+  fromIntegral#,plus,minus,over,times,
+  sqrt#,cos#,sin#,acos#,asin#,
+  -- * The 'Interval' type
+  Interval(..),Intervalize(..),
+  interval,intersectsd, union,
+  fpred,fsucc
+  ) where
+
+
+import Data.Vector.Unboxed as UV
+import qualified Data.Vector.Generic.Mutable as GMV
+import qualified Data.Vector.Generic as GV
+import Foreign.C.Types
+foreign import ccall unsafe "c_succ" c_fsucc::CDouble->CDouble
+foreign import ccall unsafe "c_pred" c_fpred::CDouble->CDouble
+
+fsucc,fpred::Double->Double
+fpred=realToFrac.c_fpred.realToFrac
+fsucc=realToFrac.c_fsucc.realToFrac
+
+{-# INLINE plus #-}
+-- | Interval addition
+plus::Double->Double->Double->Double->(# Double, Double #)
+plus !a !b !c !d=
+    let !x=a+c
+        !y=b+d
+    in
+     (# fpred x,fsucc y #)
+   
+-- | Interval substraction
+{-# INLINE minus #-}
+minus::Double->Double->Double->Double->(# Double, Double #)
+minus !a !b !c !d=
+    let !x=a-d
+        !y=b-c
+    in
+     (# fpred x, fsucc y #)
+-- | Interval multiplication
+{-# INLINE times #-}
+times::Double->Double->Double->Double->(# Double, Double #)
+times !a !b !c !d=
+    let !w=a*c
+        !x=a*d
+        !y=b*c
+        !z=b*d
+      
+        (# !aa,!bb #)=if w<x then (# w,x #) else (# x,w #)
+        (# !cc,!dd #)=if y<z then (# y,z #) else (# z,y #)
+        !m=min aa cc
+        !m'=max bb dd
+    in
+     (# fpred m, fsucc m' #)
+
+-- | Interval division
+{-# INLINE over #-}
+over::Double->Double->Double->Double->(# Double, Double #)
+over !a !b !c !d=
+    if c*d<=0 then 
+      if a>0 then (# 1/0,1/0 #) else
+        if b<0 then (# (-1/0), (-1/0) #) else
+          (# 0/0, 0/0 #)
+                         
+    else
+      let !w=a/c
+          !x=a/d
+          !y=b/c
+          !z=b/d
+      
+          !(aa,bb)=if w<x then (w,x) else (x,w)
+          !(cc,dd)=if y<z then (y,z) else (z,y)
+          !m=min aa cc
+          !m'=max bb dd
+      in
+       (# fpred m, fsucc m' #)
+
+-- | Converts an 'Integral' value into an interval.
+fromIntegral#::Integral x=>x->(# Double,Double #)
+fromIntegral# n=
+    let !n_=fromIntegral n in
+    (# fpred n_,fsucc n_ #)
+
+-- | Interval cosine
+cos#::Double->Double->(# Double,Double #)
+cos# !a !b=
+  let (# !_m0,!_m0' #)=if cos a<=cos b then (# cos a, cos b #) else (# cos b, cos a #)
+      !m0=fpred _m0
+      !m0'=fsucc _m0'
+      checkUp !(k::Int) !m !m'=
+        let (# !ka,!kb #)=fromIntegral# k
+            (# !ka0,!kb0 #)=times ka kb (fpred pi) (fsucc pi)
+        in
+         if ka0>b then (# m,m' #) else
+           if kb0<a then
+             checkUp (k+1) m m'
+           else
+             if k`mod`2==0 then
+               checkUp (k+1) m 1
+             else
+               checkUp (k+1) (-1) m'
+  in
+   checkUp (floor $ fpred (a/pi)) m0 m0'
+-- | Interval sine
+sin# ::Double->Double->(# Double,Double #)
+sin# !a !b=
+  let (# _m0,_m0' #)
+        | sin a<sin b = (# sin a, sin b #)
+        | otherwise = (# sin b, sin a #)
+      m0=max (-1) $ fpred _m0
+      m0'=min 1 $ fsucc _m0'
+      (# pa,pb #)=(# fpred pi, fsucc pi #)
+      (# ka1,kb1 #)=over pa pb 2 2
+      
+      up (k::Int) !m !m'=
+        let (# ka,kb #)=fromIntegral# k
+            (# ka0,kb0 #)=times ka kb pa pb
+            (# ka2,kb2 #)=plus ka0 kb0 ka1 kb1 -- kpi+pi/2
+        in
+         if ka2>b then
+           (# m,m' #)
+         else
+           if kb2<a then
+             up (k+1) m m'
+           else
+             if k`mod`2 == 0 then
+               up (k+1) m 1
+             else
+               up (k+1) (-1) m'
+  in
+   up (floor $ a/pi) m0 m0'
+  
+      
+sqrt#::Double->Double->(# Double,Double #)
+sqrt# !a !b=
+  let sa=sqrt a
+      sb=sqrt b
+      sa_=max 0 (fpred sa)
+      sb_=fsucc sb
+  in
+   (# sa_, sb_ #)
+
+acos#::Double->Double->(# Double,Double #)
+acos# !a !b=
+  let aca=acos $ max (-1) a
+      acb=acos $ min 1 b
+  in
+   (# fpred (min aca acb), fsucc (max aca acb) #)
+
+asin#::Double->Double->(# Double,Double #)
+asin# !a !b=
+  let aca=asin $ max (-1) a
+      acb=asin $ min 1 b
+  in
+   (# fpred (min aca acb), fsucc (max aca acb) #)
+
+-- | The interval type (most of its operations are calls to the raw functions)
+data Interval=Interval {ilow::Double,iup::Double} deriving (Eq, Show)
+
+instance Floating Interval where
+  cos (Interval a b)=
+    let (# c,d #)=cos# a b in
+    Interval c d
+  sin (Interval a b)=
+    let (# c,d #)=sin# a b in
+    Interval c d
+  sqrt (Interval a b)=
+    let (# a#,b# #)=sqrt# a b in
+    Interval a# b#
+  acos (Interval a b)=
+    let (# a#,b# #)=acos# a b in
+    Interval a# b#
+  asin (Interval a b)=
+    let (# a#,b# #)=asin# a b in
+    Interval a# b#
+  pi=Interval (fpred pi) (fsucc pi)
+  
+  
+-- | Intersection of two 'Interval's.
+{-# INLINE intersectsd #-}
+intersectsd::Interval->Interval->Bool
+intersectsd (Interval a b) (Interval c d) = b>=c && a<=d
+
+-- | Union of two intersecting intervals (undefined behaviour if they do not intersect).
+{-# INLINE union #-}
+union::Interval->Interval->Interval
+union (Interval a b) (Interval c d) = Interval (min a c) (max b d)
+
+-- | Two common operations on types defined with intervals.
+class Intervalize a where
+  intervalize::a Double->a Interval
+  intersects::a Interval->a Interval->Bool
+ 
+-- | Converts an optimal IEEE-754 representation of a number into an
+-- optimal interval containing this number.
+interval::Double->Interval
+interval x=Interval (fpred x) (fsucc x)
+
+instance Num Interval where
+  (+) (Interval a b) (Interval c d)=
+    let (# a',b' #)=plus a b c d in
+    Interval a' b'
+  (-) (Interval a b) (Interval c d)=
+    let (# a',b' #)=minus a b c d in
+    Interval a' b'
+  (*) (Interval a b) (Interval c d)=
+    let (# a',b' #)=times a b c d in
+    Interval a' b'
+  abs x@(Interval a b)=
+    if b<=0 then Interval (negate b) (negate a) else
+      if a<=0 then
+        Interval 0 (max b $ negate a)
+      else
+        x
+        
+  signum _=undefined
+  
+  fromInteger=interval.fromInteger
+      
+instance Fractional Interval where
+
+  (/) (Interval a b) (Interval c d)=
+    let (# a',b' #)=over a b c d in
+    Interval a' b'
+
+  fromRational r=
+    let r'=fromRational r in
+    Interval (fpred r') (fsucc r')
+
+
+newtype instance UV.MVector s Interval = MV_Interval (UV.MVector s (Double,Double))
+newtype instance UV.Vector Interval = V_Interval  (UV.Vector (Double,Double))
+instance Unbox Interval
+
+instance GMV.MVector UV.MVector Interval where
+  basicLength (MV_Interval a)=GMV.basicLength a
+  basicUnsafeSlice a b (MV_Interval c)=MV_Interval $ GMV.basicUnsafeSlice a b c
+  basicOverlaps (MV_Interval a) (MV_Interval b)=GMV.basicOverlaps a b
+  basicUnsafeNew a=GMV.basicUnsafeNew a >>= return.MV_Interval
+  basicUnsafeReplicate a (Interval b c)=GMV.basicUnsafeReplicate a (b,c)>>=return.MV_Interval
+  basicUnsafeRead (MV_Interval a) b=GMV.basicUnsafeRead a b >>= (\(u,v)->return $ Interval u v)
+  basicUnsafeWrite (MV_Interval a) b (Interval c d)=GMV.basicUnsafeWrite a b (c,d)
+  basicClear (MV_Interval a)=GMV.basicClear a
+  basicSet (MV_Interval a) (Interval b c)=GMV.basicSet a (b,c)
+  basicUnsafeCopy (MV_Interval a) (MV_Interval b)=GMV.basicUnsafeCopy a b
+  basicUnsafeGrow (MV_Interval a) b=GMV.basicUnsafeGrow a b >>= return.MV_Interval
+
+instance GV.Vector UV.Vector Interval where
+  basicUnsafeFreeze (MV_Interval a)=GV.basicUnsafeFreeze a >>= return.V_Interval
+  basicUnsafeThaw (V_Interval a)=GV.basicUnsafeThaw a >>= return.MV_Interval
+  basicLength (V_Interval a)=GV.basicLength a
+  basicUnsafeSlice a b (V_Interval c)=V_Interval (GV.basicUnsafeSlice a b c)
+  basicUnsafeIndexM (V_Interval a) b=GV.basicUnsafeIndexM a b >>= (\(u,v)->return $ Interval u v)
+
+(!#)::UV.Vector Interval->Int->(# Double,Double #)
+(!#) a b=
+  let Interval u v=a!b in (# u,v #)
+
diff --git a/Algebra/Polynomials/cnumerical.c b/Algebra/Polynomials/cnumerical.c
new file mode 100644
--- /dev/null
+++ b/Algebra/Polynomials/cnumerical.c
@@ -0,0 +1,143 @@
+#include <stdio.h>
+#include <HsFFI.h>
+
+union stg_ieee754_dbl
+{
+  double d;
+  struct {
+
+#if WORDS_BIGENDIAN
+    unsigned int negative:1;
+    unsigned int exponent:11;
+    unsigned int mantissa0:20;
+    unsigned int mantissa1:32;
+#else
+#if FLOAT_WORDS_BIGENDIAN
+    unsigned int mantissa0:20;
+    unsigned int exponent:11;
+    unsigned int negative:1;
+    unsigned int mantissa1:32;
+#else
+    unsigned int mantissa1:32;
+    unsigned int mantissa0:20;
+    unsigned int exponent:11;
+    unsigned int negative:1;
+#endif
+#endif
+  } ieee;
+  /* This format makes it easier to see if a NaN is a signalling NaN.  */
+  struct {
+
+#if WORDS_BIGENDIAN
+    unsigned int negative:1;
+    unsigned int exponent:11;
+    unsigned int quiet_nan:1;
+    unsigned int mantissa0:19;
+    unsigned int mantissa1:32;
+#else
+#if FLOAT_WORDS_BIGENDIAN
+    unsigned int mantissa0:19;
+    unsigned int quiet_nan:1;
+    unsigned int exponent:11;
+    unsigned int negative:1;
+    unsigned int mantissa1:32;
+#else
+    unsigned int mantissa1:32;
+    unsigned int mantissa0:19;
+    unsigned int quiet_nan:1;
+    unsigned int exponent:11;
+    unsigned int negative:1;
+#endif
+#endif
+  } ieee_nan;
+};
+
+
+
+double c_succ(double y)
+{
+  union stg_ieee754_dbl su;
+ 
+  su.d=y;
+  if (su.ieee.negative==0) {   /*  y >= 0 */
+    if (su.ieee.exponent!=2047 || su.ieee.mantissa0!=0 || su.ieee.mantissa1!=0)
+      if (su.ieee.mantissa1==0xffffffff) { 
+        su.ieee.mantissa1=0; 
+        if (su.ieee.mantissa0==1048575) { 
+          su.ieee.mantissa0=0; 
+	  su.ieee.exponent++;
+        } else { 
+          su.ieee.mantissa0++;
+        }
+      } else { 
+        su.ieee.mantissa1++;
+      }
+  } 
+  else {                  /* y < 0 */
+    if (su.ieee.exponent!=2047 || su.ieee.mantissa0!=0 || su.ieee.mantissa1==0){
+      if (su.ieee.negative==1 && su.ieee.exponent==0 && su.ieee.mantissa0==0 && su.ieee.mantissa1==0) {
+        su.ieee.negative=0;
+        su.ieee.mantissa1=1;
+      } else {
+        if (su.ieee.mantissa1==0) { 
+          su.ieee.mantissa1=0xffffffff; 
+          if (su.ieee.mantissa0==0) { 
+            su.ieee.mantissa0=1048575; 
+	    su.ieee.exponent--;
+          } else { 
+            su.ieee.mantissa0--;
+          }
+        } else { 
+          su.ieee.mantissa1--;
+        }
+      }
+    }
+  }
+  return su.d;
+}         /* end function q_succ */
+
+
+
+
+
+
+double c_pred(double y)
+{
+  union stg_ieee754_dbl su;
+
+  su.d=y;
+  if (su.ieee.negative==1) {   /*  y < 0 */
+    if (su.ieee.exponent!=2047 ||  su.ieee.mantissa0!=0 || su.ieee.mantissa1!=0 ) 
+      if (su.ieee.mantissa1==0xffffffff) { 
+        su.ieee.mantissa1=0; 
+        if (su.ieee.mantissa0==1048575) { 
+          su.ieee.mantissa0=0; 
+          su.ieee.exponent++;
+        } else { 
+          su.ieee.mantissa0++;
+        }
+      } else
+        su.ieee.mantissa1++;
+  } else {                 /* y >= 0 */
+    if (su.ieee.exponent!=2047 || su.ieee.mantissa0!=0 || su.ieee.mantissa1!=0) 
+      if (su.ieee.exponent==0 && su.ieee.mantissa0==0 && su.ieee.mantissa1==0) {
+        su.ieee.negative=1;
+        su.ieee.mantissa1=1;
+      } else {
+        if (su.ieee.mantissa1==0) {
+          su.ieee.mantissa1=0xffffffff; 
+          if (su.ieee.mantissa0==0) { 
+            su.ieee.mantissa0=1048575; 
+            su.ieee.exponent--;
+          } else { 
+            su.ieee.mantissa0--;
+          }
+        } else { 
+          su.ieee.mantissa1--;
+        }
+      }
+  }
+  
+  return su.d;
+}              /* end function q_pred */
+
diff --git a/LICENSE b/LICENSE
new file mode 100644
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,340 @@
+		    GNU GENERAL PUBLIC LICENSE
+		       Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+     59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+			    Preamble
+
+  The licenses for most software are designed to take away your
+freedom to share and change it.  By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users.  This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it.  (Some other Free Software Foundation software is covered by
+the GNU Library General Public License instead.)  You can apply it to
+your programs, too.
+
+  When we speak of free software, we are referring to freedom, not
+price.  Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+  To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+  For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have.  You must make sure that they, too, receive or can get the
+source code.  And you must show them these terms so they know their
+rights.
+
+  We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+  Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software.  If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+  Finally, any free program is threatened constantly by software
+patents.  We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary.  To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+  The precise terms and conditions for copying, distribution and
+modification follow.
+
+		    GNU GENERAL PUBLIC LICENSE
+   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+  0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License.  The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language.  (Hereinafter, translation is included without limitation in
+the term "modification".)  Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope.  The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+  1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+  2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+    a) You must cause the modified files to carry prominent notices
+    stating that you changed the files and the date of any change.
+
+    b) You must cause any work that you distribute or publish, that in
+    whole or in part contains or is derived from the Program or any
+    part thereof, to be licensed as a whole at no charge to all third
+    parties under the terms of this License.
+
+    c) If the modified program normally reads commands interactively
+    when run, you must cause it, when started running for such
+    interactive use in the most ordinary way, to print or display an
+    announcement including an appropriate copyright notice and a
+    notice that there is no warranty (or else, saying that you provide
+    a warranty) and that users may redistribute the program under
+    these conditions, and telling the user how to view a copy of this
+    License.  (Exception: if the Program itself is interactive but
+    does not normally print such an announcement, your work based on
+    the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole.  If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works.  But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+  3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+    a) Accompany it with the complete corresponding machine-readable
+    source code, which must be distributed under the terms of Sections
+    1 and 2 above on a medium customarily used for software interchange; or,
+
+    b) Accompany it with a written offer, valid for at least three
+    years, to give any third party, for a charge no more than your
+    cost of physically performing source distribution, a complete
+    machine-readable copy of the corresponding source code, to be
+    distributed under the terms of Sections 1 and 2 above on a medium
+    customarily used for software interchange; or,
+
+    c) Accompany it with the information you received as to the offer
+    to distribute corresponding source code.  (This alternative is
+    allowed only for noncommercial distribution and only if you
+    received the program in object code or executable form with such
+    an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it.  For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable.  However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+  4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License.  Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+  5. You are not required to accept this License, since you have not
+signed it.  However, nothing else grants you permission to modify or
+distribute the Program or its derivative works.  These actions are
+prohibited by law if you do not accept this License.  Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+  6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions.  You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+  7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License.  If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all.  For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices.  Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+  8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded.  In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+  9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time.  Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number.  If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation.  If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+  10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission.  For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this.  Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+			    NO WARRANTY
+
+  11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+  12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+		     END OF TERMS AND CONDITIONS
+
+	    How to Apply These Terms to Your New Programs
+
+  If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+  To do so, attach the following notices to the program.  It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+    <one line to give the program's name and a brief idea of what it does.>
+    Copyright (C) <year>  <name of author>
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+    Gnomovision version 69, Copyright (C) year  name of author
+    Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+    This is free software, and you are welcome to redistribute it
+    under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License.  Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary.  Here is a sample; alter the names:
+
+  Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+  `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+  <signature of Ty Coon>, 1 April 1989
+  Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs.  If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library.  If this is what you want to do, use the GNU Library General
+Public License instead of this License.
diff --git a/Setup.hs b/Setup.hs
new file mode 100644
--- /dev/null
+++ b/Setup.hs
@@ -0,0 +1,3 @@
+import Distribution.Simple
+
+main=defaultMain
diff --git a/polynomials-bernstein.cabal b/polynomials-bernstein.cabal
new file mode 100644
--- /dev/null
+++ b/polynomials-bernstein.cabal
@@ -0,0 +1,22 @@
+Name:		polynomials-bernstein
+Version: 	1
+Synopsis:	A solver for systems of polynomial equations in bernstein form
+Description: 	This library defines an optimized type for representing polynomials
+		in Bernstein form, as well as instances of numeric classes and other
+		manipulation functions, and a solver of systems of polynomial
+		equations in this form.
+Category:	Math
+Maintainer:	Pierre-Etienne Meunier <pierreetienne.meunier@gmail.com>
+License:	GPL
+License-file:	LICENSE
+Build-Type:	Simple
+Cabal-Version:	>=1.6
+source-repository this
+        type: darcs
+        location: http://www.lama.univ-savoie.fr/~meunier/darcs/polynomials
+        tag: 1.0
+Library
+        Build-Depends:	base<5,	vector
+        Exposed-modules: Algebra.Polynomials.Bernstein, Algebra.Polynomials.Numerical
+        ghc-options: -O2 -Wall
+        c-sources: algebra/polynomials/cnumerical.c
