

import mpmath  # for roots of unity
import numpy as np






class 	__magic_name__    :





			def __init__(		self					,  __snake_case=None					,  __snake_case=None					)   -> Tuple:




						'''simple docstring'''
						# Input as list
						__a        =list(poly_a or [0]					)[:]
						__a        =list(poly_b or [0]					)[:]

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

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

						# Add 0 to make lengths equal a power of 2
						__a        =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
						__a        =complex(mpmath.root(x=1					,  n=self.c_max_length					,  k=1					)					)

						# The product
						__a        =self.__multiply()





			def 		__magic_name__    (		self					,  __snake_case					)   -> List[str]:




						'''simple docstring'''
						__a        =[[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]
						#
						__a        =self.c_max_length // 2
						while next_ncol > 0:
									__a        =[[] for i in range(__snake_case					)]
									__a        =self.root**next_ncol

									# First half of next step
									__a        =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
									__a        =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
									__a        =new_dft
									__a        =next_ncol // 2
						return dft[0]





			def 		__magic_name__    (		self					)   -> Tuple:




						'''simple docstring'''
						__a        =self.__dft('A'					)
						__a        =self.__dft('B'					)
						__a        =[[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
						__a        =2
						while next_ncol <= self.c_max_length:
									__a        =[[] for i in range(__snake_case					)]
									__a        =self.root ** (next_ncol // 2)
									__a        =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
									__a        =new_inverse_c
									next_ncol *= 2
						# Unpack
						__a        =[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					)   -> Optional[Any]:




						'''simple docstring'''
						__a        ='A = ' + ' + '.join(
						    f'{coef}*x^{i}' for coef, i in enumerate(self.polyA[: self.len_A]					)					)
						__a        ='B = ' + ' + '.join(
						    f'{coef}*x^{i}' for coef, i in enumerate(self.polyB[: self.len_B]					)					)
						__a        ='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()












"""simple docstring"""






def      _snake_case			(				lowercase__		):
				if not isinstance(lowercase__							,    lowercase__		):
								raise ValueError('Input series is not valid, valid series - [2, 4, 6]'		)
				if len(lowercase__		) == 0:
								raise ValueError('Input list must be a non empty list'		)
				if len(lowercase__		) == 1:
								return True
				_lowerCamelCase     :			List[Any]    =    series[1] - series[0]
				for index in range(len(lowercase__		) - 1		):
								if series[index + 1] - series[index] != common_diff:
												return False
				return True







def      _snake_case			(				lowercase__		):
				if not isinstance(lowercase__							,    lowercase__		):
								raise ValueError('Input series is not valid, valid series - [2, 4, 6]'		)
				if len(lowercase__		) == 0:
								raise ValueError('Input list must be a non empty list'		)
				_lowerCamelCase     :			Optional[int]    =    0
				for val in series:
								answer += val
				return answer / len(lowercase__		)


if __name__ == "__main__":
			import doctest

			doctest.testmod()