/* Copyright (C) 2015 William Hart 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 . */ #include #include #include "flint.h" #include "nmod_vec.h" #include "nmod_mat.h" #include "nmod_poly.h" slong nmod_mat_reduce_row(nmod_mat_t M, slong * P, slong * L, slong m) { slong n = M->c, i, j, r, bits, limbs; ulong ** A = M->rows; ulong h, hi, lo; ulong * rowm; slong res = -WORD(1); TMP_INIT; bits = FLINT_BIT_COUNT(M->mod.n)*2 + FLINT_BIT_COUNT(m + 1); limbs = (bits + FLINT_BITS - 1)/FLINT_BITS; TMP_START; rowm = (ulong *) TMP_ALLOC(n*sizeof(ulong)*limbs); flint_mpn_zero(rowm, n*limbs); for (i = 0, j = 0; i < n; i++, j += limbs) rowm[j] = A[m][i]; for (i = 0; i < n; i++) { if (i != 0) { switch (limbs) { case 1: NMOD_RED(A[m][i], rowm[i], M->mod); break; case 2: NMOD2_RED2(A[m][i], rowm[2*i + 1], rowm[2*i], M->mod); break; case 3: NMOD_RED(rowm[3*i + 2], rowm[3*i + 2], M->mod); \ NMOD_RED3(A[m][i], rowm[3*i + 2], rowm[3*i + 1], rowm[3*i], M->mod); break; } } if (A[m][i] != 0) { r = P[i]; if (r != -WORD(1)) { h = n_negmod(A[m][i], M->mod.n); A[m][i] = 0; switch (limbs) { case 1: for (j = i + 1; j < L[r]; j++) rowm[j] += A[r][j]*h; break; case 2: for (j = i + 1; j < L[r]; j++) { umul_ppmm(hi, lo, A[r][j], h); add_ssaaaa(rowm[2*j + 1], rowm[2*j], rowm[2*j + 1], rowm[2*j], hi, lo); } break; case 3: for (j = i + 1; j < L[r]; j++) { umul_ppmm(hi, lo, A[r][j], h); add_sssaaaaaa(rowm[3*j + 2], rowm[3*j + 1], rowm[3*j], rowm[3*j + 2], rowm[3*j + 1], rowm[3*j], 0, hi, lo); } break; } } else { h = n_invmod(A[m][i], M->mod.n); A[m][i] = 1; switch (limbs) { case 1: for (j = i + 1; j < L[m]; j++) { NMOD_RED(A[m][j], rowm[j], M->mod); A[m][j] = n_mulmod2_preinv(A[m][j], h, M->mod.n, M->mod.ninv); } break; case 2: for (j = i + 1; j < L[m]; j++) { NMOD2_RED2(A[m][j], rowm[2*j + 1], rowm[2*j], M->mod); A[m][j] = n_mulmod2_preinv(A[m][j], h, M->mod.n, M->mod.ninv); } break; case 3: for (j = i + 1; j < L[m]; j++) { NMOD_RED(rowm[3*j + 2], rowm[3*j + 2], M->mod); \ NMOD_RED3(A[m][j], rowm[3*j + 2], rowm[3*j + 1], rowm[3*j], M->mod); A[m][j] = n_mulmod2_preinv(A[m][j], h, M->mod.n, M->mod.ninv); } break; } P[i] = m; res = i; break; } } } TMP_END; return res; }