






import mpmath  # for roots of unity
import numpy as np




class       snake_case__ :

       '''simple docstring'''



       def __init__(				self      ,    a__=None      ,    a__=None     )			->   List[Any]:






            '''simple docstring'''





            __snake_case      :str 							=    list(poly_a or [0]     )[:]
            __snake_case      :Tuple 							=    list(poly_b or [0]     )[:]

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

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

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

            # The product
            __snake_case      :Optional[int] 							=    self.__multiply()



       def        __lowercase    (				self      ,    a__     )			->   str:






            '''simple docstring'''





            __snake_case      :Optional[Any] 							=    [[x] for x in self.polyA] if which == """A""" else [[x] for x in self.polyB]
            # Corner case
            if len(a__     ) <= 1:
                 return dft[0]
            #
            __snake_case      :Union[str, Any] 							=    self.c_max_length // 2
            while next_ncol > 0:
                 __snake_case      :List[Any] 							=    [[] for i in range(a__     )]
                 __snake_case      :int 							=    self.root**next_ncol

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



       def        __lowercase    (				self     )			->   Tuple:






            '''simple docstring'''





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






            '''simple docstring'''





            __snake_case      :List[Any] 							=    """A = """ + """ + """.join(
                F'''{coef}*x^{i}''' for coef, i in enumerate(self.polyA[: self.len_A]     )     )
            __snake_case      :Tuple 							=    """B = """ + """ + """.join(
                F'''{coef}*x^{i}''' for coef, i in enumerate(self.polyB[: self.len_B]     )     )
            __snake_case      :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()










def 	UpperCamelCase	(							snake_case__  : float						,snake_case__  : int	):




     '''simple docstring'''






     if digit_amount > 0:
          return round(number - int(snake_case__	)						,snake_case__	)
     return number - int(snake_case__	)


if __name__ == "__main__":
     print(decimal_isolate(1.5_3, 0))
     print(decimal_isolate(3_5.3_4_5, 1))
     print(decimal_isolate(3_5.3_4_5, 2))
     print(decimal_isolate(3_5.3_4_5, 3))
     print(decimal_isolate(-1_4.7_8_9, 3))
     print(decimal_isolate(0, 2))
     print(decimal_isolate(-1_4.1_2_3, 1))
     print(decimal_isolate(-1_4.1_2_3, 2))
     print(decimal_isolate(-1_4.1_2_3, 3))


