# Eisenstein primes

Eisenstein primes 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.

An Eisenstein integer is a non-unit Gaussian integer a + bω where ω(1+ω) = -1, and a and b are integers.

ω is generally chosen as a cube root of unity: ${\displaystyle {\displaystyle \omega ={\frac {-1+i{\sqrt {3}}}{2}}=e^{i2\pi /3}}}$

As with a Gaussian integer, any Eisenstein integer is either a unit (an integer with a multiplicative inverse [±1, ±ω, ±(ω^-1)]), a prime (a number p such that if p divides xy, then p necessarily divides either x or y), or composite (a product of primes).

An Eisenstein integer a + bω is a prime if either it is a product of a unit and an integer prime p such that p % 3 == 2 or norm(a + bω) is an integer prime.

Eisenstein numbers can be generated by choosing any a and b such that a and b are integers. To allow generation in a relatively fixed order, such numbers can be ordered by their 2-norm or norm:

    norm(eisenstein integer(a, b)) = |a + bω|² = ${\displaystyle a^2 - ab + b^2}$

• Find, and show here as their complex number values, the first 100 (by norm order) Eisenstein primes nearest 0.
Stretch
• Plot in the complex plane at least the first 2000 such numbers (again, as found with norm closest to 0).

## J

Implementation:

