/* Copyright (C) 2009 William Hart Copyright (C) 2011 Fredrik Johansson Copyright (C) 2014 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 #include "flint.h" #include "ulong_extras.h" #include "fmpz.h" void _fmpz_CRT(fmpz_t out, const fmpz_t r1, const fmpz_t m1, fmpz_t r2, fmpz_t m2, const fmpz_t m1m2, fmpz_t c, int sign) { fmpz_t r1normal, tmp, r1mod, s; fmpz_init(tmp); fmpz_init(r1mod); fmpz_init(s); /* FIXME: assume r1 moved to [0, m1); add tests for this */ if (fmpz_sgn(r1) < 0) { fmpz_init(r1normal); fmpz_add(r1normal, r1, m1); } else { *r1normal = *r1; } fmpz_mod(r1mod, r1normal, m2); fmpz_sub(s, r2, r1mod); if (fmpz_sgn(s) < 0) fmpz_add(s, s, m2); fmpz_mul(s, s, c); fmpz_mod(s, s, m2); fmpz_mul(tmp, m1, s); fmpz_add(tmp, tmp, r1normal); if (fmpz_sgn(r1) < 0) fmpz_clear(r1normal); if (sign) { fmpz_sub(out, tmp, m1m2); if (fmpz_cmpabs(tmp, out) <= 0) fmpz_set(out, tmp); } else { fmpz_set(out, tmp); } fmpz_clear(tmp); fmpz_clear(r1mod); fmpz_clear(s); } void fmpz_CRT(fmpz_t out, const fmpz_t r1, const fmpz_t m1, fmpz_t r2, fmpz_t m2, int sign) { fmpz_t m1m2, c; fmpz_init(c); fmpz_mod(c, m1, m2); fmpz_invmod(c, c, m2); if (fmpz_is_zero(c)) { flint_printf("Exception (fmpz_CRT). m1 not invertible modulo m2.\n"); flint_abort(); } fmpz_init(m1m2); fmpz_mul(m1m2, m1, m2); _fmpz_CRT(out, r1, m1, r2, m2, m1m2, c, sign); fmpz_clear(m1m2); fmpz_clear(c); }