class_docstr: A word stemmer based on the Porter stemming algorithm.
  
  Porter, M. "An algorithm for suffix stripping."
  Program 14.3 (1980): 130-137.
  
  See http://www.tartarus.org/~martin/PorterStemmer/ for the homepage
  of the algorithm.
  
  Martin Porter has endorsed several modifications to the Porter
  algorithm since writing his original paper, and those extensions are
  included in the implementations on his website. Additionally, others
  have proposed further improvements to the algorithm, including NLTK
  contributors. Only below mode is supported currently
  PorterStemmer.NLTK_EXTENSIONS
  
  - Implementation that includes further improvements devised by
    NLTK contributors or taken from other modified implementations
    found on the web.
  
  Parameters
  ----------
      mode: Modes of stemming (Only supports (NLTK_EXTENSIONS) currently)
            default("NLTK_EXTENSIONS")
  
  Examples
  --------
  
  .. code-block:: python
  
      >>> import cudf
      >>> from cuml.preprocessing.text.stem import PorterStemmer
      >>> stemmer = PorterStemmer()
      >>> word_str_ser =  cudf.Series(['revival','singing','adjustable'])
      >>> print(stemmer.stem(word_str_ser))
      0     reviv
      1      sing
      2    adjust
      dtype: object
class_docstr_tok: ["A","word","stemmer","based","on","the","Porter","stemming","algorithm",".","Porter",",","M.","``","An","algorithm","for","suffix","stripping",".","''","Program","14.3","(","1980",")",":","130-137",".","See","http",":","\/\/www.tartarus.org\/~martin\/PorterStemmer\/","for","the","homepage","of","the","algorithm",".","Martin","Porter","has","endorsed","several","modifications","to","the","Porter","algorithm","since","writing","his","original","paper",",","and","those","extensions","are","included","in","the","implementations","on","his","website",".","Additionally",",","others","have","proposed","further","improvements","to","the","algorithm",",","including","NLTK","contributors",".","Only","below","mode","is","supported","currently","PorterStemmer.NLTK_EXTENSIONS","-","Implementation","that","includes","further","improvements","devised","by","NLTK","contributors","or","taken","from","other","modified","implementations","found","on","the","web",".","Parameters","--","--","--","--","--","mode",":","Modes","of","stemming","(","Only","supports","(","NLTK_EXTENSIONS",")","currently",")","default","(","``","NLTK_EXTENSIONS","''",")","Examples","--","--","--","--","..","code-block",":",":","python",">",">",">","import","cudf",">",">",">","from","cuml.preprocessing.text.stem","import","PorterStemmer",">",">",">","stemmer","=","PorterStemmer","(",")",">",">",">","word_str_ser","=","cudf.Series","(","[","'revival","'",",","'singing","'",",","'adjustable","'","]",")",">",">",">","print","(","stemmer.stem","(","word_str_ser",")",")","0","reviv","1","sing","2","adjust","dtype",":","object"]
docstr: Implements Step 1b from "An algorithm for suffix stripping"
  
  From the paper:
  
      (m>0) EED -> EE                    feed      ->  feed
                                      agreed    ->  agree
      (*v*) ED  ->                       plastered ->  plaster
                                      bled      ->  bled
      (*v*) ING ->                       motoring  ->  motor
                                      sing      ->  sing
  
  If the second or third of the rules in Step 1b is successful,
  the following is done:
  
      AT -> ATE                       conflat(ed)  ->  conflate
      BL -> BLE                       troubl(ed)   ->  trouble
      IZ -> IZE                       siz(ed)      ->  size
      (*d and not (*L or *S or *Z))
      -> single letter
                                      hopp(ing)    ->  hop
                                      tann(ed)     ->  tan
                                      fall(ing)    ->  fall
                                      hiss(ing)    ->  hiss
                                      fizz(ed)     ->  fizz
      (m=1 and *o) -> E               fail(ing)    ->  fail
                                      fil(ing)     ->  file
  
  The rule to map to a single letter causes the removal of one of
  the double letter pair. The -E is put back on -AT, -BL and -IZ,
  so that the suffixes -ATE, -BLE and -IZE can be recognised
  later. This E may be removed in step 4.