eisensteinprimes=: {{
rY=. >.1.5%:y
p1=. ,(w^i.3)*/(#~ 2= 3|]) p:i.rY
'a b'=. |:(2#rY)#:I.,1 p: {{(x*x)+(y*y)-x*y}}"0/~i.rY
y{.(/: *:@|)p1,(,-)(a+b*w),a+b*-w
}}


Task example (and stretch - taking the stretch goal in a minimalist literal fashion):

   20 5$eisensteinprimes 100 0j1.73205 1.5j0.866025 0j_1.73205 _1.5j_0.866025 _1j_1.73205 2 _1j1.73205 _0.5j2.59808 0.5j2.59808 2.5j0.866025 2j1.73205 2j_1.73205 2.5j_0.866025 0.5j_2.59808 _0.5j_2.59808 _2.5j_0.866025 _2j_1.73205 _2j1.73205 _2.5j0.866025 _1j3.4641 1j3.4641 1j_3.4641 _1j_3.4641 3.5j0.866025 2.5j2.59808 2.5j_2.59808 3.5j_0.866025 _3.5j_0.866025 _2.5j_2.59808 _2.5j2.59808 _3.5j0.866025 _0.5j4.33013 0.5j4.33013 3.5j2.59808 3.5j_2.59808 0.5j_4.33013 _0.5j_4.33013 _3.5j_2.59808 _3.5j2.59808 4j1.73205 4j_1.73205 _4j_1.73205 _4j1.73205 3j_3.4641 _3j3.4641 4.5j_0.866025 _4.5j0.866025 _2.5j_4.33013 5 _2.5j4.33013 _2j5.19615 2j5.19615 5.5j0.866025 3.5j4.33013 2j_5.19615 _2j_5.19615 _5.5j_0.866025 _3.5j_4.33013 _0.5j6.06218 0.5j6.06218 5j3.4641 5j_3.4641 0.5j_6.06218 _0.5j_6.06218 _5j_3.4641 _5j3.4641 5.5j2.59808 5.5j_2.59808 _5.5j_2.59808 _5.5j2.59808 4.5j_4.33013 _4.5j4.33013 6j_1.73205 _6j1.73205 _2.5j6.06218 2.5j6.06218 6.5j0.866025 4j5.19615 4j_5.19615 6.5j_0.866025 2.5j_6.06218 _2.5j_6.06218 _6.5j_0.866025 _4j_5.19615 _4j5.19615 _6.5j0.866025 5.5j_4.33013 6.5j_2.59808 _5.5j4.33013 _6.5j2.59808 4.5j_6.06218 7.5j_0.866025 _4.5j6.06218 _7.5j0.866025 _0.5j7.79423 0.5j7.79423 6.5j4.33013 0.5j_7.79423 _0.5j_7.79423 _6.5j_4.33013 require'plot' 'marker; markersize 0.3' plot eisensteinprimes 2000  ## Julia """ rosettacode.org/wiki/Eisenstein_primes """ import Base: Complex, real, imag import LinearAlgebra: norm import Primes: isprime import Plots: scatter struct Eisenstein{T<:Integer} <: Number a::T b::T Eisenstein(a::T, b::T) where {T} = new{T}(a, b) Eisenstein(a::T) where {T<:Integer} = new{T}(a, zero(T)) Eisenstein(a::Integer, b::Integer) = new{eltype(promote(a, b))}(promote(a, b)...) end const ω = Eisenstein(false, true) real(n::Eisenstein) = n.a - n.b / 2 imag(n::Eisenstein) = n.b * sqrt(big(3.0)) / 2 norm(n::Eisenstein) = n.a * n.a + n.b * n.b - n.a * n.b Complex(n::Eisenstein{T}) where {T} = Complex{typeof(real(n))}(real(n), imag(n)) """ is_eisenstein_prime(n) An Eisenstein integer is a non-unit Gaussian integer a + bω where ω(1+ω) = -1, and a and b are integers. As a Gaussian integer, any Eisenstein integer is either a unit (an integer with a multiplicative inverse [±1, ±ω, ±(ω^-1)]), prime (a number p such that if p divides xy, then p necessarily divides either x or y), or composite (a product of primes). An Eisenstein integer a + bω is a prime if either it is a product of a unit and an integer prime p such that p % 3 == 2 or norm(a + bω) is an integer prime. """ function is_eisenstein_prime(n::Eisenstein) if n.a == 0 || n.b == 0 || n.a == n.b c = max(abs(n.a), abs(n.b)) return isprime(c) && c % 3 == 2 else return isprime(norm(n)) end end function test_eisenstein_primes(graphlimitsquared = 10_000, printlimit = 100) lim = isqrt(graphlimitsquared) arr = [Eisenstein(a, b) for a = -lim:lim, b = -lim:lim] eprimes = sort!(filter(is_eisenstein_prime, arr), lt = (x, y) -> norm(x) < norm(y))) for (i, c) in enumerate(eprimes) if i <= printlimit print(lpad(round(Complex(c), digits = 4), 18), i % 5 == 0 ? "\n" : "") end end display( scatter( map(real, eprimes), map(imag, eprimes), markersize = 1, title = "Eisenstein primes with norm <$lim",
),
)
end

test_eisenstein_primes()

Output:
    0.0 - 1.7321im    -1.5 - 0.866im     1.5 - 0.866im    -1.5 + 0.866im     1.5 + 0.866im
0.0 + 1.7321im   -1.0 - 1.7321im    1.0 - 1.7321im      -2.0 + 0.0im       2.0 + 0.0im
-1.0 + 1.7321im    1.0 + 1.7321im   -0.5 - 2.5981im    0.5 - 2.5981im   -2.0 - 1.7321im
2.0 - 1.7321im    -2.5 - 0.866im     2.5 - 0.866im    -2.5 + 0.866im     2.5 + 0.866im
-2.0 + 1.7321im    2.0 + 1.7321im   -0.5 + 2.5981im    0.5 + 2.5981im   -1.0 - 3.4641im
1.0 - 3.4641im   -2.5 - 2.5981im    2.5 - 2.5981im    -3.5 - 0.866im     3.5 - 0.866im
-3.5 + 0.866im     3.5 + 0.866im   -2.5 + 2.5981im    2.5 + 2.5981im   -1.0 + 3.4641im
1.0 + 3.4641im   -0.5 - 4.3301im    0.5 - 4.3301im   -3.5 - 2.5981im    3.5 - 2.5981im
-4.0 - 1.7321im    4.0 - 1.7321im   -4.0 + 1.7321im    4.0 + 1.7321im   -3.5 + 2.5981im
3.5 + 2.5981im   -0.5 + 4.3301im    0.5 + 4.3301im   -2.5 - 4.3301im    2.5 - 4.3301im
-5.0 + 0.0im       5.0 + 0.0im   -2.5 + 4.3301im    2.5 + 4.3301im   -2.0 - 5.1962im
2.0 - 5.1962im   -3.5 - 4.3301im    3.5 - 4.3301im    -5.5 - 0.866im     5.5 - 0.866im
-5.5 + 0.866im     5.5 + 0.866im   -3.5 + 4.3301im    3.5 + 4.3301im   -2.0 + 5.1962im
2.0 + 5.1962im   -0.5 - 6.0622im    0.5 - 6.0622im   -5.0 - 3.4641im    5.0 - 3.4641im
-5.5 - 2.5981im    5.5 - 2.5981im   -5.5 + 2.5981im    5.5 + 2.5981im   -5.0 + 3.4641im
5.0 + 3.4641im   -0.5 + 6.0622im    0.5 + 6.0622im   -2.5 - 6.0622im    2.5 - 6.0622im
-4.0 - 5.1962im    4.0 - 5.1962im    -6.5 - 0.866im     6.5 - 0.866im    -6.5 + 0.866im
6.5 + 0.866im   -4.0 + 5.1962im    4.0 + 5.1962im   -2.5 + 6.0622im    2.5 + 6.0622im
-0.5 - 7.7942im    0.5 - 7.7942im   -6.5 - 4.3301im    6.5 - 4.3301im   -7.0 - 3.4641im
7.0 - 3.4641im   -7.0 + 3.4641im    7.0 + 3.4641im   -6.5 + 4.3301im    6.5 + 4.3301im


## Nim

Translation of: Wren
import std/[algorithm, complex, math, strformat]

import gnuplot

func isPrime(n: Natural): bool =
if n < 2: return false
if (n and 1) == 0: return n == 2
if n mod 3 == 0: return n == 3
var k = 5
var delta = 2
while k * k <= n:
if n mod k == 0: return false
inc k, delta
delta = 6 - delta
result = true

### Eisenstein definition.

const ω = complex(-0.5, sqrt(3.0) * 0.5)

type Eisenstein = object
a: int
b: int
n: Complex64

func initEisenstein(a, b: int): Eisenstein =
## Initialize an Eisenstein number.
Eisenstein(a: a, b: b, n: a.toFloat + b.toFloat * ω)

template re(e: Eisenstein): float = e.n.re
template im(e: Eisenstein): float = e.n.im

func norm(e: Eisenstein): int =
## return the norm of an Eisenstein number.
e.a * e.a - e.a * e.b + e.b * e.b

func isPrime(e: Eisenstein): bool =
## Return true if an Eisenstein number is prime.
if e.a == 0 or e.b == 0 or e.a == e.b:
let c = max(abs(e.a), abs(e.b))
result = c.isPrime and c mod 3 == 2
else:
result = e.norm.isPrime

func $(e: Eisenstein): string = ## Return a string representation of an Eisenstein number. let (sign, im) = if e.im >= 0: ('+', e.im) else: ('-', -e.im) result = &"{e.re:7.4f} {sign} {im:6.4f}i" ### Find Eisenstein primes. var eprimes: seq[Eisenstein] for a in -100..100: for b in -100..100: let e = initEisenstein(a, b) if e.isPrime: eprimes.add e # Try to replicate Wren sort order for easy comparison. eprimes.sort(proc (e1, e2: Eisenstein): int = result = cmp(e1.norm, e2.norm) if result == 0: result = cmp(e1.im, e2.im) if result == 0: result = cmp(e1.re, e2.re) ) # Display first 100 Eisenstein primes to terminal. echo "First 100 Eisenstein primes nearest zero:" for i in 0..99: stdout.write eprimes[i] stdout.write if i mod 4 == 3: "\n" else: " " # Generate points for the plot. var x, y: seq[float] for e in eprimes: x.add e.re y.add e.im withGnuPlot: cmd "set size ratio -1" plot(x, y, "Eisenstein primes", "with dots lw 2")  Output: First 100 Eisenstein primes nearest zero: 0.0000 - 1.7321i -1.5000 - 0.8660i 1.5000 - 0.8660i -1.5000 + 0.8660i 1.5000 + 0.8660i 0.0000 + 1.7321i -1.0000 - 1.7321i 1.0000 - 1.7321i -2.0000 + 0.0000i 2.0000 + 0.0000i -1.0000 + 1.7321i 1.0000 + 1.7321i -0.5000 - 2.5981i 0.5000 - 2.5981i -2.0000 - 1.7321i 2.0000 - 1.7321i -2.5000 - 0.8660i 2.5000 - 0.8660i -2.5000 + 0.8660i 2.5000 + 0.8660i -2.0000 + 1.7321i 2.0000 + 1.7321i -0.5000 + 2.5981i 0.5000 + 2.5981i -1.0000 - 3.4641i 1.0000 - 3.4641i -2.5000 - 2.5981i 2.5000 - 2.5981i -3.5000 - 0.8660i 3.5000 - 0.8660i -3.5000 + 0.8660i 3.5000 + 0.8660i -2.5000 + 2.5981i 2.5000 + 2.5981i -1.0000 + 3.4641i 1.0000 + 3.4641i -0.5000 - 4.3301i 0.5000 - 4.3301i -3.5000 - 2.5981i 3.5000 - 2.5981i -4.0000 - 1.7321i 4.0000 - 1.7321i -4.0000 + 1.7321i 4.0000 + 1.7321i -3.5000 + 2.5981i 3.5000 + 2.5981i -0.5000 + 4.3301i 0.5000 + 4.3301i -2.5000 - 4.3301i 2.5000 - 4.3301i -5.0000 + 0.0000i 5.0000 + 0.0000i -2.5000 + 4.3301i 2.5000 + 4.3301i -2.0000 - 5.1962i 2.0000 - 5.1962i -3.5000 - 4.3301i 3.5000 - 4.3301i -5.5000 - 0.8660i 5.5000 - 0.8660i -5.5000 + 0.8660i 5.5000 + 0.8660i -3.5000 + 4.3301i 3.5000 + 4.3301i -2.0000 + 5.1962i 2.0000 + 5.1962i -0.5000 - 6.0622i 0.5000 - 6.0622i -5.0000 - 3.4641i 5.0000 - 3.4641i -5.5000 - 2.5981i 5.5000 - 2.5981i -5.5000 + 2.5981i 5.5000 + 2.5981i -5.0000 + 3.4641i 5.0000 + 3.4641i -0.5000 + 6.0622i 0.5000 + 6.0622i -2.5000 - 6.0622i 2.5000 - 6.0622i -4.0000 - 5.1962i 4.0000 - 5.1962i -6.5000 - 0.8660i 6.5000 - 0.8660i -6.5000 + 0.8660i 6.5000 + 0.8660i -4.0000 + 5.1962i 4.0000 + 5.1962i -2.5000 + 6.0622i 2.5000 + 6.0622i -0.5000 - 7.7942i 0.5000 - 7.7942i -6.5000 - 4.3301i 6.5000 - 4.3301i -7.0000 - 3.4641i 7.0000 - 3.4641i -7.0000 + 3.4641i 7.0000 + 3.4641i -6.5000 + 4.3301i 6.5000 + 4.3301i  ## Perl Translation of: Raku use v5.36; use Math::AnyNum <pi mod max complex reals is_prime>; my$omega = exp ( complex(0,2) * pi/3 ); my @E;

sub    norm (@p)     { $p[0]**2 -$p[0]*$p[1] +$p[1]**2 }
sub display (@p)     { sprintf '%+8.4f%+8.4fi', reals($p[0] +$omega*$p[1]) } sub X ($a, $b) { my @p; for my$x ($a..$b) { for my $y ($a..$b) { push @p, [$x, $y] } } @p } sub table ($c, @V) { my $t =$c * (my $w = 1 + max map { length } @V); ( sprintf( ('%'.$w.'s')x@V, @V) ) =~ s/.{1,$t}\K/\n/gr } for (X -10, 10) { my($a,$b) = @$_;
my $c = max abs($a), abs($b); push @E, [@$_] if ((0==$a or 0==$b or $a==$b) and is_prime $c and 2 == mod$c,3) or is_prime norm @$_ } say table 4, (map { display @$_ } sort { norm(@$a) <=> norm(@$b) } @E)[0..99];

Output:
  -1.5000 -0.8660i  -0.0000 -1.7321i  -1.5000 +0.8660i  +1.5000 -0.8660i
+0.0000 +1.7321i  +1.5000 +0.8660i  -1.0000 -1.7321i  -2.0000 +0.0000i
+1.0000 -1.7321i  -1.0000 +1.7321i  +2.0000 +0.0000i  +1.0000 +1.7321i
-2.0000 -1.7321i  -2.5000 -0.8660i  -0.5000 -2.5981i  -2.5000 +0.8660i
+0.5000 -2.5981i  -2.0000 +1.7321i  +2.0000 -1.7321i  -0.5000 +2.5981i
+2.5000 -0.8660i  +0.5000 +2.5981i  +2.5000 +0.8660i  +2.0000 +1.7321i
-2.5000 -2.5981i  -3.5000 -0.8660i  -1.0000 -3.4641i  -3.5000 +0.8660i
+1.0000 -3.4641i  -2.5000 +2.5981i  +2.5000 -2.5981i  -1.0000 +3.4641i
+3.5000 -0.8660i  +1.0000 +3.4641i  +3.5000 +0.8660i  +2.5000 +2.5981i
-3.5000 -2.5981i  -4.0000 -1.7321i  -0.5000 -4.3301i  -4.0000 +1.7321i
+0.5000 -4.3301i  -3.5000 +2.5981i  +3.5000 -2.5981i  -0.5000 +4.3301i
+4.0000 -1.7321i  +0.5000 +4.3301i  +4.0000 +1.7321i  +3.5000 +2.5981i
-2.5000 -4.3301i  -5.0000 +0.0000i  +2.5000 -4.3301i  -2.5000 +4.3301i
+5.0000 +0.0000i  +2.5000 +4.3301i  -3.5000 -4.3301i  -5.5000 -0.8660i
-2.0000 -5.1962i  -5.5000 +0.8660i  +2.0000 -5.1962i  -3.5000 +4.3301i
+3.5000 -4.3301i  -2.0000 +5.1962i  +5.5000 -0.8660i  +2.0000 +5.1962i
+5.5000 +0.8660i  +3.5000 +4.3301i  -5.0000 -3.4641i  -5.5000 -2.5981i
-0.5000 -6.0622i  -5.5000 +2.5981i  +0.5000 -6.0622i  -5.0000 +3.4641i
+5.0000 -3.4641i  -0.5000 +6.0622i  +5.5000 -2.5981i  +0.5000 +6.0622i
+5.5000 +2.5981i  +5.0000 +3.4641i  -4.0000 -5.1962i  -6.5000 -0.8660i
-2.5000 -6.0622i  -6.5000 +0.8660i  +2.5000 -6.0622i  -4.0000 +5.1962i
+4.0000 -5.1962i  -2.5000 +6.0622i  +6.5000 -0.8660i  +2.5000 +6.0622i
+6.5000 +0.8660i  +4.0000 +5.1962i  -6.5000 -4.3301i  -7.0000 -3.4641i
-0.5000 -7.7942i  -7.0000 +3.4641i  +0.5000 -7.7942i  -6.5000 +4.3301i
+6.5000 -4.3301i  -0.5000 +7.7942i  +7.0000 -3.4641i  +0.5000 +7.7942i


## Phix

Library: Phix/xpGUI

Note MARKSTYLE=DOT added for this task, 1.0.3 has not yet been released, and won't be until work this needs under pwa/p2js is finished.

requires("1.0.3")
include complex.e
constant OMEGA = {-0.5, sqrt(3)*0.5}

// try to replicate Wren sort order for easy comparison
enum NORM, IMAG, REAL, IS_PRIME, ELEN=$function new_Eisenstein(integer a,b) atom {real,imag} = complex_add(complex_mul(OMEGA,b),a) integer norm = a*a-a*b+b*b, c = max(abs(a),abs(b)) bool p = iff(a=0 or b=0 or a=b?is_prime(c) and remainder(c,3)=2 :is_prime(norm)) return {norm,imag,real,p} -- nb in [NORM..IS_PRIME] order end function function Eisenstein() sequence eprimes = {} for a=-100 to 100 do for b=-100 to 100 do sequence e = new_Eisenstein(a, b) if e[IS_PRIME] then eprimes = append(eprimes,e) end if end for end for eprimes = sort(eprimes) sequence real = vslice(eprimes,REAL), imag = vslice(eprimes,IMAG), f100 = repeat("",100) for i=1 to 100 do -- convert for display integer pm = iff(imag[i]>=0?'+':'-') f100[i] = sprintf("%7.4f %c%7.4fi",{real[i],pm,abs(imag[i])}) end for return {f100,real,imag} end function sequence {f100,real,imag} = Eisenstein() printf(1,"First 100 Eisenstein primes nearest zero:\n%s\n",join_by(f100,1,4," ")) include xpGUI.e function get_data(gdx graph) return {{real,imag}} end function gdx graph = gGraph(get_data,"XMIN=-150,XMAX=150,YMIN=-100,YMAX=100"), dlg = gDialog(graph,"Eisenstein primes","SIZE=392x290") gSetAttribute(graph,"GTITLE","with norm <= 100 (%d points)",{length(real)}) gSetAttributes(graph,"XTICK=50,YTICK=25,MARKSTYLE=DOT,GRID=NO") gShow(dlg) gMainLoop()  Output same as Wren. ## Raku my \ω = exp 2i × π/3; sub norm (@p) { @p[0]² - @p[0]×@p[1] + @p[1]² } sub display (@p) { (@p[0] + ω×@p[1]).reals».fmt('%+8.4f').join ~ 'i' } my @E = gather (-10..10 X -10..10).map: -> (\a,\b) { take (a,b) if 0 == a|b || a == b ?? (.is-prime and 2 ==$_ mod 3 given (a,b)».abs.max) !! norm((a,b)).is-prime
}


