pqc/external/flint-2.4.3/ulong_extras/jacobi.c

113 lines
2.9 KiB
C

/*=============================================================================
This file is part of FLINT.
FLINT is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
FLINT is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with FLINT; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
=============================================================================*/
/******************************************************************************
Copyright (C) 2008 Peter Shrimpton
Copyright (C) 2009 William Hart
******************************************************************************/
#include <gmp.h>
#include "flint.h"
#include "ulong_extras.h"
int
n_jacobi_unsigned(mp_limb_t x, mp_limb_t y)
{
mp_limb_t a, b, temp;
int s, exp;
a = x;
b = y;
s = 1;
if ((a < b) && (b != UWORD(1)))
{
if (a == UWORD(0))
return 0;
temp = a;
a = b;
b = temp;
count_trailing_zeros(exp, b);
b >>= exp;
/* We are only interested in values mod 8, so overflows don't matter here */
if (((exp * (a * a - 1)) / 8) % 2 == UWORD(1))
s = -s;
/* We are only interested in values mod 4, so overflows don't matter here */
if ((((a - 1) * (b - 1)) / 4) % 2 == UWORD(1))
s = -s;
}
while (b != UWORD(1))
{
if ((a >> 2) < b)
{
temp = a - b;
a = b;
if (temp < b)
b = temp;
else if (temp < (b << 1))
b = temp - a;
else
b = temp - (a << 1);
}
else
{
temp = a % b;
a = b;
b = temp;
}
if (b == UWORD(0))
return 0;
count_trailing_zeros(exp, b);
b >>= exp;
/* We are only interested in values mod 8, so overflows don't matter here */
if (((exp * (a * a - 1)) / 8) % 2 == UWORD(1))
s = -s;
/* We are only interested in values mod 4, so overflows don't matter here */
if ((((a - 1) * (b - 1)) / 4) % 2 == UWORD(1))
s = -s;
}
return s;
}
int
n_jacobi(mp_limb_signed_t x, mp_limb_t y)
{
if (x < WORD(0))
{
if (((y - 1) / 2) % 2 == UWORD(1))
return -n_jacobi_unsigned(-x, y);
else
return n_jacobi_unsigned(-x, y);
}
else
return n_jacobi_unsigned(x, y);
}