text: # DataFrame = pd.DataFrame
  
  import cudf
  from cudf import Series
  
  from optimus.engines.base.functions import Functions
  
  
  def functions(self):
      class CUDFFunctions(Functions):
          def __init__(self, df):
              super(CUDFFunctions, self).__init__(df)
  
  
  
          def count_zeros(self, *args):
              # Cudf can not handle null so we fill it with non zero values.
              series = self.series
              non_zero_value = 1
              return (series.ext.to_float().fillna(non_zero_value).values == 0).sum()
  
          def kurtosis(self):
              series = self.series
              return series.ext.to_float().kurt()
  
          def skew(self):
              series = self.series
              return series.ext.to_float().skew()
  
          def exp(self):
              series = self.series
              return cudf.exp(series.ext.to_float())
  
          def sqrt(self):
              series = self.series
              return series.ext.to_float().sqrt()
  
          def unique(self, *args):
              series = self.series
              # Cudf can not handle null so we fill it with non zero values.
              return series.astype(str).unique()
  
          # def mod(self, other):
          #     series = self.series
          #     return cudf.mod(series.ext.to_float(), other)
  
          def radians(self):
              series = self.series
              return cudf.radians(series.ext.to_float())
  
          def degrees(self):
              series = self.series
              return cudf.degrees(series.ext.to_float())
  
          def ln(self):
              series = self.series
              return cudf.log(series.ext.to_float())
  
          def log(self):
              series = self.series
              return series.ext.to_float().log() / cudf.log(10)
  
          def ceil(self):
              series = self.series
              return series.ext.to_float().ceil()
  
          def floor(self):
              series = self.series
              return series.ext.to_float().ceil()
  
          def sin(self):
              series = self.series
              return series.ext.to_float().sin()
  
          def cos(self):
              series = self.series
              return series.ext.to_float().cos()
  
          def tan(self):
              series = self.series
              return series.ext.to_float().tan()
  
          def asin(self):
              series = self.series
              return series.ext.to_float().asin()
  
          def acos(self):
              series = self.series
              return series.ext.to_float().acos()
  
          def atan(self):
              series = self.series
              return series.ext.to_float().atan()
  
          def sinh(self):
              series = self.series
              return 1 / 2 * (cudf.exp(series) - cudf.exp(-series))
  
          def cosh(self):
              series = self.series
              return 1 / 2 * (cudf.exp(series) + cudf.exp(-series))
  
          def tanh(self):
              return self.sinh() / self.cosh()
  
          def asinh(self):
              return 1 / self.sinh()
  
          def acosh(self):
              return 1 / self.cosh()
  
          def atanh(self):
              return 1 / self.tanh()
  
          def clip(self, lower_bound, upper_bound):
              series = self.series
              return series.ext.to_float().clip(float(lower_bound), float(upper_bound))
  
          def cut(self, bins):
              raise NotImplementedError("Not implemented yet https://github.com/rapidsai/cudf/issues/5589")
  
          def replace_string(self, search, replace_by):
              series = self.series
              return series.astype(str).str.replace(search, replace_by)
  
          def remove_special_chars(self):
              series = self.series
              return series.astype(str).str.filter_alphanum()
  
          def remove_accents(self):
              series = self.series
              if not series.isnull().all():
                  return series.astype(str).str.normalize_characters()
              else:
                  return series
  
          def date_format(self, current_format=None, output_format=None):
              series = self.series
              # Some formats are no supported yet. https://github.com/rapidsai/cudf/issues/5991
              return cudf.to_datetime(series, format=current_format, errors="coerce").dt.strftime(output_format)
  
          def years_between(self, date_format=None):
              series = self.series
              raise NotImplementedError("Not implemented yet see https://github.com/rapidsai/cudf/issues/1041")
              # return cudf.to_datetime(series).astype('str', format=date_format) - datetime.now().date()
  
      return CUDFFunctions(self)
  
  
  Series.functions = property(functions)
  