Output:
 -1.5000 -0.8660i  -0.0000 -1.7321i  -1.5000 +0.8660i  +1.5000 -0.8660i
+0.0000 +1.7321i  +1.5000 +0.8660i  -1.0000 -1.7321i  -2.0000 +0.0000i
+1.0000 -1.7321i  -1.0000 +1.7321i  +2.0000 +0.0000i  +1.0000 +1.7321i
-2.0000 -1.7321i  -2.5000 -0.8660i  -0.5000 -2.5981i  -2.5000 +0.8660i
+0.5000 -2.5981i  -2.0000 +1.7321i  +2.0000 -1.7321i  -0.5000 +2.5981i
+2.5000 -0.8660i  +0.5000 +2.5981i  +2.5000 +0.8660i  +2.0000 +1.7321i
-2.5000 -2.5981i  -3.5000 -0.8660i  -1.0000 -3.4641i  -3.5000 +0.8660i
+1.0000 -3.4641i  -2.5000 +2.5981i  +2.5000 -2.5981i  -1.0000 +3.4641i
+3.5000 -0.8660i  +1.0000 +3.4641i  +3.5000 +0.8660i  +2.5000 +2.5981i
-3.5000 -2.5981i  -4.0000 -1.7321i  -0.5000 -4.3301i  -4.0000 +1.7321i
+0.5000 -4.3301i  -3.5000 +2.5981i  +3.5000 -2.5981i  -0.5000 +4.3301i
+4.0000 -1.7321i  +0.5000 +4.3301i  +4.0000 +1.7321i  +3.5000 +2.5981i
-2.5000 -4.3301i  -5.0000 +0.0000i  +2.5000 -4.3301i  -2.5000 +4.3301i
+5.0000 +0.0000i  +2.5000 +4.3301i  -3.5000 -4.3301i  -5.5000 -0.8660i
-2.0000 -5.1962i  -5.5000 +0.8660i  +2.0000 -5.1962i  -3.5000 +4.3301i
+3.5000 -4.3301i  -2.0000 +5.1962i  +5.5000 -0.8660i  +2.0000 +5.1962i
+5.5000 +0.8660i  +3.5000 +4.3301i  -5.0000 -3.4641i  -5.5000 -2.5981i
-0.5000 -6.0622i  -5.5000 +2.5981i  +0.5000 -6.0622i  -5.0000 +3.4641i
+5.0000 -3.4641i  -0.5000 +6.0622i  +5.5000 -2.5981i  +0.5000 +6.0622i
+5.5000 +2.5981i  +5.0000 +3.4641i  -4.0000 -5.1962i  -6.5000 -0.8660i
-2.5000 -6.0622i  -6.5000 +0.8660i  +2.5000 -6.0622i  -4.0000 +5.1962i
+4.0000 -5.1962i  -2.5000 +6.0622i  +6.5000 -0.8660i  +2.5000 +6.0622i
+6.5000 +0.8660i  +4.0000 +5.1962i  -6.5000 -4.3301i  -7.0000 -3.4641i
-0.5000 -7.7942i  -7.0000 +3.4641i  +0.5000 -7.7942i  -6.5000 +4.3301i
+6.5000 -4.3301i  -0.5000 +7.7942i  +7.0000 -3.4641i  +0.5000 +7.7942i


