package org.dgpf.search.api.utils;
import org.sfc.collections.Arrays;
import org.sfc.utils.Typesafe;
/**
* This class is used to build a weighted set.
* @param <Type> The sort of the individuals to be stored in the weighted
* set.
* @author Thomas Weise
*/
public final class WeightedSetBuilder<Type>
{
/**
* The data.
*/
Type[] m_data ;
/**
* The weight.
*/
double[] m_weights ;
/**
* The individual count.
*/
int m_count ;
/**
* The class of the items.
*/
final Class<Type> m_class ;
/**
* Create a new weighted set builder.
* @param p_class The class of the items.
*/
public WeightedSetBuilder(final Class p_class)
{
super();
this.m_class = Typesafe.cast(p_class);
this.m_weights = new double[8];
this.m_data = Arrays.create(this.m_class, 8);
}
/**
* Check whether an item is contained in the weighted set builder or not.
* @param p_item The item to find.
* @return <code>true</code> if and only if this item is contained in the
* weighted set builder, <code>false</code> otherwise.
*/
public final boolean contains (final Type p_item)
{
int l_c;
Type[] l_d;
if(p_item != null)
{
l_d = this.m_data;
for(l_c = (this.m_count-1); l_c >= 0; l_c--)
{
if(l_d[l_c].equals(p_item)) return true;
}
}
return false;
}
/**
* Add a set of items.
* @param p_items The items to be added.
* @param p_weights The weights of the items to be added.
*/
public final void add (final Type[] p_items,
final double[] p_weights)
{
int l_i;
for(l_i = (Math.min(p_items.length, p_weights.length)-1); l_i >= 0; l_i--)
{
this.add(p_items[l_i], p_weights[l_i]);
}
}
/**
* Add a new object to this weighted set builder.
* @param p_item The new item to be added.
* @param p_weight The weight of this item.
*/
public final void add (final Type p_item,
final double p_weight)
{
int l_c, l_i;
Type[] l_d;
double[] l_p;
if((p_item == null) || (p_weight <= 0.0d)) return ;
l_d = this.m_data;
l_c = this.m_count;
l_p = this.m_weights;
for(l_i = (l_c-1); l_i >= 0; l_i--)
{
if(l_d[l_i] == p_item)
{
l_p[l_i] += p_weight;
return;
}
}
if(l_c >= l_d.length)
{
l_d = Arrays.create(this.m_class, l_c << 1);
System.arraycopy(this.m_data, 0, l_d, 0, l_c);
this.m_data = l_d;
l_p = new double[l_c << 1];
System.arraycopy(this.m_weights, 0, l_p, 0, l_c);
this.m_weights = l_p;
}
l_d[l_c] = p_item;
l_p[l_c] = p_weight;
this.m_count = (l_c+1);
}
/**
* Add all items of another weighted set builder to this set builder.
* @param p_set The set to be added.
*/
public final void add (final WeightedSetBuilder<? extends Type> p_set)
{
int l_i;
double[] l_d;
Type[] l_x;
if( (p_set != null) && ((l_i = (l_d = p_set.m_weights).length) > 0))
{
l_x = p_set.m_data;
for(--l_i; l_i >= 0; l_i--)
{
this.add(l_x[l_i], l_d[l_i]);
}
}
}
/**
* Add all items of another weighted set to this set builder.
* @param p_set The set to be added.
*/
public final void add (final WeightedSet<? extends Type> p_set)
{
double l_w, l_ov, l_z;
int l_i, l_j;
double[] l_d;
Type[] l_x;
if( (p_set != null) && ((l_i = (l_d = p_set.m_weights).length) > 0) &&
((l_w = p_set.m_weight) > 0.0d))
{
l_x = p_set.m_data;
l_ov = 0.0d;
l_i--;
for(l_j = 0; l_j < l_i; l_j++)
{
l_z = l_d[l_j];
this.add(l_x[l_j], ((l_z - l_ov)*l_w));
l_ov = l_z;
}
this.add(l_x[l_i], ((1.0d - l_ov)*l_w));
}
}
/**
* Obtain the count of stored elements.
* @return The count of stored elements.
*/
public final int get_count()
{
return this.m_count;
}
/**
* Obtain the weight of the item at index <code>p_index</code>.
* @param p_index The index of the item to obtain the weight of.
* @return The weight of the item at index <code>p_index</code>.
*/
public final double get_weight(final int p_index)
{
return this.m_weights[p_index];
}
/**
* Obtain the item at index <code>p_index</code>.
* @param p_index The index of the item to obtain.
* @return The item at index <code>p_index</code>.
*/
public final Type get(final int p_index)
{
return this.m_data[p_index];
}
}