Trochę zabawne jest używanie arytmetyki zmiennoprzecinkowej (Math.floor) do algorytmu ściśle bitowego.
Zakładając, że wysoki stan to 1, a niski, to 0 (zamiast przyjmowania "radiowego" 1 i -1) można zrobić efektywny algorytm tworzący dowolny kod dla bitów 0 i 1.
Rzuć okiem na metodę get poniższego kodu. To jest algorytm kodowania o który Ci chodzi. Algorytm używa interfejsu BitVector, ale można go dość łatwo zamienić na boolean[] (tyle, że wtedy marnujemy 7/8 bitów takiej tablicy oraz jeszcze bardziej pogarsza to czytelność). Same wiersze w głównej pętli są dość nieczytelne, ale java niestety nie posiada możliwości definiowania operatorów, co w tym przypadku bardzo ułatwiłoby zrozumienie zapisu. Wyniki pośrednie są usuwane z użycia zaraz po każdym drugim obrocie pętli (in = out). Pierwszym argumentem jest jednoelementowa tablica tablic bitowych zawierająca jeden bit tworzona w get(boolean), a następnie przekazywana do cyklicznego rozszerzania w get(BitVector[]).
BitVect nie została tu zaimplementowana, ale nie ma to wpływu na sam kod.
public class OVSF
{
public OVSF(int sizeExponent)
{
this.sizeExp = sizeExponent;
}
public BitVector[] get(boolean bit)
{
BitVector[] wynik = new BitVector[1];
wynik[0] = new BitVect(1).set(0, bit);
return get(wynik);
}
private BitVector[] get(BitVector[] bity)
{
final int size = 1 << sizeExp;
BitVector[] in, out = null;
for(in = bity; in.length < size; in = out)
{ //ilość obrotów potrzebna do uzyskania żądanej długości
int len = in.length;
out = new BitVector[len << 1]; //dwa razy więcej ciągów
for(int i = 0; i < len; ++i) //powielamy i wydłużamy ciągi
{
//pierwsza połowa ciągów
//wydłużamy ciąg przez powielenie
out[i] = in[i].clone().insert(len, in[i]);
//druga połowa ciągów
//wydłużamy ciąg j.w., ale druga część jest odwrócona
//ostatnia zmiana zawartości na in[i] nie wymaga clone()
out[len + i] = in[i].clone().insert(len, in[i].flip());
}
}
return out;
}
private int sizeExp; // np. 5 dla 32, 9 dla 512 (SF)
}
/////////////////////////////////////////////////////////////////
//interfejs tablicy bitowej (implementacja zwykle na long[])
public interface BitVector
extends Cloneable, RandomAccess, Iterable<Boolean>
{
BitVector clone();
long size();
//operacje dostępu
boolean get(int index);
BitVector set(int index, boolean value);
BitVector get(int fromIndex, int toIndex);
//operacje na bitach
BitVector flip();
BitVector and(BitVector other);
BitVector or(BitVector other);
BitVector xor(BitVector other);
//operacje zmieniające indeksy bitów
BitVector shiftLeft(int shift);
BitVector shiftRight(int shift);
BitVector rollLeft(int shift);
BitVector rollRight(int shift);
//operacje zmieniające rozmiar tablicy (i indeksy bitów)
BitVector insert(int index, BitVector other);
BitVector delete(int index, int count);
}
public class BitVect implements BitVector
{
public BitVect()
{
//...
}
public BitVect(int size)
{
//...
}
public BitVect(BitVect toClone)
{
//...
}
//...
}
Implementację BitVector można sobie zrobić np. na podstawe kodu java.util.Bitset.