def train( self, row ):

    if Frontend.train( self, row ):
      return True;

    for ( i, xval ) in enumerate( row ):

      if not i in self._dbs:
        dbdn = None;
        with TemporaryDirectory() as tmpdirname:
          dbdn = tmpdirname;        
        self._dbdirs.append( dbdn );
        self._dbs[ i ] = plyvel.DB( dbdn, create_if_missing=True );

      xval \
        = int( float(xval) * 1000.0 );

      assert xval < (1<<30);

      xval \
        = pack( ">I", (1<<31) + xval );

      xcnt \
        = unpack(
              ">I",
              self._dbs[ i ].get( xval, default=pack( ">I", 0 ) )
            )[ 0 ];

      xcnt += 1;

      self._dbs[ i ].put( xval, pack( ">I", xcnt ) );

    return False;
  def train( self, row ):

    if Frontend.train( self, row ):
      return True;

    self._data.append( row );

    return False;
  def train( self, row ):

    if Frontend.train( self, row ):
      return True;

    b = 0;
    for i in range( 0, len(row) ):
      if row[i] == 1:
        b |= (1<<i);

    self._stats[ b ] = self._stats.get( b, 0 ) + 1;

    return False;
  def train( self, row ):

    ( y, c, b, x ) = row;

    if self._len_c is None:
      self._len_c = len(c);
    assert self._len_c == len(c);

    if self._len_b is None:
      self._len_b = len(b);
    assert self._len_b == len(b);

    if self._len_x is None:
      self._len_x = len(x);
    assert self._len_x == len(x);

    row = c + b + x;

    if Frontend.train( self, row ):
      return True;

    keyfmt = '>IIIII';

    for i in range( 0, self._lenrow ):
      for j in range( 0, self._lenrow ):

        if ( i >= j ) and ( not ( i == self._lenrow-1 ) ):
          continue;

        key = pack( keyfmt, i, j, y, row[i], row[j] );

        try:
          assert self._kdb.increment( key, 1, 0 );
        except:
          print( str(self._kdb.error()) );
          raise;