## Sidef

Translation of: Raku
class Eisenstein(a, b, w = (-1 + sqrt(3).i)/2) {
method norm {
a**2 - a*b + b**2
}

method to_s {
sprintf('%+8.4f%+8.4fi', reals(a + b*w))
}
}

var E = []

for e in (-10..10 ~X -10..10 -> map_2d {|x,y| Eisenstein(x,y) }) {
var c = [e.a,e.b].map{.abs}.max
if (
((0 ~~ [e.a, e.b]) || (e.a == e.b)) ?
(c.is_congruent(2,3) && c.is_prime) : e.norm.is_prime
) {
E << e
}
}

E.sort_by { .norm }.first(100).slices(4).each {|s|
say s.join('  ')
}

Output:
 -1.5000 -0.8660i   +0.0000 -1.7321i   -1.5000 +0.8660i   +1.5000 -0.8660i
+0.0000 +1.7321i   +1.5000 +0.8660i   -1.0000 -1.7321i   -2.0000 +0.0000i
+1.0000 -1.7321i   -1.0000 +1.7321i   +2.0000 +0.0000i   +1.0000 +1.7321i
-2.0000 -1.7321i   -2.5000 -0.8660i   -0.5000 -2.5981i   -2.5000 +0.8660i
+0.5000 -2.5981i   -2.0000 +1.7321i   +2.0000 -1.7321i   -0.5000 +2.5981i
+2.5000 -0.8660i   +0.5000 +2.5981i   +2.5000 +0.8660i   +2.0000 +1.7321i
-2.5000 -2.5981i   -3.5000 -0.8660i   -1.0000 -3.4641i   -3.5000 +0.8660i
+1.0000 -3.4641i   -2.5000 +2.5981i   +2.5000 -2.5981i   -1.0000 +3.4641i
+3.5000 -0.8660i   +1.0000 +3.4641i   +3.5000 +0.8660i   +2.5000 +2.5981i
-3.5000 -2.5981i   -4.0000 -1.7321i   -0.5000 -4.3301i   -4.0000 +1.7321i
+0.5000 -4.3301i   -3.5000 +2.5981i   +3.5000 -2.5981i   -0.5000 +4.3301i
+4.0000 -1.7321i   +0.5000 +4.3301i   +4.0000 +1.7321i   +3.5000 +2.5981i
-2.5000 -4.3301i   -5.0000 +0.0000i   +2.5000 -4.3301i   -2.5000 +4.3301i
+5.0000 +0.0000i   +2.5000 +4.3301i   -3.5000 -4.3301i   -5.5000 -0.8660i
-2.0000 -5.1962i   -5.5000 +0.8660i   +2.0000 -5.1962i   -3.5000 +4.3301i
+3.5000 -4.3301i   -2.0000 +5.1962i   +5.5000 -0.8660i   +2.0000 +5.1962i
+5.5000 +0.8660i   +3.5000 +4.3301i   -5.0000 -3.4641i   -5.5000 -2.5981i
-0.5000 -6.0622i   -5.5000 +2.5981i   +0.5000 -6.0622i   -5.0000 +3.4641i
+5.0000 -3.4641i   -0.5000 +6.0622i   +5.5000 -2.5981i   +0.5000 +6.0622i
+5.5000 +2.5981i   +5.0000 +3.4641i   -4.0000 -5.1962i   -6.5000 -0.8660i
-2.5000 -6.0622i   -6.5000 +0.8660i   +2.5000 -6.0622i   -4.0000 +5.1962i
+4.0000 -5.1962i   -2.5000 +6.0622i   +6.5000 -0.8660i   +2.5000 +6.0622i
+6.5000 +0.8660i   +4.0000 +5.1962i   -6.5000 -4.3301i   -7.0000 -3.4641i
-0.5000 -7.7942i   -7.0000 +3.4641i   +0.5000 -7.7942i   -6.5000 +4.3301i
+6.5000 -4.3301i   -0.5000 +7.7942i   +7.0000 -3.4641i   +0.5000 +7.7942i


