/*
Copyright (C) 2011, 2012, 2013 Sebastian Pancratz
This file is part of FLINT.
FLINT is free software: you can redistribute it and/or modify it under
the terms of the GNU Lesser General Public License (LGPL) as published
by the Free Software Foundation; either version 2.1 of the License, or
(at your option) any later version. See .
*/
#ifndef PADIC_MAT_H
#define PADIC_MAT_H
#ifdef PADIC_MAT_INLINES_C
#define PADIC_MAT_INLINE FLINT_DLL
#else
#define PADIC_MAT_INLINE static __inline__
#endif
#undef ulong
#define ulong ulongxx /* interferes with system includes */
#include
#undef ulong
#include
#define ulong mp_limb_t
#include "flint.h"
#include "fmpz.h"
#include "fmpz_mat.h"
#include "fmpq_mat.h"
#include "padic.h"
#ifdef __cplusplus
extern "C" {
#endif
typedef struct
{
fmpz_mat_struct mat;
slong val;
slong N;
} padic_mat_struct;
typedef padic_mat_struct padic_mat_t[1];
/* Macros *******************************************************************/
PADIC_MAT_INLINE
fmpz_mat_struct * padic_mat(const padic_mat_t A)
{
return (fmpz_mat_struct *)(&(A->mat));
}
PADIC_MAT_INLINE
fmpz * padic_mat_entry(const padic_mat_t A, slong i, slong j)
{
return A->mat.rows[i] + j;
}
#define padic_mat_val(A) ((A)->val)
#define padic_mat_prec(A) ((A)->N)
PADIC_MAT_INLINE
slong padic_mat_get_val(const padic_mat_t A)
{
return A->val;
}
PADIC_MAT_INLINE
slong padic_mat_get_prec(const padic_mat_t A)
{
return A->N;
}
PADIC_MAT_INLINE
slong padic_mat_nrows(const padic_mat_t A)
{
return (A->mat).r;
}
PADIC_MAT_INLINE
slong padic_mat_ncols(const padic_mat_t A)
{
return (A->mat).c;
}
/* Memory management ********************************************************/
FLINT_DLL void padic_mat_init(padic_mat_t A, slong r, slong c);
FLINT_DLL void padic_mat_init2(padic_mat_t A, slong r, slong c, slong prec);
FLINT_DLL void padic_mat_clear(padic_mat_t A);
FLINT_DLL void _padic_mat_canonicalise(padic_mat_t A, const padic_ctx_t ctx);
FLINT_DLL void _padic_mat_reduce(padic_mat_t A, const padic_ctx_t ctx);
FLINT_DLL void padic_mat_reduce(padic_mat_t A, const padic_ctx_t ctx);
PADIC_MAT_INLINE int
padic_mat_is_empty(const padic_mat_t A)
{
return fmpz_mat_is_empty(padic_mat(A));
}
PADIC_MAT_INLINE int
padic_mat_is_square(const padic_mat_t A)
{
return fmpz_mat_is_square(padic_mat(A));
}
PADIC_MAT_INLINE int
padic_mat_is_canonical(const padic_mat_t A, const padic_ctx_t ctx)
{
if (fmpz_mat_is_zero(padic_mat(A)))
{
return (padic_mat_val(A) == 0);
}
else
{
slong i, j;
int canonical = 0;
for (i = 0; i < padic_mat(A)->r; i++)
for (j = 0; j < padic_mat(A)->c; j++)
if (!fmpz_divisible(padic_mat_entry(A, i, j), ctx->p))
canonical = 1;
return canonical;
}
}
PADIC_MAT_INLINE int
padic_mat_is_reduced(const padic_mat_t A, const padic_ctx_t ctx)
{
if (padic_mat_is_empty(A))
{
return 1;
}
else if (fmpz_mat_is_zero(padic_mat(A)))
{
return (padic_mat_val(A) == 0);
}
else if (padic_mat_is_canonical(A, ctx))
{
const slong v = padic_mat_val(A);
const slong N = padic_mat_prec(A);
if (v >= N)
{
return 0;
}
else
{
slong i, j;
fmpz_t pN;
int reduced = 1;
int alloc = _padic_ctx_pow_ui(pN, N - v, ctx);
for (i = 0; (i < padic_mat_nrows(A)) && reduced; i++)
for (j = 0; (j < padic_mat_ncols(A)) && reduced; j++)
reduced = (fmpz_cmp(padic_mat_entry(A, i, j), pN) < 0);
if (alloc)
fmpz_clear(pN);
return reduced;
}
}
else
{
return 0;
}
}
/* Basic assignment **********************************************************/
FLINT_DLL void padic_mat_set(padic_mat_t B, const padic_mat_t A, const padic_ctx_t ctx);
FLINT_DLL void padic_mat_swap(padic_mat_t A, padic_mat_t B);
PADIC_MAT_INLINE void
padic_mat_swap_entrywise(padic_mat_t mat1, padic_mat_t mat2)
{
slong i, j;
for (i = 0; i < padic_mat_nrows(mat1); i++)
for (j = 0; j < padic_mat_ncols(mat1); j++)
fmpz_swap(padic_mat_entry(mat2, i, j), padic_mat_entry(mat1, i, j));
}
FLINT_DLL void padic_mat_zero(padic_mat_t A);
FLINT_DLL void padic_mat_one(padic_mat_t A);
/* Conversions ***************************************************************/
FLINT_DLL void padic_mat_set_fmpq_mat(padic_mat_t B,
const fmpq_mat_t A, const padic_ctx_t ctx);
FLINT_DLL void padic_mat_get_fmpq_mat(fmpq_mat_t B,
const padic_mat_t A, const padic_ctx_t ctx);
/* Entries *******************************************************************/
FLINT_DLL void padic_mat_get_entry_padic(padic_t rop,
const padic_mat_t op, slong i, slong j,
const padic_ctx_t ctx);
FLINT_DLL void padic_mat_set_entry_padic(padic_mat_t rop, slong i, slong j,
const padic_t op, const padic_ctx_t ctx);
/* Comparison ****************************************************************/
FLINT_DLL int padic_mat_equal(const padic_mat_t A, const padic_mat_t B);
FLINT_DLL int padic_mat_is_zero(const padic_mat_t A);
/* Input and output *********************************************************/
FLINT_DLL int padic_mat_fprint(FILE * file,
const padic_mat_t A, const padic_ctx_t ctx);
FLINT_DLL int padic_mat_fprint_pretty(FILE * file, const padic_mat_t A,
const padic_ctx_t ctx);
PADIC_MAT_INLINE
int padic_mat_print(const padic_mat_t A, const padic_ctx_t ctx)
{
return padic_mat_fprint(stdout, A, ctx);
}
PADIC_MAT_INLINE
int padic_mat_print_pretty(const padic_mat_t A, const padic_ctx_t ctx)
{
return padic_mat_fprint_pretty(stdout, A, ctx);
}
/* Random matrix generation *************************************************/
FLINT_DLL void padic_mat_randtest(padic_mat_t mat, flint_rand_t state,
const padic_ctx_t ctx);
/* Transpose *****************************************************************/
FLINT_DLL void padic_mat_transpose(padic_mat_t B, const padic_mat_t A);
/* Addition and subtraction **************************************************/
FLINT_DLL void _padic_mat_add(padic_mat_t C, const padic_mat_t A, const padic_mat_t B,
const padic_ctx_t ctx);
FLINT_DLL void padic_mat_add(padic_mat_t C, const padic_mat_t A, const padic_mat_t B,
const padic_ctx_t ctx);
FLINT_DLL void _padic_mat_sub(padic_mat_t C, const padic_mat_t A, const padic_mat_t B,
const padic_ctx_t ctx);
FLINT_DLL void padic_mat_sub(padic_mat_t C, const padic_mat_t A, const padic_mat_t B,
const padic_ctx_t ctx);
FLINT_DLL void _padic_mat_neg(padic_mat_t B, const padic_mat_t A);
FLINT_DLL void padic_mat_neg(padic_mat_t B, const padic_mat_t A, const padic_ctx_t ctx);
/* Scalar operations *********************************************************/
FLINT_DLL void _padic_mat_scalar_mul_padic(padic_mat_t B,
const padic_mat_t A, const padic_t c,
const padic_ctx_t ctx);
FLINT_DLL void padic_mat_scalar_mul_padic(padic_mat_t B,
const padic_mat_t A, const padic_t c,
const padic_ctx_t ctx);
FLINT_DLL void _padic_mat_scalar_mul_fmpz(padic_mat_t B,
const padic_mat_t A, const fmpz_t c,
const padic_ctx_t ctx);
FLINT_DLL void padic_mat_scalar_mul_fmpz(padic_mat_t B,
const padic_mat_t A, const fmpz_t c,
const padic_ctx_t ctx);
FLINT_DLL void padic_mat_scalar_div_fmpz(padic_mat_t B,
const padic_mat_t A, const fmpz_t c,
const padic_ctx_t ctx);
/* Multiplication ************************************************************/
FLINT_DLL void padic_mat_mul(padic_mat_t C, const padic_mat_t A, const padic_mat_t B,
const padic_ctx_t ctx);
#ifdef __cplusplus
}
#endif
#endif