Flint2-0.1.0.0: src/Data/Number/Flint/Padic/Mat/FFI.hsc
{-|
module : Data.Number.Flint.Padic.Mat.FFI
copyright : (c) 2022 Hartmut Monien
license : GNU GPL, version 2 or above (see LICENSE)
maintainer : hmonien@uni-bonn.de
-}
module Data.Number.Flint.Padic.Mat.FFI (
-- * Matrices over p-adic numbers
PadicMat (..)
, CPadicMat (..)
-- * Constructors
, newPadicMat
, withPadicMat
-- * Macros
, padic_mat
, padic_mat_entry
-- , padic_mat_val
-- , padic_mat_prec
, padic_mat_get_val
, padic_mat_get_prec
, padic_mat_nrows
, padic_mat_ncols
-- * Memory management
, padic_mat_init
, padic_mat_init2
, padic_mat_clear
, _padic_mat_canonicalise
, _padic_mat_reduce
, padic_mat_reduce
, padic_mat_is_empty
, padic_mat_is_square
, padic_mat_is_canonical
-- * Basic assignment
, padic_mat_set
, padic_mat_swap
, padic_mat_swap_entrywise
, padic_mat_zero
, padic_mat_one
-- * Conversions
, padic_mat_set_fmpq_mat
, padic_mat_get_fmpq_mat
-- * Entries
, padic_mat_get_entry_padic
, padic_mat_set_entry_padic
-- * Comparison
, padic_mat_equal
, padic_mat_is_zero
-- * Input and output
, padic_mat_get_str
, padic_mat_get_str_pretty
, padic_mat_fprint
, padic_mat_fprint_pretty
, padic_mat_print
, padic_mat_print_pretty
-- * Random matrix generation
, padic_mat_randtest
-- * Transpose
, padic_mat_transpose
-- * Addition and subtraction
, _padic_mat_add
, padic_mat_add
, _padic_mat_sub
, padic_mat_sub
, _padic_mat_neg
, padic_mat_neg
-- * Scalar operations
, _padic_mat_scalar_mul_padic
, padic_mat_scalar_mul_padic
, _padic_mat_scalar_mul_fmpz
, padic_mat_scalar_mul_fmpz
, padic_mat_scalar_div_fmpz
-- * Multiplication
, padic_mat_mul
) where
-- matrices over p-adic numbers ------------------------------------------------
import Control.Monad
import Foreign.C.String
import Foreign.C.Types
import Foreign.ForeignPtr
import Foreign.Ptr ( Ptr, FunPtr, plusPtr, castPtr )
import Foreign.Storable
import Foreign.Marshal ( free )
import Data.Number.Flint.Flint
import Data.Number.Flint.Fmpz
import Data.Number.Flint.Fmpz.Mat
import Data.Number.Flint.Fmpq.Mat
import Data.Number.Flint.Padic
#include <flint/flint.h>
#include <flint/padic.h>
#include <flint/padic_mat.h>
-- padic_mat_t -----------------------------------------------------------------
data PadicMat = PadicMat {-# UNPACK #-} !(ForeignPtr CPadicMat)
data CPadicMat = CPadicMat (Ptr CFmpzMat) CLong CLong
instance Storable CPadicMat where
{-# INLINE sizeOf #-}
sizeOf _ = #{size padic_mat_t}
{-# INLINE alignment #-}
alignment _ = #{alignment padic_mat_t}
peek ptr = return CPadicMat
`ap` #{peek padic_mat_struct, mat} ptr
`ap` #{peek padic_mat_struct, val} ptr
`ap` #{peek padic_mat_struct, N } ptr
poke = undefined
newPadicMat rows cols prec = do
x <- mallocForeignPtr
withForeignPtr x $ \x -> padic_mat_init x rows cols prec
addForeignPtrFinalizer p_padic_mat_clear x
return $ PadicMat x
{-# INLINE withPadicMat #-}
withPadicMat (PadicMat x) f = do
withForeignPtr x $ \px -> f px >>= return . (PadicMat x,)
-- Module documentation --------------------------------------------------------
-- We represent a matrix over \(\mathbf{Q}_p\) as a product \(p^v M\),
-- where \(p\) is a prime number, \(v \in \mathbf{Z}\) and \(M\) a matrix
-- over \(\mathbf{Z}\). We say this matrix is in /canonical form/ if either
-- \(M\) is zero, in which case we choose \(v = 0\), too, or if \(M\)
-- contains at least one p-adic unit. We say this matrix is /reduced/
-- modulo \(p^N\) if it is canonical form and if all coefficients of \(M\)
-- lie in the range \([0, p^{N-v})\).
--
-- | /padic_mat/ /A/
--
-- Returns a pointer to the unit part of the matrix, which is a matrix over
-- \(\mathbf{Z}\).
--
-- The return value can be used as an argument to the functions in the
-- @fmpz_mat@ module.
padic_mat :: Ptr CPadicMat -> IO (Ptr CFmpzMat)
padic_mat ptr = return $ castPtr ptr
-- | /padic_mat_entry/ /A/ /i/ /j/
--
-- Returns a pointer to unit part of the entry in position \((i, j)\). Note
-- that this is not necessarily a unit.
--
-- The return value can be used as an argument to the functions in the
-- @fmpz@ module.
padic_mat_entry :: Ptr CPadicMat -> CLong -> CLong -> IO (Ptr CFmpz)
padic_mat_entry a i j = do
CPadicMat mat _ _ <- peek a
fmpz_mat_entry mat i j
-- | /padic_mat_get_val/ /A/
--
-- Returns the valuation of the matrix.
foreign import ccall "padic_mat.h padic_mat_get_val"
padic_mat_get_val :: Ptr CPadicMat -> IO CLong
-- | /padic_mat_get_prec/ /A/
--
-- Returns the \(p\)-adic precision of the matrix.
foreign import ccall "padic_mat.h padic_mat_get_prec"
padic_mat_get_prec :: Ptr CPadicMat -> IO CLong
-- | /padic_mat_nrows/ /A/
--
-- Returns the number of rows of the matrix \(A\).
foreign import ccall "padic_mat.h padic_mat_nrows"
padic_mat_nrows :: Ptr CPadicMat -> IO CLong
-- | /padic_mat_ncols/ /A/
--
-- Returns the number of columns of the matrix \(A\).
foreign import ccall "padic_mat.h padic_mat_ncols"
padic_mat_ncols :: Ptr CPadicMat -> IO CLong
-- Memory management -----------------------------------------------------------
-- | /padic_mat_init/ /A/ /r/ /c/
--
-- Initialises the matrix \(A\) as a zero matrix with the specified numbers
-- of rows and columns and precision @PADIC_DEFAULT_PREC@.
foreign import ccall "padic_mat.h padic_mat_init"
padic_mat_init :: Ptr CPadicMat -> CLong -> CLong -> CLong -> IO ()
-- | /padic_mat_init2/ /A/ /r/ /c/ /prec/
--
-- Initialises the matrix \(A\) as a zero matrix with the specified numbers
-- of rows and columns and the given precision.
foreign import ccall "padic_mat.h padic_mat_init2"
padic_mat_init2 :: Ptr CPadicMat -> CLong -> CLong -> CLong -> IO ()
-- | /padic_mat_clear/ /A/
--
-- Clears the matrix \(A\).
foreign import ccall "padic_mat.h padic_mat_clear"
padic_mat_clear :: Ptr CPadicMat -> IO ()
foreign import ccall "padic_mat.h &padic_mat_clear"
p_padic_mat_clear :: FunPtr (Ptr CPadicMat -> IO ())
-- | /_padic_mat_canonicalise/ /A/ /ctx/
--
-- Ensures that the matrix \(A\) is in canonical form.
foreign import ccall "padic_mat.h _padic_mat_canonicalise"
_padic_mat_canonicalise :: Ptr CPadicMat -> Ptr CPadicCtx -> IO ()
-- | /_padic_mat_reduce/ /A/ /ctx/
--
-- Ensures that the matrix \(A\) is reduced modulo \(p^N\), assuming that
-- it is in canonical form already.
foreign import ccall "padic_mat.h _padic_mat_reduce"
_padic_mat_reduce :: Ptr CPadicMat -> Ptr CPadicCtx -> IO ()
-- | /padic_mat_reduce/ /A/ /ctx/
--
-- Ensures that the matrix \(A\) is reduced modulo \(p^N\), without
-- assuming that it is necessarily in canonical form.
foreign import ccall "padic_mat.h padic_mat_reduce"
padic_mat_reduce :: Ptr CPadicMat -> Ptr CPadicCtx -> IO ()
-- | /padic_mat_is_empty/ /A/
--
-- Returns whether the matrix \(A\) is empty, that is, whether it has zero
-- rows or zero columns.
foreign import ccall "padic_mat.h padic_mat_is_empty"
padic_mat_is_empty :: Ptr CPadicMat -> IO CInt
-- | /padic_mat_is_square/ /A/
--
-- Returns whether the matrix \(A\) is square.
foreign import ccall "padic_mat.h padic_mat_is_square"
padic_mat_is_square :: Ptr CPadicMat -> IO CInt
-- | /padic_mat_is_canonical/ /A/ /p/
--
-- Returns whether the matrix \(A\) is in canonical form.
foreign import ccall "padic_mat.h padic_mat_is_canonical"
padic_mat_is_canonical :: Ptr CPadicMat -> Ptr CFmpz -> IO CInt
-- Basic assignment ------------------------------------------------------------
-- | /padic_mat_set/ /B/ /A/
--
-- Sets \(B\) to a copy of \(A\), respecting the precision of \(B\).
foreign import ccall "padic_mat.h padic_mat_set"
padic_mat_set :: Ptr CPadicMat -> Ptr CPadicMat -> IO ()
-- | /padic_mat_swap/ /A/ /B/
--
-- Swaps the two matrices \(A\) and \(B\). This is done efficiently by
-- swapping pointers.
foreign import ccall "padic_mat.h padic_mat_swap"
padic_mat_swap :: Ptr CPadicMat -> Ptr CPadicMat -> IO ()
-- | /padic_mat_swap_entrywise/ /mat1/ /mat2/
--
-- Swaps two matrices by swapping the individual entries rather than
-- swapping the contents of the structs.
foreign import ccall "padic_mat.h padic_mat_swap_entrywise"
padic_mat_swap_entrywise :: Ptr CPadicMat -> Ptr CPadicMat -> IO ()
-- | /padic_mat_zero/ /A/
--
-- Sets the matrix \(A\) to zero.
foreign import ccall "padic_mat.h padic_mat_zero"
padic_mat_zero :: Ptr CPadicMat -> IO ()
-- | /padic_mat_one/ /A/
--
-- Sets the matrix \(A\) to the identity matrix. If the precision is
-- negative then the matrix will be the zero matrix.
foreign import ccall "padic_mat.h padic_mat_one"
padic_mat_one :: Ptr CPadicMat -> IO ()
-- Conversions -----------------------------------------------------------------
-- | /padic_mat_set_fmpq_mat/ /B/ /A/ /ctx/
--
-- Sets the \(p\)-adic matrix \(B\) to the rational matrix \(A\), reduced
-- according to the given context.
foreign import ccall "padic_mat.h padic_mat_set_fmpq_mat"
padic_mat_set_fmpq_mat :: Ptr CPadicMat -> Ptr CFmpqMat -> Ptr CPadicCtx -> IO ()
-- | /padic_mat_get_fmpq_mat/ /B/ /A/ /ctx/
--
-- Sets the rational matrix \(B\) to the \(p\)-adic matrices \(A\); no
-- reduction takes place.
foreign import ccall "padic_mat.h padic_mat_get_fmpq_mat"
padic_mat_get_fmpq_mat :: Ptr CFmpqMat -> Ptr CPadicMat -> Ptr CPadicCtx -> IO ()
-- Entries ---------------------------------------------------------------------
-- Because of the choice of the data structure, representing the matrix as
-- \(p^v M\), setting an entry of the matrix might lead to changes in all
-- entries in the matrix \(M\). Also, a specific entry is not readily
-- available as a \(p\)-adic number. Thus, there are separate functions
-- available for getting and setting entries.
--
-- | /padic_mat_get_entry_padic/ /rop/ /op/ /i/ /j/ /ctx/
--
-- Sets @rop@ to the entry in position \((i, j)\) in the matrix @op@.
foreign import ccall "padic_mat.h padic_mat_get_entry_padic"
padic_mat_get_entry_padic :: Ptr CPadic -> Ptr CPadicMat -> CLong -> CLong -> Ptr CPadicCtx -> IO ()
-- | /padic_mat_set_entry_padic/ /rop/ /i/ /j/ /op/ /ctx/
--
-- Sets the entry in position \((i, j)\) in the matrix to @rop@.
foreign import ccall "padic_mat.h padic_mat_set_entry_padic"
padic_mat_set_entry_padic :: Ptr CPadicMat -> CLong -> CLong -> Ptr CPadic -> Ptr CPadicCtx -> IO ()
-- Comparison ------------------------------------------------------------------
-- | /padic_mat_equal/ /A/ /B/
--
-- Returns whether the two matrices \(A\) and \(B\) are equal.
foreign import ccall "padic_mat.h padic_mat_equal"
padic_mat_equal :: Ptr CPadicMat -> Ptr CPadicMat -> IO CInt
-- | /padic_mat_is_zero/ /A/
--
-- Returns whether the matrix \(A\) is zero.
foreign import ccall "padic_mat.h padic_mat_is_zero"
padic_mat_is_zero :: Ptr CPadicMat -> IO CInt
-- Input and output ------------------------------------------------------------
foreign import ccall "padic_mat.h padic_mat_get_str"
padic_mat_get_str:: Ptr CPadicMat -> Ptr CPadicCtx -> IO CString
foreign import ccall "padic_mat.h padic_mat_get_str_pretty"
padic_mat_get_str_pretty:: Ptr CPadicMat -> Ptr CPadicCtx -> IO CString
-- | /padic_mat_fprint/ /file/ /A/ /ctx/
--
-- Prints a simple representation of the matrix \(A\) to the output stream
-- @file@. The format is the number of rows, a space, the number of
-- columns, two spaces, followed by a list of all the entries, one row
-- after the other.
--
-- In the current implementation, always returns \(1\).
foreign import ccall "padic_mat.h padic_mat_fprint"
padic_mat_fprint :: Ptr CFile -> Ptr CPadicMat -> Ptr CPadicCtx -> IO CInt
-- | /padic_mat_fprint_pretty/ /file/ /A/ /ctx/
--
-- Prints a /pretty/ representation of the matrix \(A\) to the output
-- stream @file@.
--
-- In the current implementation, always returns \(1\).
foreign import ccall "padic_mat.h padic_mat_fprint_pretty"
padic_mat_fprint_pretty :: Ptr CFile -> Ptr CPadicMat -> Ptr CPadicCtx -> IO CInt
-- | /padic_mat_print/ /file/ /A/ /ctx/
--
-- Prints a simple representation of the matrix \(A\) to @stdout@. The
-- format is the number of rows, a space, the number of columns, two
-- spaces, followed by a list of all the entries, one row after the
-- other.
--
-- In the current implementation, always returns \(1\).
padic_mat_print :: Ptr CPadicMat -> Ptr CPadicCtx -> IO CInt
padic_mat_print mat ctx = printCStr (flip padic_mat_get_str ctx) mat
-- | /padic_mat_print_pretty/ /file/ /A/ /ctx/
--
-- Prints a /pretty/ representation of the matrix \(A\) to @stdout@.
--
-- In the current implementation, always returns \(1\).
padic_mat_print_pretty :: Ptr CPadicMat -> Ptr CPadicCtx -> IO CInt
padic_mat_print_pretty mat ctx = printCStr (flip padic_mat_get_str_pretty ctx) mat
-- Random matrix generation ----------------------------------------------------
-- | /padic_mat_randtest/ /A/ /state/ /ctx/
--
-- Sets \(A\) to a random matrix.
--
-- The valuation will be in the range \([- \lceil N/10\rceil, N)\),
-- \([N - \lceil -N/10\rceil, N)\), or \([-10, 0)\) as \(N\) is positive,
-- negative or zero.
foreign import ccall "padic_mat.h padic_mat_randtest"
padic_mat_randtest :: Ptr CPadicMat -> Ptr CFRandState -> Ptr CPadicCtx -> IO ()
-- Transpose -------------------------------------------------------------------
-- | /padic_mat_transpose/ /B/ /A/
--
-- Sets \(B\) to \(A^t\).
foreign import ccall "padic_mat.h padic_mat_transpose"
padic_mat_transpose :: Ptr CPadicMat -> Ptr CPadicMat -> IO ()
-- Addition and subtraction ----------------------------------------------------
-- | /_padic_mat_add/ /C/ /A/ /B/ /ctx/
--
-- Sets \(C\) to the exact sum \(A + B\), ensuring that the result is in
-- canonical form.
foreign import ccall "padic_mat.h _padic_mat_add"
_padic_mat_add :: Ptr CPadicMat -> Ptr CPadicMat -> Ptr CPadicMat -> Ptr CPadicCtx -> IO ()
-- | /padic_mat_add/ /C/ /A/ /B/ /ctx/
--
-- Sets \(C\) to the sum \(A + B\) modulo \(p^N\).
foreign import ccall "padic_mat.h padic_mat_add"
padic_mat_add :: Ptr CPadicMat -> Ptr CPadicMat -> Ptr CPadicMat -> Ptr CPadicCtx -> IO ()
-- | /_padic_mat_sub/ /C/ /A/ /B/ /ctx/
--
-- Sets \(C\) to the exact difference \(A - B\), ensuring that the result
-- is in canonical form.
foreign import ccall "padic_mat.h _padic_mat_sub"
_padic_mat_sub :: Ptr CPadicMat -> Ptr CPadicMat -> Ptr CPadicMat -> Ptr CPadicCtx -> IO ()
-- | /padic_mat_sub/ /C/ /A/ /B/ /ctx/
--
-- Sets \(C\) to \(A - B\), ensuring that the result is reduced.
foreign import ccall "padic_mat.h padic_mat_sub"
padic_mat_sub :: Ptr CPadicMat -> Ptr CPadicMat -> Ptr CPadicMat -> Ptr CPadicCtx -> IO ()
-- | /_padic_mat_neg/ /B/ /A/
--
-- Sets \(B\) to \(-A\) in canonical form.
foreign import ccall "padic_mat.h _padic_mat_neg"
_padic_mat_neg :: Ptr CPadicMat -> Ptr CPadicMat -> IO ()
-- | /padic_mat_neg/ /B/ /A/ /ctx/
--
-- Sets \(B\) to \(-A\), ensuring the result is reduced.
foreign import ccall "padic_mat.h padic_mat_neg"
padic_mat_neg :: Ptr CPadicMat -> Ptr CPadicMat -> Ptr CPadicCtx -> IO ()
-- Scalar operations -----------------------------------------------------------
-- | /_padic_mat_scalar_mul_padic/ /B/ /A/ /c/ /ctx/
--
-- Sets \(B\) to \(c A\), ensuring that the result is in canonical form.
foreign import ccall "padic_mat.h _padic_mat_scalar_mul_padic"
_padic_mat_scalar_mul_padic :: Ptr CPadicMat -> Ptr CPadicMat -> Ptr CPadic -> Ptr CPadicCtx -> IO ()
-- | /padic_mat_scalar_mul_padic/ /B/ /A/ /c/ /ctx/
--
-- Sets \(B\) to \(c A\), ensuring that the result is reduced.
foreign import ccall "padic_mat.h padic_mat_scalar_mul_padic"
padic_mat_scalar_mul_padic :: Ptr CPadicMat -> Ptr CPadicMat -> Ptr CPadic -> Ptr CPadicCtx -> IO ()
-- | /_padic_mat_scalar_mul_fmpz/ /B/ /A/ /c/ /ctx/
--
-- Sets \(B\) to \(c A\), ensuring that the result is in canonical form.
foreign import ccall "padic_mat.h _padic_mat_scalar_mul_fmpz"
_padic_mat_scalar_mul_fmpz :: Ptr CPadicMat -> Ptr CPadicMat -> Ptr CFmpz -> Ptr CPadicCtx -> IO ()
-- | /padic_mat_scalar_mul_fmpz/ /B/ /A/ /c/ /ctx/
--
-- Sets \(B\) to \(c A\), ensuring that the result is reduced.
foreign import ccall "padic_mat.h padic_mat_scalar_mul_fmpz"
padic_mat_scalar_mul_fmpz :: Ptr CPadicMat -> Ptr CPadicMat -> Ptr CFmpz -> Ptr CPadicCtx -> IO ()
-- | /padic_mat_scalar_div_fmpz/ /B/ /A/ /c/ /ctx/
--
-- Sets \(B\) to \(c^{-1} A\), assuming that \(c \neq 0\). Ensures that the
-- result \(B\) is reduced.
foreign import ccall "padic_mat.h padic_mat_scalar_div_fmpz"
padic_mat_scalar_div_fmpz :: Ptr CPadicMat -> Ptr CPadicMat -> Ptr CFmpz -> Ptr CPadicCtx -> IO ()
-- Multiplication --------------------------------------------------------------
-- | /padic_mat_mul/ /C/ /A/ /B/ /ctx/
--
-- Sets \(C\) to the product \(A B\) of the two matrices \(A\) and \(B\),
-- ensuring that \(C\) is reduced.
foreign import ccall "padic_mat.h padic_mat_mul"
padic_mat_mul :: Ptr CPadicMat -> Ptr CPadicMat -> Ptr CPadicMat -> Ptr CPadicCtx -> IO ()