
import argparse
import gc
import json
import os

import torch
from datasets import load_dataset
from torch.optim import AdamW
from torch.utils.data import DataLoader
from transformers import AutoModelForSequenceClassification, AutoTokenizer, get_linear_schedule_with_warmup, set_seed

from accelerate import Accelerator, DistributedType
from accelerate.utils.deepspeed import DummyOptim, DummyScheduler


_lowerCamelCase			:							int         =     16
_lowerCamelCase			:							List[Any]         =     32






def 			a_						(			__lowercase  :      Optional[Any]					)					->    str:
			return int(x / 2**20					)




class   SCREAMING_SNAKE_CASE__	:





	'''simple docstring'''



	def __enter__(    self      :       List[Any]      ):


				'''simple docstring'''


				gc.collect()
				torch.cuda.empty_cache()
				torch.cuda.reset_max_memory_allocated()  # reset the peak gauge to zero
				_snake_case            =     torch.cuda.memory_allocated()
				return self





	def __exit__(    self      :       List[str]     ,    *lowercase      :       str      ):


				'''simple docstring'''


				gc.collect()
				torch.cuda.empty_cache()
				_snake_case            =     torch.cuda.memory_allocated()
				_snake_case            =     torch.cuda.max_memory_allocated()
				_snake_case            =     bamb(self.end - self.begin      )
				_snake_case            =     bamb(self.peak - self.begin      )
				# print(f"delta used/peak {self.used:4d}/{self.peaked:4d}")






def 			a_						(			__lowercase  :      str			,   __lowercase  :      List[Any] = 16			,   __lowercase  :      Union[str, Any] = "bert-base-cased"			,   __lowercase  :      List[str] = 320			,   __lowercase  :      int = 160			,   )					->    str:
			_snake_case            =     AutoTokenizer.from_pretrained(lowercase__					)
			_snake_case            =     load_dataset(
			    'glue'			,   'mrpc'			,   split={'train': f'''train[:{n_train}]''', 'validation': f'''validation[:{n_val}]'''}					)

			def tokenize_function(__lowercase  :      Union[str, Any]					):
						# max_length=None => use the model max length (it's actually the default)
						_snake_case            =     tokenizer(examples['sentence1']			,   examples['sentence2']			,   truncation=lowercase__			,   max_length=lowercase__					)
						return outputs

			# Apply the method we just defined to all the examples in all the splits of the dataset
			_snake_case            =     datasets.map(
			    lowercase__			,   batched=lowercase__			,   remove_columns=['idx', 'sentence1', 'sentence2']			,   load_from_cache_file=lowercase__					)

			# We also rename the 'label' column to 'labels' which is the expected name for labels by the models of the
			# transformers library
			_snake_case            =     tokenized_datasets.rename_column('label'			,   'labels'					)

			def collate_fn(__lowercase  :      int					):
						# On TPU it's best to pad everything to the same length or training will be very slow.
						if accelerator.distributed_type == DistributedType.TPU:
									return tokenizer.pad(lowercase__			,   padding='max_length'			,   max_length=128			,   return_tensors='pt'					)
						return tokenizer.pad(lowercase__			,   padding='longest'			,   return_tensors='pt'					)

			# Instantiate dataloaders.
			_snake_case            =     DataLoader(
			    tokenized_datasets['train']			,   shuffle=lowercase__			,   collate_fn=lowercase__			,   batch_size=lowercase__					)
			_snake_case            =     DataLoader(
			    tokenized_datasets['validation']			,   shuffle=lowercase__			,   collate_fn=lowercase__			,   batch_size=lowercase__					)

			return train_dataloader, eval_dataloader






