1 /*
2 Copyright (C) 2011, 2013 Sebastian Pancratz
3
4 This file is part of FLINT.
5
6 FLINT is free software: you can redistribute it and/or modify it under
7 the terms of the GNU Lesser General Public License (LGPL) as published
8 by the Free Software Foundation; either version 2.1 of the License, or
9 (at your option) any later version. See <http://www.gnu.org/licenses/>.
10 */
11
12 #include "fmpz_mat.h"
13 #include "padic_mat.h"
14
15 /*
16 Assumptions:
17
18 o That the matrix dimensions be compatible.
19 o That the matrices be non-empty.
20 o That ord_p(A) >= ord_p(B).
21 */
22
_padic_mat_add(padic_mat_t C,const padic_mat_t A,const padic_mat_t B,const padic_ctx_t ctx)23 void _padic_mat_add(padic_mat_t C, const padic_mat_t A, const padic_mat_t B,
24 const padic_ctx_t ctx)
25 {
26 if (padic_mat_is_zero(A))
27 {
28 padic_mat_set(C, B, ctx);
29 return;
30 }
31 if (padic_mat_is_zero(B))
32 {
33 padic_mat_set(C, A, ctx);
34 return;
35 }
36 if (padic_mat_val(B) >= padic_mat_prec(C))
37 {
38 padic_mat_zero(C);
39 return;
40 }
41
42
43 if (padic_mat_val(A) == padic_mat_val(B))
44 {
45 fmpz_mat_add(padic_mat(C), padic_mat(A), padic_mat(B));
46 padic_mat_val(C) = padic_mat_val(B);
47 _padic_mat_canonicalise(C, ctx);
48 }
49 else /* padic_mat_val(A) > padic_mat_val(B) */
50 {
51 fmpz_t x;
52
53 fmpz_init(x);
54 fmpz_pow_ui(x, ctx->p, padic_mat_val(A) - padic_mat_val(B));
55
56 if (C == B)
57 {
58 fmpz_mat_scalar_addmul_fmpz(padic_mat(C), padic_mat(A), x);
59 }
60 else if (C == A)
61 {
62 fmpz_mat_scalar_mul_fmpz(padic_mat(C), padic_mat(A), x);
63 fmpz_mat_add(padic_mat(C), padic_mat(B), padic_mat(C));
64 padic_mat_val(C) = padic_mat_val(B);
65 }
66 else
67 {
68 fmpz_mat_set(padic_mat(C), padic_mat(B));
69 fmpz_mat_scalar_addmul_fmpz(padic_mat(C), padic_mat(A), x);
70 padic_mat_val(C) = padic_mat_val(B);
71 }
72
73 fmpz_clear(x);
74 }
75
76 /* Reduction */
77 {
78 fmpz_t pow;
79 int alloc = _padic_ctx_pow_ui(pow, padic_mat_prec(C)- padic_mat_val(C), ctx);
80
81 /* TODO: Improve, use input precision */
82 _fmpz_vec_scalar_mod_fmpz(padic_mat(C)->entries,
83 padic_mat(C)->entries, padic_mat_nrows(C)*padic_mat_ncols(C), pow);
84
85 if (fmpz_mat_is_zero(padic_mat(C)))
86 {
87 padic_mat_val(C) = 0;
88 }
89
90
91 if (alloc)
92 fmpz_clear(pow);
93 }
94 }
95
padic_mat_add(padic_mat_t C,const padic_mat_t A,const padic_mat_t B,const padic_ctx_t ctx)96 void padic_mat_add(padic_mat_t C, const padic_mat_t A, const padic_mat_t B,
97 const padic_ctx_t ctx)
98 {
99 if (padic_mat_is_empty(C))
100 {
101 return;
102 }
103
104 if (padic_mat_val(A) >= padic_mat_val(B))
105 {
106 _padic_mat_add(C, A, B, ctx);
107 }
108 else
109 {
110 _padic_mat_add(C, B, A, ctx);
111 }
112 }
113
114