packages feed

moonlight-linalg-0.1.0.0: src-dense/Moonlight/LinAlg/Internal/Backend/Core.hs

{-# LANGUAGE AllowAmbiguousTypes #-}
{-# LANGUAGE DefaultSignatures #-}

module Moonlight.LinAlg.Internal.Backend.Core
  ( DenseRankBackend (..),
    runPluDecomp,
    runKernel,
    runSmithNormalForm,
    runSmithDiagonalForm,
  )
where

import Data.Kind (Constraint, Type)
import GHC.TypeNats (KnownNat)
import Moonlight.Algebra.Pure.Ring (EuclideanDomain)
import Moonlight.Core
  ( Field,
    MoonlightError (..),
  )
import Moonlight.LinAlg.Internal.Backend.PLU (PLU, pluDecompPure)
import Moonlight.LinAlg.Internal.Backend.RREF (KernelBasis, kernelPure, rankPure)
import Moonlight.LinAlg.Internal.Backend.Smith (SmithDiagonalForm, SmithNormalForm, smithDiagonalFormPure, smithNormalFormPure)
import Moonlight.LinAlg.Pure.Dense.GF2
  ( GF2
  , mkGF2PackedMatrixFromRowMajor
  , rankGF2PackedMatrix
  )
import Moonlight.LinAlg.Pure.Dense.Types (Matrix, matrixShape, toListMatrix)
import Prelude

type DenseRankBackend :: Type -> Constraint
class DenseRankBackend a where
  runRank ::
    forall r c.
    (KnownNat r, KnownNat c, Eq a, Field a) =>
    Matrix r c a ->
    Either MoonlightError Int
  default runRank ::
    forall r c.
    (KnownNat r, KnownNat c, Eq a, Field a) =>
    Matrix r c a ->
    Either MoonlightError Int
  runRank = rankPure

instance DenseRankBackend Double

instance DenseRankBackend GF2 where
  runRank matrixValue =
    let (rowCount, columnCount) =
          matrixShape matrixValue
     in either
          (Left . InvariantViolation . ("GF2 DenseRank: " <>) . show)
          (Right . rankGF2PackedMatrix)
          ( mkGF2PackedMatrixFromRowMajor
              (fromIntegral rowCount)
              (fromIntegral columnCount)
              (toListMatrix matrixValue)
          )

instance DenseRankBackend Integer

instance DenseRankBackend Rational

runPluDecomp ::
  forall r c a.
  (KnownNat r, KnownNat c, Field a) =>
  Matrix r c a ->
  Either MoonlightError (PLU r c a)
runPluDecomp = pluDecompPure

runKernel ::
  forall r c a.
  (KnownNat r, KnownNat c, Eq a, Field a) =>
  Matrix r c a ->
  Either MoonlightError (KernelBasis c a)
runKernel = kernelPure

runSmithNormalForm ::
  forall r c a.
  (KnownNat r, KnownNat c, EuclideanDomain a) =>
  Matrix r c a ->
  Either MoonlightError (SmithNormalForm r c a)
runSmithNormalForm = smithNormalFormPure

runSmithDiagonalForm ::
  forall r c a.
  (KnownNat r, KnownNat c, EuclideanDomain a) =>
  Matrix r c a ->
  Either MoonlightError (SmithDiagonalForm r c a)
runSmithDiagonalForm = smithDiagonalFormPure