## Wren

Library: DOME
Library: Wren-plot
Library: Wren-iterate
Library: Wren-complex
Library: Wren-math
Library: Wren-fmt
import "dome" for Window
import "graphics" for Canvas, Color
import "./plot" for Axes
import "./iterate" for Stepped
import "./complex" for Complex
import "./math2" for Math, Int
import "./fmt" for Fmt

var OMEGA = Complex.new(-0.5, 3.sqrt * 0.5)

class Eisenstein {
construct new(a, b) {
_a = a
_b = b
_n = OMEGA * b + a
}

a { _a }
b { _b }
n { _n }

real { _n.real }
imag { _n.imag }
norm { _a *_a - _a * _b + _b * _b }

isPrime {
if (_a == 0 || _b == 0 || _a == _b) {
var c = Math.max(_a.abs, _b.abs)
return Int.isPrime(c) && c % 3 == 2
}
return Int.isPrime(norm)
}

toString { _n.toString }
}

var eprimes = []
for (a in -100..100) {
for (b in -100..100) {
var e = Eisenstein.new(a, b)
}
}

// try to replicate Julia sort order for easy comparison
eprimes.sort { |e1, e2|
if (e1.norm < e2.norm) return true
if (e1.norm == e2.norm) {
if (e1.imag < e2.imag) return true
if (e1.imag == e2.imag) return e1.real < e2.real
return false
}
return false
}

