Jacobi symbol

From Rosetta Code
Jacobi symbol is a draft programming task. It is not yet considered ready to be promoted as a complete task, for reasons that should be found in its talk page.

The Jacobi symbol is a multiplicative function that generalizes the Legendre symbol. Specifically, the Jacobi symbol (a | n) equals the product of the Legendre symbols (a | p_i)^(k_i), where n = p_1^(k_1)*p_2^(k_2)*...*p_i^(k_i) and the Legendre symbol (a | p) denotes the value of a ^ ((p-1)/2) (mod p)

  • (a | p) ≡   1     if a is a square (mod p)
  • (a | p) ≡ -1     if a is not a square (mod p)
  • (a | p) ≡   0     if a ≡ 0

If n is prime, then the Jacobi symbol (a | n) equals the Legendre symbol (a | n).

Task

Calculate the Jacobi symbol (a | n).

Reference


AWK[edit]

Translation of: Go
 
# syntax: GAWK -f JACOBI_SYMBOL.AWK
BEGIN {
max_n = 29
max_a = max_n + 1
printf("n\\a")
for (i=1; i<=max_a; i++) {
printf("%3d",i)
underline = underline " --"
}
printf("\n---%s\n",underline)
for (n=1; n<=max_n; n+=2) {
printf("%3d",n)
for (a=1; a<=max_a; a++) {
printf("%3d",jacobi(a,n))
}
printf("\n")
}
exit(0)
}
function jacobi(a,n, result,tmp) {
if (n%2 == 0) {
print("error: 'n' must be a positive odd integer")
exit
}
a %= n
result = 1
while (a != 0) {
while (a%2 == 0) {
a /= 2
if (n%8 == 3 || n%8 == 5) {
result = -result
}
}
tmp = a
a = n
n = tmp
if (a%4 == 3 && n%4 == 3) {
result = -result
}
a %= n
}
if (n == 1) {
return(result)
}
return(0)
}
 
Output:
n\a  1  2  3  4  5  6  7  8  9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
--- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
  1  1  1  1  1  1  1  1  1  1  1  1  1  1  1  1  1  1  1  1  1  1  1  1  1  1  1  1  1  1  1
  3  1 -1  0  1 -1  0  1 -1  0  1 -1  0  1 -1  0  1 -1  0  1 -1  0  1 -1  0  1 -1  0  1 -1  0
  5  1 -1 -1  1  0  1 -1 -1  1  0  1 -1 -1  1  0  1 -1 -1  1  0  1 -1 -1  1  0  1 -1 -1  1  0
  7  1  1 -1  1 -1 -1  0  1  1 -1  1 -1 -1  0  1  1 -1  1 -1 -1  0  1  1 -1  1 -1 -1  0  1  1
  9  1  1  0  1  1  0  1  1  0  1  1  0  1  1  0  1  1  0  1  1  0  1  1  0  1  1  0  1  1  0
 11  1 -1  1  1  1 -1 -1 -1  1 -1  0  1 -1  1  1  1 -1 -1 -1  1 -1  0  1 -1  1  1  1 -1 -1 -1
 13  1 -1  1  1 -1 -1 -1 -1  1  1 -1  1  0  1 -1  1  1 -1 -1 -1 -1  1  1 -1  1  0  1 -1  1  1
 15  1  1  0  1  0  0 -1  1  0  0 -1  0 -1 -1  0  1  1  0  1  0  0 -1  1  0  0 -1  0 -1 -1  0
 17  1  1 -1  1 -1 -1 -1  1  1 -1 -1 -1  1 -1  1  1  0  1  1 -1  1 -1 -1 -1  1  1 -1 -1 -1  1
 19  1 -1 -1  1  1  1  1 -1  1 -1  1 -1 -1 -1 -1  1  1 -1  0  1 -1 -1  1  1  1  1 -1  1 -1  1
 21  1 -1  0  1  1  0  0 -1  0 -1 -1  0 -1  0  0  1  1  0 -1  1  0  1 -1  0  1  1  0  0 -1  0
 23  1  1  1  1 -1  1 -1  1  1 -1 -1  1  1 -1 -1  1 -1  1 -1 -1 -1 -1  0  1  1  1  1 -1  1 -1
 25  1  1  1  1  0  1  1  1  1  0  1  1  1  1  0  1  1  1  1  0  1  1  1  1  0  1  1  1  1  0
 27  1 -1  0  1 -1  0  1 -1  0  1 -1  0  1 -1  0  1 -1  0  1 -1  0  1 -1  0  1 -1  0  1 -1  0
 29  1 -1 -1  1  1  1  1 -1  1 -1 -1 -1  1 -1 -1  1 -1 -1 -1  1 -1  1  1  1  1 -1 -1  1  0  1

