def iterate dim
    @cells[dim].each_key do |cell| yield cell end
  end
  
  
  
  
  
  
  
  
  
  
  def add (lower,data = nil, inverted = false)
    begin
      
      lower.each do |lowCell|
        if (!lowCell.is_a?(Cell) || !member?(lowCell))
          raise "object #{lowCell} is not a cell" 
        end
      end
      
      
      if (lower != [])
        ld = lower[0].dim
        exit if ld >= @dim
        lower.each do |lowCell|
          if (lowCell.dim != ld) 
            raise "boundary cells have different dimension" 
          end
        end
      end
      
      
      cellDim = (lower.empty? ? 0 : lower[0].dim+1 )
      cell = @cellCreate.call(self, cellDim, data)
      @lower[cell] = lower
      @upper[cell] = Array.new
      @cells[cellDim][cell] = true
      @inverted[cell] = inverted
      
      
      
      
      lower.each do |lowCell|
        @lower[lowCell].each do |lowestCell|
          matches = @upper[lowestCell] & lower
          if (matches.length > 2)
            raise "diamond property violation"
          end
          if (matches.length == 2)
            @switchH[[lowestCell,matches[1],cell]] = matches[0]
            @switchH[[lowestCell,matches[0],cell]] = matches[1]
          end
        end
        @upper[lowCell].push(cell)
      end
      
      
      
      
      if (cellDim == 1)
        if lower.length > 2
          raise "diamond property violation" 
        end
        if (lower.length == 2) 
          @switchH[[nil,lower[0],cell]] = lower[1]
          @switchH[[nil,lower[1],cell]] = lower[0]
        else
          
          @switchH[[nil,lower[0],cell]] = lower[0]
        end
      end
      
      
      
      
      
      if (cell.dim == @dim)
        lower.each do |lowCell|
          upper = @upper[lowCell]
          if upper.length > 2
            raise "diamond property violation"
          end
          if (upper.length == 2)
            @switchH[[lowCell,upper[0],nil]] = upper[1]
            @switchH[[lowCell,upper[1],nil]] = upper[0]
          end
        end
      end
    return cell
    rescue
      raise $!
      
      
    end
  end
  
  
  
  def switch(k, tuple)
    raise "nil Tuple given to switch" if tuple == nil
    raise "non-Tuple given to switch" if !tuple.is_a? CellTuple
    raise "bad call to switch" if k<0 || k>tuple.dim
    raise "bad tuple given to switch" if !tuple.dim.is_a? Integer
    triple = [tuple[k-1], tuple[k], tuple[k+1]]
    otherCell = @switchH[triple]
    if (otherCell == nil) 
      return nil
    else
      newTupArr = Array.new
      for j in 0..tuple.dim
        newTupArr[j] = tuple[j]
      end
      newTupArr[k] = otherCell
      return CellTuple.new(newTupArr)
    end
  end
  
  
  
  
  def delete cell
    
    
    upper = @upper[cell].clone
    upper.each do |upCell| delete upCell end
   
    
    
    @lower[cell].each do |lowCell|
      
      @lower[lowCell].each do |lowestCell|
        otherCell = @switchH[[lowestCell,lowCell,cell]]
        if (otherCell != nil)
          @switchH[[lowestCell,lowCell,cell]] = nil
          @switchH[[lowestCell,otherCell,cell]] = nil
        end
      end
      
      
      if (cell.dim == @dim) 
        otherCell = @switchH[[lowCell, cell, nil]]
        if otherCell != nil
          @switchH[[lowCell, cell, nil]] = nil
          @switchH[[lowCell, otherCell, nil]] = nil
        end
      end
      @upper[lowCell].delete(cell)
    end
    
    @cells[cell.dim].delete(cell)
    @lower[cell] = nil
    @upper[cell] = nil
    @inverted[cell] = nil
  end
  
  
  
  def member? cell
    return @cells[cell.dim].member?(cell)
  end
  
  
  
  
  def down(cell,offset=1)
    return [cell] if (offset == 0)
    lower = Array.new
    @lower[cell].each do |lowCell|
        lower |= self.down(lowCell,offset-1)
    end
    return lower
  end
  
  
  
  
  def up(cell,offset=1)
    return [cell] if (offset == 0)
    upper = Array.new
    return [] if @upper[cell] == nil
    @upper[cell].each do |upCell|
        upper |= self.up(upCell,offset-1)
    end
    return upper
  end
  
  
  
  
  
  
  
  
  
  
  
  def rotate(k, tuple)
    index = k - 1
    nextCell = cell = tuple[index]
    nextTuple = tuple
    begin 
      yield nextCell
      oldTuple = nextTuple
      nextTuple = switch(index, nextTuple)
      index = (index == k) ? k - 1 : k
      nextCell = nextTuple[index] if nextTuple != nil
    end until (nextCell == cell || nextTuple == nil) 
    if (nextTuple == nil)
      yield oldTuple[k-1]
    end
  end
    
  
  
  
  
  
  
  
  
  
  def getTuple(cell)
    begin
      tuple = []
      
      
      k = cell.dim
      if dim < 0 || dim > @dim
        raise "cell has dimesion #{dim} and complex has dimension #{@dim}"
      end
      c = cell
      while k >= 0 do
        tuple[k] = c
        lowC = @lower[c]
        c = (lowC == nil) ? nil : lowC[0]
        if c == nil && k > 0
          raise "non-vertex cell has no boundary elements #{k} #{cell}"
        end
        k -= 1
      end
      
      ctuple = CellTuple.new(tuple)
      ctuple = switch(0, ctuple) if @inverted[ctuple[@dim]]
    return ctuple
  
    rescue => exc
      print "CellComplex.getTuple: ", $!
      puts exc.backtrace
      exit
    end
  end
  
  
  def getFullTuple v
    e = up(v)[0]
    t = up(e)[0]
    CellTuple.new(v, e, t)
  end
  
  
  def getOTuple(ed,tri = nil)
    puts "Warning" if ed==nil
    tri = up(ed)[0] if (tri==nil)
    if tri==nil 
      puts "Cell Complex is not properly constructed. This should not be."
      puts ed
      puts up(ed)
      puts down(ed)
    end
    tup = getTuple(tri)
    while (tup[1] != ed)
      tup = switch(1,switch(0,tup))
    end
    return tup
  end
  
  
  def getOTupleV(v,tri = nil)
    t1 = up(up(v)[0])[0]
    tup = getTuple(t1)
    while (tup[0] != v)
      tup = switch(0,switch(1,tup))
    end
    return tup
  end
  
  
  
  
  def show
    @cells.each do |dCells|
      dCells.each_key do |cell|
        puts "Cell: #{cell} #{cell.data}"
        puts "Upper:"
        @upper[cell].each do |upCell|
          puts "#{upCell}"
        end
        puts "Lower:"
        @lower[cell].each do |lowCell|
          puts "#{lowCell}"
        end
      end
    end
  end
  
  
  
  
  def import otherComplex
    @switchH.update(otherComplex.switchH)
    @cells.each_index {|i| @cells[i].update(otherComplex.cells[i]) }
    @lower.update(otherComplex.lower)
    @upper.update(otherComplex.upper)
    @inverted.update(otherComplex.inverted)
  end
  attr_reader :dim
  attr_reader :cells,:switchH,:lower,:upper,:inverted
  
  
  
end