def 			a_						(			__lowercase  :      Dict			,   __lowercase  :      List[str]					)					->    Dict:
			# Initialize accelerator
			_snake_case            =     Accelerator()

			# Sample hyper-parameters for learning rate, batch size, seed and a few other HPs
			_snake_case            =     config["lr"]
			_snake_case            =     int(config['num_epochs']					)
			_snake_case            =     int(config['seed']					)
			_snake_case            =     int(config['batch_size']					)
			_snake_case            =     args.model_name_or_path

			set_seed(lowercase__					)
			_snake_case            =     get_dataloaders(lowercase__			,   lowercase__			,   lowercase__			,   args.n_train			,   args.n_val					)

			# Instantiate the model (we build the model here so that the seed also control new weights initialization)
			_snake_case            =     AutoModelForSequenceClassification.from_pretrained(lowercase__			,   return_dict=lowercase__					)

			# Instantiate optimizer
			_snake_case            =     (
			    AdamW
			    if accelerator.state.deepspeed_plugin is None
			    or "optimizer" not in accelerator.state.deepspeed_plugin.deepspeed_config
			    else DummyOptim
			)
			_snake_case            =     optimizer_cls(params=model.parameters()			,   lr=lowercase__					)

			if accelerator.state.deepspeed_plugin is not None:
						_snake_case            =     accelerator.state.deepspeed_plugin.deepspeed_config[
						    "gradient_accumulation_steps"
						]
			else:
						_snake_case            =     1
			_snake_case            =     (len(lowercase__					) * num_epochs) // gradient_accumulation_steps

			# Instantiate scheduler
			if (
			    accelerator.state.deepspeed_plugin is None
			    or "scheduler" not in accelerator.state.deepspeed_plugin.deepspeed_config
			):
						_snake_case            =     get_linear_schedule_with_warmup(
						    optimizer=lowercase__			,   num_warmup_steps=0			,   num_training_steps=lowercase__			,   )
			else:
						_snake_case            =     DummyScheduler(lowercase__			,   total_num_steps=lowercase__			,   warmup_num_steps=0					)

			# Prepare everything
			# There is no specific order to remember, we just need to unpack the objects in the same order we gave them to the
			# prepare method.
			_snake_case            =     accelerator.prepare(
			    lowercase__			,   lowercase__			,   lowercase__			,   lowercase__			,   lowercase__					)

			# We need to keep track of how many total steps we have iterated over
			_snake_case            =     0
			# We also need to keep track of the stating epoch so files are named properly
			_snake_case            =     0

			# Now we train the model
			_snake_case            =     {}
			for epoch in range(lowercase__			,   lowercase__					):
						with TorchTracemalloc() as tracemalloc:
									model.train()
									for step, batch in enumerate(lowercase__					):
												_snake_case            =     model(**lowercase__					)
												_snake_case            =     outputs.loss
												_snake_case            =     loss / gradient_accumulation_steps
												accelerator.backward(lowercase__					)
												if step % gradient_accumulation_steps == 0:
															optimizer.step()
															lr_scheduler.step()
															optimizer.zero_grad()

												overall_step += 1

												    # Printing the GPU memory usage details such as allocated memory, peak memory, and total memory usage
						accelerator.print('Memory before entering the train : {}'.format(bamb(tracemalloc.begin					)					)					)
						accelerator.print('Memory consumed at the end of the train (end-begin): {}'.format(tracemalloc.used					)					)
						accelerator.print('Peak Memory consumed during the train (max-begin): {}'.format(tracemalloc.peaked					)					)
						accelerator.print(
						    'Total Peak Memory consumed during the train (max): {}'.format(
						        tracemalloc.peaked + bamb(tracemalloc.begin					)					)					)
						_snake_case            =     tracemalloc.peaked + bamb(tracemalloc.begin					)
						if args.peak_memory_upper_bound is not None:
									assert (
									    train_total_peak_memory[f'''epoch-{epoch}'''] <= args.peak_memory_upper_bound
									), "Peak memory usage exceeded the upper bound"

			accelerator.wait_for_everyone()
			if accelerator.is_main_process:
						with open(os.path.join(args.output_dir			,   'peak_memory_utilization.json'					)			,   'w'					) as f:
									json.dump(lowercase__			,   lowercase__					)






