


import mpmath  # for roots of unity
import numpy as np







class 		_snake_case  :




 def __init__(		self					,  _lowerCamelCase=None					,  _lowerCamelCase=None    ):
       # Input as list
       a						:int 							=       list(poly_a or [0]    )[:]
       a						:List[Any] 							=       list(poly_b or [0]    )[:]

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

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

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

       # The product
       a						:Tuple 							=       self.__multiply()




 def        SCREAMING_SNAKE_CASE__				(		self					,  _lowerCamelCase    ):
       a						:Optional[Any] 							=       [[x] for x in self.polyA] if which == '''A''' else [[x] for x in self.polyB]
       # Corner case
       if len(_lowerCamelCase    ) <= 1:
             return dft[0]
       #
       a						:Dict 							=       self.c_max_length // 2
       while next_ncol > 0:
             a						:Union[str, Any] 							=       [[] for i in range(_lowerCamelCase    )]
             a						:Union[str, Any] 							=       self.root**next_ncol

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




 def        SCREAMING_SNAKE_CASE__				(		self    ):
       a						:Optional[int] 							=       self.__dft('''A'''    )
       a						:List[Any] 							=       self.__dft('''B'''    )
       a						:Dict 							=       [[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						:Dict 							=       2
       while next_ncol <= self.c_max_length:
             a						:str 							=       [[] for i in range(_lowerCamelCase    )]
             a						:List[Any] 							=       self.root ** (next_ncol // 2)
             a						:List[str] 							=       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						:int 							=       new_inverse_c
             next_ncol *= 2
       # Unpack
       a						:Any 							=       [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    ):
       a						:Dict 							=       '''A = ''' + ''' + '''.join(
           F'''{coef}*x^{i}''' for coef, i in enumerate(self.polyA[: self.len_A]    )    )
       a						:Any 							=       '''B = ''' + ''' + '''.join(
           F'''{coef}*x^{i}''' for coef, i in enumerate(self.polyB[: self.len_B]    )    )
       a						:Tuple 							=       '''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()









from maths.prime_factors import prime_factors
def 				__lowerCamelCase						( UpperCAmelCase_						:		int						):




      """simple docstring"""





      if not isinstance(UpperCAmelCase_ ,  UpperCAmelCase_						):
            a						:Dict 							=       F'''Input value of [number={number}] must be an integer'''
            raise TypeError(UpperCAmelCase_						)
      if number < 1:
            raise ValueError('''Input must be a positive integer'''						)
      return -1 if len(prime_factors(UpperCAmelCase_						)						) % 2 else 1


if __name__ == "__main__":
     import doctest

     doctest.testmod()





