



import torch
from torch import nn



class 	lowerCamelCase      (						nn.Module  ):







					'''simple docstring'''







					def __init__(			self    ,	lowerCAmelCase    ,	lowerCAmelCase    ,	lowerCAmelCase    ,	lowerCAmelCase    ,	lowerCAmelCase=1    ,	lowerCAmelCase=False     ):
							super().__init__()

							UpperCAmelCase_						=				n_token
							UpperCAmelCase_						=				d_embed
							UpperCAmelCase_						=				d_proj

							UpperCAmelCase_						=				cutoffs + [n_token]
							UpperCAmelCase_						=				[0] + self.cutoffs
							UpperCAmelCase_						=				div_val

							UpperCAmelCase_						=				self.cutoffs[0]
							UpperCAmelCase_						=				len(self.cutoffs     ) - 1
							UpperCAmelCase_						=				self.shortlist_size + self.n_clusters

							if self.n_clusters > 0:
									UpperCAmelCase_						=				nn.Parameter(torch.zeros(self.n_clusters    ,	self.d_embed     )     )
									UpperCAmelCase_						=				nn.Parameter(torch.zeros(self.n_clusters     )     )

							UpperCAmelCase_						=				nn.ModuleList()
							UpperCAmelCase_						=				nn.ParameterList()

							if div_val == 1:
									for i in range(len(self.cutoffs     )     ):
											if d_proj != d_embed:
													self.out_projs.append(nn.Parameter(torch.FloatTensor(lowerCAmelCase    ,	lowerCAmelCase     )     )     )
											else:
													self.out_projs.append(lowerCAmelCase     )

									self.out_layers.append(nn.Linear(lowerCAmelCase    ,	lowerCAmelCase     )     )
							else:
									for i in range(len(self.cutoffs     )     ):
											UpperCAmelCase_					,						UpperCAmelCase_						=				self.cutoff_ends[i], self.cutoff_ends[i + 1]
											UpperCAmelCase_						=				d_embed // (div_val**i)

											self.out_projs.append(nn.Parameter(torch.FloatTensor(lowerCAmelCase    ,	lowerCAmelCase     )     )     )

											self.out_layers.append(nn.Linear(lowerCAmelCase    ,	r_idx - l_idx     )     )

							UpperCAmelCase_						=				keep_order



					def    A__		(			self    ,	lowerCAmelCase    ,	lowerCAmelCase    ,	lowerCAmelCase    ,	lowerCAmelCase     ):
							if proj is None:
									UpperCAmelCase_						=				nn.functional.linear(lowerCAmelCase    ,	lowerCAmelCase    ,	bias=lowerCAmelCase     )
							else:
									# if CUDA_MAJOR <= 9 and CUDA_MINOR <= 1:
									UpperCAmelCase_						=				nn.functional.linear(lowerCAmelCase    ,	proj.t().contiguous()     )
									UpperCAmelCase_						=				nn.functional.linear(lowerCAmelCase    ,	lowerCAmelCase    ,	bias=lowerCAmelCase     )
									# else:
									#     logit = torch.einsum('bd,de,ev->bv', (hidden, proj, weight.t()))
									#     if bias is not None:
									#         logit = logit + bias

							return logit



					def    A__		(			self    ,	lowerCAmelCase    ,	lowerCAmelCase=None    ,	lowerCAmelCase=False     ):

							if labels is not None:
									# Shift so that tokens < n predict n
									UpperCAmelCase_						=				hidden[..., :-1, :].contiguous()
									UpperCAmelCase_						=				labels[..., 1:].contiguous()
									UpperCAmelCase_						=				hidden.view(-1    ,	hidden.size(-1     )     )
									UpperCAmelCase_						=				labels.view(-1     )
									if hidden.size(0     ) != labels.size(0     ):
											raise RuntimeError("Input and labels should have the same size in the batch dimension."     )
							else:
									UpperCAmelCase_						=				hidden.view(-1    ,	hidden.size(-1     )     )

							if self.n_clusters == 0:
									UpperCAmelCase_						=				self._compute_logit(lowerCAmelCase    ,	self.out_layers[0].weight    ,	self.out_layers[0].bias    ,	self.out_projs[0]     )
									if labels is not None:
											UpperCAmelCase_						=				labels != -100
											UpperCAmelCase_						=				torch.zeros_like(lowerCAmelCase    ,	dtype=hidden.dtype    ,	device=hidden.device     )
											UpperCAmelCase_						=				(
											    -nn.functional.log_softmax(lowerCAmelCase    ,	dim=-1     )[mask].gather(1    ,	labels[mask].unsqueeze(1     )     ).squeeze(1     )
											)
									else:
											UpperCAmelCase_						=				nn.functional.log_softmax(lowerCAmelCase    ,	dim=-1     )
							else:
									# construct weights and biases
									UpperCAmelCase_					,						UpperCAmelCase_						=				[], []
									for i in range(len(self.cutoffs     )     ):
											if self.div_val == 1:
													UpperCAmelCase_					,						UpperCAmelCase_						=				self.cutoff_ends[i], self.cutoff_ends[i + 1]
													UpperCAmelCase_						=				self.out_layers[0].weight[l_idx:r_idx]
													UpperCAmelCase_						=				self.out_layers[0].bias[l_idx:r_idx]
											else:
													UpperCAmelCase_						=				self.out_layers[i].weight
													UpperCAmelCase_						=				self.out_layers[i].bias

											if i == 0:
													UpperCAmelCase_						=				torch.cat([weight_i, self.cluster_weight]    ,	dim=0     )
													UpperCAmelCase_						=				torch.cat([bias_i, self.cluster_bias]    ,	dim=0     )

											weights.append(lowerCAmelCase     )
											biases.append(lowerCAmelCase     )

									UpperCAmelCase_					,						UpperCAmelCase_					,						UpperCAmelCase_						=				weights[0], biases[0], self.out_projs[0]

									UpperCAmelCase_						=				self._compute_logit(lowerCAmelCase    ,	lowerCAmelCase    ,	lowerCAmelCase    ,	lowerCAmelCase     )
									UpperCAmelCase_						=				nn.functional.log_softmax(lowerCAmelCase    ,	dim=1     )

									if labels is None:
											UpperCAmelCase_						=				hidden.new_empty((head_logit.size(0     ), self.n_token)     )
									else:
											UpperCAmelCase_						=				torch.zeros_like(lowerCAmelCase    ,	dtype=hidden.dtype    ,	device=hidden.device     )

									UpperCAmelCase_						=				0
									UpperCAmelCase_						=				[0] + self.cutoffs
									for i in range(len(lowerCAmelCase     ) - 1     ):
											UpperCAmelCase_					,						UpperCAmelCase_						=				cutoff_values[i], cutoff_values[i + 1]

											if labels is not None:
													UpperCAmelCase_						=				(labels >= l_idx) & (labels < r_idx)
													UpperCAmelCase_						=				mask_i.nonzero().squeeze()

													if indices_i.numel() == 0:
															continue

													UpperCAmelCase_						=				labels.index_select(0    ,	lowerCAmelCase     ) - l_idx
													UpperCAmelCase_						=				head_logprob.index_select(0    ,	lowerCAmelCase     )
													UpperCAmelCase_						=				hidden.index_select(0    ,	lowerCAmelCase     )
											else:
													UpperCAmelCase_						=				hidden

											if i == 0:
													if labels is not None:
															UpperCAmelCase_						=				head_logprob_i.gather(1    ,	target_i[:, None]     ).squeeze(1     )
													else:
															UpperCAmelCase_						=				head_logprob[:, : self.cutoffs[0]]
											else:
													UpperCAmelCase_					,						UpperCAmelCase_					,						UpperCAmelCase_						=				weights[i], biases[i], self.out_projs[i]

													UpperCAmelCase_						=				self._compute_logit(lowerCAmelCase    ,	lowerCAmelCase    ,	lowerCAmelCase    ,	lowerCAmelCase     )
													UpperCAmelCase_						=				nn.functional.log_softmax(lowerCAmelCase    ,	dim=1     )
													UpperCAmelCase_						=				self.cutoffs[0] + i - 1  # No probability for the head cluster
													if labels is not None:
															UpperCAmelCase_						=				head_logprob_i[:, cluster_prob_idx] + tail_logprob_i.gather(
															    1    ,	target_i[:, None]     ).squeeze(1     )
													else:
															UpperCAmelCase_						=				head_logprob[:, cluster_prob_idx, None] + tail_logprob_i
															UpperCAmelCase_						=				logprob_i

											if labels is not None:
													if (hasattr(self    ,	"keep_order"     ) and self.keep_order) or keep_order:
															out.index_copy_(0    ,	lowerCAmelCase    ,	-logprob_i     )
													else:
															out[offset : offset + logprob_i.size(0     )].copy_(-logprob_i     )
													offset += logprob_i.size(0     )

							return out



					def    A__		(			self    ,	lowerCAmelCase     ):
							if self.n_clusters == 0:
									UpperCAmelCase_						=				self._compute_logit(lowerCAmelCase    ,	self.out_layers[0].weight    ,	self.out_layers[0].bias    ,	self.out_projs[0]     )
									return nn.functional.log_softmax(lowerCAmelCase    ,	dim=-1     )
							else:
									# construct weights and biases
									UpperCAmelCase_					,						UpperCAmelCase_						=				[], []
									for i in range(len(self.cutoffs     )     ):
											if self.div_val == 1:
													UpperCAmelCase_					,						UpperCAmelCase_						=				self.cutoff_ends[i], self.cutoff_ends[i + 1]
													UpperCAmelCase_						=				self.out_layers[0].weight[l_idx:r_idx]
													UpperCAmelCase_						=				self.out_layers[0].bias[l_idx:r_idx]
											else:
													UpperCAmelCase_						=				self.out_layers[i].weight
													UpperCAmelCase_						=				self.out_layers[i].bias

											if i == 0:
													UpperCAmelCase_						=				torch.cat([weight_i, self.cluster_weight]    ,	dim=0     )
													UpperCAmelCase_						=				torch.cat([bias_i, self.cluster_bias]    ,	dim=0     )

											weights.append(lowerCAmelCase     )
											biases.append(lowerCAmelCase     )

									UpperCAmelCase_					,						UpperCAmelCase_					,						UpperCAmelCase_						=				weights[0], biases[0], self.out_projs[0]
									UpperCAmelCase_						=				self._compute_logit(lowerCAmelCase    ,	lowerCAmelCase    ,	lowerCAmelCase    ,	lowerCAmelCase     )

									UpperCAmelCase_						=				hidden.new_empty((head_logit.size(0     ), self.n_token)     )
									UpperCAmelCase_						=				nn.functional.log_softmax(lowerCAmelCase    ,	dim=1     )

									UpperCAmelCase_						=				[0] + self.cutoffs
									for i in range(len(lowerCAmelCase     ) - 1     ):
											UpperCAmelCase_					,						UpperCAmelCase_						=				cutoff_values[i], cutoff_values[i + 1]

											if i == 0:
													UpperCAmelCase_						=				head_logprob[:, : self.cutoffs[0]]
											else:
													UpperCAmelCase_					,						UpperCAmelCase_					,						UpperCAmelCase_						=				weights[i], biases[i], self.out_projs[i]

													UpperCAmelCase_						=				self._compute_logit(lowerCAmelCase    ,	lowerCAmelCase    ,	lowerCAmelCase    ,	lowerCAmelCase     )
													UpperCAmelCase_						=				nn.functional.log_softmax(lowerCAmelCase    ,	dim=1     )

													UpperCAmelCase_						=				head_logprob[:, -i] + tail_logprob_i
													UpperCAmelCase_						=				logprob_i

									return out






