/** * */ // package edu.neu.ccs.evergreen.ir; /** * @author mohsen * Class RelationCore provides primitive operations for managing packed truth tables * RelationCore is a utility class */ /** * @author mohsen * */ public class RelationCore { /** * Returns a magic number associated with a certain truth table column and value * The magic number associated with column number 0 of the truth table and value 0 * is basically a sequence of alternating 0 and 1 bits, packed together in one integer. * The magic number associated with column number 0 of the truth table and value 1 * is a sequence of alternating 1 and 0 bits, packed together in one integer. * In general: (getMagicNumber(r,n,0) == ~getMagicNumber(r,n,1)) * For column 1: magic numbers are fromed from sequences of two 0's followed by two 1's * For column 2: magic numbers are formed from sequences of four 0's followed by four 1's * For column 3: magic numbers are formed from sequeneces of eight 0's followed by eight 1's * For column 4:magic numbers are formed from sequeneces of sixteen 0's followed by sixteen 1's * There is no other possible columns as long as we are using 32 bit integers * @param rank The rank of the relation, used to determine the truth table height and to check * the position argument * @param variablePosition the position of the desired magic number * @param value the value associated with the desired magic number * @return * @throws IllegalArgumentException */ public static int getMagicNumber(int rank, int variablePosition, int value) throws IllegalArgumentException{ checkRank(rank); checkVariablePosition(variablePosition, rank); checkValue(value); //Truth Table order //each entry in this array represents a packed truth table column int[] MagicNumbers= { 0x55555555, 0x33333333, 0x0F0F0F0F, 0x00FF00FF, 0x0000FFFF }; // used to cut the truth table column at a certain height int mask = getMask(rank); //cut the truth table column int maskedColumn = ((MagicNumbers[variablePosition])&mask); //for value 0 return the masked truth table column //for value 1 return the one's complement of the masked truth table column int returnval = (value==1?mask^maskedColumn:maskedColumn); return returnval; } /** * @param rank the rank for which a mask is seeked * @return 2^2^rank-1 taking care of the case where 2^2^n is out side * the integer range but 2^2^n-1 is not */ public static int getMask(int rank){ checkRank(rank); int[] mask = { 0x1, 0x3, 0xF, 0xFF, 0xFFFF, 0xFFFFFFFF }; return mask[rank]; } /** * Checks if the variable at a given position is irrelevant to the relation * @param relationNumber The relation number * @param rank rank of the relation * @param variablePosition the variable to be checked * @return true if the variable at vairablePosition is irrelevant otherwise returns false */ static public boolean isIrrelevant(int relationNumber,int rank, int variablePosition){ checkRank(rank); checkRelationNumber(relationNumber, rank); checkVariablePosition(variablePosition, rank); //Note that the maximum value of variable position is less than rank by one //Therefore, right shift by (1<>> (unsigned shift right) coz relations of rank 5 might be -ve return ((relationNumber&m)>>>(1<=upperbound)) // throw new IllegalArgumentException("RelationNumber "+relationNumber+" out of range for rank "+rank); } /** * Checks if the given relation forces the given variablePosition * @param relationNumber * @param rank rank of the given relation * @param variablePosition positon of the varible checked for being forced * @return 0 if the given relation forces the given variable to 0 * 1 if the given relation forces the given variable to 1 * -1 given relation doesn't forces the given variable */ static public int isForced(int relationNumber,int rank, int variablePosition){ checkRank(rank); checkRelationNumber(relationNumber, rank); checkVariablePosition(variablePosition, rank); if (isIrrelevant(relationNumber, rank, variablePosition)){ return -1; }else{ int m = getMagicNumber(rank,variablePosition, 1); int rm = relationNumber&m; if(rm == 0){ return 0; }else if (rm==relationNumber){ return 1; }else{ return -1; } } } /** * gets the position of the first variable forced by the given relation * @param relationNumber relation number * @param rank rank of the given relation number * @return -1 if nothing is forced * the position of the first forced variable */ static public int firstForcedVariable(int relationNumber,int rank){ checkRank(rank); checkRelationNumber(relationNumber, rank); int forcedVarPos = -1; for(int variablePosition=0;variablePosition>>s); return r; } /** * Reduces a relation by assigning a value to one of its variables * @param relationNumber * @param rank * @param variablePosition * @param value * @return */ static public int reduce(int relationNumber,int rank,int variablePosition,int value){ checkRank(rank); checkRelationNumber(relationNumber, rank); checkVariablePosition(variablePosition, rank); checkValue(value); int m = getMagicNumber(rank, variablePosition, value); int rm = (relationNumber&m); if (value==0){ rm = rm|(rm<<(1<>>(1<=rank)) throw new IllegalArgumentException("Variable Position "+variablePosition+" is invalid for relations of rank "+rank); } /** * Checks if the given value is either 0 or 1. An IllegalArgumentException is thrown if value is not 0 nor 1. * @param value the value that needs to be checked * @throws IllegalArgumentException */ public static void checkValue(int value) throws IllegalArgumentException{ if((value<0)||(value>1)) throw new IllegalArgumentException("Variables can only be either 0 or 1. recieved "+value); } /** * Checks if the given rank is valid. 32 Bit integers allow for up to rank 5 * Rank has to be >=1. * If the rank is outside the range an IllegalArgumentExcepton is thrown * @param rank the rank to be checked * @throws IllegalArgumentException */ public static void checkRank(int rank) throws IllegalArgumentException{ if((rank<1)||(rank>5)) throw new IllegalArgumentException("Supported ranks are within [1,5]. Sent rank "+rank); } }