{- | 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
   it under the terms of the GNU General Public License as published by
   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)