Erlang[edit]

 
jacobi(_, N) when N < 0 -> 0;
jacobi(_, N) when (N band 1) =:= 0 -> 0; % N is even
jacobi(A, N) when A < 0 ->
J2 = ja(-A, N),
case N band 3 of
1 -> J2;
3 -> -J2
end;
jacobi(A, N) -> ja(A, N).
 
ja(0, _) -> 0;
ja(1, _) -> 1;
ja(A, N) when A >= N -> ja(A rem N, N);
ja(A, N) when (A band 1) =:= 0 -> % A is even
J2 = ja(A bsr 1, N),
case N band 7 of
1 -> J2;
3 -> -J2;
5 -> -J2;
7 -> J2
end;
ja(A, N) -> % if we get here, A is odd, so we can flip it.
J2 = ja(N, A),
case (A band 3 =:= 3) and (N band 3 =:= 3) of
true -> -J2;
false -> J2
end.
 

Factor[edit]

The jacobi word already exists in the math.extras vocabulary. See the implementation here.

Go[edit]

The big.Jacobi function in the standard library (for 'big integers') returns the Jacobi symbol for given values of 'a' and 'n'.

This translates the Lua code in the above referenced Wikipedia article to Go (for 8 byte integers) and checks that it gives the same answers for a small table of values - which it does.

package main
 
import (
"fmt"
"log"
"math/big"
)
 
func jacobi(a, n uint64) int {
if n%2 == 0 {
log.Fatal("'n' must be a positive odd integer")
}
a %= n
result := 1
for a != 0 {
for a%2 == 0 {
a /= 2
nn := n % 8
if nn == 3 || nn == 5 {
result = -result
}
}
a, n = n, a
if a%4 == 3 && n%4 == 3 {
result = -result
}
a %= n
}
if n == 1 {
return result
}
return 0
}
 
func main() {
fmt.Println("Using hand-coded version:")
fmt.Println("n/a 0 1 2 3 4 5 6 7 8 9")
fmt.Println("---------------------------------")
for n := uint64(1); n <= 17; n += 2 {
fmt.Printf("%2d ", n)
for a := uint64(0); a <= 9; a++ {
fmt.Printf(" % d", jacobi(a, n))
}
fmt.Println()
}
 
ba, bn := new(big.Int), new(big.Int)
fmt.Println("\nUsing standard library function:")
fmt.Println("n/a 0 1 2 3 4 5 6 7 8 9")
fmt.Println("---------------------------------")
for n := uint64(1); n <= 17; n += 2 {
fmt.Printf("%2d ", n)
for a := uint64(0); a <= 9; a++ {
ba.SetUint64(a)
bn.SetUint64(n)
fmt.Printf(" % d", big.Jacobi(ba, bn))
}
fmt.Println()
}
}
Output:
Using hand-coded version:
n/a  0  1  2  3  4  5  6  7  8  9
---------------------------------
 1   1  1  1  1  1  1  1  1  1  1
 3   0  1 -1  0  1 -1  0  1 -1  0
 5   0  1 -1 -1  1  0  1 -1 -1  1
 7   0  1  1 -1  1 -1 -1  0  1  1
 9   0  1  1  0  1  1  0  1  1  0
11   0  1 -1  1  1  1 -1 -1 -1  1
13   0  1 -1  1  1 -1 -1 -1 -1  1
15   0  1  1  0  1  0  0 -1  1  0
17   0  1  1 -1  1 -1 -1 -1  1  1

Using standard library function:
n/a  0  1  2  3  4  5  6  7  8  9
---------------------------------
 1   1  1  1  1  1  1  1  1  1  1
 3   0  1 -1  0  1 -1  0  1 -1  0
 5   0  1 -1 -1  1  0  1 -1 -1  1
 7   0  1  1 -1  1 -1 -1  0  1  1
 9   0  1  1  0  1  1  0  1  1  0