def 			a_						(			)					->    Optional[Any]:
			_snake_case            =     argparse.ArgumentParser(description='Simple example of training script tracking peak GPU memory usage.'					)
			parser.add_argument(
			    '--model_name_or_path'			,   type=lowercase__			,   default='bert-base-cased'			,   help='Path to pretrained model or model identifier from huggingface.co/models.'			,   required=lowercase__			,   )
			parser.add_argument(
			    '--output_dir'			,   type=lowercase__			,   default='.'			,   help='Optional save directory where all checkpoint folders will be stored. Default is the current working directory.'			,   )
			parser.add_argument(
			    '--peak_memory_upper_bound'			,   type=lowercase__			,   default=lowercase__			,   help='The upper bound of peak memory usage in MB. If set, the training will throw an error if the peak memory usage exceeds this value.'			,   )
			parser.add_argument(
			    '--n_train'			,   type=lowercase__			,   default=320			,   help='Number of training examples to use.'			,   )
			parser.add_argument(
			    '--n_val'			,   type=lowercase__			,   default=160			,   help='Number of validation examples to use.'			,   )
			parser.add_argument(
			    '--num_epochs'			,   type=lowercase__			,   default=1			,   help='Number of train epochs.'			,   )
			_snake_case            =     parser.parse_args()
			_snake_case            =     {"lr": 2E-5, "num_epochs": args.num_epochs, "seed": 42, "batch_size": 16}
			training_function(lowercase__			,   lowercase__					)


if __name__ == "__main__":
			main()


"""simple docstring"""

from binascii import hexlify
from hashlib import shaaaa
from os import urandom

# RFC 3526 - More Modular Exponential (MODP) Diffie-Hellman groups for
# Internet Key Exchange (IKE) https://tools.ietf.org/html/rfc3526

