// Lookup a cell based on a uint64 key value. Returns nil if key not found.
func (t *HashTableSomeStruct) Lookup(key uint64) *CellSomeStruct {

	var cell *CellSomeStruct

	if key == 0 {
		if t.zero().unHashedKey == 1 {
			return t.zero()
		}
		return nil
	}

	h := util.IntegerHash(uint64(key)) % t.ArraySize

	for {
		cell = t.cellAt(h)
		if cell.unHashedKey == key {
			return cell
		}
		if cell.unHashedKey == 0 {
			return nil
		}
		h++
		if h == t.ArraySize {
			h = 0
		}
	}
}
func (t *HashTableSomeStruct) Insert(key uint64) (*CellSomeStruct, bool) {
	var cell *CellSomeStruct

	if key == 0 {
		zc := t.zero()
		// inuse
		isNew := zc.unHashedKey == 0
		if isNew {
			t.Population++
			zc.unHashedKey = 1
		}
		return zc, isNew
	}

	// if key != 0 {
	for {
		h := util.IntegerHash(uint64(key)) % t.ArraySize
		for {
			cell = t.cellAt(h)
			if cell.unHashedKey == key {
				// already exists
				return cell, false
			}
			if cell.unHashedKey == 0 {
				if (t.Population+1)*4 >= t.ArraySize*3 {
					t.Repopulate(t.ArraySize * 2)
					// resized, so start all over
					break
				}
				t.Population++
				cell.unHashedKey = key
				return cell, true
			}

			h++
			if h == t.ArraySize {
				h = 0
			}

		}
	}
}
// DeleteCellSomeStruct deletes the cell pointed to by cell.
func (t *HashTableSomeStruct) DeleteCellSomeStruct(cell *CellSomeStruct) {

	pos := uint64((uintptr(unsafe.Pointer(cell)) - uintptr(unsafe.Pointer(t.cells))) / uintptr(unsafe.Sizeof(CellSomeStruct{})))

	// Delete from regular cells
	if pos < 0 || pos >= t.ArraySize {
		panic(fmt.Sprintf("cell out of bounds: pos %v was < 0 or >= t.ArraySize == %v", pos, t.ArraySize))
	}

	if t.cellAt(pos).unHashedKey == 0 {
		panic("zero unHashedKey in non-zero CellSomeStruct!")
	}

	// Remove this cell by shuffling neighboring cells so there are no gaps in anyone's probe chain
	nei := pos + 1
	if nei >= t.ArraySize {
		nei = 0
	}
	var neighbor *CellSomeStruct
	var circular_offset_ideal_pos int64
	var circular_offset_ideal_nei int64
	var cellPos *CellSomeStruct

	for {
		neighbor = t.cellAt(nei)

		if neighbor.unHashedKey == 0 {
			// There's nobody to swap with. Go ahead and clear this cell, then return
			cellPos = t.cellAt(pos)
			cellPos.unHashedKey = 0
			cellPos.ZeroValue()
			t.Population--
			return
		}

		ideal := util.IntegerHash(neighbor.unHashedKey) % t.ArraySize

		if pos >= ideal {
			circular_offset_ideal_pos = int64(pos) - int64(ideal)
		} else {
			// pos < ideal, so pos - ideal is negative, wrap-around has happened.
			circular_offset_ideal_pos = int64(t.ArraySize) - int64(ideal) + int64(pos)
		}

		if nei >= ideal {
			circular_offset_ideal_nei = int64(nei) - int64(ideal)
		} else {
			// nei < ideal, so nei - ideal is negative, wrap-around has happened.
			circular_offset_ideal_nei = int64(t.ArraySize) - int64(ideal) + int64(nei)
		}

		if circular_offset_ideal_pos < circular_offset_ideal_nei {
			// Swap with neighbor, then make neighbor the new cell to remove.
			*t.cellAt(pos) = *neighbor
			pos = nei
		}

		nei++
		if nei >= t.ArraySize {
			nei = 0
		}
	}
}