11   0  1 -1  1  1  1 -1 -1 -1  1
13   0  1 -1  1  1 -1 -1 -1 -1  1
15   0  1  1  0  1  0  0 -1  1  0
17   0  1  1 -1  1 -1 -1 -1  1  1

Haskell[edit]

Translation of: Scheme
jacobi :: Integer -> Integer -> Integer
jacobi 0 1 = 1
jacobi 0 _ = 0
jacobi a n = do
let a_mod_n = rem a n
if even a_mod_n then
case rem n 8 of
1 -> jacobi (div a_mod_n 2) n
3 -> negate $ jacobi (div a_mod_n 2) n
5 -> negate $ jacobi (div a_mod_n 2) n
7 -> jacobi (div a_mod_n 2) n
else
if rem a_mod_n 4 == 3 && rem n 4 == 3 then negate $ jacobi n a_mod_n else jacobi n a_mod_n
 

Julia[edit]

Translation of: Python
function jacobi(a, n)
a %= n
result = 1
while a != 0
while iseven(a)
a ÷= 2
((n % 8) in [3, 5]) && (result *= -1)
end
a, n = n, a
(a % 4 == n % 4 == 3) && (result *= -1)
a %= n
end
return n == 1 ? result : 0
end
 
print(" Table of jacobi(a, n) for a 1 to 12, n 1 to 31\n 1 2 3 4 5 6 7 8",
" 9 10 11 12\nn\n_____________________________________________________")
for n in 1:2:31
print("\n", rpad(n, 3))
for a in 1:11
print(lpad(jacobi(a, n), 4))
end
end
 
Output:
 Table of jacobi(a, n) for a 1 to 12, n 1 to 31
   1   2   3   4   5   6   7   8   9  10  11  12
n
_____________________________________________________
1     1   1   1   1   1   1   1   1   1   1   1
3     1  -1   0   1  -1   0   1  -1   0   1  -1
5     1  -1  -1   1   0   1  -1  -1   1   0   1
7     1   1  -1   1  -1  -1   0   1   1  -1   1
9     1   1   0   1   1   0   1   1   0   1   1
11    1  -1   1   1   1  -1  -1  -1   1  -1   0
13    1  -1   1   1  -1  -1  -1  -1   1   1  -1
15    1   1   0   1   0   0  -1   1   0   0  -1
17    1   1  -1   1  -1  -1  -1   1   1  -1  -1
19    1  -1  -1   1   1   1   1  -1   1  -1   1
21    1  -1   0   1   1   0   0  -1   0  -1  -1
23    1   1   1   1  -1   1  -1   1   1  -1  -1
25    1   1   1   1   0   1   1   1   1   0   1
27    1  -1   0   1  -1   0   1  -1   0   1  -1
29    1  -1  -1   1   1   1   1  -1   1  -1  -1
31    1   1  -1   1   1  -1   1   1   1   1  -1

Perl[edit]

Translation of: Perl 6
use strict;
use warnings;
 
sub J {
my($k,$n) = @_;
 
$k %= $n;
my $jacobi = 1;
while ($k) {
while (0 == $k % 2) {
$k = int $k / 2;
$jacobi *= -1 if $n%8 == 3 or $n%8 == 5;
}
($k, $n) = ($n, $k);
$jacobi *= -1 if $n%4 == 3 and $k%4 == 3;
$k %= $n;
}
$n == 1 ? $jacobi : 0
}
 
my $maxa = 1 + (my $maxn = 29);
 
print 'n\k';
printf '%4d', $_ for 1..$maxa;
print "\n";
print ' ' . '-' x (4 * $maxa) . "\n";
 
