1 /*
2     Copyright (C) 2012 Fredrik Johansson
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 
14 void
fmpz_mat_pow(fmpz_mat_t B,const fmpz_mat_t A,ulong exp)15 fmpz_mat_pow(fmpz_mat_t B, const fmpz_mat_t A, ulong exp)
16 {
17     slong d = fmpz_mat_nrows(A);
18 
19     if (exp <= 2 || d <= 1)
20     {
21         if (exp == 0 || d == 0)
22         {
23             fmpz_mat_one(B);
24         }
25         else if (d == 1)
26         {
27             fmpz_pow_ui(fmpz_mat_entry(B, 0, 0),
28                  fmpz_mat_entry(A, 0, 0), exp);
29         }
30         else if (exp == 1)
31         {
32             fmpz_mat_set(B, A);
33         }
34         else if (exp == 2)
35         {
36             fmpz_mat_sqr(B, A);
37         }
38     }
39     else
40     {
41         fmpz_mat_t T, U;
42         slong i;
43 
44         fmpz_mat_init_set(T, A);
45         fmpz_mat_init(U, d, d);
46 
47         for (i = ((slong) FLINT_BIT_COUNT(exp)) - 2; i >= 0; i--)
48         {
49             fmpz_mat_sqr(U, T);
50 
51             if (exp & (WORD(1) << i))
52                 fmpz_mat_mul(T, U, A);
53             else
54                 fmpz_mat_swap(T, U);
55         }
56 
57         fmpz_mat_swap(B, T);
58         fmpz_mat_clear(T);
59         fmpz_mat_clear(U);
60     }
61 }
62