diff options
author | Alberto Ruiz <aruiz@um.es> | 2007-06-16 15:52:07 +0000 |
---|---|---|
committer | Alberto Ruiz <aruiz@um.es> | 2007-06-16 15:52:07 +0000 |
commit | b2af660f87a55dd15f4519b21e66837ec811dc25 (patch) | |
tree | f48a2dc5b1d996595e7cd69fbbff6397d3e7b600 | |
parent | cc2c8c39dc088dcace0d2749cfe9180bf5fdbfd2 (diff) |
Fourier, minimization, polySolve
-rw-r--r-- | HSSL.cabal | 8 | ||||
-rw-r--r-- | examples/tests.hs | 33 | ||||
-rw-r--r-- | lib/Data/Packed/Internal/Matrix.hs | 8 | ||||
-rw-r--r-- | lib/Data/Packed/Matrix.hs | 23 | ||||
-rw-r--r-- | lib/GSL/Fourier.hs | 46 | ||||
-rw-r--r-- | lib/GSL/Minimization.hs | 211 | ||||
-rw-r--r-- | lib/GSL/Polynomials.hs | 54 |
7 files changed, 377 insertions, 6 deletions
@@ -24,9 +24,11 @@ Exposed-modules: Data.Packed.Internal, Data.Packed.Internal.Common, | |||
24 | Data.Packed.Internal.Tensor, | 24 | Data.Packed.Internal.Tensor, |
25 | LAPACK, | 25 | LAPACK, |
26 | GSL.Vector, | 26 | GSL.Vector, |
27 | GSL.Differentiation, | 27 | GSL.Differentiation, GSL.Integration, |
28 | GSL.Integration, | 28 | GSL.Special, |
29 | GSL.Special | 29 | GSL.Fourier, |
30 | GSL.Polynomials, | ||
31 | GSL.Minimization | ||
30 | Other-modules: | 32 | Other-modules: |
31 | C-sources: lib/Data/Packed/Internal/aux.c, | 33 | C-sources: lib/Data/Packed/Internal/aux.c, |
32 | lib/LAPACK/lapack-aux.c, | 34 | lib/LAPACK/lapack-aux.c, |
diff --git a/examples/tests.hs b/examples/tests.hs index 3b1d878..22c4674 100644 --- a/examples/tests.hs +++ b/examples/tests.hs | |||
@@ -12,11 +12,14 @@ import GSL.Vector | |||
12 | import GSL.Integration | 12 | import GSL.Integration |
13 | import GSL.Differentiation | 13 | import GSL.Differentiation |
14 | import GSL.Special | 14 | import GSL.Special |
15 | import GSL.Fourier | ||
16 | import GSL.Polynomials | ||
15 | import LAPACK | 17 | import LAPACK |
16 | import Test.QuickCheck | 18 | import Test.QuickCheck |
17 | import Test.HUnit | 19 | import Test.HUnit |
18 | import Complex | 20 | import Complex |
19 | 21 | ||
22 | |||
20 | {- | 23 | {- |
21 | -- Bravo por quickCheck! | 24 | -- Bravo por quickCheck! |
22 | 25 | ||
@@ -244,6 +247,29 @@ pinvSVDR m = linearSolveSVDR Nothing m (ident (rows m)) | |||
244 | 247 | ||
245 | pinvSVDC m = linearSolveSVDC Nothing m (ident (rows m)) | 248 | pinvSVDC m = linearSolveSVDC Nothing m (ident (rows m)) |
246 | 249 | ||
250 | -------------------------------------------------------------------- | ||
251 | |||
252 | polyEval cs x = foldr (\c ac->ac*x+c) 0 cs | ||
253 | |||
254 | polySolveTest' p = length p <2 || last p == 0|| 1E-8 > maximum (map magnitude $ map (polyEval (map (:+0) p)) (polySolve p)) | ||
255 | where l1 |~~| l2 = eps > aproxL magnitude l1 l2 | ||
256 | |||
257 | polySolveTest = assertBool "polySolve" (polySolveTest' [1,2,3,4]) | ||
258 | |||
259 | --------------------------------------------------------------------- | ||
260 | |||
261 | quad f a b = fst $ integrateQAGS 1E-9 100 f a b | ||
262 | |||
263 | -- A multiple integral can be easily defined using partial application | ||
264 | quad2 f a b g1 g2 = quad h a b | ||
265 | where h x = quad (f x) (g1 x) (g2 x) | ||
266 | |||
267 | volSphere r = 8 * quad2 (\x y -> sqrt (r*r-x*x-y*y)) | ||
268 | 0 r (const 0) (\x->sqrt (r*r-x*x)) | ||
269 | |||
270 | integrateTest = assertBool "integrate" (abs (volSphere 2.5 - 4/3*pi*2.5^3) < eps) | ||
271 | |||
272 | |||
247 | --------------------------------------------------------------------- | 273 | --------------------------------------------------------------------- |
248 | 274 | ||
249 | arit1 u = vectorMapValR PowVS 2 (vectorMapR Sin u) | 275 | arit1 u = vectorMapValR PowVS 2 (vectorMapR Sin u) |
@@ -271,6 +297,8 @@ exponentialTest = do | |||
271 | tests = TestList | 297 | tests = TestList |
272 | [ TestCase $ besselTest | 298 | [ TestCase $ besselTest |
273 | , TestCase $ exponentialTest | 299 | , TestCase $ exponentialTest |
300 | , TestCase $ polySolveTest | ||
301 | , TestCase $ integrateTest | ||
274 | ] | 302 | ] |
275 | 303 | ||
276 | ---------------------------------------------------------------------- | 304 | ---------------------------------------------------------------------- |
@@ -315,9 +343,12 @@ main = do | |||
315 | quickCheck arit2 | 343 | quickCheck arit2 |
316 | putStrLn "--------- GSL ------" | 344 | putStrLn "--------- GSL ------" |
317 | runTestTT tests | 345 | runTestTT tests |
346 | quickCheck $ \v -> ifft (fft v) ~~ v | ||
318 | 347 | ||
319 | kk = (2><2) | 348 | kk = (2><2) |
320 | [ 1.0, 0.0 | 349 | [ 1.0, 0.0 |
321 | , -1.5, 1.0 ::Double] | 350 | , -1.5, 1.0 ::Double] |
322 | 351 | ||
323 | v = 11 # [0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0::Double] \ No newline at end of file | 352 | v = 11 # [0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0::Double] |
353 | |||
354 | pol = [14.125,-7.666666666666667,-14.3,-13.0,-7.0,-9.6,4.666666666666666,13.0,0.5] \ No newline at end of file | ||
diff --git a/lib/Data/Packed/Internal/Matrix.hs b/lib/Data/Packed/Internal/Matrix.hs index 2c0acdf..fccf8bb 100644 --- a/lib/Data/Packed/Internal/Matrix.hs +++ b/lib/Data/Packed/Internal/Matrix.hs | |||
@@ -281,3 +281,11 @@ fromColumns m = trans . fromRows $ m | |||
281 | -- | Creates a list of vectors from the columns of a matrix | 281 | -- | Creates a list of vectors from the columns of a matrix |
282 | toColumns :: Field t => Matrix t -> [Vector t] | 282 | toColumns :: Field t => Matrix t -> [Vector t] |
283 | toColumns m = toRows . trans $ m | 283 | toColumns m = toRows . trans $ m |
284 | |||
285 | |||
286 | -- | Reads a matrix position. | ||
287 | (@@>) :: Field t => Matrix t -> (Int,Int) -> t | ||
288 | infixl 9 @@> | ||
289 | m@M {rows = r, cols = c} @@> (i,j) | ||
290 | | i<0 || i>=r || j<0 || j>=c = error "matrix indexing out of range" | ||
291 | | otherwise = cdat m `at` (i*c+j) | ||
diff --git a/lib/Data/Packed/Matrix.hs b/lib/Data/Packed/Matrix.hs index 6ea76c0..ec5744d 100644 --- a/lib/Data/Packed/Matrix.hs +++ b/lib/Data/Packed/Matrix.hs | |||
@@ -14,7 +14,7 @@ | |||
14 | 14 | ||
15 | module Data.Packed.Matrix ( | 15 | module Data.Packed.Matrix ( |
16 | Matrix(rows,cols), Field, | 16 | Matrix(rows,cols), Field, |
17 | toLists, (><), (>|<), | 17 | toLists, (><), (>|<), (@@>), |
18 | trans, | 18 | trans, |
19 | reshape, | 19 | reshape, |
20 | fromRows, toRows, fromColumns, toColumns, | 20 | fromRows, toRows, fromColumns, toColumns, |
@@ -22,7 +22,9 @@ module Data.Packed.Matrix ( | |||
22 | flipud, fliprl, | 22 | flipud, fliprl, |
23 | liftMatrix, liftMatrix2, | 23 | liftMatrix, liftMatrix2, |
24 | multiply, | 24 | multiply, |
25 | subMatrix, diag, takeDiag, diagRect, ident | 25 | subMatrix, |
26 | takeRows, dropRows, takeColumns, dropColumns, | ||
27 | diag, takeDiag, diagRect, ident | ||
26 | ) where | 28 | ) where |
27 | 29 | ||
28 | import Data.Packed.Internal | 30 | import Data.Packed.Internal |
@@ -69,3 +71,20 @@ r >|< c = f where | |||
69 | | otherwise = error $ "inconsistent list size = " | 71 | | otherwise = error $ "inconsistent list size = " |
70 | ++show (dim v) ++"in ("++show r++"><"++show c++")" | 72 | ++show (dim v) ++"in ("++show r++"><"++show c++")" |
71 | where v = fromList l | 73 | where v = fromList l |
74 | |||
75 | ---------------------------------------------------------------- | ||
76 | |||
77 | -- | Creates a matrix with the first n rows of another matrix | ||
78 | takeRows :: Field t => Int -> Matrix t -> Matrix t | ||
79 | takeRows n mat = subMatrix (0,0) (n, cols mat) mat | ||
80 | -- | Creates a copy of a matrix without the first n rows | ||
81 | dropRows :: Field t => Int -> Matrix t -> Matrix t | ||
82 | dropRows n mat = subMatrix (n,0) (rows mat - n, cols mat) mat | ||
83 | -- |Creates a matrix with the first n columns of another matrix | ||
84 | takeColumns :: Field t => Int -> Matrix t -> Matrix t | ||
85 | takeColumns n mat = subMatrix (0,0) (rows mat, n) mat | ||
86 | -- | Creates a copy of a matrix without the first n columns | ||
87 | dropColumns :: Field t => Int -> Matrix t -> Matrix t | ||
88 | dropColumns n mat = subMatrix (0,n) (rows mat, cols mat - n) mat | ||
89 | |||
90 | ---------------------------------------------------------------- | ||
diff --git a/lib/GSL/Fourier.hs b/lib/GSL/Fourier.hs new file mode 100644 index 0000000..c8c79f0 --- /dev/null +++ b/lib/GSL/Fourier.hs | |||
@@ -0,0 +1,46 @@ | |||
1 | {-# OPTIONS_GHC -fglasgow-exts #-} | ||
2 | ----------------------------------------------------------------------------- | ||
3 | {- | | ||
4 | Module : GSL.Fourier | ||
5 | Copyright : (c) Alberto Ruiz 2006 | ||
6 | License : GPL-style | ||
7 | |||
8 | Maintainer : Alberto Ruiz (aruiz at um dot es) | ||
9 | Stability : provisional | ||
10 | Portability : uses ffi | ||
11 | |||
12 | Fourier Transform. | ||
13 | |||
14 | <http://www.gnu.org/software/gsl/manual/html_node/Fast-Fourier-Transforms.html#Fast-Fourier-Transforms> | ||
15 | |||
16 | -} | ||
17 | ----------------------------------------------------------------------------- | ||
18 | module GSL.Fourier ( | ||
19 | fft, | ||
20 | ifft | ||
21 | ) where | ||
22 | |||
23 | import Data.Packed.Internal | ||
24 | import Complex | ||
25 | import Foreign | ||
26 | |||
27 | genfft code v = unsafePerformIO $ do | ||
28 | r <- createVector (dim v) | ||
29 | c_fft code // vec v // vec r // check "fft" [v] | ||
30 | return r | ||
31 | |||
32 | foreign import ccall "gsl-aux.h fft" c_fft :: Int -> Complex Double :> Complex Double :> IO Int | ||
33 | |||
34 | |||
35 | {- | Fast 1D Fourier transform of a 'Vector' @(@'Complex' 'Double'@)@ using /gsl_fft_complex_forward/. It uses the same scaling conventions as GNU Octave. | ||
36 | |||
37 | @> fft ('GSL.Matrix.fromList' [1,2,3,4]) | ||
38 | vector (4) [10.0 :+ 0.0,(-2.0) :+ 2.0,(-2.0) :+ 0.0,(-2.0) :+ (-2.0)]@ | ||
39 | |||
40 | -} | ||
41 | fft :: Vector (Complex Double) -> Vector (Complex Double) | ||
42 | fft = genfft 0 | ||
43 | |||
44 | -- | The inverse of 'fft', using /gsl_fft_complex_inverse/. | ||
45 | ifft :: Vector (Complex Double) -> Vector (Complex Double) | ||
46 | ifft = genfft 1 | ||
diff --git a/lib/GSL/Minimization.hs b/lib/GSL/Minimization.hs new file mode 100644 index 0000000..bc228a7 --- /dev/null +++ b/lib/GSL/Minimization.hs | |||
@@ -0,0 +1,211 @@ | |||
1 | {-# OPTIONS_GHC -fglasgow-exts #-} | ||
2 | ----------------------------------------------------------------------------- | ||
3 | {- | | ||
4 | Module : GSL.Minimization | ||
5 | Copyright : (c) Alberto Ruiz 2006 | ||
6 | License : GPL-style | ||
7 | |||
8 | Maintainer : Alberto Ruiz (aruiz at um dot es) | ||
9 | Stability : provisional | ||
10 | Portability : uses ffi | ||
11 | |||
12 | Minimization of a multidimensional function Minimization of a multidimensional function using some of the algorithms described in: | ||
13 | |||
14 | <http://www.gnu.org/software/gsl/manual/html_node/Multidimensional-Minimization.html> | ||
15 | |||
16 | -} | ||
17 | ----------------------------------------------------------------------------- | ||
18 | module GSL.Minimization ( | ||
19 | minimizeConjugateGradient, | ||
20 | minimizeNMSimplex | ||
21 | ) where | ||
22 | |||
23 | |||
24 | import Data.Packed.Internal | ||
25 | import Data.Packed.Matrix | ||
26 | import Foreign | ||
27 | import Complex | ||
28 | |||
29 | |||
30 | ------------------------------------------------------------------------- | ||
31 | |||
32 | {- | The method of Nelder and Mead, implemented by /gsl_multimin_fminimizer_nmsimplex/. The gradient of the function is not required. This is the example in the GSL manual: | ||
33 | |||
34 | @minimize f xi = minimizeNMSimplex f xi (replicate (length xi) 1) 1e-2 100 | ||
35 | \ | ||
36 | f [x,y] = 10*(x-1)^2 + 20*(y-2)^2 + 30 | ||
37 | \ | ||
38 | main = do | ||
39 | let (s,p) = minimize f [5,7] | ||
40 | print s | ||
41 | print p | ||
42 | \ | ||
43 | \> main | ||
44 | [0.9920430849306285,1.9969168063253164] | ||
45 | 0. 512.500 1.082 6.500 5. | ||
46 | 1. 290.625 1.372 5.250 4. | ||
47 | 2. 290.625 1.372 5.250 4. | ||
48 | 3. 252.500 1.372 5.500 1. | ||
49 | 4. 101.406 1.823 2.625 3.500 | ||
50 | 5. 101.406 1.823 2.625 3.500 | ||
51 | 6. 60. 1.823 0. 3. | ||
52 | 7. 42.275 1.303 2.094 1.875 | ||
53 | 8. 42.275 1.303 2.094 1.875 | ||
54 | 9. 35.684 1.026 0.258 1.906 | ||
55 | 10. 35.664 0.804 0.588 2.445 | ||
56 | 11. 30.680 0.467 1.258 2.025 | ||
57 | 12. 30.680 0.356 1.258 2.025 | ||
58 | 13. 30.539 0.285 1.093 1.849 | ||
59 | 14. 30.137 0.168 0.883 2.004 | ||
60 | 15. 30.137 0.123 0.883 2.004 | ||
61 | 16. 30.090 0.100 0.958 2.060 | ||
62 | 17. 30.005 6.051e-2 1.022 2.004 | ||
63 | 18. 30.005 4.249e-2 1.022 2.004 | ||
64 | 19. 30.005 4.249e-2 1.022 2.004 | ||
65 | 20. 30.005 2.742e-2 1.022 2.004 | ||
66 | 21. 30.005 2.119e-2 1.022 2.004 | ||
67 | 22. 30.001 1.530e-2 0.992 1.997 | ||
68 | 23. 30.001 1.259e-2 0.992 1.997 | ||
69 | 24. 30.001 7.663e-3 0.992 1.997@ | ||
70 | |||
71 | The path to the solution can be graphically shown by means of: | ||
72 | |||
73 | @'GSL.Plot.mplot' $ drop 3 ('toColumns' p)@ | ||
74 | |||
75 | -} | ||
76 | minimizeNMSimplex :: ([Double] -> Double) -- ^ function to minimize | ||
77 | -> [Double] -- ^ starting point | ||
78 | -> [Double] -- ^ sizes of the initial search box | ||
79 | -> Double -- ^ desired precision of the solution | ||
80 | -> Int -- ^ maximum number of iterations allowed | ||
81 | -> ([Double], Matrix Double) | ||
82 | -- ^ solution vector, and the optimization trajectory followed by the algorithm | ||
83 | minimizeNMSimplex f xi sz tol maxit = unsafePerformIO $ do | ||
84 | let xiv = fromList xi | ||
85 | szv = fromList sz | ||
86 | n = dim xiv | ||
87 | fp <- mkVecfun (iv (f.toList)) | ||
88 | rawpath <- createMIO maxit (n+3) | ||
89 | (c_minimizeNMSimplex fp tol maxit // vec xiv // vec szv) | ||
90 | "minimizeNMSimplex" [xiv,szv] | ||
91 | let it = round (rawpath @@> (maxit-1,0)) | ||
92 | path = takeRows it rawpath | ||
93 | [sol] = toLists $ dropRows (it-1) path | ||
94 | freeHaskellFunPtr fp | ||
95 | return (drop 3 sol, path) | ||
96 | |||
97 | |||
98 | foreign import ccall "gsl-aux.h minimize" | ||
99 | c_minimizeNMSimplex:: FunPtr (Int -> Ptr Double -> Double) -> Double -> Int | ||
100 | -> Double :> Double :> Double ::> IO Int | ||
101 | |||
102 | ---------------------------------------------------------------------------------- | ||
103 | |||
104 | {- | The Fletcher-Reeves conjugate gradient algorithm /gsl_multimin_fminimizer_conjugate_fr/. This is the example in the GSL manual: | ||
105 | |||
106 | @minimize = minimizeConjugateGradient 1E-2 1E-4 1E-3 30 | ||
107 | f [x,y] = 10*(x-1)^2 + 20*(y-2)^2 + 30 | ||
108 | \ | ||
109 | df [x,y] = [20*(x-1), 40*(y-2)] | ||
110 | \ | ||
111 | main = do | ||
112 | let (s,p) = minimize f df [5,7] | ||
113 | print s | ||
114 | print p | ||
115 | \ | ||
116 | \> main | ||
117 | [1.0,2.0] | ||
118 | 0. 687.848 4.996 6.991 | ||
119 | 1. 683.555 4.989 6.972 | ||
120 | 2. 675.013 4.974 6.935 | ||
121 | 3. 658.108 4.944 6.861 | ||
122 | 4. 625.013 4.885 6.712 | ||
123 | 5. 561.684 4.766 6.415 | ||
124 | 6. 446.467 4.528 5.821 | ||
125 | 7. 261.794 4.053 4.632 | ||
126 | 8. 75.498 3.102 2.255 | ||
127 | 9. 67.037 2.852 1.630 | ||
128 | 10. 45.316 2.191 1.762 | ||
129 | 11. 30.186 0.869 2.026 | ||
130 | 12. 30. 1. 2.@ | ||
131 | |||
132 | The path to the solution can be graphically shown by means of: | ||
133 | |||
134 | @'GSL.Plot.mplot' $ drop 2 ('toColumns' p)@ | ||
135 | |||
136 | -} | ||
137 | minimizeConjugateGradient :: | ||
138 | Double -- ^ initial step size | ||
139 | -> Double -- ^ minimization parameter | ||
140 | -> Double -- ^ desired precision of the solution (gradient test) | ||
141 | -> Int -- ^ maximum number of iterations allowed | ||
142 | -> ([Double] -> Double) -- ^ function to minimize | ||
143 | -> ([Double] -> [Double]) -- ^ gradient | ||
144 | -> [Double] -- ^ starting point | ||
145 | -> ([Double], Matrix Double) -- ^ solution vector, and the optimization trajectory followed by the algorithm | ||
146 | minimizeConjugateGradient istep minimpar tol maxit f df xi = unsafePerformIO $ do | ||
147 | let xiv = fromList xi | ||
148 | n = dim xiv | ||
149 | f' = f . toList | ||
150 | df' = (fromList . df . toList) | ||
151 | fp <- mkVecfun (iv f') | ||
152 | dfp <- mkVecVecfun (aux_vTov df') | ||
153 | rawpath <- createMIO maxit (n+2) | ||
154 | (c_minimizeConjugateGradient fp dfp istep minimpar tol maxit // vec xiv) | ||
155 | "minimizeDerivV" [xiv] | ||
156 | let it = round (rawpath @@> (maxit-1,0)) | ||
157 | path = takeRows it rawpath | ||
158 | sol = toList $ cdat $ dropColumns 2 $ dropRows (it-1) path | ||
159 | freeHaskellFunPtr fp | ||
160 | freeHaskellFunPtr dfp | ||
161 | return (sol,path) | ||
162 | |||
163 | |||
164 | foreign import ccall "gsl-aux.h minimizeWithDeriv" | ||
165 | c_minimizeConjugateGradient :: FunPtr (Int -> Ptr Double -> Double) | ||
166 | -> FunPtr (Int -> Ptr Double -> Ptr Double -> IO ()) | ||
167 | -> Double -> Double -> Double -> Int | ||
168 | -> Double :> Double ::> IO Int | ||
169 | |||
170 | --------------------------------------------------------------------- | ||
171 | iv :: (Vector Double -> Double) -> (Int -> Ptr Double -> Double) | ||
172 | iv f n p = f (createV n copy "iv" []) where | ||
173 | copy n q = do | ||
174 | copyArray q p n | ||
175 | return 0 | ||
176 | |||
177 | -- | conversion of Haskell functions into function pointers that can be used in the C side | ||
178 | foreign import ccall "wrapper" | ||
179 | mkVecfun :: (Int -> Ptr Double -> Double) | ||
180 | -> IO( FunPtr (Int -> Ptr Double -> Double)) | ||
181 | |||
182 | -- | another required conversion | ||
183 | foreign import ccall "wrapper" | ||
184 | mkVecVecfun :: (Int -> Ptr Double -> Ptr Double -> IO ()) | ||
185 | -> IO (FunPtr (Int -> Ptr Double -> Ptr Double->IO())) | ||
186 | |||
187 | aux_vTov :: (Vector Double -> Vector Double) -> (Int -> Ptr Double -> Ptr Double -> IO()) | ||
188 | aux_vTov f n p r = g where | ||
189 | V {fptr = pr, ptr = p} = f x | ||
190 | x = createV n copy "aux_vTov" [] | ||
191 | copy n q = do | ||
192 | copyArray q p n | ||
193 | return 0 | ||
194 | g = withForeignPtr pr $ \_ -> copyArray r p n | ||
195 | |||
196 | -------------------------------------------------------------------- | ||
197 | |||
198 | createV n fun msg ptrs = unsafePerformIO $ do | ||
199 | r <- createVector n | ||
200 | fun // vec r // check msg ptrs | ||
201 | return r | ||
202 | |||
203 | createM r c fun msg ptrs = unsafePerformIO $ do | ||
204 | r <- createMatrix RowMajor r c | ||
205 | fun // mat cdat r // check msg ptrs | ||
206 | return r | ||
207 | |||
208 | createMIO r c fun msg ptrs = do | ||
209 | r <- createMatrix RowMajor r c | ||
210 | fun // mat cdat r // check msg ptrs | ||
211 | return r | ||
diff --git a/lib/GSL/Polynomials.hs b/lib/GSL/Polynomials.hs new file mode 100644 index 0000000..d7db9a3 --- /dev/null +++ b/lib/GSL/Polynomials.hs | |||
@@ -0,0 +1,54 @@ | |||
1 | {-# OPTIONS_GHC -fglasgow-exts #-} | ||
2 | ----------------------------------------------------------------------------- | ||
3 | {- | | ||
4 | Module : GSL.Polynomials | ||
5 | Copyright : (c) Alberto Ruiz 2006 | ||
6 | License : GPL-style | ||
7 | |||
8 | Maintainer : Alberto Ruiz (aruiz at um dot es) | ||
9 | Stability : provisional | ||
10 | Portability : uses ffi | ||
11 | |||
12 | Polynomials. | ||
13 | |||
14 | <http://www.gnu.org/software/gsl/manual/html_node/General-Polynomial-Equations.html#General-Polynomial-Equations> | ||
15 | |||
16 | -} | ||
17 | ----------------------------------------------------------------------------- | ||
18 | module GSL.Polynomials ( | ||
19 | polySolve | ||
20 | ) where | ||
21 | |||
22 | import Data.Packed.Internal | ||
23 | import Complex | ||
24 | import Foreign | ||
25 | |||
26 | {- | Solution of general polynomial equations, using /gsl_poly_complex_solve/. For example, | ||
27 | the three solutions of x^3 + 8 = 0 | ||
28 | |||
29 | @\> polySolve [8,0,0,1] | ||
30 | [(-1.9999999999999998) :+ 0.0, | ||
31 | 1.0 :+ 1.732050807568877, | ||
32 | 1.0 :+ (-1.732050807568877)]@ | ||
33 | |||
34 | The example in the GSL manual: To find the roots of x^5 -1 = 0: | ||
35 | |||
36 | @\> polySolve [-1, 0, 0, 0, 0, 1] | ||
37 | [(-0.8090169943749475) :+ 0.5877852522924731, | ||
38 | (-0.8090169943749475) :+ (-0.5877852522924731), | ||
39 | 0.30901699437494734 :+ 0.9510565162951536, | ||
40 | 0.30901699437494734 :+ (-0.9510565162951536), | ||
41 | 1.0 :+ 0.0]@ | ||
42 | |||
43 | -} | ||
44 | polySolve :: [Double] -> [Complex Double] | ||
45 | polySolve = toList . polySolve' . fromList | ||
46 | |||
47 | polySolve' :: Vector Double -> Vector (Complex Double) | ||
48 | polySolve' v | dim v > 1 = unsafePerformIO $ do | ||
49 | r <- createVector (dim v-1) | ||
50 | c_polySolve // vec v // vec r // check "polySolve" [v] | ||
51 | return r | ||
52 | | otherwise = error "polySolve on a polynomial of degree zero" | ||
53 | |||
54 | foreign import ccall "gsl-aux.h polySolve" c_polySolve:: Double :> Complex Double :> IO Int | ||