function strip_affixes ( str )
{
  str=to_lower_case(str);
  str=clean(str+";");
  str=strip_prefixes(str);
  str=strip_suffixes(str);
  return str;
}

function to_lower_case ( kwd )
{
  return kwd.toLowerCase();
}

function clean ( kwd )
{
  last = kwd.length;
  result = "";
  var i = 0;
  while (i < last) {
    while (i<last && isvalid(kwd.charAt(i)) != 0) 
      i++;
    var j=i;
    while (j<last && isvalid(kwd.charAt(j)) == 0)
      j++;
    if (i<last && j<=last) {
      piece = kwd.substr(i, j-i);
      result = result + piece;
    }
    i = j;
  }
  return result;
}

function isvalid(l)
{
  if ( (l >= 'a') && (l <= 'z') )
    return(0);
  if ( (l >= 'A') && (l <= 'Z') )
    return(0);
  if ( (l >= '0') && (l <= '9') )
    return(0);
  return(1);
}

var prefixes = ["kilo", "micro", "milli", "intra", "ultra", "mega", "nano", "pico", "pseudo", 0];
function strip_prefixes ( str )
{
  for ( i=0 ; prefixes[i] != 0 ; i++ ) 
    if ( str.indexOf(prefixes[i], 0) == 0 ) {
      str = str.substr(prefixes[i].length, str.length-prefixes[i].length);
      return str;
    }
  return str;
}

function strip_suffixes ( str )
{
  str=step_1 ( str );
  str=step_2 ( str );
  str=step_3 ( str );
  str=step_4 ( str );
  str=step_5 ( str );
  return str;
}

function remove_suffix(str, nr)
{
  if (str.length >= nr)
    return str.substr(0, str.length - nr);
  else
    return "";
}

var stem;
function step_1 ( str )
{
  stem = "";
  if ( str.charAt(str.length-1) == "s" ) {
    if ( (has_suffix(str,"sses") == 1) ||
	 (has_suffix(str,"ies") == 1 ) )
      str = remove_suffix(str, 2);
    else
      if ( str.charAt(str.length-2) != "s" )
	str = remove_suffix(str, 1);
  }
  if ( has_suffix(str,"eed") == 1 ) {
    if ( measure(stem) > 0 )
      str = remove_suffix(str, 1);
  }
  else {
    if ( ( (has_suffix(str,"ed") == 1 )
	   || (has_suffix(str,"ing") == 1 ) )
	 && (contains_vowel(stem) == 1 ) ) {
      str = remove_suffix(str,str.length - stem.length -1);
      if ( ( has_suffix(str,"at",stem) == 1 )
	   || ( has_suffix(str,"bl") == 1 )
	   || ( has_suffix(str,"iz") == 1 ) ) 
	str = str.concat("e");
      else {
        len = str.length;
      if ( str.charAt(len) == str.charAt(len-2)
	   && (str.charAt(len-1) != 'l')
	   && (str.charAt(len-1) != 's')
	   && (str.charAt(len-1) != 'z') )
	str = remove_suffix(str, 1);
      else
	if ( measure(str) == 1 ) {
	  if ( cvc(str) == 1 ) 
	    str = str.concat("e");
	}
      }
    }
  }
  if ( (has_suffix(str,"y") == 1) &&
       (contains_vowel(stem) == 1) ) {
    str = remove_suffix(str, 1);
    str = str.concat("i");
  }
  return str;
}

var suffixes2 = [[ "ational", "ate" ],
		 [ "tional",  "tion" ],
		 [ "enci",    "ence" ],
		 [ "anci",    "ance" ],
		 [ "izer",    "ize" ],
		 [ "iser",    "ize" ],
		 [ "abli",    "able" ],
		 [ "alli",    "al" ],
		 [ "entli",   "ent" ],
		 [ "eli",     "e" ],
		 [ "ousli",   "ous" ],
		 [ "ization", "ize" ],
		 [ "isation", "ize" ],
		 [ "ation",   "ate" ],
		 [ "ator",    "ate" ],
		 [ "alism",   "al" ],
		 [ "iveness", "ive" ],
		 [ "fulness", "ful" ],
		 [ "ousness", "ous" ],
		 [ "aliti",   "al" ],
		 [ "iviti",   "ive" ],
		 [ "biliti",  "ble" ],
		 [  0,        0     ]];