_UpperCamelCase		     =    {
    # 1536-bit
    5: {
        """prime""": int(
            """FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1"""
            + """29024E088A67CC74020BBEA63B139B22514A08798E3404DD"""
            + """EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245"""
            + """E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED"""
            + """EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3D"""
            + """C2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F"""
            + """83655D23DCA3AD961C62F356208552BB9ED529077096966D"""
            + """670C354E4ABC9804F1746C08CA237327FFFFFFFFFFFFFFFF""",
            base=1_6,
        ),
        """generator""": 2,
    },
    # 2048-bit
    1_4: {
        """prime""": int(
            """FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1"""
            + """29024E088A67CC74020BBEA63B139B22514A08798E3404DD"""
            + """EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245"""
            + """E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED"""
            + """EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3D"""
            + """C2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F"""
            + """83655D23DCA3AD961C62F356208552BB9ED529077096966D"""
            + """670C354E4ABC9804F1746C08CA18217C32905E462E36CE3B"""
            + """E39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9"""
            + """DE2BCBF6955817183995497CEA956AE515D2261898FA0510"""
            + """15728E5A8AACAA68FFFFFFFFFFFFFFFF""",
            base=1_6,
        ),
        """generator""": 2,
    },
    # 3072-bit
    1_5: {
        """prime""": int(
            """FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1"""
            + """29024E088A67CC74020BBEA63B139B22514A08798E3404DD"""
            + """EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245"""
            + """E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED"""
            + """EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3D"""
            + """C2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F"""
            + """83655D23DCA3AD961C62F356208552BB9ED529077096966D"""
            + """670C354E4ABC9804F1746C08CA18217C32905E462E36CE3B"""
            + """E39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9"""
            + """DE2BCBF6955817183995497CEA956AE515D2261898FA0510"""
            + """15728E5A8AAAC42DAD33170D04507A33A85521ABDF1CBA64"""
            + """ECFB850458DBEF0A8AEA71575D060C7DB3970F85A6E1E4C7"""
            + """ABF5AE8CDB0933D71E8C94E04A25619DCEE3D2261AD2EE6B"""
            + """F12FFA06D98A0864D87602733EC86A64521F2B18177B200C"""
            + """BBE117577A615D6C770988C0BAD946E208E24FA074E5AB31"""
            + """43DB5BFCE0FD108E4B82D120A93AD2CAFFFFFFFFFFFFFFFF""",
            base=1_6,
        ),
        """generator""": 2,
    },
    # 4096-bit
    1_6: {
        """prime""": int(
            """FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1"""
            + """29024E088A67CC74020BBEA63B139B22514A08798E3404DD"""
            + """EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245"""
            + """E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED"""
            + """EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3D"""
            + """C2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F"""
            + """83655D23DCA3AD961C62F356208552BB9ED529077096966D"""
            + """670C354E4ABC9804F1746C08CA18217C32905E462E36CE3B"""
            + """E39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9"""
            + """DE2BCBF6955817183995497CEA956AE515D2261898FA0510"""
            + """15728E5A8AAAC42DAD33170D04507A33A85521ABDF1CBA64"""
            + """ECFB850458DBEF0A8AEA71575D060C7DB3970F85A6E1E4C7"""
            + """ABF5AE8CDB0933D71E8C94E04A25619DCEE3D2261AD2EE6B"""
            + """F12FFA06D98A0864D87602733EC86A64521F2B18177B200C"""
            + """BBE117577A615D6C770988C0BAD946E208E24FA074E5AB31"""
            + """43DB5BFCE0FD108E4B82D120A92108011A723C12A787E6D7"""
            + """88719A10BDBA5B2699C327186AF4E23C1A946834B6150BDA"""
            + """2583E9CA2AD44CE8DBBBC2DB04DE8EF92E8EFC141FBECAA6"""
            + """287C59474E6BC05D99B2964FA090C3A2233BA186515BE7ED"""
            + """1F612970CEE2D7AFB81BDD762170481CD0069127D5B05AA9"""
            + """93B4EA988D8FDDC186FFB7DC90A6C08F4DF435C934063199"""
            + """FFFFFFFFFFFFFFFF""",
            base=1_6,
        ),
        """generator""": 2,
    },
    # 6144-bit
    1_7: {
        """prime""": int(
            """FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E08"""
            + """8A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B"""
            + """302B0A6DF25F14374FE1356D6D51C245E485B576625E7EC6F44C42E9"""
            + """A637ED6B0BFF5CB6F406B7EDEE386BFB5A899FA5AE9F24117C4B1FE6"""
            + """49286651ECE45B3DC2007CB8A163BF0598DA48361C55D39A69163FA8"""
            + """FD24CF5F83655D23DCA3AD961C62F356208552BB9ED529077096966D"""
            + """670C354E4ABC9804F1746C08CA18217C32905E462E36CE3BE39E772C"""
            + """180E86039B2783A2EC07A28FB5C55DF06F4C52C9DE2BCBF695581718"""
            + """3995497CEA956AE515D2261898FA051015728E5A8AAAC42DAD33170D"""
            + """04507A33A85521ABDF1CBA64ECFB850458DBEF0A8AEA71575D060C7D"""
            + """B3970F85A6E1E4C7ABF5AE8CDB0933D71E8C94E04A25619DCEE3D226"""
            + """1AD2EE6BF12FFA06D98A0864D87602733EC86A64521F2B18177B200C"""
            + """BBE117577A615D6C770988C0BAD946E208E24FA074E5AB3143DB5BFC"""
            + """E0FD108E4B82D120A92108011A723C12A787E6D788719A10BDBA5B26"""
            + """99C327186AF4E23C1A946834B6150BDA2583E9CA2AD44CE8DBBBC2DB"""
            + """04DE8EF92E8EFC141FBECAA6287C59474E6BC05D99B2964FA090C3A2"""
            + """233BA186515BE7ED1F612970CEE2D7AFB81BDD762170481CD0069127"""
            + """D5B05AA993B4EA988D8FDDC186FFB7DC90A6C08F4DF435C934028492"""
            + """36C3FAB4D27C7026C1D4DCB2602646DEC9751E763DBA37BDF8FF9406"""
            + """AD9E530EE5DB382F413001AEB06A53ED9027D831179727B0865A8918"""
            + """DA3EDBEBCF9B14ED44CE6CBACED4BB1BDB7F1447E6CC254B33205151"""
            + """2BD7AF426FB8F401378CD2BF5983CA01C64B92ECF032EA15D1721D03"""
            + """F482D7CE6E74FEF6D55E702F46980C82B5A84031900B1C9E59E7C97F"""
            + """BEC7E8F323A97A7E36CC88BE0F1D45B7FF585AC54BD407B22B4154AA"""
            + """CC8F6D7EBF48E1D814CC5ED20F8037E0A79715EEF29BE32806A1D58B"""
            + """B7C5DA76F550AA3D8A1FBFF0EB19CCB1A313D55CDA56C9EC2EF29632"""
            + """387FE8D76E3C0468043E8F663F4860EE12BF2D5B0B7474D6E694F91E"""
            + """6DCC4024FFFFFFFFFFFFFFFF""",
            base=1_6,
        ),
        """generator""": 2,
    },
    # 8192-bit
    1_8: {
        """prime""": int(
            """FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1"""
            + """29024E088A67CC74020BBEA63B139B22514A08798E3404DD"""
            + """EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245"""
            + """E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED"""
            + """EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3D"""
            + """C2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F"""
            + """83655D23DCA3AD961C62F356208552BB9ED529077096966D"""
            + """670C354E4ABC9804F1746C08CA18217C32905E462E36CE3B"""
            + """E39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9"""
            + """DE2BCBF6955817183995497CEA956AE515D2261898FA0510"""
            + """15728E5A8AAAC42DAD33170D04507A33A85521ABDF1CBA64"""
            + """ECFB850458DBEF0A8AEA71575D060C7DB3970F85A6E1E4C7"""
            + """ABF5AE8CDB0933D71E8C94E04A25619DCEE3D2261AD2EE6B"""
            + """F12FFA06D98A0864D87602733EC86A64521F2B18177B200C"""
            + """BBE117577A615D6C770988C0BAD946E208E24FA074E5AB31"""
            + """43DB5BFCE0FD108E4B82D120A92108011A723C12A787E6D7"""
            + """88719A10BDBA5B2699C327186AF4E23C1A946834B6150BDA"""
            + """2583E9CA2AD44CE8DBBBC2DB04DE8EF92E8EFC141FBECAA6"""
            + """287C59474E6BC05D99B2964FA090C3A2233BA186515BE7ED"""
            + """1F612970CEE2D7AFB81BDD762170481CD0069127D5B05AA9"""
            + """93B4EA988D8FDDC186FFB7DC90A6C08F4DF435C934028492"""
            + """36C3FAB4D27C7026C1D4DCB2602646DEC9751E763DBA37BD"""
            + """F8FF9406AD9E530EE5DB382F413001AEB06A53ED9027D831"""
            + """179727B0865A8918DA3EDBEBCF9B14ED44CE6CBACED4BB1B"""
            + """DB7F1447E6CC254B332051512BD7AF426FB8F401378CD2BF"""
            + """5983CA01C64B92ECF032EA15D1721D03F482D7CE6E74FEF6"""
            + """D55E702F46980C82B5A84031900B1C9E59E7C97FBEC7E8F3"""
            + """23A97A7E36CC88BE0F1D45B7FF585AC54BD407B22B4154AA"""
            + """CC8F6D7EBF48E1D814CC5ED20F8037E0A79715EEF29BE328"""
            + """06A1D58BB7C5DA76F550AA3D8A1FBFF0EB19CCB1A313D55C"""
            + """DA56C9EC2EF29632387FE8D76E3C0468043E8F663F4860EE"""
            + """12BF2D5B0B7474D6E694F91E6DBE115974A3926F12FEE5E4"""
            + """38777CB6A932DF8CD8BEC4D073B931BA3BC832B68D9DD300"""
            + """741FA7BF8AFC47ED2576F6936BA424663AAB639C5AE4F568"""
            + """3423B4742BF1C978238F16CBE39D652DE3FDB8BEFC848AD9"""
            + """22222E04A4037C0713EB57A81A23F0C73473FC646CEA306B"""
            + """4BCBC8862F8385DDFA9D4B7FA2C087E879683303ED5BDD3A"""
            + """062B3CF5B3A278A66D2A13F83F44F82DDF310EE074AB6A36"""
            + """4597E899A0255DC164F31CC50846851DF9AB48195DED7EA1"""
            + """B1D510BD7EE74D73FAF36BC31ECFA268359046F4EB879F92"""
            + """4009438B481C6CD7889A002ED5EE382BC9190DA6FC026E47"""
            + """9558E4475677E9AA9E3050E2765694DFC81F56E880B96E71"""
            + """60C980DD98EDD3DFFFFFFFFFFFFFFFFF""",
            base=1_6,
        ),
        """generator""": 2,
    },
}






