//method buildWaveletTree() constructs wavelet tree. It calls creation of RRR lookup table and //adds RRR data structure to every node. public void buildWaveletTree(ArrayList currentAlphabet, String currentLabel, WaveletNode currentNode) { if (currentAlphabet.Count > 2) { StringBuilder bitmapBuilder = new StringBuilder(); StringBuilder leftLabel = new StringBuilder(); StringBuilder rightLabel = new StringBuilder(); StringBuilder RRRbitmap = new StringBuilder(); int blockSize; int superblockSize; int mid = (currentAlphabet.Count + 1) / 2; //creation of node bitmap foreach (char c in currentLabel) { if (getIndex(Char.ToUpper(c), currentAlphabet) < mid) { bitmapBuilder.Append("0"); leftLabel.Append(Char.ToUpper(c)); } else { bitmapBuilder.Append("1"); rightLabel.Append(Char.ToUpper(c)); } } currentNode.setBitmap(bitmapBuilder.ToString()); blockSize = (int)(Math.Log(currentNode.getBitmap().Length, 2) / 2); if (blockSize == 0) { blockSize = 1; } superblockSize = (int)(blockSize * Math.Floor(Math.Log(currentNode.getBitmap().Length, 2))); //creation of RRRLookupTable currentNode.RRRTable.BlockSize = blockSize; currentNode.RRRTable.SuperblockSize = superblockSize; currentNode.RRRTable.ClassBitsNeeded = (int)Math.Floor(Math.Log(blockSize, 2)) + 1; currentNode.RRRTable.buildTableG(); //filling the bitmap with additional zeroes so that every block is equal in size if (bitmapBuilder.Length % blockSize != 0) { do { bitmapBuilder.Append("0"); } while (bitmapBuilder.Length % blockSize != 0); } //creation of bitmap which is being used for creation od RRR data structure currentNode.setHelpBitmap(bitmapBuilder.ToString()); //creation od RRR Data Structure int totalPopcount = 0; for (int i = 0; i < currentNode.getHelpBitmap().Length; i = i + blockSize) { int popCount = popcount(currentNode.getHelpBitmap().Substring(i, blockSize)); RRRbitmap.Append(ToBin(popCount, currentNode.RRRTable.ClassBitsNeeded)); //spremi klasu sa potrebnim brojem bitova RRRbitmap.Append(ToBin(currentNode.RRRTable.TableG.FirstOrDefault(t => t.Key == popCount).Value.IndexOf(currentNode.getHelpBitmap().Substring(i, blockSize)), (int)Math.Ceiling(Math.Log((GetBinCoeff(blockSize, popCount)), 2)))); totalPopcount += popCount; if (((i + blockSize) % superblockSize) == 0 || (i + blockSize) >= currentNode.getHelpBitmap().Length) { currentNode.RRRStruct.superblockSums.Add(totalPopcount); currentNode.RRRStruct.superblockOffsets.Add(RRRbitmap.Length); } } currentNode.RRRStruct.Bitmap = RRRbitmap.ToString(); currentNode.setLeftChild(new WaveletNode()); currentNode.getLeftChild().setParent(currentNode); buildWaveletTree(currentAlphabet.GetRange(0, mid), leftLabel.ToString(), currentNode.getLeftChild()); //if current alphabet has more than 3 characters, than it creates right child and calls recursion on this child if (currentAlphabet.Count > 3) { currentNode.setRightChild(new WaveletNode()); currentNode.getRightChild().setParent(currentNode); buildWaveletTree(currentAlphabet.GetRange(mid, (currentAlphabet.Count - mid)), rightLabel.ToString(), currentNode.getRightChild()); } } else { //creation of child nodes if (currentAlphabet.Count == 2) { StringBuilder bitmapBuilder = new StringBuilder(); StringBuilder RRRbitmap = new StringBuilder(); int blockSize; int superblockSize; foreach (char c in currentLabel) { if (getIndex(Char.ToUpper(c), currentAlphabet) + 1 == 1) { bitmapBuilder.Append("0"); } else { bitmapBuilder.Append("1"); } } currentNode.setBitmap(bitmapBuilder.ToString()); blockSize = (int)(Math.Log(currentNode.getBitmap().Length, 2) / 2); superblockSize = (int)(blockSize * Math.Floor(Math.Log(currentNode.getBitmap().Length, 2))); currentNode.RRRTable.BlockSize = blockSize; currentNode.RRRTable.SuperblockSize = superblockSize; currentNode.RRRTable.ClassBitsNeeded = (int)Math.Floor(Math.Log(blockSize, 2)) + 1; currentNode.RRRTable.buildTableG(); if (bitmapBuilder.Length % blockSize != 0) { do { bitmapBuilder.Append("0"); } while (bitmapBuilder.Length % blockSize != 0); } currentNode.setHelpBitmap(bitmapBuilder.ToString()); int totalPopcount = 0; for (int i = 0; i < currentNode.getHelpBitmap().Length; i = i + blockSize) { int popCount = popcount(currentNode.getHelpBitmap().Substring(i, blockSize)); RRRbitmap.Append(ToBin(popCount, currentNode.RRRTable.ClassBitsNeeded)); //spremi klasu sa potrebnim brojem bitova RRRbitmap.Append(ToBin(currentNode.RRRTable.TableG.FirstOrDefault(t => t.Key == popCount).Value.IndexOf(currentNode.getHelpBitmap().Substring(i, blockSize)), (int)Math.Ceiling(Math.Log((GetBinCoeff(blockSize, popCount)), 2)))); totalPopcount += popCount; if (((i + blockSize) % superblockSize) == 0 || (i + blockSize) >= currentNode.getHelpBitmap().Length) { currentNode.RRRStruct.superblockSums.Add(totalPopcount); currentNode.RRRStruct.superblockOffsets.Add(RRRbitmap.Length); } } currentNode.RRRStruct.Bitmap = RRRbitmap.ToString(); } return; } }