



import mpmath  # for roots of unity
import numpy as np






class 						__a :



	def __init__(						self							:    Optional[Any]				,	snake_case_							:    Tuple=None				,	snake_case_							:    int=None)->							Dict:
						__lowerCAmelCase	   =list(poly_a or [0])[:]
						__lowerCAmelCase	   =list(poly_b or [0])[:]

						# Remove leading zero coefficients
						while self.polyA[-1] == 0:
											self.polyA.pop()
						__lowerCAmelCase	   =len(self.polyA)

						while self.polyB[-1] == 0:
											self.polyB.pop()
						__lowerCAmelCase	   =len(self.polyB)

						# Add 0 to make lengths equal a power of 2
						__lowerCAmelCase	   =int(
						    2 ** np.ceil(np.loga(len(self.polyA) + len(self.polyB) - 1)))

						while len(self.polyA) < self.c_max_length:
											self.polyA.append(0)
						while len(self.polyB) < self.c_max_length:
											self.polyB.append(0)
						# A complex root used for the fourier transform
						__lowerCAmelCase	   =complex(mpmath.root(x=1				,	n=self.c_max_length				,	k=1))

						# The product
						__lowerCAmelCase	   =self.__multiply()



	def 		UpperCamelCase							(						self							:    Tuple				,	snake_case_							:    Dict)->							Tuple:
						__lowerCAmelCase	   =[[x] for x in self.polyA] if which == 'A' else [[x] for x in self.polyB]
						# Corner case
						if len(snake_case_) <= 1:
											return dft[0]
						#
						__lowerCAmelCase	   =self.c_max_length // 2
						while next_ncol > 0:
											__lowerCAmelCase	   =[[] for i in range(snake_case_)]
											__lowerCAmelCase	   =self.root**next_ncol

											# First half of next step
											__lowerCAmelCase	   =1
											for j in range(self.c_max_length // (next_ncol * 2)):
																for i in range(snake_case_):
																					new_dft[i].append(dft[i][j] + current_root * dft[i + next_ncol][j])
																current_root *= root
											# Second half of next step
											__lowerCAmelCase	   =1
											for j in range(self.c_max_length // (next_ncol * 2)):
																for i in range(snake_case_):
																					new_dft[i].append(dft[i][j] - current_root * dft[i + next_ncol][j])
																current_root *= root
											# Update
											__lowerCAmelCase	   =new_dft
											__lowerCAmelCase	   =next_ncol // 2
						return dft[0]



	def 		UpperCamelCase							(						self							:    Tuple)->							Any:
						__lowerCAmelCase	   =self.__dft("""A""")
						__lowerCAmelCase	   =self.__dft("""B""")
						__lowerCAmelCase	   =[[dft_a[i] * dft_b[i] for i in range(self.c_max_length)]]
						del dft_a
						del dft_b

						# Corner Case
						if len(inverce_c[0]) <= 1:
											return inverce_c[0]
						# Inverse DFT
						__lowerCAmelCase	   =2
						while next_ncol <= self.c_max_length:
											__lowerCAmelCase	   =[[] for i in range(snake_case_)]
											__lowerCAmelCase	   =self.root ** (next_ncol // 2)
											__lowerCAmelCase	   =1
											# First half of next step
											for j in range(self.c_max_length // next_ncol):
																for i in range(next_ncol // 2):
																					# Even positions
																					new_inverse_c[i].append(
																					    (
																					        inverce_c[i][j]
																					        + inverce_c[i][j + self.c_max_length // next_ncol]
																					    )
																					    / 2)
																					# Odd positions
																					new_inverse_c[i + next_ncol // 2].append(
																					    (
																					        inverce_c[i][j]
																					        - inverce_c[i][j + self.c_max_length // next_ncol]
																					    )
																					    / (2 * current_root))
																current_root *= root
											# Update
											__lowerCAmelCase	   =new_inverse_c
											next_ncol *= 2
						# Unpack
						__lowerCAmelCase	   =[round(x[0].real				,	8) + round(x[0].imag				,	8) * 1j for x in inverce_c]

						# Remove leading 0's
						while inverce_c[-1] == 0:
											inverce_c.pop()
						return inverce_c



	def __str__(						self							:    Tuple)->							Optional[int]:
						__lowerCAmelCase	   ='A = ' + ' + '.join(
						    F"""{coef}*x^{i}""" for coef, i in enumerate(self.polyA[: self.len_A]))
						__lowerCAmelCase	   ='B = ' + ' + '.join(
						    F"""{coef}*x^{i}""" for coef, i in enumerate(self.polyB[: self.len_B]))
						__lowerCAmelCase	   ='A*B = ' + ' + '.join(
						    F"""{coef}*x^{i}""" for coef, i in enumerate(self.product))

						return F"""{a}\n{b}\n{c}"""


# Unit tests
if __name__ == "__main__":
				import doctest

				doctest.testmod()









def 					__lowerCAmelCase		(  __lowerCamelCase	:    list[int]	)  ->						int:
					if not numbers:
										return 0

					if not isinstance(__lowerCamelCase				,   (list, tuple)	) or not all(
					    isinstance(__lowerCamelCase				,   __lowerCamelCase	) for number in numbers	):
										raise ValueError("""numbers must be an iterable of integers"""	)

					__lowerCAmelCase	   =__lowerCAmelCase	   =__lowerCAmelCase	   =numbers[0]

					for i in range(1				,   len(__lowerCamelCase	)	):
										# update the maximum and minimum subarray products
										__lowerCAmelCase	   =numbers[i]
										if number < 0:
															__lowerCAmelCase   ,	__lowerCAmelCase	   =min_till_now, max_till_now
										__lowerCAmelCase	   =max(__lowerCamelCase				,   max_till_now * number	)
										__lowerCAmelCase	   =min(__lowerCamelCase				,   min_till_now * number	)

										# update the maximum product found till now
										__lowerCAmelCase	   =max(__lowerCamelCase				,   __lowerCamelCase	)

					return max_prod




