Class for Perfect Hashing operations with perfect numbering

It also stores the free identifiers for the perfect numbering

Introduced properties

fun phand(ids: Array[Int]): Int

perfect_hashing :: Perfecthashing :: phand

Returns a mask composed by discriminants bits
fun phandp(ids: Array[Int], mask: Int): Bool

perfect_hashing :: Perfecthashing :: phandp

Checks if the mask is a perfect hashing function for
fun pnand(ids: Array[Int], n: Int, idc: Array[Int]): Int

perfect_hashing :: Perfecthashing :: pnand

Perfect numbering : give new free identifiers

Redefined properties

redef type SELF: Perfecthashing

perfect_hashing $ Perfecthashing :: SELF

Type of this instance, automatically specialized in every class
redef init init

perfect_hashing $ Perfecthashing :: init

Initialize the structure of free identifiers

All properties

fun !=(other: nullable Object): Bool

core :: Object :: !=

Have self and other different values?
fun ==(other: nullable Object): Bool

core :: Object :: ==

Have self and other the same value?
type CLASS: Class[SELF]

core :: Object :: CLASS

The type of the class of self.
type SELF: Object

core :: Object :: SELF

Type of this instance, automatically specialized in every class
protected fun class_factory(name: String): CLASS

core :: Object :: class_factory

Implementation used by get_class to create the specific class.
fun class_name: String

core :: Object :: class_name

The class name of the object.
fun get_class: CLASS

core :: Object :: get_class

The meta-object representing the dynamic type of self.
fun hash: Int

core :: Object :: hash

The hash code of the object.
init init

core :: Object :: init

fun inspect: String

core :: Object :: inspect

Developer readable representation of self.
protected fun inspect_head: String

core :: Object :: inspect_head

Return "CLASSNAME:#OBJECTID".
intern fun is_same_instance(other: nullable Object): Bool

core :: Object :: is_same_instance

Return true if self and other are the same instance (i.e. same identity).
fun is_same_serialized(other: nullable Object): Bool

core :: Object :: is_same_serialized

Is self the same as other in a serialization context?
intern fun is_same_type(other: Object): Bool

core :: Object :: is_same_type

Return true if self and other have the same dynamic type.
intern fun object_id: Int

core :: Object :: object_id

An internal hash code for the object based on its identity.
fun output

core :: Object :: output

Display self on stdout (debug only).
intern fun output_class_name

core :: Object :: output_class_name

Display class name on stdout (debug only).
fun phand(ids: Array[Int]): Int

perfect_hashing :: Perfecthashing :: phand

Returns a mask composed by discriminants bits
fun phandp(ids: Array[Int], mask: Int): Bool

perfect_hashing :: Perfecthashing :: phandp

Checks if the mask is a perfect hashing function for
fun pnand(ids: Array[Int], n: Int, idc: Array[Int]): Int

perfect_hashing :: Perfecthashing :: pnand

Perfect numbering : give new free identifiers
fun serialization_hash: Int

core :: Object :: serialization_hash

Hash value use for serialization
intern fun sys: Sys

core :: Object :: sys

Return the global sys object, the only instance of the Sys class.
abstract fun to_jvalue(env: JniEnv): JValue

core :: Object :: to_jvalue

fun to_s: String

core :: Object :: to_s

User readable representation of self.
package_diagram perfect_hashing::Perfecthashing Perfecthashing core::Object Object perfect_hashing::Perfecthashing->core::Object

Parents

interface Object

core :: Object

The root of the class hierarchy.

Class definitions