for my $n (1..$maxn) {
next if 0 == $n % 2;
printf '%3d', $n;
printf '%4d', J($_, $n) for 1..$maxa;
print "\n"
}
Output:
n\k   1   2   3   4   5   6   7   8   9  10  11  12  13  14  15  16  17  18  19  20  21  22  23  24  25  26  27  28  29  30
   ------------------------------------------------------------------------------------------------------------------------
  1   1   1   1   1   1   1   1   1   1   1   1   1   1   1   1   1   1   1   1   1   1   1   1   1   1   1   1   1   1   1
  3   1  -1   0   1  -1   0   1  -1   0   1  -1   0   1  -1   0   1  -1   0   1  -1   0   1  -1   0   1  -1   0   1  -1   0
  5   1  -1  -1   1   0   1  -1  -1   1   0   1  -1  -1   1   0   1  -1  -1   1   0   1  -1  -1   1   0   1  -1  -1   1   0
  7   1   1  -1   1  -1  -1   0   1   1  -1   1  -1  -1   0   1   1  -1   1  -1  -1   0   1   1  -1   1  -1  -1   0   1   1
  9   1   1   0   1   1   0   1   1   0   1   1   0   1   1   0   1   1   0   1   1   0   1   1   0   1   1   0   1   1   0
 11   1  -1   1   1   1  -1  -1  -1   1  -1   0   1  -1   1   1   1  -1  -1  -1   1  -1   0   1  -1   1   1   1  -1  -1  -1
 13   1  -1   1   1  -1  -1  -1  -1   1   1  -1   1   0   1  -1   1   1  -1  -1  -1  -1   1   1  -1   1   0   1  -1   1   1
 15   1   1   0   1   0   0  -1   1   0   0  -1   0  -1  -1   0   1   1   0   1   0   0  -1   1   0   0  -1   0  -1  -1   0
 17   1   1  -1   1  -1  -1  -1   1   1  -1  -1  -1   1  -1   1   1   0   1   1  -1   1  -1  -1  -1   1   1  -1  -1  -1   1
 19   1  -1  -1   1   1   1   1  -1   1  -1   1  -1  -1  -1  -1   1   1  -1   0   1  -1  -1   1   1   1   1  -1   1  -1   1
 21   1  -1   0   1   1   0   0  -1   0  -1  -1   0  -1   0   0   1   1   0  -1   1   0   1  -1   0   1   1   0   0  -1   0
 23   1   1   1   1  -1   1  -1   1   1  -1  -1   1   1  -1  -1   1  -1   1  -1  -1  -1  -1   0   1   1   1   1  -1   1  -1
 25   1   1   1   1   0   1   1   1   1   0   1   1   1   1   0   1   1   1   1   0   1   1   1   1   0   1   1   1   1   0
 27   1  -1   0   1  -1   0   1  -1   0   1  -1   0   1  -1   0   1  -1   0   1  -1   0   1  -1   0   1  -1   0   1  -1   0
 29   1  -1  -1   1   1   1   1  -1   1  -1  -1  -1   1  -1  -1   1  -1  -1  -1   1  -1   1   1   1   1  -1  -1   1   0   1

Perl 6[edit]

Works with: Rakudo version 2019.11
# Jacobi function
sub infix:<J> (Int $k is copy, Int $n is copy where * % 2) {
$k %= $n;
my $jacobi = 1;
while $k {
while $k %% 2 {
$k div= 2;
$jacobi *= -1 if $n % 8 == 3 | 5;
}
($k, $n) = $n, $k;
$jacobi *= -1 if 3 == $n%4 & $k%4;
$k %= $n;
}
$n == 1 ?? $jacobi !! 0
}
 
# Testing
 
my $maxa = 30;
my $maxn = 29;
 
