1 /*
2     Copyright (C) 2011 Fredrik Johansson
3     Copyright (C) 2013 Mike Hansen
4 
5     This file is part of FLINT.
6 
7     FLINT is free software: you can redistribute it and/or modify it under
8     the terms of the GNU Lesser General Public License (LGPL) as published
9     by the Free Software Foundation; either version 2.1 of the License, or
10     (at your option) any later version.  See <http://www.gnu.org/licenses/>.
11 */
12 
13 #ifdef T
14 
15 #include "templates.h"
16 
17 slong
TEMPLATE(T,mat_nullspace)18 TEMPLATE(T, mat_nullspace) (TEMPLATE(T, mat_t) X, const TEMPLATE(T, mat_t) A,
19                             const TEMPLATE(T, ctx_t) ctx)
20 {
21     slong i, j, k, m, n, rank, nullity;
22     slong *p;
23     slong *pivots;
24     slong *nonpivots;
25     TEMPLATE(T, mat_t) tmp;
26 
27     m = A->r;
28     n = A->c;
29 
30     p = flint_malloc(sizeof(slong) * FLINT_MAX(m, n));
31 
32     TEMPLATE(T, mat_init_set) (tmp, A, ctx);
33     rank = TEMPLATE(T, mat_rref) (tmp, ctx);
34     nullity = n - rank;
35 
36     TEMPLATE(T, mat_zero) (X, ctx);
37 
38     if (rank == 0)
39     {
40         for (i = 0; i < nullity; i++)
41             TEMPLATE(T, one) (TEMPLATE(T, mat_entry) (X, i, i), ctx);
42     }
43     else if (nullity)
44     {
45         pivots = p;             /* length = rank */
46         nonpivots = p + rank;   /* length = nullity */
47 
48         for (i = j = k = 0; i < rank; i++)
49         {
50             while (TEMPLATE(T, is_zero)
51                    (TEMPLATE(T, mat_entry) (tmp, i, j), ctx))
52             {
53                 nonpivots[k] = j;
54                 k++;
55                 j++;
56             }
57             pivots[i] = j;
58             j++;
59         }
60         while (k < nullity)
61         {
62             nonpivots[k] = j;
63             k++;
64             j++;
65         }
66 
67         for (i = 0; i < nullity; i++)
68         {
69             for (j = 0; j < rank; j++)
70             {
71                 TEMPLATE(T, neg) (TEMPLATE(T, mat_entry) (X, pivots[j], i),
72                                   TEMPLATE(T, mat_entry) (tmp, j,
73                                                           nonpivots[i]), ctx);
74             }
75 
76             TEMPLATE(T, one) (TEMPLATE(T, mat_entry) (X, nonpivots[i], i),
77                               ctx);
78         }
79     }
80 
81     flint_free(p);
82     TEMPLATE(T, mat_clear) (tmp, ctx);
83 
84     return nullity;
85 }
86 
87 #endif
88