

'''simple docstring'''

from __future__ import annotations

import numpy as np
from numpy import floataa
from numpy.typing import NDArray




def 				UpperCamelCase(					UpperCAmelCase_  ,	UpperCAmelCase_  ,	UpperCAmelCase_  ,	UpperCAmelCase_  ,	):
 UpperCAmelCase ,			UpperCAmelCase	:     List[str]						 =			coefficient_matrix.shape
 UpperCAmelCase ,			UpperCAmelCase	:     Optional[int]						 =			constant_matrix.shape

 if rowsa != colsa:
  UpperCAmelCase	:     int						 =			F"""Coefficient matrix dimensions must be nxn but received {rowsa}x{colsa}"""
  raise ValueError(UpperCAmelCase_     )

 if colsa != 1:
  UpperCAmelCase	:     Any						 =			F"""Constant matrix must be nx1 but received {rowsa}x{colsa}"""
  raise ValueError(UpperCAmelCase_     )

 if rowsa != rowsa:
  UpperCAmelCase	:     Optional[int]						 =			(
      'Coefficient and constant matrices dimensions must be nxn and nx1 but '
      F"""received {rowsa}x{colsa} and {rowsa}x{colsa}"""
  )
  raise ValueError(UpperCAmelCase_     )

 if len(UpperCAmelCase_     ) != rowsa:
  UpperCAmelCase	:     Union[str, Any]						 =			(
      'Number of initial values must be equal to number of rows in coefficient '
      F"""matrix but received {len(UpperCAmelCase_     )} and {rowsa}"""
  )
  raise ValueError(UpperCAmelCase_     )

 if iterations <= 0:
  raise ValueError('Iterations must be at least 1'     )

 UpperCAmelCase	:     NDArray[floataa]						 =			np.concatenate(
     (coefficient_matrix, constant_matrix)  ,	axis=1     )

 UpperCAmelCase ,			UpperCAmelCase	:     Dict						 =			table.shape

 strictly_diagonally_dominant(UpperCAmelCase_     )

 # Iterates the whole matrix for given number of times
 for _ in range(UpperCAmelCase_     ):
  UpperCAmelCase	:     Optional[int]						 =			[]
  for row in range(UpperCAmelCase_     ):
   UpperCAmelCase	:     Tuple						 =			0
   for col in range(UpperCAmelCase_     ):
    if col == row:
     UpperCAmelCase	:     int						 =			table[row][col]
    elif col == cols - 1:
     UpperCAmelCase	:     Any						 =			table[row][col]
    else:
     temp += (-1) * table[row][col] * init_val[col]
   UpperCAmelCase	:     Optional[Any]						 =			(temp + val) / denom
   new_val.append(UpperCAmelCase_     )
  UpperCAmelCase	:     Optional[int]						 =			new_val

 return [float(UpperCAmelCase_     ) for i in new_val]




def 				UpperCamelCase(					UpperCAmelCase_     ):
 UpperCAmelCase ,			UpperCAmelCase	:     List[Any]						 =			table.shape

 UpperCAmelCase	:     int						 =			True

 for i in range(0  ,	UpperCAmelCase_     ):
  UpperCAmelCase	:     List[Any]						 =			0
  for j in range(0  ,	cols - 1     ):
   if i == j:
    continue
   else:
    total += table[i][j]

  if table[i][i] <= total:
   raise ValueError('Coefficient matrix is not strictly diagonally dominant'     )

 return is_diagonally_dominant


# Test Cases
if __name__ == "__main__":
 import doctest

 doctest.testmod()







'''simple docstring'''

import os
import random
import sys

from . import cryptomath_module as cryptomath
from . import rabin_miller

lowercase__         =      3




def 				UpperCamelCase(					UpperCAmelCase_     ):
 print('Generating primitive root of p'     )
 while True:
  UpperCAmelCase	:     Union[str, Any]						 =			random.randrange(3  ,	UpperCAmelCase_     )
  if pow(UpperCAmelCase_  ,	2  ,	UpperCAmelCase_     ) == 1:
   continue
  if pow(UpperCAmelCase_  ,	UpperCAmelCase_  ,	UpperCAmelCase_     ) == 1:
   continue
  return g




def 				UpperCamelCase(					UpperCAmelCase_     ):
 print('Generating prime p...'     )
 UpperCAmelCase	:     str						 =			rabin_miller.generate_large_prime(UpperCAmelCase_     )  # select large prime number.
 UpperCAmelCase	:     List[str]						 =			primitive_root(UpperCAmelCase_     )  # one primitive root on modulo p.
 UpperCAmelCase	:     List[Any]						 =			random.randrange(3  ,	UpperCAmelCase_     )  # private_key -> have to be greater than 2 for safety.
 UpperCAmelCase	:     List[Any]						 =			cryptomath.find_mod_inverse(pow(UpperCAmelCase_  ,	UpperCAmelCase_  ,	UpperCAmelCase_     )  ,	UpperCAmelCase_     )

 UpperCAmelCase	:     Tuple						 =			(key_size, e_a, e_a, p)
 UpperCAmelCase	:     Optional[int]						 =			(key_size, d)

 return public_key, private_key




def 				UpperCamelCase(					UpperCAmelCase_  ,	UpperCAmelCase_     ):
 if os.path.exists(F"""{name}_pubkey.txt"""     ) or os.path.exists(F"""{name}_privkey.txt"""     ):
  print('\nWARNING:'     )
  print(
      F"""\"{name}_pubkey.txt\" or \"{name}_privkey.txt\" already exists. \n"""
      'Use a different name or delete these files and re-run this program.'     )
  sys.exit()

 UpperCAmelCase ,			UpperCAmelCase	:     Dict						 =			generate_key(UpperCAmelCase_     )
 print(F"""\nWriting public key to file {name}_pubkey.txt..."""     )
 with open(F"""{name}_pubkey.txt"""  ,	'w'     ) as fo:
  fo.write(F"""{public_key[0]},{public_key[1]},{public_key[2]},{public_key[3]}"""     )

 print(F"""Writing private key to file {name}_privkey.txt..."""     )
 with open(F"""{name}_privkey.txt"""  ,	'w'     ) as fo:
  fo.write(F"""{private_key[0]},{private_key[1]}"""     )




def 				UpperCamelCase(					):
 print('Making key files...'     )
 make_key_files('elgamal'  ,	20_48     )
 print('Key files generation successful'     )


if __name__ == "__main__":
 main()