def snake_case__  (			__SCREAMING_SNAKE_CASE )		->							int:
		UpperCAmelCase_						=				[1]

		UpperCAmelCase_					,						UpperCAmelCase_					,						UpperCAmelCase_						=				0, 0, 0
		UpperCAmelCase_						=				ugly_nums[ia] * 2
		UpperCAmelCase_						=				ugly_nums[ia] * 3
		UpperCAmelCase_						=				ugly_nums[ia] * 5

		for _ in range(1			,     __SCREAMING_SNAKE_CASE ):
				UpperCAmelCase_						=				min(__SCREAMING_SNAKE_CASE			,     __SCREAMING_SNAKE_CASE			,     __SCREAMING_SNAKE_CASE )
				ugly_nums.append(__SCREAMING_SNAKE_CASE )
				if next_num == next_a:
						ia += 1
						UpperCAmelCase_						=				ugly_nums[ia] * 2
				if next_num == next_a:
						ia += 1
						UpperCAmelCase_						=				ugly_nums[ia] * 3
				if next_num == next_a:
						ia += 1
						UpperCAmelCase_						=				ugly_nums[ia] * 5
		return ugly_nums[-1]


if __name__ == "__main__":
			from doctest import testmod

			testmod(verbose=True)
			print(f'''{ugly_numbers(200) = }''')