perfect_hashing $ Perfecthashing
# Class for Perfect Hashing operations with perfect numbering
# It also stores the free identifiers for the perfect numbering
class Perfecthashing

	# Union of interval for implementing perfect numbering
	# Represents the interval of free identifiers
	# A null value represents the upper bound of identifier
	private var interval = new List[Couple[nullable Int, nullable Int]]

	# An array used as a temporary Hashtable for
	# checking there is no collision between identifiers
	private var tempht = new Array[nullable Int]

	# Initialize the structure of free identifiers
	init
	do
		# By default, all identifiers are available
		interval.push(new Couple[nullable Int, nullable Int](1, null))
	end

	# Returns a mask composed by discriminants bits
	# for these given identifiers
	# The mask + 1 value is the size of the hastable to create
	fun phand(ids: Array[Int]): Int
	do
		var mask = 1

		# If ids is null return 1
		if ids.length == 0 then
			return mask
		end

		var orMask = 0
		var andMask = 0
		for i in ids do
			orMask |= i
			andMask &= i
		end

		mask = orMask ^ andMask

		# Re-initialize the hashtable with null values
		for i in [0..(mask+1)] do tempht[i] = null

		# Optimize the already computed mask
		var newmask = 0
		var i = mask.highest_bit
		while i != 0 do
			if mask.getbit(i) == 1 then
				newmask = mask ^ (1 << i)

				# If there is no collision, replace the old mask
				if phandp(ids, newmask) then
					mask = newmask
				end
			end

			i -= 1
		end

		return mask + 1
	end

	# Checks if the mask is a perfect hashing function for
	# these identifiers
	fun phandp(ids: Array[Int], mask: Int): Bool
	do
		for i in ids do
			var hv = i & mask
			if tempht[hv] == mask then
				return false
			else
				tempht[hv] = mask
			end
		end

		return true
	end

	# Perfect numbering : give new free identifiers
	# ids : identifiers to hash (super-classes)
	# n : number of required free identifiers
	# idc : This array will be filled with n free identifiers
	# return the size of hashTable to create for theses identifiers (mask + 1)
	#
	#     var ph = new Perfecthashing
	#     var idc = new Array[Int]
	#     assert ph.pnand([3, 7, 10], 1, idc) == 6
	#     assert idc[0] == 4
	#     var idc1 = new Array[Int]
	#     assert ph.pnand([3, 7, 10], 1, idc1) == 6
	#     assert idc1[0] == 6
	fun pnand(ids: Array[Int], n: Int, idc: Array[Int]): Int
	do
		var mask = phand(ids) -1
		var i = 0
		while n+ids.length > (1 << mask.number_bits(1)) do
			# When there are not enough 1-bits
			if mask.getbit(i) == 0 then
				mask = mask ^ (1 << i)
			end
			i += 1
		end

		# Resetting hashtable
		for j in [0..(mask+1)] do tempht[j] = null

		# Set the temporary hashtable for `compute_least_free_ids`
		phandp(ids, mask)

		# Fill the given array with n free identifiers
		compute_least_free_ids(n, mask, idc)

		return mask + 1
	end


	# Compute free identifiers for future perfect numbering
	# n : number of required ids
	# mask : perfect hashing parameter
	# idc : This array will be filled with n free identifiers
	private fun compute_least_free_ids(n: Int, mask: Int, idc: Array[Int])
	do
		while n != 0 do
			idc.push(first_valid_id(mask))
			n = n - 1
		end
	end

	# Returns the first valid free identifier which correspond to this mask
	private fun first_valid_id(mask: Int): Int
	do
		# Search for the first valid free identifier
		var inter = interval.iterator
		var found = false
		var id = 0
		while inter.is_ok and not found do
			var i = inter.item.first.as(not null)
			while i != inter.item.second and not found do
				# Tests if this id is free for this mask
				var hv = i & mask

				# If the hashtable if full, push an empty item
				if hv >= tempht.length then
					tempht.push(null)
				end

				if tempht[hv] != mask then
					found = true
					id = i
				end
				i = i + 1
			end

			if not found then
				inter.next
			end
		end

		# Updates the structure of union of intervals
		if id == inter.item.first then
			if inter.item.first == inter.item.second then
				inter.delete
			else
				inter.item.first += 1
			end
		else
			if id != inter.item.first and id != inter.item.second then
				# We need to split in two this interval
				var last = inter.item.second
				inter.item.second = id - 1
				inter.next

				var p = new Couple[nullable Int, nullable Int](id + 1, last)
				if inter.is_ok then
					inter.insert_before(p)
				else
					interval.push(p)
				end
			else
				inter.item.second = id - 1
			end
		end

		return id
	end
end
lib/perfect_hashing/perfect_hashing.nit:20,1--206,3