class 			__a					:





       """simple docstring"""


       def __init__(   self			,					snake_case = 14   ):





        """simple docstring"""

        if group not in primes:
         raise ValueError("Unsupported Group"   )
        lowerCAmelCase__   :				int 			=				primes[group]["prime"]
        lowerCAmelCase__   :				List[str] 			=				primes[group]["generator"]

        lowerCAmelCase__   :				Any 			=				int(hexlify(urandom(32   )   )			,					base=16   )






       def 			SCREAMING_SNAKE_CASE_	(   self   ):





        """simple docstring"""

        return hex(self.__private_key   )[2:]






       def 			SCREAMING_SNAKE_CASE_	(   self   ):





        """simple docstring"""

        lowerCAmelCase__   :				Optional[int] 			=				pow(self.generator			,					self.__private_key			,					self.prime   )
        return hex(snake_case   )[2:]






       def 			SCREAMING_SNAKE_CASE_	(   self			,					snake_case   ):





        """simple docstring"""

        return (
            2 <= key <= self.prime - 2
            and pow(snake_case			,					(self.prime - 1) // 2			,					self.prime   ) == 1
        )






       def 			SCREAMING_SNAKE_CASE_	(   self			,					snake_case   ):





        """simple docstring"""

        lowerCAmelCase__   :				int 			=				int(snake_case			,					base=16   )
        if not self.is_valid_public_key(snake_case   ):
         raise ValueError("Invalid public key"   )
        lowerCAmelCase__   :				Tuple 			=				pow(snake_case			,					self.__private_key			,					self.prime   )
        return shaaaa(str(snake_case   ).encode()   ).hexdigest()






       @staticmethod
       def 			SCREAMING_SNAKE_CASE_	(   snake_case			,					snake_case   ):





        """simple docstring"""

        return (
            2 <= remote_public_key_str <= prime - 2
            and pow(snake_case			,					(prime - 1) // 2			,					snake_case   ) == 1
        )






       @staticmethod
       def 			SCREAMING_SNAKE_CASE_	(   snake_case			,					snake_case			,					snake_case = 14   ):





        """simple docstring"""

        lowerCAmelCase__   :				str 			=				int(snake_case			,					base=16   )
        lowerCAmelCase__   :				Union[str, Any] 			=				int(snake_case			,					base=16   )
        lowerCAmelCase__   :				List[str] 			=				primes[group]["prime"]
        if not DiffieHellman.is_valid_public_key_static(snake_case			,					snake_case   ):
         raise ValueError("Invalid public key"   )
        lowerCAmelCase__   :				Optional[int] 			=				pow(snake_case			,					snake_case			,					snake_case   )
        return shaaaa(str(snake_case   ).encode()   ).hexdigest()


if __name__ == "__main__":
    import doctest

    doctest.testmod()






