{-| module : Data.Number.Flint.Fmpq.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.Fmpq.Mat.FFI ( -- * Matrices over the rational numbers FmpqMat (..) , CFmpqMat (..) , newFmpqMat , withFmpqMat , withNewFmpqMat -- * Memory management , fmpq_mat_init , fmpq_mat_init_set , fmpq_mat_clear , fmpq_mat_swap , fmpq_mat_swap_entrywise -- * Entry access , fmpq_mat_entry , fmpq_mat_entry_num , fmpq_mat_entry_den , fmpq_mat_set_entry , fmpq_mat_get_entry , fmpq_mat_nrows , fmpq_mat_ncols -- * Basic assignment , fmpq_mat_set , fmpq_mat_zero , fmpq_mat_one , fmpq_mat_transpose , fmpq_mat_swap_rows , fmpq_mat_swap_cols , fmpq_mat_invert_rows , fmpq_mat_invert_cols -- * Addition, scalar multiplication , fmpq_mat_add , fmpq_mat_sub , fmpq_mat_neg , fmpq_mat_scalar_mul_fmpq , fmpq_mat_scalar_mul_fmpz , fmpq_mat_scalar_div_fmpz -- * Input and output , fmpq_mat_get_str , fmpq_mat_fprint , fmpq_mat_print -- * Random matrix generation , fmpq_mat_randbits , fmpq_mat_randtest -- * Window , fmpq_mat_window_init , fmpq_mat_window_clear -- * Concatenate , fmpq_mat_concat_vertical , fmpq_mat_concat_horizontal -- * Special matrices , fmpq_mat_hilbert_matrix -- * Basic comparison and properties , fmpq_mat_equal , fmpq_mat_is_integral , fmpq_mat_is_zero , fmpq_mat_is_one , fmpq_mat_is_empty , fmpq_mat_is_square -- * Integer matrix conversion , fmpq_mat_get_fmpz_mat , fmpq_mat_get_fmpz_mat_entrywise , fmpq_mat_get_fmpz_mat_matwise , fmpq_mat_get_fmpz_mat_rowwise , fmpq_mat_get_fmpz_mat_rowwise_2 , fmpq_mat_get_fmpz_mat_colwise , fmpq_mat_set_fmpz_mat , fmpq_mat_set_fmpz_mat_div_fmpz -- * Modular reduction and rational reconstruction , fmpq_mat_get_fmpz_mat_mod_fmpz , fmpq_mat_set_fmpz_mat_mod_fmpz -- * Matrix multiplication , fmpq_mat_mul_direct , fmpq_mat_mul_cleared , fmpq_mat_mul , fmpq_mat_mul_fmpz_mat , fmpq_mat_mul_r_fmpz_mat , fmpq_mat_mul_fmpq_vec , fmpq_mat_fmpq_vec_mul -- * Kronecker product , fmpq_mat_kronecker_product -- * Trace , fmpq_mat_trace -- * Determinant , fmpq_mat_det -- * Nonsingular solving , fmpq_mat_solve_fraction_free , fmpq_mat_solve_dixon , fmpq_mat_solve_multi_mod , fmpq_mat_solve , fmpq_mat_solve_fmpz_mat_fraction_free , fmpq_mat_solve_fmpz_mat_dixon , fmpq_mat_solve_fmpz_mat_multi_mod , fmpq_mat_solve_fmpz_mat , fmpq_mat_can_solve_multi_mod , fmpq_mat_can_solve_fraction_free , fmpq_mat_can_solve_fmpz_mat_dixon , fmpq_mat_can_solve_dixon , fmpq_mat_can_solve -- * Inverse , fmpq_mat_inv -- * Echelon form , fmpq_mat_pivot , fmpq_mat_rref_classical , fmpq_mat_rref_fraction_free , fmpq_mat_rref -- * Gram-Schmidt Orthogonalisation , fmpq_mat_gso -- * Transforms , fmpq_mat_similarity -- * Characteristic polynomial , _fmpq_mat_charpoly , fmpq_mat_charpoly -- * Minimal polynomial , _fmpq_mat_minpoly , fmpq_mat_minpoly ) where -- Matrices over the rational numbers ------------------------------------------ import Foreign.C.String import Foreign.C.Types import Foreign.ForeignPtr import Foreign.Ptr ( Ptr, FunPtr, plusPtr ) import Foreign.Storable import Foreign.Marshal ( free ) import Foreign.Marshal.Array ( advancePtr ) import Data.Number.Flint.Flint import Data.Number.Flint.Fmpz import Data.Number.Flint.Fmpz.Mat import Data.Number.Flint.Fmpq import Data.Number.Flint.Fmpq.Poly #include #include #include -- fmpq_mat_t ------------------------------------------------------------------ data FmpqMat = FmpqMat {-# UNPACK #-} !(ForeignPtr CFmpqMat) data CFmpqMat = CFmpqMat (Ptr CFmpq) CLong CLong (Ptr (Ptr CFmpq)) instance Storable CFmpqMat where {-# INLINE sizeOf #-} sizeOf _ = #{size fmpq_mat_t} {-# INLINE alignment #-} alignment _ = #{alignment fmpq_mat_t} peek ptr = CFmpqMat <$> #{peek fmpq_mat_struct, entries} ptr <*> #{peek fmpq_mat_struct, r } ptr <*> #{peek fmpq_mat_struct, c } ptr <*> #{peek fmpq_mat_struct, rows } ptr poke = error "CFmpqMat.poke: Not defined." newFmpqMat rows cols = do x <- mallocForeignPtr withForeignPtr x $ \x -> fmpq_mat_init x rows cols addForeignPtrFinalizer p_fmpq_mat_clear x return $ FmpqMat x {-# INLINE withFmpqMat #-} withFmpqMat (FmpqMat x) f = do withForeignPtr x $ \px -> f px >>= return . (FmpqMat x,) {-# INLINE withNewFmpqMat #-} withNewFmpqMat rows cols f = do x <- newFmpqMat rows cols withFmpqMat x f -- Memory management ----------------------------------------------------------- -- | /fmpq_mat_init/ /mat/ /rows/ /cols/ -- -- Initialises a matrix with the given number of rows and columns for use. foreign import ccall "fmpq_mat.h fmpq_mat_init" fmpq_mat_init :: Ptr CFmpqMat -> CLong -> CLong -> IO () -- | /fmpq_mat_init_set/ /mat1/ /mat2/ -- -- Initialises @mat1@ and sets it equal to @mat2@. foreign import ccall "fmpq_mat.h fmpq_mat_init_set" fmpq_mat_init_set :: Ptr CFmpqMat -> Ptr CFmpqMat -> IO () -- | /fmpq_mat_clear/ /mat/ -- -- Frees all memory associated with the matrix. The matrix must be -- reinitialised if it is to be used again. foreign import ccall "fmpq_mat.h fmpq_mat_clear" fmpq_mat_clear :: Ptr CFmpqMat -> IO () foreign import ccall "fmpq_mat.h &fmpq_mat_clear" p_fmpq_mat_clear :: FunPtr (Ptr CFmpqMat -> IO ()) -- | /fmpq_mat_swap/ /mat1/ /mat2/ -- -- Swaps two matrices. The dimensions of @mat1@ and @mat2@ are allowed to -- be different. foreign import ccall "fmpq_mat.h fmpq_mat_swap" fmpq_mat_swap :: Ptr CFmpqMat -> Ptr CFmpqMat -> IO () -- | /fmpq_mat_swap_entrywise/ /mat1/ /mat2/ -- -- Swaps two matrices by swapping the individual entries rather than -- swapping the contents of the structs. foreign import ccall "fmpq_mat.h fmpq_mat_swap_entrywise" fmpq_mat_swap_entrywise :: Ptr CFmpqMat -> Ptr CFmpqMat -> IO () -- Entry access ---------------------------------------------------------------- -- | /fmpq_mat_entry/ /mat/ /i/ /j/ -- -- Gives a reference to the entry at row @i@ and column @j@. The reference -- can be passed as an input or output variable to any @fmpq@ function for -- direct manipulation of the matrix element. No bounds checking is -- performed. fmpq_mat_entry :: Ptr CFmpqMat -> CLong -> CLong -> IO (Ptr CFmpq) fmpq_mat_entry mat i j = do CFmpqMat entries r c rows <- peek mat return $ entries `advancePtr` (fromIntegral (i*c + j)) fmpq_mat_set_entry :: Ptr CFmpqMat -> CLong -> CLong -> Ptr CFmpq -> IO () fmpq_mat_set_entry mat i j x = do p <- fmpq_mat_entry mat i j fmpq_set p x fmpq_mat_get_entry :: Ptr CFmpq -> Ptr CFmpqMat -> CLong -> CLong -> IO () fmpq_mat_get_entry x mat i j = do p <- fmpq_mat_entry mat i j fmpq_set x p -- | /fmpq_mat_entry_num/ /mat/ /i/ /j/ -- -- Gives a reference to the numerator of the entry at row @i@ and column -- @j@. The reference can be passed as an input or output variable to any -- @fmpz@ function for direct manipulation of the matrix element. No bounds -- checking is performed. foreign import ccall "fmpq_mat.h fmpq_mat_entry_num" fmpq_mat_entry_num :: Ptr CFmpqMat -> CLong -> CLong -> IO (Ptr CFmpz) -- | /fmpq_mat_entry_den/ /mat/ /i/ /j/ -- -- Gives a reference to the denominator of the entry at row @i@ and column -- @j@. The reference can be passed as an input or output variable to any -- @fmpz@ function for direct manipulation of the matrix element. No bounds -- checking is performed. foreign import ccall "fmpq_mat.h fmpq_mat_entry_den" fmpq_mat_entry_den :: Ptr CFmpqMat -> CLong -> CLong -> IO (Ptr CFmpz) -- | /fmpq_mat_nrows/ /mat/ -- -- Return the number of rows of the matrix @mat@. foreign import ccall "fmpq_mat.h fmpq_mat_nrows" fmpq_mat_nrows :: Ptr CFmpqMat -> IO CLong -- | /fmpq_mat_ncols/ /mat/ -- -- Return the number of columns of the matrix @mat@. foreign import ccall "fmpq_mat.h fmpq_mat_ncols" fmpq_mat_ncols :: Ptr CFmpqMat -> IO CLong -- Basic assignment ------------------------------------------------------------ -- | /fmpq_mat_set/ /dest/ /src/ -- -- Sets the entries in @dest@ to the same values as in @src@, assuming the -- two matrices have the same dimensions. foreign import ccall "fmpq_mat.h fmpq_mat_set" fmpq_mat_set :: Ptr CFmpqMat -> Ptr CFmpqMat -> IO () -- | /fmpq_mat_zero/ /mat/ -- -- Sets @mat@ to the zero matrix. foreign import ccall "fmpq_mat.h fmpq_mat_zero" fmpq_mat_zero :: Ptr CFmpqMat -> IO () -- | /fmpq_mat_one/ /mat/ -- -- Let \(m\) be the minimum of the number of rows and columns in the matrix -- @mat@. This function sets the first \(m \times m\) block to the identity -- matrix, and the remaining block to zero. foreign import ccall "fmpq_mat.h fmpq_mat_one" fmpq_mat_one :: Ptr CFmpqMat -> IO () -- | /fmpq_mat_transpose/ /rop/ /op/ -- -- Sets the matrix @rop@ to the transpose of the matrix @op@, assuming that -- their dimensions are compatible. foreign import ccall "fmpq_mat.h fmpq_mat_transpose" fmpq_mat_transpose :: Ptr CFmpqMat -> Ptr CFmpqMat -> IO () -- | /fmpq_mat_swap_rows/ /mat/ /perm/ /r/ /s/ -- -- Swaps rows @r@ and @s@ of @mat@. If @perm@ is non-@NULL@, the -- permutation of the rows will also be applied to @perm@. foreign import ccall "fmpq_mat.h fmpq_mat_swap_rows" fmpq_mat_swap_rows :: Ptr CFmpqMat -> Ptr CLong -> CLong -> CLong -> IO () -- | /fmpq_mat_swap_cols/ /mat/ /perm/ /r/ /s/ -- -- Swaps columns @r@ and @s@ of @mat@. If @perm@ is non-@NULL@, the -- permutation of the columns will also be applied to @perm@. foreign import ccall "fmpq_mat.h fmpq_mat_swap_cols" fmpq_mat_swap_cols :: Ptr CFmpqMat -> Ptr CLong -> CLong -> CLong -> IO () -- | /fmpq_mat_invert_rows/ /mat/ /perm/ -- -- Swaps rows @i@ and @r - i@ of @mat@ for @0 \<= i \< r\/2@, where @r@ is -- the number of rows of @mat@. If @perm@ is non-@NULL@, the permutation of -- the rows will also be applied to @perm@. foreign import ccall "fmpq_mat.h fmpq_mat_invert_rows" fmpq_mat_invert_rows :: Ptr CFmpqMat -> Ptr CLong -> IO () -- | /fmpq_mat_invert_cols/ /mat/ /perm/ -- -- Swaps columns @i@ and @c - i@ of @mat@ for @0 \<= i \< c\/2@, where @c@ -- is the number of columns of @mat@. If @perm@ is non-@NULL@, the -- permutation of the columns will also be applied to @perm@. foreign import ccall "fmpq_mat.h fmpq_mat_invert_cols" fmpq_mat_invert_cols :: Ptr CFmpqMat -> Ptr CLong -> IO () -- Addition, scalar multiplication --------------------------------------------- -- | /fmpq_mat_add/ /mat/ /mat1/ /mat2/ -- -- Sets @mat@ to the sum of @mat1@ and @mat2@, assuming that all three -- matrices have the same dimensions. foreign import ccall "fmpq_mat.h fmpq_mat_add" fmpq_mat_add :: Ptr CFmpqMat -> Ptr CFmpqMat -> Ptr CFmpqMat -> IO () -- | /fmpq_mat_sub/ /mat/ /mat1/ /mat2/ -- -- Sets @mat@ to the difference of @mat1@ and @mat2@, assuming that all -- three matrices have the same dimensions. foreign import ccall "fmpq_mat.h fmpq_mat_sub" fmpq_mat_sub :: Ptr CFmpqMat -> Ptr CFmpqMat -> Ptr CFmpqMat -> IO () -- | /fmpq_mat_neg/ /rop/ /op/ -- -- Sets @rop@ to the negative of @op@, assuming that the two matrices have -- the same dimensions. foreign import ccall "fmpq_mat.h fmpq_mat_neg" fmpq_mat_neg :: Ptr CFmpqMat -> Ptr CFmpqMat -> IO () -- | /fmpq_mat_scalar_mul_fmpq/ /rop/ /op/ /x/ -- -- Sets @rop@ to @op@ multiplied by the rational \(x\), assuming that the -- two matrices have the same dimensions. -- -- Note that the rational @x@ may not be aliased with any part of the -- entries of @rop@. foreign import ccall "fmpq_mat.h fmpq_mat_scalar_mul_fmpq" fmpq_mat_scalar_mul_fmpq :: Ptr CFmpqMat -> Ptr CFmpqMat -> Ptr CFmpq -> IO () -- | /fmpq_mat_scalar_mul_fmpz/ /rop/ /op/ /x/ -- -- Sets @rop@ to @op@ multiplied by the integer \(x\), assuming that the -- two matrices have the same dimensions. -- -- Note that the integer \(x\) may not be aliased with any part of the -- entries of @rop@. foreign import ccall "fmpq_mat.h fmpq_mat_scalar_mul_fmpz" fmpq_mat_scalar_mul_fmpz :: Ptr CFmpqMat -> Ptr CFmpqMat -> Ptr CFmpz -> IO () -- | /fmpq_mat_scalar_div_fmpz/ /rop/ /op/ /x/ -- -- Sets @rop@ to @op@ divided by the integer \(x\), assuming that the two -- matrices have the same dimensions and that \(x\) is non-zero. -- -- Note that the integer \(x\) may not be aliased with any part of the -- entries of @rop@. foreign import ccall "fmpq_mat.h fmpq_mat_scalar_div_fmpz" fmpq_mat_scalar_div_fmpz :: Ptr CFmpqMat -> Ptr CFmpqMat -> Ptr CFmpz -> IO () -- Input and output ------------------------------------------------------------ -- | /fmpq_mat_get_str/ /mat/ -- -- Returns a string representation. foreign import ccall "fmpq_mat.h fmpq_mat_get_str" fmpq_mat_get_str :: Ptr CFmpqMat -> IO CString -- | /fmpq_mat_fprint/ /file/ /mat/ -- -- Prints the matrix @mat@ to the stream @file@. foreign import ccall "fmpq_mat.h fmpq_mat_fprint" fmpq_mat_fprint :: Ptr CFile -> Ptr CFmpqMat -> IO () -- | /fmpq_mat_print/ /mat/ -- -- Prints the matrix @mat@ to standard output. fmpq_mat_print :: Ptr CFmpqMat -> IO CInt fmpq_mat_print mat = printCStr (fmpq_mat_get_str) mat -- Random matrix generation ---------------------------------------------------- -- | /fmpq_mat_randbits/ /mat/ /state/ /bits/ -- -- This is equivalent to applying @fmpq_randbits@ to all entries in the -- matrix. foreign import ccall "fmpq_mat.h fmpq_mat_randbits" fmpq_mat_randbits :: Ptr CFmpqMat -> Ptr CFRandState -> CFBitCnt -> IO () -- | /fmpq_mat_randtest/ /mat/ /state/ /bits/ -- -- This is equivalent to applying @fmpq_randtest@ to all entries in the -- matrix. foreign import ccall "fmpq_mat.h fmpq_mat_randtest" fmpq_mat_randtest :: Ptr CFmpqMat -> Ptr CFRandState -> CFBitCnt -> IO () -- Window ---------------------------------------------------------------------- -- | /fmpq_mat_window_init/ /window/ /mat/ /r1/ /c1/ /r2/ /c2/ -- -- Initializes the matrix @window@ to be an @r2 - r1@ by @c2 - c1@ -- submatrix of @mat@ whose @(0,0)@ entry is the @(r1, c1)@ entry of @mat@. -- The memory for the elements of @window@ is shared with @mat@. foreign import ccall "fmpq_mat.h fmpq_mat_window_init" fmpq_mat_window_init :: Ptr CFmpqMat -> Ptr CFmpqMat -> CLong -> CLong -> CLong -> CLong -> IO () -- | /fmpq_mat_window_clear/ /window/ -- -- Clears the matrix @window@ and releases any memory that it uses. Note -- that the memory to the underlying matrix that @window@ points to is not -- freed. foreign import ccall "fmpq_mat.h fmpq_mat_window_clear" fmpq_mat_window_clear :: Ptr CFmpqMat -> IO () -- Concatenate ----------------------------------------------------------------- -- | /fmpq_mat_concat_vertical/ /res/ /mat1/ /mat2/ -- -- Sets @res@ to vertical concatenation of (@mat1@, @mat2@) in that order. -- Matrix dimensions : @mat1@ : \(m \times n\), @mat2@ : \(k \times n\), -- @res@ : \((m + k) \times n\). foreign import ccall "fmpq_mat.h fmpq_mat_concat_vertical" fmpq_mat_concat_vertical :: Ptr CFmpqMat -> Ptr CFmpqMat -> Ptr CFmpqMat -> IO () -- | /fmpq_mat_concat_horizontal/ /res/ /mat1/ /mat2/ -- -- Sets @res@ to horizontal concatenation of (@mat1@, @mat2@) in that -- order. Matrix dimensions : @mat1@ : \(m \times n\), @mat2@ : -- \(m \times k\), @res@ : \(m \times (n + k)\). foreign import ccall "fmpq_mat.h fmpq_mat_concat_horizontal" fmpq_mat_concat_horizontal :: Ptr CFmpqMat -> Ptr CFmpqMat -> Ptr CFmpqMat -> IO () -- Special matrices ------------------------------------------------------------ -- | /fmpq_mat_hilbert_matrix/ /mat/ -- -- Sets @mat@ to a Hilbert matrix of the given size. That is, the entry at -- row \(i\) and column \(j\) is set to \(1/(i+j+1)\). foreign import ccall "fmpq_mat.h fmpq_mat_hilbert_matrix" fmpq_mat_hilbert_matrix :: Ptr CFmpqMat -> IO () -- Basic comparison and properties --------------------------------------------- -- | /fmpq_mat_equal/ /mat1/ /mat2/ -- -- Returns nonzero if @mat1@ and @mat2@ have the same shape and all their -- entries agree, and returns zero otherwise. Assumes the entries in both -- @mat1@ and @mat2@ are in canonical form. foreign import ccall "fmpq_mat.h fmpq_mat_equal" fmpq_mat_equal :: Ptr CFmpqMat -> Ptr CFmpqMat -> IO CInt -- | /fmpq_mat_is_integral/ /mat/ -- -- Returns nonzero if all entries in @mat@ are integer-valued, and returns -- zero otherwise. Assumes that the entries in @mat@ are in canonical form. foreign import ccall "fmpq_mat.h fmpq_mat_is_integral" fmpq_mat_is_integral :: Ptr CFmpqMat -> IO CInt -- | /fmpq_mat_is_zero/ /mat/ -- -- Returns nonzero if all entries in @mat@ are zero, and returns zero -- otherwise. foreign import ccall "fmpq_mat.h fmpq_mat_is_zero" fmpq_mat_is_zero :: Ptr CFmpqMat -> IO CInt -- | /fmpq_mat_is_one/ /mat/ -- -- Returns nonzero if @mat@ ones along the diagonal and zeros elsewhere, -- and returns zero otherwise. foreign import ccall "fmpq_mat.h fmpq_mat_is_one" fmpq_mat_is_one :: Ptr CFmpqMat -> IO CInt -- | /fmpq_mat_is_empty/ /mat/ -- -- Returns a non-zero value if the number of rows or the number of columns -- in @mat@ is zero, and otherwise returns zero. foreign import ccall "fmpq_mat.h fmpq_mat_is_empty" fmpq_mat_is_empty :: Ptr CFmpqMat -> IO CInt -- | /fmpq_mat_is_square/ /mat/ -- -- Returns a non-zero value if the number of rows is equal to the number of -- columns in @mat@, and otherwise returns zero. foreign import ccall "fmpq_mat.h fmpq_mat_is_square" fmpq_mat_is_square :: Ptr CFmpqMat -> IO CInt -- Integer matrix conversion --------------------------------------------------- -- | /fmpq_mat_get_fmpz_mat/ /dest/ /mat/ -- -- Sets @dest@ to @mat@ and returns nonzero if all entries in @mat@ are -- integer-valued. If not all entries in @mat@ are integer-valued, sets -- @dest@ to an undefined matrix and returns zero. Assumes that the entries -- in @mat@ are in canonical form. foreign import ccall "fmpq_mat.h fmpq_mat_get_fmpz_mat" fmpq_mat_get_fmpz_mat :: Ptr CFmpzMat -> Ptr CFmpqMat -> IO CInt -- | /fmpq_mat_get_fmpz_mat_entrywise/ /num/ /den/ /mat/ -- -- Sets the integer matrices @num@ and @den@ respectively to the numerators -- and denominators of the entries in @mat@. foreign import ccall "fmpq_mat.h fmpq_mat_get_fmpz_mat_entrywise" fmpq_mat_get_fmpz_mat_entrywise :: Ptr CFmpzMat -> Ptr CFmpzMat -> Ptr CFmpqMat -> IO () -- | /fmpq_mat_get_fmpz_mat_matwise/ /num/ /den/ /mat/ -- -- Converts all entries in @mat@ to a common denominator, storing the -- rescaled numerators in @num@ and the denominator in @den@. The -- denominator will be minimal if the entries in @mat@ are in canonical -- form. foreign import ccall "fmpq_mat.h fmpq_mat_get_fmpz_mat_matwise" fmpq_mat_get_fmpz_mat_matwise :: Ptr CFmpzMat -> Ptr CFmpz -> Ptr CFmpqMat -> IO () -- | /fmpq_mat_get_fmpz_mat_rowwise/ /num/ /den/ /mat/ -- -- Clears denominators in @mat@ row by row. The rescaled numerators are -- written to @num@, and the denominator of row @i@ is written to position -- @i@ in @den@ which can be a preinitialised @fmpz@ vector. Alternatively, -- @NULL@ can be passed as the @den@ variable, in which case the -- denominators will not be stored. foreign import ccall "fmpq_mat.h fmpq_mat_get_fmpz_mat_rowwise" fmpq_mat_get_fmpz_mat_rowwise :: Ptr CFmpzMat -> Ptr CFmpz -> Ptr CFmpqMat -> IO () -- | /fmpq_mat_get_fmpz_mat_rowwise_2/ /num/ /num2/ /den/ /mat/ /mat2/ -- -- Clears denominators row by row of both @mat@ and @mat2@, writing the -- respective numerators to @num@ and @num2@. This is equivalent to -- concatenating @mat@ and @mat2@ horizontally, calling -- @fmpq_mat_get_fmpz_mat_rowwise@, and extracting the two submatrices in -- the result. foreign import ccall "fmpq_mat.h fmpq_mat_get_fmpz_mat_rowwise_2" fmpq_mat_get_fmpz_mat_rowwise_2 :: Ptr CFmpzMat -> Ptr CFmpzMat -> Ptr CFmpz -> Ptr CFmpqMat -> Ptr CFmpqMat -> IO () -- | /fmpq_mat_get_fmpz_mat_colwise/ /num/ /den/ /mat/ -- -- Clears denominators in @mat@ column by column. The rescaled numerators -- are written to @num@, and the denominator of column @i@ is written to -- position @i@ in @den@ which can be a preinitialised @fmpz@ vector. -- Alternatively, @NULL@ can be passed as the @den@ variable, in which case -- the denominators will not be stored. foreign import ccall "fmpq_mat.h fmpq_mat_get_fmpz_mat_colwise" fmpq_mat_get_fmpz_mat_colwise :: Ptr CFmpzMat -> Ptr CFmpz -> Ptr CFmpqMat -> IO () -- | /fmpq_mat_set_fmpz_mat/ /dest/ /src/ -- -- Sets @dest@ to @src@. foreign import ccall "fmpq_mat.h fmpq_mat_set_fmpz_mat" fmpq_mat_set_fmpz_mat :: Ptr CFmpqMat -> Ptr CFmpzMat -> IO () -- | /fmpq_mat_set_fmpz_mat_div_fmpz/ /mat/ /num/ /den/ -- -- Sets @mat@ to the integer matrix @num@ divided by the common denominator -- @den@. foreign import ccall "fmpq_mat.h fmpq_mat_set_fmpz_mat_div_fmpz" fmpq_mat_set_fmpz_mat_div_fmpz :: Ptr CFmpqMat -> Ptr CFmpzMat -> Ptr CFmpz -> IO () -- Modular reduction and rational reconstruction ------------------------------- -- | /fmpq_mat_get_fmpz_mat_mod_fmpz/ /dest/ /mat/ /mod/ -- -- Sets each entry in @dest@ to the corresponding entry in @mat@, reduced -- modulo @mod@. foreign import ccall "fmpq_mat.h fmpq_mat_get_fmpz_mat_mod_fmpz" fmpq_mat_get_fmpz_mat_mod_fmpz :: Ptr CFmpzMat -> Ptr CFmpqMat -> Ptr CFmpz -> IO () -- | /fmpq_mat_set_fmpz_mat_mod_fmpz/ /X/ /Xmod/ /mod/ -- -- Set @X@ to the entrywise rational reconstruction integer matrix @Xmod@ -- modulo @mod@, and returns nonzero if the reconstruction is successful. -- If rational reconstruction fails for any element, returns zero and sets -- the entries in @X@ to undefined values. foreign import ccall "fmpq_mat.h fmpq_mat_set_fmpz_mat_mod_fmpz" fmpq_mat_set_fmpz_mat_mod_fmpz :: Ptr CFmpqMat -> Ptr CFmpzMat -> Ptr CFmpz -> IO CInt -- Matrix multiplication ------------------------------------------------------- -- | /fmpq_mat_mul_direct/ /C/ /A/ /B/ -- -- Sets @C@ to the matrix product @AB@, computed naively using rational -- arithmetic. This is typically very slow and should only be used in -- circumstances where clearing denominators would consume too much memory. foreign import ccall "fmpq_mat.h fmpq_mat_mul_direct" fmpq_mat_mul_direct :: Ptr CFmpqMat -> Ptr CFmpqMat -> Ptr CFmpqMat -> IO () -- | /fmpq_mat_mul_cleared/ /C/ /A/ /B/ -- -- Sets @C@ to the matrix product @AB@, computed by clearing denominators -- and multiplying over the integers. foreign import ccall "fmpq_mat.h fmpq_mat_mul_cleared" fmpq_mat_mul_cleared :: Ptr CFmpqMat -> Ptr CFmpqMat -> Ptr CFmpqMat -> IO () -- | /fmpq_mat_mul/ /C/ /A/ /B/ -- -- Sets @C@ to the matrix product @AB@. This simply calls -- @fmpq_mat_mul_cleared@. foreign import ccall "fmpq_mat.h fmpq_mat_mul" fmpq_mat_mul :: Ptr CFmpqMat -> Ptr CFmpqMat -> Ptr CFmpqMat -> IO () -- | /fmpq_mat_mul_fmpz_mat/ /C/ /A/ /B/ -- -- Sets @C@ to the matrix product @AB@, with @B@ an integer matrix. This -- function works efficiently by clearing denominators of @A@. foreign import ccall "fmpq_mat.h fmpq_mat_mul_fmpz_mat" fmpq_mat_mul_fmpz_mat :: Ptr CFmpqMat -> Ptr CFmpqMat -> Ptr CFmpzMat -> IO () -- | /fmpq_mat_mul_r_fmpz_mat/ /C/ /A/ /B/ -- -- Sets @C@ to the matrix product @AB@, with @A@ an integer matrix. This -- function works efficiently by clearing denominators of @B@. foreign import ccall "fmpq_mat.h fmpq_mat_mul_r_fmpz_mat" fmpq_mat_mul_r_fmpz_mat :: Ptr CFmpqMat -> Ptr CFmpzMat -> Ptr CFmpqMat -> IO () -- | /fmpq_mat_mul_fmpq_vec/ /c/ /A/ /b/ /blen/ -- -- Compute a matrix-vector product of @A@ and @(b, blen)@ and store the -- result in @c@. The vector @(b, blen)@ is either truncated or -- zero-extended to the number of columns of @A@. The number entries -- written to @c@ is always equal to the number of rows of @A@. foreign import ccall "fmpq_mat.h fmpq_mat_mul_fmpq_vec" fmpq_mat_mul_fmpq_vec :: Ptr CFmpq -> Ptr CFmpqMat -> Ptr CFmpq -> CLong -> IO () -- | /fmpq_mat_fmpq_vec_mul/ /c/ /a/ /alen/ /B/ -- -- Compute a vector-matrix product of @(a, alen)@ and @B@ and and store the -- result in @c@. The vector @(a, alen)@ is either truncated or -- zero-extended to the number of rows of @B@. The number entries written -- to @c@ is always equal to the number of columns of @B@. foreign import ccall "fmpq_mat.h fmpq_mat_fmpq_vec_mul" fmpq_mat_fmpq_vec_mul :: Ptr CFmpq -> Ptr CFmpq -> CLong -> Ptr CFmpqMat -> IO () -- Kronecker product ----------------------------------------------------------- -- | /fmpq_mat_kronecker_product/ /C/ /A/ /B/ -- -- Sets @C@ to the Kronecker product of @A@ and @B@. foreign import ccall "fmpq_mat.h fmpq_mat_kronecker_product" fmpq_mat_kronecker_product :: Ptr CFmpqMat -> Ptr CFmpqMat -> Ptr CFmpqMat -> IO () -- Trace ----------------------------------------------------------------------- -- | /fmpq_mat_trace/ /trace/ /mat/ -- -- Computes the trace of the matrix, i.e. the sum of the entries on the -- main diagonal. The matrix is required to be square. foreign import ccall "fmpq_mat.h fmpq_mat_trace" fmpq_mat_trace :: Ptr CFmpq -> Ptr CFmpqMat -> IO () -- Determinant ----------------------------------------------------------------- -- | /fmpq_mat_det/ /det/ /mat/ -- -- Sets @det@ to the determinant of @mat@. In the general case, the -- determinant is computed by clearing denominators and computing a -- determinant over the integers. Matrices of size 0, 1 or 2 are handled -- directly. foreign import ccall "fmpq_mat.h fmpq_mat_det" fmpq_mat_det :: Ptr CFmpq -> Ptr CFmpqMat -> IO () -- Nonsingular solving --------------------------------------------------------- -- | /fmpq_mat_solve_fraction_free/ /X/ /A/ /B/ foreign import ccall "fmpq_mat.h fmpq_mat_solve_fraction_free" fmpq_mat_solve_fraction_free :: Ptr CFmpqMat -> Ptr CFmpqMat -> Ptr CFmpqMat -> IO CInt -- | /fmpq_mat_solve_dixon/ /X/ /A/ /B/ foreign import ccall "fmpq_mat.h fmpq_mat_solve_dixon" fmpq_mat_solve_dixon :: Ptr CFmpqMat -> Ptr CFmpqMat -> Ptr CFmpqMat -> IO CInt -- | /fmpq_mat_solve_multi_mod/ /X/ /A/ /B/ foreign import ccall "fmpq_mat.h fmpq_mat_solve_multi_mod" fmpq_mat_solve_multi_mod :: Ptr CFmpqMat -> Ptr CFmpqMat -> Ptr CFmpqMat -> IO CInt -- | /fmpq_mat_solve/ /X/ /A/ /B/ -- -- Solves @AX = B@ for nonsingular @A@. Returns nonzero if @A@ is -- nonsingular or if the right hand side is empty, and zero otherwise. -- -- All algorithms clear denominators to obtain a rescaled system over the -- integers. The /fraction_free/ algorithm uses FFLU solving over the -- integers. The /dixon/ and /multi_mod/ algorithms use Dixon p-adic -- lifting or multimodular solving, followed by rational reconstruction -- with an adaptive stopping test. The /dixon/ and /multi_mod/ algorithms -- are generally the best choice for large systems. -- -- The default method chooses an algorithm automatically. foreign import ccall "fmpq_mat.h fmpq_mat_solve" fmpq_mat_solve :: Ptr CFmpqMat -> Ptr CFmpqMat -> Ptr CFmpqMat -> IO CInt -- | /fmpq_mat_solve_fmpz_mat_fraction_free/ /X/ /A/ /B/ foreign import ccall "fmpq_mat.h fmpq_mat_solve_fmpz_mat_fraction_free" fmpq_mat_solve_fmpz_mat_fraction_free :: Ptr CFmpqMat -> Ptr CFmpzMat -> Ptr CFmpzMat -> IO CInt -- | /fmpq_mat_solve_fmpz_mat_dixon/ /X/ /A/ /B/ foreign import ccall "fmpq_mat.h fmpq_mat_solve_fmpz_mat_dixon" fmpq_mat_solve_fmpz_mat_dixon :: Ptr CFmpqMat -> Ptr CFmpzMat -> Ptr CFmpzMat -> IO CInt -- | /fmpq_mat_solve_fmpz_mat_multi_mod/ /X/ /A/ /B/ foreign import ccall "fmpq_mat.h fmpq_mat_solve_fmpz_mat_multi_mod" fmpq_mat_solve_fmpz_mat_multi_mod :: Ptr CFmpqMat -> Ptr CFmpzMat -> Ptr CFmpzMat -> IO CInt -- | /fmpq_mat_solve_fmpz_mat/ /X/ /A/ /B/ -- -- Solves @AX = B@ for nonsingular @A@, where /A/ and /B/ are integer -- matrices. Returns nonzero if @A@ is nonsingular or if the right hand -- side is empty, and zero otherwise. foreign import ccall "fmpq_mat.h fmpq_mat_solve_fmpz_mat" fmpq_mat_solve_fmpz_mat :: Ptr CFmpqMat -> Ptr CFmpzMat -> Ptr CFmpzMat -> IO CInt -- | /fmpq_mat_can_solve_multi_mod/ /X/ /A/ /B/ -- -- Returns \(1\) if @AX = B@ has a solution and if so, sets @X@ to one such -- solution. The matrices can have any shape but must have the same number -- of rows. foreign import ccall "fmpq_mat.h fmpq_mat_can_solve_multi_mod" fmpq_mat_can_solve_multi_mod :: Ptr CFmpqMat -> Ptr CFmpqMat -> Ptr CFmpqMat -> IO CInt -- | /fmpq_mat_can_solve_fraction_free/ /X/ /A/ /B/ -- -- Returns \(1\) if @AX = B@ has a solution and if so, sets @X@ to one such -- solution. The matrices can have any shape but must have the same number -- of rows. foreign import ccall "fmpq_mat.h fmpq_mat_can_solve_fraction_free" fmpq_mat_can_solve_fraction_free :: Ptr CFmpqMat -> Ptr CFmpqMat -> Ptr CFmpqMat -> IO CInt -- | /fmpq_mat_can_solve_fmpz_mat_dixon/ /X/ /A/ /B/ -- -- Returns if \(AX = B\) has a solution and if so, sets \(X\) to one -- such solution. The matrices can have any shape but must have the -- same number of rows. The input matrices must have integer entries -- and cannot be an empty matrix. foreign import ccall "fmpq_mat.h fmpq_mat_can_solve_fmpz_mat_dixon" fmpq_mat_can_solve_fmpz_mat_dixon :: Ptr CFmpqMat -> Ptr CFmpzMat -> Ptr CFmpzMat -> IO CInt -- | /fmpq_mat_can_solve_dixon/ /X/ /A/ /B/ -- -- Returns \(1\) if \(AX = B\) has a solution and if so, sets \(X\) to one -- such solution. The matrices can have any shape but must have the -- same number of rows. foreign import ccall "fmpq_mat.h fmpq_mat_can_solve_dixon" fmpq_mat_can_solve_dixon :: Ptr CFmpqMat -> Ptr CFmpqMat -> Ptr CFmpqMat -> IO CInt -- | /fmpq_mat_can_solve/ /X/ /A/ /B/ -- -- Returns \(1\) if @AX = B@ has a solution and if so, sets @X@ to one such -- solution. The matrices can have any shape but must have the same number -- of rows. foreign import ccall "fmpq_mat.h fmpq_mat_can_solve" fmpq_mat_can_solve :: Ptr CFmpqMat -> Ptr CFmpqMat -> Ptr CFmpqMat -> IO CInt -- Inverse --------------------------------------------------------------------- -- | /fmpq_mat_inv/ /B/ /A/ -- -- Sets @B@ to the inverse matrix of @A@ and returns nonzero. Returns zero -- if @A@ is singular. @A@ must be a square matrix. foreign import ccall "fmpq_mat.h fmpq_mat_inv" fmpq_mat_inv :: Ptr CFmpqMat -> Ptr CFmpqMat -> IO CInt -- Echelon form ---------------------------------------------------------------- -- | /fmpq_mat_pivot/ /perm/ /mat/ /r/ /c/ -- -- Helper function for row reduction. Returns 1 if the entry of @mat@ at -- row \(r\) and column \(c\) is nonzero. Otherwise searches for a nonzero -- entry in the same column among rows \(r+1, r+2, \ldots\). If a nonzero -- entry is found at row \(s\), swaps rows \(r\) and \(s\) and the -- corresponding entries in @perm@ (unless @NULL@) and returns -1. If no -- nonzero pivot entry is found, leaves the inputs unchanged and returns 0. foreign import ccall "fmpq_mat.h fmpq_mat_pivot" fmpq_mat_pivot :: Ptr CLong -> Ptr CFmpqMat -> CLong -> CLong -> IO CInt -- | /fmpq_mat_rref_classical/ /B/ /A/ -- -- Sets @B@ to the reduced row echelon form of @A@ and returns the rank. -- Performs Gauss-Jordan elimination directly over the rational numbers. -- This algorithm is usually inefficient and is mainly intended to be used -- for testing purposes. foreign import ccall "fmpq_mat.h fmpq_mat_rref_classical" fmpq_mat_rref_classical :: Ptr CFmpqMat -> Ptr CFmpqMat -> IO CLong -- | /fmpq_mat_rref_fraction_free/ /B/ /A/ -- -- Sets @B@ to the reduced row echelon form of @A@ and returns the rank. -- Clears denominators and performs fraction-free Gauss-Jordan elimination -- using @fmpz_mat@ functions. foreign import ccall "fmpq_mat.h fmpq_mat_rref_fraction_free" fmpq_mat_rref_fraction_free :: Ptr CFmpqMat -> Ptr CFmpqMat -> IO CLong -- | /fmpq_mat_rref/ /B/ /A/ -- -- Sets @B@ to the reduced row echelon form of @A@ and returns the rank. -- This function automatically chooses between the classical and -- fraction-free algorithms depending on the size of the matrix. foreign import ccall "fmpq_mat.h fmpq_mat_rref" fmpq_mat_rref :: Ptr CFmpqMat -> Ptr CFmpqMat -> IO CLong -- Gram-Schmidt Orthogonalisation ---------------------------------------------- -- | /fmpq_mat_gso/ /B/ /A/ -- -- Takes a subset of \(\mathbb{Q}^m\) \(S = \{a_1, a_2, \ldots ,a_n\}\) (as -- the columns of a \(m \times n\) matrix @A@) and generates an orthogonal -- set \(S' = \{b_1, b_2, \ldots ,b_n\}\) (as the columns of the -- \(m \times n\) matrix @B@) that spans the same subspace of -- \(\mathbb{Q}^m\) as \(S\). foreign import ccall "fmpq_mat.h fmpq_mat_gso" fmpq_mat_gso :: Ptr CFmpqMat -> Ptr CFmpqMat -> IO () -- Transforms ------------------------------------------------------------------ -- | /fmpq_mat_similarity/ /A/ /r/ /d/ -- -- Applies a similarity transform to the \(n\times n\) matrix \(M\) -- in-place. -- -- If \(P\) is the \(n\times n\) identity matrix the zero entries of whose -- row \(r\) (0-indexed) have been replaced by \(d\), this transform is -- equivalent to \(M = P^{-1}MP\). -- -- Similarity transforms preserve the determinant, characteristic -- polynomial and minimal polynomial. foreign import ccall "fmpq_mat.h fmpq_mat_similarity" fmpq_mat_similarity :: Ptr CFmpqMat -> CLong -> Ptr CFmpq -> IO () -- Characteristic polynomial --------------------------------------------------- -- | /_fmpq_mat_charpoly/ /coeffs/ /den/ /mat/ -- -- Set @(coeffs, den)@ to the characteristic polynomial of the given -- \(n\times n\) matrix. foreign import ccall "fmpq_mat.h _fmpq_mat_charpoly" _fmpq_mat_charpoly :: Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpqMat -> IO () -- | /fmpq_mat_charpoly/ /pol/ /mat/ -- -- Set @pol@ to the characteristic polynomial of the given \(n\times n\) -- matrix. If @mat@ is not square, an exception is raised. foreign import ccall "fmpq_mat.h fmpq_mat_charpoly" fmpq_mat_charpoly :: Ptr CFmpqPoly -> Ptr CFmpqMat -> IO () -- Minimal polynomial ---------------------------------------------------------- -- | /_fmpq_mat_minpoly/ /coeffs/ /den/ /mat/ -- -- Set @(coeffs, den)@ to the minimal polynomial of the given \(n\times n\) -- matrix and return the length of the polynomial. foreign import ccall "fmpq_mat.h _fmpq_mat_minpoly" _fmpq_mat_minpoly :: Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpqMat -> IO CLong -- | /fmpq_mat_minpoly/ /pol/ /mat/ -- -- Set @pol@ to the minimal polynomial of the given \(n\times n\) matrix. -- If @mat@ is not square, an exception is raised. foreign import ccall "fmpq_mat.h fmpq_mat_minpoly" fmpq_mat_minpoly :: Ptr CFmpqPoly -> Ptr CFmpqMat -> IO ()