docstr_tok: ["Implements","Step","1b","from","``","An","algorithm","for","suffix","stripping","''","From","the","paper",":","(","m",">","0",")","EED","-",">","EE","feed","-",">","feed","agreed","-",">","agree","(","*","v","*",")","ED","-",">","plastered","-",">","plaster","bled","-",">","bled","(","*","v","*",")","ING","-",">","motoring","-",">","motor","sing","-",">","sing","If","the","second","or","third","of","the","rules","in","Step","1b","is","successful",",","the","following","is","done",":","AT","-",">","ATE","conflat","(","ed",")","-",">","conflate","BL","-",">","BLE","troubl","(","ed",")","-",">","trouble","IZ","-",">","IZE","siz","(","ed",")","-",">","size","(","*","d","and","not","(","*","L","or","*","S","or","*","Z",")",")","-",">","single","letter","hopp","(","ing",")","-",">","hop","tann","(","ed",")","-",">","tan","fall","(","ing",")","-",">","fall","hiss","(","ing",")","-",">","hiss","fizz","(","ed",")","-",">","fizz","(","m=1","and","*","o",")","-",">","E","fail","(","ing",")","-",">","fail","fil","(","ing",")","-",">","file","The","rule","to","map","to","a","single","letter","causes","the","removal","of","one","of","the","double","letter","pair",".","The","-E","is","put","back","on","-AT",",","-BL","and","-IZ",",","so","that","the","suffixes","-ATE",",","-BLE","and","-IZE","can","be","recognised","later",".","This","E","may","be","removed","in","step","4","."]
code: def _step1b(self, word_str_ser, can_replace_mask=None):
      """Implements Step 1b from "An algorithm for suffix stripping"
  
      From the paper:
  
          (m>0) EED -> EE                    feed      ->  feed
                                          agreed    ->  agree
          (*v*) ED  ->                       plastered ->  plaster
                                          bled      ->  bled
          (*v*) ING ->                       motoring  ->  motor
                                          sing      ->  sing
  
      If the second or third of the rules in Step 1b is successful,
      the following is done:
  
          AT -> ATE                       conflat(ed)  ->  conflate
          BL -> BLE                       troubl(ed)   ->  trouble
          IZ -> IZE                       siz(ed)      ->  size
          (*d and not (*L or *S or *Z))
          -> single letter
                                          hopp(ing)    ->  hop
                                          tann(ed)     ->  tan
                                          fall(ing)    ->  fall
                                          hiss(ing)    ->  hiss
                                          fizz(ed)     ->  fizz
          (m=1 and *o) -> E               fail(ing)    ->  fail
                                          fil(ing)     ->  file
  
      The rule to map to a single letter causes the removal of one of
      the double letter pair. The -E is put back on -AT, -BL and -IZ,
      so that the suffixes -ATE, -BLE and -IZE can be recognised
      later. This E may be removed in step 4.
      """
  
      can_replace_mask = build_can_replace_mask(
          len_mask=len(word_str_ser), mask=can_replace_mask
      )
  
      # this NLTK-only block extends the original algorithm, so that
      # 'spied'->'spi' but 'died'->'die' etc
      if self.mode == "NLTK_EXTENSIONS":
          # word.endswith('ied'):
          suffix_mask = ends_with_suffix(word_str_ser, "ied")
          len_mask = len_eq_n(word_str_ser, 4)
  
          condition_mask = suffix_mask & len_mask
  
          valid_mask = can_replace_mask & condition_mask
          word_str_ser = replace_suffix(
              word_str_ser, "ied", "ie", valid_mask
          )
  
          # update can replace mask
          can_replace_mask &= ~condition_mask
  
          condition_mask = suffix_mask
          valid_mask = can_replace_mask & condition_mask
          word_str_ser = replace_suffix(
              word_str_ser, "ied", "i", valid_mask
          )
  
          # update can replace mask
          can_replace_mask &= ~condition_mask
  
      # (m>0) EED -> EE
      # if suffix ==eed we stop processing
      # to be consistent with nltk
      suffix_mask = ends_with_suffix(word_str_ser, "eed")
      valid_mask = suffix_mask & can_replace_mask
  
      stem = replace_suffix(word_str_ser, "eed", "", valid_mask)
      measure_mask = measure_gt_n(stem, 0)
  
      valid_mask = measure_mask & suffix_mask & can_replace_mask
      # adding ee series to stem
      word_str_ser = replace_suffix(
          word_str_ser, "eed", "ee", valid_mask
      )
  
      # to be consistent with nltk we dont replace
      # if word.endswith('eed') we stop proceesing
      can_replace_mask &= ~suffix_mask
  
      # rule 2
      #    (*v*) ED  ->   plastered ->  plaster
      #                   bled      ->  bled
  
      ed_suffix_mask = ends_with_suffix(word_str_ser, "ed")
      intermediate_stem = replace_suffix(
          word_str_ser, "ed", "", ed_suffix_mask & can_replace_mask
      )
      vowel_mask = contains_vowel(intermediate_stem)
  
      rule_2_mask = vowel_mask & ed_suffix_mask & can_replace_mask
  
      # rule 3
  
      #    (*v*) ING ->  motoring  ->  motor
      #                   sing      ->  sing
      ing_suffix_mask = ends_with_suffix(word_str_ser, "ing")
      intermediate_stem = replace_suffix(
          word_str_ser, "ing", "", ing_suffix_mask & can_replace_mask
      )
      vowel_mask = contains_vowel(intermediate_stem)
      rule_3_mask = vowel_mask & ing_suffix_mask & can_replace_mask
  
      rule_2_or_rule_3_mask = rule_2_mask | rule_3_mask
  
      # replace masks only if rule_2_or_rule_3_mask
      intermediate_stem_1 = replace_suffix(
          word_str_ser, "ed", "", rule_2_mask
      )
      intermediate_stem_2 = replace_suffix(
          intermediate_stem_1, "ing", "", rule_3_mask
      )
  
      can_replace_mask = can_replace_mask & rule_2_or_rule_3_mask
      return apply_rule_list(
          intermediate_stem_2,
          [
              ("at", "ate", None),  # AT -> ATE
              ("bl", "ble", None),  # BL -> BLE
              ("iz", "ize", None),  # IZ -> IZE
              # (*d and not (*L or *S or *Z))
              # -> single letter
              (
                  "*d",
                  -1,  # intermediate_stem[-1],
                  lambda stem: last_char_not_in(
                      stem, characters=["l", "s", "z"]
                  ),
              ),
              # (m=1 and *o) -> E
              (
                  "",
                  "e",
                  lambda stem: measure_eq_n(stem, n=1) & ends_cvc(stem),
              ),
          ],
          can_replace_mask,
      )[0]
  
imports: from .porter_stemmer_utils.measure_utils import has_positive_measure, measure_gt_n, measure_eq_n
  from .porter_stemmer_utils.len_flags_utils import len_eq_n, len_gt_n
  from .porter_stemmer_utils.consonant_vowel_utils import contains_vowel, is_consonant
  from .porter_stemmer_utils.porter_stemmer_rules import ends_with_suffix, ends_with_double_constant, last_char_not_in, last_char_in, ends_cvc
  from .porter_stemmer_utils.suffix_utils import get_stem_series, get_str_replacement_series, replace_suffix
  from cuml.internals.safe_imports import gpu_only_import
label_desc: Use image node_id 4 for calling the PorterStemmer obj's underlying member method code with example usage: obj._step1b(word_str_ser, can_replace_mask) and returns: apply_rule_list