var suffixes3 = [[ "icate", "ic" ],
		 [ "ative", "" ],
		 [ "alize", "al" ],
		 [ "alise", "al" ],
		 [ "iciti", "ic" ],
		 [ "ical",  "ic" ],
		 [ "ful",   "" ],
		 [ "ness",  "" ],
		 [ 0,       0 ] ];

function suffix_replace_array ( str , suff)
{
  stem = "";
  for ( index = 0 ; suff[index][0] != 0 ; index++ ) {
    if ( has_suffix ( str, suff[index][0], stem ) == 1 ) {
      if ( measure ( stem ) > 0 ) {
	str = stem.concat(suff[index][1] );
	return str;
      }
    }
  }
  return str;
}

function step_2(str)
{
  return suffix_replace_array ( str, suffixes2);
}

function step_3(str)
{
  return suffix_replace_array ( str, suffixes3);
}

var suffixes4 = ["al", "ance", "ence", "er", "ic", "able",
		 "ible", "ant", "ement", "ment", "ent", "sion", "tion",
		 "ou", "ism", "ate", "iti", "ous", "ive", "ize", "ise", 0 ];
function step_4 ( str )
{
  stem = "";
  for ( index = 0 ; suffixes4[index] != 0 ; index++ ) {
    if ( has_suffix ( str, suffixes4[index], stem ) == 1 )
      if ( measure ( stem ) > 1 ) {
	str = stem;
	return str;
      }
  }
  return str;
}

function step_5 ( str )
{
  if ( str.charAt(str.length-1) == 'e' ) {
    if ( measure(str) > 1 )
      /* measure(str)==measure(stem) if ends in vowel */
      str = remove_suffix(str, 1);
    else
      if ( measure(str) == 1 ) {
	stem = str.substr(0, str.length-1);
	if ( cvc(stem) == 0 )
	  str = remove_suffix(str, 1);
      }
  }
  if ( (str.charAt(str.length-1) == 'l')
       && (str.charAt(str.length-2) == 'l')
       && (measure(str) > 1) )
    str = remove_suffix(str, 1);
  return str;
}

function has_suffix ( word, suffix)
{
  tmp = "";
  if ( word.length <= suffix.length )
    return(0);
  if ( (suffix.length > 1) &&
       ( word.charAt(word.length-2) != suffix.charAt(suffix.length-2) ) )
    return 0;
  stem = word.substr(0, word.length - suffix.length);
  tmp = stem;
  tmp = tmp.concat(suffix);
  if (tmp == word)
    return 1;
  else
    return 0;
}

function cvc ( str )
{
  len = str.length;
  if ( len < 3 )
    return 0;
  if ( (vowel(str.charAt(len-1),str.charAt(len-2)) == 0)
       && (str.charAt(len-1) != 'w')
       && (str.charAt(len-1) != 'x')
       && (str.charAt(len-1) != 'y')
       && (vowel(str.charAt(len-2),str.charAt(len-3)) == 1)
       && ( ( (len==3) && (vowel(str.charAt(0),'a') == 0) )
	    || (vowel(str.charAt(len-3),str.charAt(len-4))==0) ) )
    return 1;
  else
    return 0;
}

function vowel ( ch, prev )
{
  switch ( ch ) {
  case 'a':
  case 'e':
  case 'i':
  case 'o':
  case 'u': 
    return 1;
    break;
  case 'y': 
    return( vowel(prev,'?') == 1 );
    break;
  default : 
    return 0;
    break;
  }
}

function measure ( stem )
{
  i=0; 
  count = 0;
  len = stem.length;
  while ( i < len ) {
    for ( ; i < len ; i++ ) 
      if ( i > 0 ) {
	if ( vowel(stem.charAt(i),stem.charAt(i-1)) == 1 )
	  break;
      }
      else 	
        if ( vowel(stem.charAt(i),'a') == 1 )
	  break;
    for ( i++ ; i < len ; i++ ) 
      if ( i > 0 ) {
	if ( vowel(stem.charAt(i),stem.charAt(i-1)) == 0 )
	  break;
      }
      else 
        if ( vowel(stem.charAt(i),'?') == 0 )
	  break;
    if ( i < len ) {
      count++;
      i++;
    }
  }
  return count;
}

function contains_vowel ( word )
{
  for ( i=0 ; i < word.length ; i++ )
    if ( i > 0 ) {
      if ( vowel(word.charAt(i),word.charAt(i-1)) == 1 )
	return 1;
    }
    else 
      if ( vowel(word.charAt(0),'a') == 1 )
        return 1;
  return 0;
}

