```{- | HasGP Gaussian Process Library. This module contains assorted
functions that support the construction of matrices from
functions.

Copyright (C) 2011 Sean Holden. sbh11\@cl.cam.ac.uk.
-}
{- This file is part of HasGP.

HasGP is free software: you can redistribute it and/or modify
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

HasGP 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 HasGP.  If not, see <http://www.gnu.org/licenses/>.
-}
module HasGP.Support.MatrixFunction where

import Numeric.LinearAlgebra

import HasGP.Types.MainTypes
import HasGP.Support.Functions as F

-- | Take two vectors and a function. The vectors contain inputs 1 and 2.
--   The function maps a pair of inputs to a value. Produce a matrix
--   containing the values of the function at the relevant points.
makeMatrixFromFunction2 :: (DVector -> Double)
-> DVector
-> DVector
-> DMatrix
makeMatrixFromFunction2 f x1 x2 =
flipud \$ ((length x1L)><(length x2L)) (map f l)
where
x1L = toList x1
x2L = toList x2
l = map fromList [[a,b] | a <- x1L, b <-x2L ]

-- | Take a function and a matrix of instance vectors. Apply the function to
--   each possible pair of instance vectors and return the result as a matrix.
makeMatrixFromPairs2 :: (DVector -> DVector -> Double) -> DMatrix -> DMatrix
makeMatrixFromPairs2 f i = (d><d) [f x1 x2 | x1 <- x, x2 <- x]
where
d = rows i
x = toRows i

-- | Same as makeMatrixFromPairs but the function returns a vector. In this
-- case the output is a list of matrices, one for each element of the
-- function value.
makeMatricesFromPairs :: (DVector -> DVector -> DVector) -> DMatrix -> [DMatrix]
makeMatricesFromPairs f i = map (d><d) (reArrange lists [])
where
d = rows i
x = toRows i
lists = map toList [f x1 x2 | x1 <- x, x2 <- x]
reArrange [] r = reverse r
reArrange l@(h:t) r
| (h == []) = reverse r
| otherwise = reArrange (map tail l) ((map head l):r)

```