say 'n\k ', (1..$maxa).fmt: '%3d';
say ' ', '-' x 4 * $maxa;
for 1,*+2$maxn -> $n {
print $n.fmt: '%3d';
for 1..$maxa -> $k {
print ($k J $n).fmt: '%4d';
}
print "\n";
}
Output:
n\k   1   2   3   4   5   6   7   8   9  10  11  12  13  14  15  16  17  18  19  20  21  22  23  24  25  26  27  28  29  30
   ------------------------------------------------------------------------------------------------------------------------
  1   1   1   1   1   1   1   1   1   1   1   1   1   1   1   1   1   1   1   1   1   1   1   1   1   1   1   1   1   1   1
  3   1  -1   0   1  -1   0   1  -1   0   1  -1   0   1  -1   0   1  -1   0   1  -1   0   1  -1   0   1  -1   0   1  -1   0
  5   1  -1  -1   1   0   1  -1  -1   1   0   1  -1  -1   1   0   1  -1  -1   1   0   1  -1  -1   1   0   1  -1  -1   1   0
  7   1   1  -1   1  -1  -1   0   1   1  -1   1  -1  -1   0   1   1  -1   1  -1  -1   0   1   1  -1   1  -1  -1   0   1   1
  9   1   1   0   1   1   0   1   1   0   1   1   0   1   1   0   1   1   0   1   1   0   1   1   0   1   1   0   1   1   0
 11   1  -1   1   1   1  -1  -1  -1   1  -1   0   1  -1   1   1   1  -1  -1  -1   1  -1   0   1  -1   1   1   1  -1  -1  -1
 13   1  -1   1   1  -1  -1  -1  -1   1   1  -1   1   0   1  -1   1   1  -1  -1  -1  -1   1   1  -1   1   0   1  -1   1   1
 15   1   1   0   1   0   0  -1   1   0   0  -1   0  -1  -1   0   1   1   0   1   0   0  -1   1   0   0  -1   0  -1  -1   0
 17   1   1  -1   1  -1  -1  -1   1   1  -1  -1  -1   1  -1   1   1   0   1   1  -1   1  -1  -1  -1   1   1  -1  -1  -1   1
 19   1  -1  -1   1   1   1   1  -1   1  -1   1  -1  -1  -1  -1   1   1  -1   0   1  -1  -1   1   1   1   1  -1   1  -1   1
 21   1  -1   0   1   1   0   0  -1   0  -1  -1   0  -1   0   0   1   1   0  -1   1   0   1  -1   0   1   1   0   0  -1   0
 23   1   1   1   1  -1   1  -1   1   1  -1  -1   1   1  -1  -1   1  -1   1  -1  -1  -1  -1   0   1   1   1   1  -1   1  -1
 25   1   1   1   1   0   1   1   1   1   0   1   1   1   1   0   1   1   1   1   0   1   1   1   1   0   1   1   1   1   0
 27   1  -1   0   1  -1   0   1  -1   0   1  -1   0   1  -1   0   1  -1   0   1  -1   0   1  -1   0   1  -1   0   1  -1   0
 29   1  -1  -1   1   1   1   1  -1   1  -1  -1  -1   1  -1  -1   1  -1  -1  -1   1  -1   1   1   1   1  -1  -1   1   0   1

Phix[edit]

function jacobi(integer a, n)
atom result = 1
a = remainder(a,n)
while a!=0 do
while remainder(a,2)==0 do
a /= 2
if find(remainder(n,8),{3,5}) then result *= -1 end if
end while
{a, n} = {n, a}
if remainder(a,4)==3 and remainder(n,4)==3 then result *= -1 end if
a = remainder(a,n)
end while
return iff(n==1 ? result : 0)
end function
 
printf(1,"n\\a 0 1 2 3 4 5 6 7 8 9 10 11\n")
printf(1," ________________________________________________\n")
for n=1 to 31 by 2 do
printf(1,"%3d", n)
for a=0 to 11 do
printf(1,"%4d",jacobi(a, n))
end for
printf(1,"\n")
end for
Output:
n\a   0   1   2   3   4   5   6   7   8   9  10  11
   ________________________________________________
  1   1   1   1   1   1   1   1   1   1   1   1   1
  3   0   1  -1   0   1  -1   0   1  -1   0   1  -1
  5   0   1  -1  -1   1   0   1  -1  -1   1   0   1
  7   0   1   1  -1   1  -1  -1   0   1   1  -1   1
  9   0   1   1   0   1   1   0   1   1   0   1   1
 11   0   1  -1   1   1   1  -1  -1  -1   1  -1   0
 13   0   1  -1   1   1  -1  -1  -1  -1   1   1  -1
 15   0   1   1   0   1   0   0  -1   1   0   0  -1
 17   0   1   1  -1   1  -1  -1  -1   1   1  -1  -1
 19   0   1  -1  -1   1   1   1   1  -1   1  -1   1
 21   0   1  -1   0   1   1   0   0  -1   0  -1  -1
 23   0   1   1   1   1  -1   1  -1   1   1  -1  -1
 25   0   1   1   1   1   0   1   1   1   1   0   1
 27   0   1  -1   0   1  -1   0   1  -1   0   1  -1
 29   0   1  -1  -1   1   1   1   1  -1   1  -1  -1
 31   0   1   1  -1   1   1  -1   1   1   1   1  -1

Python[edit]

