packages feed

moonlight-linalg-0.1.0.0: src-carrier/Moonlight/LinAlg/Internal/DenseList.hs

module Moonlight.LinAlg.Internal.DenseList
  ( dotProductWith,
    matrixVectorProductWith,
    zipMatrixWith,
    scaleMatrixWith,
    outerProductWith,
  )
where

import Data.Function ((&))
import Prelude

dotProductWith :: (left -> right -> product) -> (product -> accumulator -> accumulator) -> accumulator -> [left] -> [right] -> Either String accumulator
dotProductWith multiply append zeroValue left right =
  if leftLength == rightLength
    then Right (foldr append zeroValue (zipWith multiply left right))
    else Left ("length mismatch (left=" <> show leftLength <> ", right=" <> show rightLength <> ")")
  where
    leftLength = length left
    rightLength = length right

matrixVectorProductWith :: (entry -> value -> product) -> (product -> accumulator -> accumulator) -> accumulator -> [[entry]] -> [value] -> Either String [accumulator]
matrixVectorProductWith multiply append zeroValue matrixRows vectorValue =
  traverse
    (\(rowIndex, rowValues) ->
      dotProductWith multiply append zeroValue rowValues vectorValue
        & either
          (Left . (\message -> "row " <> show rowIndex <> ": " <> message))
          Right
    )
    (zip [0 :: Int ..] matrixRows)

zipMatrixWith :: (left -> right -> result) -> [[left]] -> [[right]] -> [[result]]
zipMatrixWith combine = zipWith (zipWith combine)

scaleMatrixWith :: (scalar -> value -> result) -> scalar -> [[value]] -> [[result]]
scaleMatrixWith multiply scalarValue =
  map (map (multiply scalarValue))

outerProductWith :: (left -> right -> result) -> [left] -> [right] -> [[result]]
outerProductWith multiply left right =
  map (\leftEntry -> map (multiply leftEntry) right) left