def fill(self, direction, stop_before=None):
        """Should give the same output as fill, except it
        doesn't support non-cardinal directions or stop_before.
        Twenty times faster than fill in test_ravel."""
        if direction in (UP_RIGHT, DOWN_RIGHT, UP_LEFT,
                                        UP_RIGHT):
            return self._fill(direction, stop_before)

        def what_to_get(cell):
            """converts bag coordinates into thing to pass to get_at"""
            cell_coord = (cell.x, cell.y)
            retval = []
            for cell_coord, direction_coord in zip(cell_coord, direction):
                if direction_coord != 0:
                    retval.append(None)
                else:
                    retval.append(cell_coord)
            return tuple(retval)  # TODO yuck

        if direction not in (UP, RIGHT, DOWN, LEFT):
            raise ValueError("Must be a cardinal direction!")

        ### this is what same_row/col should look like!
        small_table = None
        for cell in self.unordered_cells:
            got_rowcol = self.table.get_at(*what_to_get(cell))
            if small_table:
                small_table = small_table.union(got_rowcol)
            else:
                small_table = got_rowcol
        if small_table is None:
            small_table = Bag(table=self.table)

        # now we use the small_table as if it was the table.
        (left_right, up_down) = direction
        bag = small_table.select_other(
            lambda table, bag: cmp(table.x, bag.x) == left_right
            and cmp(table.y, bag.y) == up_down,
            self
        )
        if stop_before is not None:
            return bag.stop_before(stop_before)
        else:
            return bag