def jacobi(a, n):
if n <= 0:
raise ValueError("'n' must be a positive integer.")
if n % 2 == 0:
raise ValueError("'n' must be odd.")
a %= n
result = 1
while a != 0:
while a % 2 == 0:
a /= 2
n_mod_8 = n % 8
if n_mod_8 in (3, 5):
result = -result
a, n = n, a
if a % 4 == 3 and n % 4 == 3:
result = -result
a %= n
if n == 1:
return result
else:
return 0

REXX[edit]

Translation of: Go


A little extra code was added to make a prettier grid.

/*REXX pgm computes/displays the Jacobi symbol, the # of rows & columns can be specified*/
parse arg rows cols . /*obtain optional arguments from the CL*/
if rows='' | rows=="," then rows= 17 /*Not specified? Then use the default.*/
if cols='' | cols=="," then cols= 16 /* " " " " " " */
call hdrs /*display the (two) headers to the term*/
do r=1 by 2 to rows; _= right(r, 3) /*build odd (numbered) rows of a table.*/
do c=0 to cols /* [↓] build a column for a table row.*/
_= _ ! right(jacobi(c, r), 2);  != '│' /*reset grid end char.*/
end /*c*/
say _ '║';  != '║' /*display a table row; reset grid glyph*/
end /*r*/
say translate(@.2, '╩╧╝', "╬╤╗") /*display the bottom of the grid border*/
exit /*stick a fork in it, we're all done. */
/*──────────────────────────────────────────────────────────────────────────────────────*/
hdrs: @.1= 'n/a ║'; do c=0 to cols; @.1= @.1 || right(c, 3)" "; end
L= length(@.1); @.1= left(@.1, L - 1)  ; say @.1
@.2= '════╬'; do c=0 to cols; @.2= @.2 || "════╤"  ; end
L= length(@.2); @.2= left(@.2, L - 1)"╗" ; say @.2
 != '║'  ; return /*define an external grid border glyph.*/
/*──────────────────────────────────────────────────────────────────────────────────────*/
jacobi: procedure; parse arg a,n; er= '***error***'; $ = 1 /*define result.*/
if n//2==0 then do; say er n " must be a positive odd integer."; exit 13
end
a= a // n /*obtain A modulus N */
do while a\==0 /*perform while A isn't zero. */
do while a//2==0; a= a % 2 /*divide A (as a integer) by 2 */
if n//8==3 | n//8==5 then $= -$ /*use N mod 8 */
end /*while a//2==0*/
parse value a n with n a /*swap values of variables: A N */
if a//4==3 & n//4==3 then $= -$ /* A mod 4, N mod 4. Both ≡ 3 ?*/
a= a // n /*obtain A modulus N */
end /*while a\==0*/
if n==1 then return $
return 0
output   when using the default inputs:
n/a ║  0    1    2    3    4    5    6    7    8    9   10   11   12   13   14   15   16
════╬════╤════╤════╤════╤════╤════╤════╤════╤════╤════╤════╤════╤════╤════╤════╤════╤════╗
  1 ║  1 │  1 │  1 │  1 │  1 │  1 │  1 │  1 │  1 │  1 │  1 │  1 │  1 │  1 │  1 │  1 │  1 ║
  3 ║  0 │  1 │ -1 │  0 │  1 │ -1 │  0 │  1 │ -1 │  0 │  1 │ -1 │  0 │  1 │ -1 │  0 │  1 ║
  5 ║  0 │  1 │ -1 │ -1 │  1 │  0 │  1 │ -1 │ -1 │  1 │  0 │  1 │ -1 │ -1 │  1 │  0 │  1 ║
  7 ║  0 │  1 │  1 │ -1 │  1 │ -1 │ -1 │  0 │  1 │  1 │ -1 │  1 │ -1 │ -1 │  0 │  1 │  1 ║
  9 ║  0 │  1 │  1 │  0 │  1 │  1 │  0 │  1 │  1 │  0 │  1 │  1 │  0 │  1 │  1 │  0 │  1 ║
 11 ║  0 │  1 │ -1 │  1 │  1 │  1 │ -1 │ -1 │ -1 │  1 │ -1 │  0 │  1 │ -1 │  1 │  1 │  1 ║
 13 ║  0 │  1 │ -1 │  1 │  1 │ -1 │ -1 │ -1 │ -1 │  1 │  1 │ -1 │  1 │  0 │  1 │ -1 │  1 ║
 15 ║  0 │  1 │  1 │  0 │  1 │  0 │  0 │ -1 │  1 │  0 │  0 │ -1 │  0 │ -1 │ -1 │  0 │  1 ║
 17 ║  0 │  1 │  1 │ -1 │  1 │ -1 │ -1 │ -1 │  1 │  1 │ -1 │ -1 │ -1 │  1 │ -1 │  1 │  1 ║