// convert to Complex numbers for easy display
eprimes = eprimes.map { |e| e.n }

// display first 100 to terminal
System.print("First 100 Eisenstein primes nearest zero:")
Fmt.tprint("\$ 6.4z ", eprimes.take(100), 4)

// generate points for the plot
var Pts = eprimes.map { |e| [e.real, e.imag] }.toList

class Main {
construct new() {
Window.title = "Eisenstein primes with norm <= 100  (%(Pts.count) points)"
Canvas.resize(1000, 600)
Window.resize(1000, 600)
Canvas.cls(Color.white)
var axes = Axes.new(100, 500, 800, 400, -160..160, -100..100)
axes.draw(Color.black, 2)
var xMarks = Stepped.new(-150..150, 50)
var yMarks = Stepped.new(-75..75, 25)
axes.mark(xMarks, yMarks, Color.black, 2)
axes.label(xMarks, yMarks, Color.black, 2, Color.black)
axes.plot(Pts, Color.black, "·") // uses interpunct character 0xb7
}

init() {}

update() {}

draw(alpha) {}
}

var Game = Main.new()

Output:

Terminal output:

First 100 Eisenstein primes nearest zero:
0.0000 - 1.7321i  -1.5000 - 0.8660i   1.5000 - 0.8660i  -1.5000 + 0.8660i
1.5000 + 0.8660i   0.0000 + 1.7321i  -1.0000 - 1.7321i   1.0000 - 1.7321i
-2.0000 + 0.0000i   2.0000 + 0.0000i  -1.0000 + 1.7321i   1.0000 + 1.7321i
-0.5000 - 2.5981i   0.5000 - 2.5981i  -2.0000 - 1.7321i   2.0000 - 1.7321i
-2.5000 - 0.8660i   2.5000 - 0.8660i  -2.5000 + 0.8660i   2.5000 + 0.8660i
-2.0000 + 1.7321i   2.0000 + 1.7321i  -0.5000 + 2.5981i   0.5000 + 2.5981i
-1.0000 - 3.4641i   1.0000 - 3.4641i  -2.5000 - 2.5981i   2.5000 - 2.5981i
-3.5000 - 0.8660i   3.5000 - 0.8660i  -3.5000 + 0.8660i   3.5000 + 0.8660i
-2.5000 + 2.5981i   2.5000 + 2.5981i  -1.0000 + 3.4641i   1.0000 + 3.4641i
-0.5000 - 4.3301i   0.5000 - 4.3301i  -3.5000 - 2.5981i   3.5000 - 2.5981i
-4.0000 - 1.7321i   4.0000 - 1.7321i  -4.0000 + 1.7321i   4.0000 + 1.7321i
-3.5000 + 2.5981i   3.5000 + 2.5981i  -0.5000 + 4.3301i   0.5000 + 4.3301i
-2.5000 - 4.3301i   2.5000 - 4.3301i  -5.0000 + 0.0000i   5.0000 + 0.0000i
-2.5000 + 4.3301i   2.5000 + 4.3301i  -2.0000 - 5.1962i   2.0000 - 5.1962i
-3.5000 - 4.3301i   3.5000 - 4.3301i  -5.5000 - 0.8660i   5.5000 - 0.8660i
-5.5000 + 0.8660i   5.5000 + 0.8660i  -3.5000 + 4.3301i   3.5000 + 4.3301i
-2.0000 + 5.1962i   2.0000 + 5.1962i  -0.5000 - 6.0622i   0.5000 - 6.0622i
-5.0000 - 3.4641i   5.0000 - 3.4641i  -5.5000 - 2.5981i   5.5000 - 2.5981i
-5.5000 + 2.5981i   5.5000 + 2.5981i  -5.0000 + 3.4641i   5.0000 + 3.4641i
-0.5000 + 6.0622i   0.5000 + 6.0622i  -2.5000 - 6.0622i   2.5000 - 6.0622i
-4.0000 - 5.1962i   4.0000 - 5.1962i  -6.5000 - 0.8660i   6.5000 - 0.8660i
-6.5000 + 0.8660i   6.5000 + 0.8660i  -4.0000 + 5.1962i   4.0000 + 5.1962i
-2.5000 + 6.0622i   2.5000 + 6.0622i  -0.5000 - 7.7942i   0.5000 - 7.7942i
-6.5000 - 4.3301i   6.5000 - 4.3301i  -7.0000 - 3.4641i   7.0000 - 3.4641i
-7.0000 + 3.4641i   7.0000 + 3.4641i  -6.5000 + 4.3301i   6.5000 + 4.3301i