commit state before changing what noether considers primitive roots
This commit is contained in:
parent
a168a728ce
commit
33bcffdc69
11 changed files with 441 additions and 36 deletions
19
README
Normal file
19
README
Normal file
|
|
@ -0,0 +1,19 @@
|
||||||
|
Noether is a project I plan to complete over a LONG period of time (years).
|
||||||
|
A collection of useful commands for solving various math problems.
|
||||||
|
|
||||||
|
A personal little MATLAB alternative I suppose :)
|
||||||
|
|
||||||
|
|
||||||
|
In future I'd love to start using a developed TUI library like [textual](https://github.com/Textualize/textual?tab=readme-ov-file),
|
||||||
|
but for now everything is just a custom ANSI wrapper thing.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
NOTES:
|
||||||
|
1. could I define something like "primality classes"?
|
||||||
|
ie class one: 2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, ...
|
||||||
|
class two: 3, 5, 11, 17, 31, ... (class 1 with a prime index, ie 11 is the 5th class 1 prime)
|
||||||
|
class three: 5, 11, 31, ... (class 2 with a prime index, ie 11 is the 3rd class 2 prime)
|
||||||
|
|
||||||
|
2. figure out all possible patterns that can appear amongst primitive roots
|
||||||
|
can we then categorise primes by their primitive root behaviour?
|
||||||
|
|
@ -1,24 +0,0 @@
|
||||||
# Euler's Totient (Phi) Function
|
|
||||||
def totient(n):
|
|
||||||
phi = int(n > 1 and n)
|
|
||||||
for p in range(2, int(n ** .5) + 1):
|
|
||||||
if not n % p:
|
|
||||||
phi -= phi // p
|
|
||||||
while not n % p:
|
|
||||||
n //= p
|
|
||||||
#if n is > 1 it means it is prime
|
|
||||||
if n > 1: phi -= phi // n
|
|
||||||
return phi
|
|
||||||
|
|
||||||
|
|
||||||
def orbit(b, m):
|
|
||||||
generated = []
|
|
||||||
x = b
|
|
||||||
for i in range(m):
|
|
||||||
x = (x * b) % m
|
|
||||||
if x not in generated:
|
|
||||||
generated.append(x)
|
|
||||||
return generated
|
|
||||||
|
|
||||||
def order(b, m):
|
|
||||||
return len(orbit(b, m))
|
|
||||||
8
py/NOTES
Normal file
8
py/NOTES
Normal file
|
|
@ -0,0 +1,8 @@
|
||||||
|
TODO:
|
||||||
|
NOTE: currently my "primitive roots" are actually just the numbers that generate every integer below the modulus, that is `a` such that `orbit(a) = Z_n`
|
||||||
|
1. How I'm calculating something as a primtive root, and its order is not correct.
|
||||||
|
For instance, consider a modulus n=4, a=3 is a primitive root, and a=2 SHOULD have order 0 (it is aperiodic)
|
||||||
|
|
||||||
|
|
||||||
|
This site is useful as a reference:
|
||||||
|
https://owlsmath.neocities.org/Primitive%20Root%20Calculator/calculator
|
||||||
76
py/mquiet.py
Normal file
76
py/mquiet.py
Normal file
|
|
@ -0,0 +1,76 @@
|
||||||
|
# Modulo Test
|
||||||
|
from prbraid.math import *
|
||||||
|
from prbraid.color import *
|
||||||
|
|
||||||
|
import sys
|
||||||
|
|
||||||
|
PROMPT = '[n]: '
|
||||||
|
|
||||||
|
'''
|
||||||
|
Pairwise orbit cumulative summation (cum orb)
|
||||||
|
'''
|
||||||
|
def orb_cum(cum, orb):
|
||||||
|
for i in range(len(cum)):
|
||||||
|
cum[i] += orb[i]
|
||||||
|
|
||||||
|
def main():
|
||||||
|
while True:
|
||||||
|
n = None
|
||||||
|
strlen_n = None
|
||||||
|
try:
|
||||||
|
uprint(PROMPT, color=Color.Blue, end='')
|
||||||
|
n = input()
|
||||||
|
strlen_n = len(n)
|
||||||
|
n = int(n)
|
||||||
|
except ValueError:
|
||||||
|
continue
|
||||||
|
|
||||||
|
# calculate phi of n
|
||||||
|
phi = totient(n)
|
||||||
|
# determine if n is prime
|
||||||
|
prime = n - 1 == phi
|
||||||
|
if prime:
|
||||||
|
uprint('', moveup=1, end='', flush=False)
|
||||||
|
column = len(PROMPT) + strlen_n + 1
|
||||||
|
sys.stdout.write(f'\033[{column}C')
|
||||||
|
uprint('[PRIME]', color=Color.Magenta, style=Color.Bold, flush=True)
|
||||||
|
# primitive root values
|
||||||
|
proot_v = []
|
||||||
|
# primitive root count
|
||||||
|
proot_c = 0
|
||||||
|
# cumulative sum of primitive root orbits
|
||||||
|
prorb_cum = []
|
||||||
|
|
||||||
|
# find all invertible elements (skipped for now)
|
||||||
|
for a in range(n):
|
||||||
|
orb, ord = orbit(a, n)
|
||||||
|
# check if `a` is a primitive root
|
||||||
|
proot = (ord + 1 == n)
|
||||||
|
proot_c += proot
|
||||||
|
|
||||||
|
if proot:
|
||||||
|
proot_v.append(a)
|
||||||
|
if not prorb_cum:
|
||||||
|
prorb_cum = orb
|
||||||
|
else:
|
||||||
|
orb_cum(prorb_cum, orb)
|
||||||
|
print(a)
|
||||||
|
uprint('Cum Orb: ', end='', color=Color.Cyan)
|
||||||
|
uprint(f'{prorb_cum}', flush=True)
|
||||||
|
prorb_cum_mod = [x % n for x in prorb_cum]
|
||||||
|
uprint(f' {prorb_cum_mod}', flush=True)
|
||||||
|
|
||||||
|
uprint('Roots: ', end='', color=Color.Cyan)
|
||||||
|
uprint(proot_v, flush=True)
|
||||||
|
root_delta = [proot_v[i+1] - proot_v[i] for i in range(proot_c - 1)]
|
||||||
|
uprint('Delta: ', end='', color=Color.Cyan)
|
||||||
|
uprint(root_delta, flush=True)
|
||||||
|
|
||||||
|
uprint('Roots/Phi: ', end='', color=Color.Cyan)
|
||||||
|
uprint(f'{proot_c}/{phi}\n', flush=True)
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
try:
|
||||||
|
main()
|
||||||
|
except (KeyboardInterrupt, EOFError):
|
||||||
|
pass
|
||||||
|
|
@ -1,11 +1,20 @@
|
||||||
# Modulo Test
|
#!/usr/bin/env python3
|
||||||
from prbraid.math import *
|
|
||||||
from prbraid.color import *
|
|
||||||
|
|
||||||
import sys
|
import sys
|
||||||
|
import readline
|
||||||
|
|
||||||
|
from noether.math import *
|
||||||
|
from noether.cli import *
|
||||||
|
|
||||||
|
|
||||||
PROMPT = '[n]: '
|
PROMPT = '[n]: '
|
||||||
|
|
||||||
|
'''
|
||||||
|
Pairwise orbit cumulative summation (cum orb)
|
||||||
|
'''
|
||||||
|
def orb_cum(cum, orb):
|
||||||
|
for i in range(len(cum)):
|
||||||
|
cum[i] += orb[i]
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
while True:
|
while True:
|
||||||
n = None
|
n = None
|
||||||
|
|
@ -22,13 +31,17 @@ def main():
|
||||||
phi = totient(n)
|
phi = totient(n)
|
||||||
# determine if n is prime
|
# determine if n is prime
|
||||||
prime = n - 1 == phi
|
prime = n - 1 == phi
|
||||||
# sys.stdout.write('\x1b[1A')
|
|
||||||
# sys.stdout.flush()
|
|
||||||
if prime:
|
if prime:
|
||||||
uprint('', moveup=1, end='', flush=False)
|
uprint('', moveup=1, end='', flush=False)
|
||||||
column = len(PROMPT) + strlen_n + 1
|
column = len(PROMPT) + strlen_n + 1
|
||||||
sys.stdout.write(f'\033[{column}C')
|
sys.stdout.write(f'\033[{column}C')
|
||||||
uprint('[PRIME]', color=Color.Magenta, style=Color.Bold, flush=True)
|
uprint('[PRIME]', color=Color.Magenta, style=Color.Bold, flush=True)
|
||||||
|
# primitive root values
|
||||||
|
proot_v = []
|
||||||
|
# primitive root count
|
||||||
|
proot_c = 0
|
||||||
|
# cumulative sum of primitive root orbits
|
||||||
|
prorb_cum = []
|
||||||
|
|
||||||
# calculate left padding to align i values
|
# calculate left padding to align i values
|
||||||
# lpadded = strlen_n
|
# lpadded = strlen_n
|
||||||
|
|
@ -37,11 +50,11 @@ def main():
|
||||||
|
|
||||||
# find all invertible elements (skipped for now)
|
# find all invertible elements (skipped for now)
|
||||||
for a in range(n):
|
for a in range(n):
|
||||||
orb = orbit(a, n)
|
orb, ord = orbit(a, n)
|
||||||
ord = len(orb)
|
|
||||||
|
|
||||||
# check if `a` is a primitive root
|
# check if `a` is a primitive root
|
||||||
proot = (ord + 1 == n)
|
proot = (ord + 1 == n)
|
||||||
|
proot_c += proot
|
||||||
|
|
||||||
# calculate padding
|
# calculate padding
|
||||||
lpad = ' ' * (strlen_n - len(str(a)))
|
lpad = ' ' * (strlen_n - len(str(a)))
|
||||||
|
|
@ -51,20 +64,39 @@ def main():
|
||||||
color_ord = None
|
color_ord = None
|
||||||
color_orb = None
|
color_orb = None
|
||||||
style_ord = None
|
style_ord = None
|
||||||
style_orb = None
|
style_orb = None
|
||||||
if proot:
|
if proot:
|
||||||
color_a = Color.Green
|
color_a = Color.Green
|
||||||
color_ord = Color.Yellow
|
color_ord = Color.Yellow
|
||||||
color_orb = Color.Green
|
color_orb = Color.Green
|
||||||
style_ord = Color.Bold
|
style_ord = Color.Bold
|
||||||
style_orb = Color.Bold
|
style_orb = Color.Bold
|
||||||
|
proot_v.append(a)
|
||||||
|
if not prorb_cum:
|
||||||
|
prorb_cum = orb
|
||||||
|
else:
|
||||||
|
orb_cum(prorb_cum, orb)
|
||||||
|
elif gcd(a, n) == 1:
|
||||||
|
color_a = Color.Yellow
|
||||||
|
|
||||||
uprint(f'{lpad}{a}', color=color_a, style=Color.Bold, end=' ', flush=False)
|
uprint(f'{lpad}{a}', color=color_a, style=Color.Bold, end=' ', flush=False)
|
||||||
uprint(f'->', end=' ', flush=False)
|
uprint('->', end=' ', flush=False)
|
||||||
uprint(f'{ord}{rpad}', color=color_ord, style=style_ord, end=' ', flush=False)
|
uprint(f'{ord}{rpad}', color=color_ord, style=style_ord, end=' ', flush=False)
|
||||||
uprint(f'|', end=' ', flush=False)
|
uprint('|', end=' ', flush=False)
|
||||||
uprint(f'{orb}', color=color_orb, style=style_orb, flush=True)
|
uprint(f'{orb}', color=color_orb, style=style_orb, flush=True)
|
||||||
print() # empty new line
|
uprint('Cum Orb: ', end='', color=Color.Cyan)
|
||||||
|
uprint(f'{prorb_cum}', flush=True)
|
||||||
|
prorb_cum_mod = [x % n for x in prorb_cum]
|
||||||
|
uprint(f' {prorb_cum_mod}', flush=True)
|
||||||
|
|
||||||
|
uprint('Roots: ', end='', color=Color.Cyan)
|
||||||
|
uprint(proot_v, flush=True)
|
||||||
|
root_delta = [proot_v[i+1] - proot_v[i] for i in range(proot_c - 1)]
|
||||||
|
uprint('Delta: ', end='', color=Color.Cyan)
|
||||||
|
uprint(root_delta, flush=True)
|
||||||
|
|
||||||
|
uprint('Roots/Phi: ', end='', color=Color.Cyan)
|
||||||
|
uprint(f'{proot_c}/{phi}\n', flush=True)
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
try:
|
try:
|
||||||
172
py/noether/ansi.py
Normal file
172
py/noether/ansi.py
Normal file
|
|
@ -0,0 +1,172 @@
|
||||||
|
'''
|
||||||
|
=== ANSI Escape Sequences ===
|
||||||
|
This file exists to organise and name
|
||||||
|
all important ANSI escape sequences
|
||||||
|
for management of the CLI.
|
||||||
|
'''
|
||||||
|
|
||||||
|
from sys import stdout
|
||||||
|
from enum import StrEnum
|
||||||
|
|
||||||
|
RESET = '\x1b[0m'
|
||||||
|
|
||||||
|
class Color(StrEnum):
|
||||||
|
BLACK = '\x1b[30m'
|
||||||
|
RED = '\x1b[31m'
|
||||||
|
GREEN = '\x1b[32m'
|
||||||
|
YELLOW = '\x1b[33m'
|
||||||
|
BLUE = '\x1b[34m'
|
||||||
|
MAGENTA = '\x1b[35m'
|
||||||
|
CYAN = '\x1b[36m'
|
||||||
|
WHITE = '\x1b[37m'
|
||||||
|
|
||||||
|
class Style(StrEnum):
|
||||||
|
BOLD = '\x1b[1m'
|
||||||
|
DIM = '\x1b[2m'
|
||||||
|
ITALICS = '\x1b[3m'
|
||||||
|
UNDERLINE = '\x1b[4m'
|
||||||
|
BLINK = '\x1b[5m'
|
||||||
|
REVERSE = '\x1b[7m'
|
||||||
|
HIDE = '\x1b[8m'
|
||||||
|
|
||||||
|
_DISABLE = [
|
||||||
|
'\x1b[21m', # BOLD
|
||||||
|
'\x1b[22m', # DIM
|
||||||
|
'\x1b[24m', # UNDERLINE
|
||||||
|
'\x1b[25m', # BLINK
|
||||||
|
'\x1b[27m', # REVERSE
|
||||||
|
'\x1b[28m' # HIDE
|
||||||
|
]
|
||||||
|
|
||||||
|
'''
|
||||||
|
Implements cursor movement functionality.
|
||||||
|
NOTE:
|
||||||
|
The Cursor class currently has no ability
|
||||||
|
to handle EXACT line (row) numbers. Currently
|
||||||
|
I'm assuming all functionality of noether can
|
||||||
|
be implemented solely via relative movements.
|
||||||
|
'''
|
||||||
|
class Cursor(StrEnum):
|
||||||
|
# SAVE current / RESTORE last saved cursor position
|
||||||
|
SAVE = f'\x1b[7'
|
||||||
|
RESTORE = f'\x1b[8'
|
||||||
|
|
||||||
|
_MV_UP = 'A'
|
||||||
|
_MV_DOWN = 'B'
|
||||||
|
_MV_LEFT = 'C'
|
||||||
|
_MV_RIGHT = 'D'
|
||||||
|
# NEXT/PREV are the same as DOWN/UP (respectively)
|
||||||
|
# except that the cursor will reset to column 0
|
||||||
|
_MV_NEXT = 'E'
|
||||||
|
_MV_PREV = 'F'
|
||||||
|
# move cursor to the start of the current line
|
||||||
|
_MV_START = '\r' # there is no ESC CSI for carriage return
|
||||||
|
|
||||||
|
_MV_COLUMN = 'G'
|
||||||
|
|
||||||
|
'''
|
||||||
|
Generates an ESC code sequence corresponding
|
||||||
|
to a horizontal movement relative to the
|
||||||
|
cursor's current vertical position.
|
||||||
|
+ive = right
|
||||||
|
-ive = left
|
||||||
|
'''
|
||||||
|
@staticmethod
|
||||||
|
def _XMOVE_REL(n: int) -> str:
|
||||||
|
if n > 0:
|
||||||
|
return f'\x1b[{n}{Cursor._MV_RIGHT}'
|
||||||
|
if n < 0:
|
||||||
|
return f'\x1b[{n}{Cursor._MV_LEFT}'
|
||||||
|
return ''
|
||||||
|
|
||||||
|
'''
|
||||||
|
Generates an ESC code sequence corresponding
|
||||||
|
to a horizontal movement to an EXACT column.
|
||||||
|
'''
|
||||||
|
@staticmethod
|
||||||
|
def _XMOVE(n: int) -> str:
|
||||||
|
return f'\x1b[{n}{Cursor._MV_COLUMN}'
|
||||||
|
|
||||||
|
'''
|
||||||
|
Generates an ESC code sequence corresponding
|
||||||
|
to a vertical movement relative to the
|
||||||
|
cursor's current vertical position.
|
||||||
|
+ive = down
|
||||||
|
-ive = up
|
||||||
|
'''
|
||||||
|
@staticmethod
|
||||||
|
def _YMOVE_REL(n: int, reset: bool = False) -> str:
|
||||||
|
if n > 0:
|
||||||
|
if reset:
|
||||||
|
return f'\x1b[{n}{Cursor._MV_NEXT}'
|
||||||
|
return f'\x1b[{n}{Cursor._MV_DOWN}'
|
||||||
|
if n < 0:
|
||||||
|
if reset:
|
||||||
|
return f'\x1b[{n}{Cursor._MV_PREV}'
|
||||||
|
return f'\x1b[{n}{Cursor._MV_UP}'
|
||||||
|
return ''
|
||||||
|
|
||||||
|
'''
|
||||||
|
Sets the cursor column (horizontal) position to an exact value.
|
||||||
|
NOTE: does NOT flush stdout buffer
|
||||||
|
'''
|
||||||
|
@staticmethod
|
||||||
|
def set_x(n: int) -> None:
|
||||||
|
stdout.write(Cursor.XMOVE(n))
|
||||||
|
|
||||||
|
'''
|
||||||
|
Moves the cursor left/right n columns (relative).
|
||||||
|
NOTE: does NOT flush stdout buffer
|
||||||
|
'''
|
||||||
|
@staticmethod
|
||||||
|
def move_x(n: int) -> None:
|
||||||
|
stdout.write(Cursor._XMOVE_REL(n))
|
||||||
|
|
||||||
|
'''
|
||||||
|
Moves the cursor up/down n rows and resets the
|
||||||
|
cursor to be at the start of the line
|
||||||
|
NOTE: does NOT flush stdout buffer
|
||||||
|
'''
|
||||||
|
@staticmethod
|
||||||
|
def move_y(n: int, reset: bool = True) -> None:
|
||||||
|
stdout.write(Cursor._YMOVE_REL(n, reset=reset))
|
||||||
|
|
||||||
|
'''
|
||||||
|
Saves the current cursor position.
|
||||||
|
NOTE: does NOT flush stdout buffer
|
||||||
|
'''
|
||||||
|
@staticmethod
|
||||||
|
def save() -> None:
|
||||||
|
stdout.write(Cursor.SAVE)
|
||||||
|
|
||||||
|
'''
|
||||||
|
Restores the cursor position to a saved position.
|
||||||
|
NOTE: does NOT flush stdout buffer
|
||||||
|
'''
|
||||||
|
@staticmethod
|
||||||
|
def restore() -> None:
|
||||||
|
stdout.write(Cursor.RESTORE)
|
||||||
|
|
||||||
|
'''
|
||||||
|
Handles erasing content displayed on the screen.
|
||||||
|
NOTE that the cursor position is NOT updated
|
||||||
|
via these sequences. The \r code should be given after.
|
||||||
|
'''
|
||||||
|
class Erase(StrEnum):
|
||||||
|
# erase everything from the current cursor
|
||||||
|
# position to the START/END of the screen
|
||||||
|
ER_SCR_END = '\x1b[0J'
|
||||||
|
ER_SCR_START = '\x1b[1J'
|
||||||
|
# ER_SCR_ALL = '\x1b[2J'
|
||||||
|
ER_SCR_ALL = '\x1b[3J' # erase screen and delete all saved cursors
|
||||||
|
|
||||||
|
# ER_SAVED = '\x1b[3J' # erase saved lines
|
||||||
|
|
||||||
|
# erase everything from the current cursor
|
||||||
|
# position to the START/END of the current line
|
||||||
|
ER_LINE_END = '\x1b[0K'
|
||||||
|
ER_LINE_START = '\x1b[1K'
|
||||||
|
ER_LINE_ALL = '\x1b[2K'
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
# TODO COME BACK HERE
|
||||||
0
py/noether/lib/__init__.py
Normal file
0
py/noether/lib/__init__.py
Normal file
42
py/noether/math.py
Normal file
42
py/noether/math.py
Normal file
|
|
@ -0,0 +1,42 @@
|
||||||
|
from math import gcd
|
||||||
|
|
||||||
|
# Euler's Totient (Phi) Function
|
||||||
|
def totient(n):
|
||||||
|
phi = int(n > 1 and n)
|
||||||
|
for p in range(2, int(n ** .5) + 1):
|
||||||
|
if not n % p:
|
||||||
|
phi -= phi // p
|
||||||
|
while not n % p:
|
||||||
|
n //= p
|
||||||
|
#if n is > 1 it means it is prime
|
||||||
|
if n > 1: phi -= phi // n
|
||||||
|
return phi
|
||||||
|
|
||||||
|
def is_prime(n):
|
||||||
|
return n - 1 == totient(n)
|
||||||
|
|
||||||
|
def orbit(b, m):
|
||||||
|
orb = []
|
||||||
|
ord = 0
|
||||||
|
x = 1 # start at identity
|
||||||
|
for i in range(m):
|
||||||
|
x = (x * b) % m
|
||||||
|
if x in orb:
|
||||||
|
break
|
||||||
|
orb.append(x)
|
||||||
|
ord += 1
|
||||||
|
return orb, ord
|
||||||
|
|
||||||
|
def order(b, m):
|
||||||
|
return len(orbit(b, m))
|
||||||
|
|
||||||
|
|
||||||
|
'''
|
||||||
|
Functions for Testing my Conjectures
|
||||||
|
|
||||||
|
The conjecture is specifically that, for all positive integers n
|
||||||
|
where n + 1 is prime, then conj_phigcd(n) is also prime.
|
||||||
|
'''
|
||||||
|
def conj_phigcd(n):
|
||||||
|
phi = totient(n)
|
||||||
|
return phi / gcd(n, phi) - 1
|
||||||
80
py/primes.py
Normal file
80
py/primes.py
Normal file
|
|
@ -0,0 +1,80 @@
|
||||||
|
# Modulo Test
|
||||||
|
from prbraid.math import *
|
||||||
|
from prbraid.color import *
|
||||||
|
|
||||||
|
import sys
|
||||||
|
from math import gcd
|
||||||
|
from time import sleep
|
||||||
|
|
||||||
|
PROMPT = '[n]: '
|
||||||
|
|
||||||
|
'''
|
||||||
|
Modify the body of this function, it will be run
|
||||||
|
against every prime number ascending.
|
||||||
|
'''
|
||||||
|
def test_function(p: int, phi: int):
|
||||||
|
p_color = Color.Green
|
||||||
|
result_color = Color.Yellow
|
||||||
|
|
||||||
|
result = phi / gcd(p, phi) - 1
|
||||||
|
if result < 0 or not is_prime(result):
|
||||||
|
p_color = Color.Red
|
||||||
|
result_color = Color.Red
|
||||||
|
uprint(p, color=p_color, style=Color.Bold, end=' -> ', flush=False)
|
||||||
|
uprint(result, color=result_color, flush=True)
|
||||||
|
sleep(0.1)
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
n = -1
|
||||||
|
while True:
|
||||||
|
n += 1
|
||||||
|
|
||||||
|
# calculate phi of n
|
||||||
|
phi = totient(n)
|
||||||
|
# determine if n is prime
|
||||||
|
prime = n - 1 == phi
|
||||||
|
if not prime:
|
||||||
|
continue
|
||||||
|
|
||||||
|
# # primitive root values
|
||||||
|
# proot_v = []
|
||||||
|
# # primitive root count
|
||||||
|
# proot_c = 0
|
||||||
|
# # cumulative sum of primitive root orbits
|
||||||
|
# prorb_cum = []
|
||||||
|
|
||||||
|
# # find all invertible elements (skipped for now)
|
||||||
|
# for a in range(n):
|
||||||
|
# orb, ord = orbit(a, n)
|
||||||
|
# # check if `a` is a primitive root
|
||||||
|
# proot = (ord + 1 == n)
|
||||||
|
# proot_c += proot
|
||||||
|
|
||||||
|
# if proot:
|
||||||
|
# proot_v.append(a)
|
||||||
|
# if not prorb_cum:
|
||||||
|
# prorb_cum = orb
|
||||||
|
# else:
|
||||||
|
# orb_cum(prorb_cum, orb)
|
||||||
|
# print(a)
|
||||||
|
# uprint('Cum Orb: ', end='', color=Color.Cyan)
|
||||||
|
# uprint(f'{prorb_cum}', flush=True)
|
||||||
|
# prorb_cum_mod = [x % n for x in prorb_cum]
|
||||||
|
# uprint(f' {prorb_cum_mod}', flush=True)
|
||||||
|
|
||||||
|
# uprint('Roots: ', end='', color=Color.Cyan)
|
||||||
|
# uprint(proot_v, flush=True)
|
||||||
|
# root_delta = [proot_v[i+1] - proot_v[i] for i in range(proot_c - 1)]
|
||||||
|
# uprint('Delta: ', end='', color=Color.Cyan)
|
||||||
|
# uprint(root_delta, flush=True)
|
||||||
|
|
||||||
|
# uprint('Roots/Phi: ', end='', color=Color.Cyan)
|
||||||
|
# uprint(f'{proot_c}/{phi}\n', flush=True)
|
||||||
|
test_function(n, phi)
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
try:
|
||||||
|
main()
|
||||||
|
except (KeyboardInterrupt, EOFError):
|
||||||
|
pass
|
||||||
Loading…
Add table
Add a link
Reference in a new issue