════╩════╧════╧════╧════╧════╧════╧════╧════╧════╧════╧════╧════╧════╧════╧════╧════╧════╝

Scheme[edit]

(define jacobi (lambda (a n)
(let ((a-mod-n (modulo a n)))
(if (zero? a-mod-n)
(if (= n 1)
1
0)
(if (even? a-mod-n)
(case (modulo n 8)
((3 5) (- (jacobi (/ a-mod-n 2) n)))
((1 7) (jacobi (/ a-mod-n 2) n)))
(if (and (= (modulo a-mod-n 4) 3) (= (modulo n 4) 3))
(- (jacobi n a-mod-n))
(jacobi n a-mod-n)))))))

Sidef[edit]

Also built-in as kronecker(n,k).

func jacobi(n, k) {
 
assert(k > 0, "#{k} must be positive")
assert(k.is_odd, "#{k} must be odd")
 
var t = 1
while (n %= k) {
var v = n.valuation(2)
t *= (-1)**v if (k%8 ~~ [3,5])
n >>= v
(n,k) = (k,n)
t = -t if ([n%4, k%4] == [3,3])
}
 
k==1 ? t : 0
}
 
for n in (0..50), k in (0..50) {
assert_eq(jacobi(n, 2*k + 1), kronecker(n, 2*k + 1))
}

zkl[edit]

fcn jacobi(a,n){
if(n.isEven or n<1)
throw(Exception.ValueError("'n' must be a positive odd integer"));
a=a%n; result,t := 1,0;
while(a!=0){
while(a.isEven){
a/=2; n_mod_8:=n%8;
if(n_mod_8==3 or n_mod_8==5) result=-result;
}
t,a,n = a,n,t;
if(a%4==3 and n%4==3) result=-result;
a=a%n;
}
if(n==1) result else 0
}
println("Using hand-coded version:");
println("n/a 0 1 2 3 4 5 6 7 8 9");
println("---------------------------------");
foreach n in ([1..17,2]){
print("%2d ".fmt(n));
foreach a in (10){ print(" % d".fmt(jacobi(a,n))) }
println();
}
Library: GMP
GNU Multiple Precision Arithmetic Library
var [const] BI=Import.lib("zklBigNum");  // libGMP
println("\nUsing BigInt library function:");
println("n/a 0 1 2 3 4 5 6 7 8 9");
println("---------------------------------");
foreach n in ([1..17,2]){
print("%2d ".fmt(n));
foreach a in (10){ print(" % d".fmt(BI(a).jacobi(n))) }
println();
}
Output:
Using hand-coded version:
n/a  0  1  2  3  4  5  6  7  8  9
---------------------------------
 1   1  1  1  1  1  1  1  1  1  1
 3   0  1 -1  0  1 -1  0  1 -1  0
 5   0  1 -1 -1  1  0  1 -1 -1  1
 7   0  1  1 -1  1 -1 -1  0  1  1
 9   0  1  1  0  1  1  0  1  1  0
11   0  1 -1  1  1  1 -1 -1 -1  1
13   0  1 -1  1  1 -1 -1 -1 -1  1
15   0  1  1  0  1  0  0 -1  1  0
17   0  1  1 -1  1 -1 -1 -1  1  1

Using BigInt library function:
n/a  0  1  2  3  4  5  6  7  8  9
---------------------------------
 1   1  1  1  1  1  1  1  1  1  1
 3   0  1 -1  0  1 -1  0  1 -1  0
 5   0  1 -1 -1  1  0  1 -1 -1  1
 7   0  1  1 -1  1 -1 -1  0  1  1
 9   0  1  1  0  1  1  0  1  1  0
11   0  1 -1  1  1  1 -1 -1 -1  1
13   0  1 -1  1  1 -1 -1 -1 -1  1
15   0  1  1  0  1  0  0 -1  1  0
17   0  1  1 -1  1 -1 -1 -1  1  1