rt300@34: // rt300@34: // hilbert.cpp rt300@34: // sonicZoom rt300@34: // rt300@34: // Created by Robert Tubb on 04/04/2013. rt300@34: // rt300@34: // rt300@34: rt300@34: #include "hilbert.h" rt300@34: rt300@43: // UTILS rt300@34: //-------------------------------------------------------------------- rt300@34: unsigned int rotl(unsigned int value, int shift, int digits) { rt300@34: unsigned int ones = (1 << digits) - 1; rt300@34: if(shift >= digits) rt300@34: shift -= digits; rt300@34: rt300@34: unsigned int out = (value << shift) | (value >> (digits - shift)); rt300@34: return out & ones; rt300@34: } rt300@34: //-------------------------------------------------------------------- rt300@34: unsigned int rotr(unsigned int value, int shift, int digits) { rt300@34: int ones = (1 << digits) - 1; rt300@34: // can only handle -digits to 2*digits-1 rt300@34: if(shift >= digits) shift = shift - digits; rt300@34: if(shift < 0) shift = digits + shift; rt300@34: unsigned int out = (value >> shift) | (value << (digits - shift)); rt300@34: return out & ones; rt300@34: } rt300@34: //-------------------------------------------------------------------- rt300@34: unsigned int bin2dec(vector binary){ rt300@34: // takes in a vector of booleans. we assume that the leftmost bool (highest index) is the MSB rt300@34: unsigned int dec = 0; rt300@34: int i,pwr; rt300@34: int N = binary.size(); rt300@34: rt300@34: for (i = 0; i dec2bin(unsigned int number, unsigned int size){ rt300@34: vector bin; rt300@34: int i, pwr; rt300@34: for(i=0;i= (1 << size)){ rt300@34: cout << " bad size for Hilbert::dec2bin" << "\n"; rt300@34: return bin; rt300@34: } rt300@34: for(i=0;i vcode){ rt300@34: vector::iterator bit; rt300@34: rt300@34: for(bit=vcode.begin(); bit!=vcode.end() ; bit++){ rt300@34: rt300@34: cout << *bit; rt300@34: } rt300@34: cout << "\n"; rt300@34: rt300@34: } rt300@34: //-------------------------------------------------------------------- rt300@43: //==================================================================== rt300@43: //-------------------------------------------------------------------- rt300@43: rt300@43: Hilbert::Hilbert(){ rt300@43: N = 7; rt300@43: P = 5; rt300@43: codeLength = (int)pow(2.0,P); rt300@43: rt300@43: rt300@43: makeCode(); rt300@43: makeRotationRules(); rt300@43: rt300@43: } rt300@43: rt300@43: //-------------------------------------------------------------------- rt300@43: rt300@43: Hilbert::Hilbert(int aN, int aP){ rt300@34: N = aN; rt300@34: P = aP; rt300@34: codeLength = (int)pow(2.0,P); rt300@43: rt300@43: rt300@34: makeCode(); rt300@34: makeRotationRules(); rt300@34: rt300@43: } rt300@43: //-------------------------------------------------------------------- rt300@43: rt300@43: void Hilbert::changeCurve(int aN, int aP){ rt300@43: N = aN; rt300@43: P = aP; rt300@43: codeLength = (int)pow(2.0,P); rt300@34: rt300@34: rt300@43: makeCode(); rt300@43: makeRotationRules(); rt300@34: rt300@34: } rt300@34: //-------------------------------------------------------------- rt300@34: void Hilbert::makeRotationRules(){ rt300@43: theRotations.clear(); rt300@43: theEntryVertices.clear(); rt300@34: rt300@43: const int *rp; rt300@43: const int *ep; rt300@43: if(P == 5){ rt300@43: rp = rotations5; rt300@43: ep = entryVertices5; rt300@43: }else if(P == 4){ rt300@43: rp = rotations4; rt300@43: ep = entryVertices4; rt300@43: }else if(P == 3){ rt300@43: rp = rotations3; rt300@43: ep = entryVertices3; rt300@43: }else if(P == 2){ rt300@43: rp = rotations2; rt300@43: ep = entryVertices2; rt300@43: }else if(P == 1){ // will this even work? rt300@43: rp = rotations1; rt300@43: ep = entryVertices1; rt300@43: }else{ rt300@43: cout << "ERROR: makeRotationRules: bad numb of MIDI params"; rt300@43: return; rt300@43: } rt300@43: rt300@43: for(int i=0; i < codeLength; i++){ // fill vector rt300@43: rt300@43: theEntryVertices.push_back(ep[i]); rt300@43: theRotations.push_back(rp[i]); rt300@43: rt300@43: } rt300@34: rt300@34: } rt300@34: //-------------------------------------------------------------- rt300@34: void Hilbert::makeCode(){ rt300@34: rt300@34: ////////////////////////////////~~~,,,,,,,,......... rt300@34: ////////// gray code generation rt300@34: ////// rt300@34: /// rt300@43: // choose the gray code sequence and rotation based on the numnber of dimensions P rt300@34: rt300@34: // ALL SEQUENCES SHOULD END WITH 1 0 0 ... i.e. MSB changes rt300@34: rt300@34: // max MRL 5 digit rt300@43: rt300@43: theGrayCode.clear(); rt300@43: theGrayCodeD.clear(); rt300@43: rt300@43: int trans5[] = {2,3,4,0,2,1,4,3,2,0,4,3,2,1,4,0,2,3,4,0,2,1,4,3,2,0,4,3,2,1,4,0}; rt300@34: rt300@34: // other ones rt300@34: int trans4[] = {1,2,0,3,0,2,1,2,3,0,3,2,1,3,1,0}; rt300@34: int trans3[] = {1,2,1,0,1,2,1,0}; rt300@34: int trans2[] = {1,0,1,0}; rt300@43: int trans1[] = {0,0}; rt300@34: // balanced 5 rt300@34: int transB5[] = {1,2,3,4,5,1,5,2,3,5,2,4,2,3,4,1,4,3,2,3,1,5,3,4,1,5,2,5,3,4,1,3}; rt300@34: rt300@43: int *tp; rt300@43: rt300@34: rt300@34: if(P == 5){ rt300@43: tp = trans5; rt300@43: }else if(P == 4){ rt300@43: tp = trans4; rt300@43: }else if(P == 3){ rt300@43: tp = trans3; rt300@43: }else if(P == 2){ rt300@43: tp = trans2; rt300@43: }else if(P == 1){ // will this even work? rt300@43: tp = trans1; rt300@34: } rt300@43: rt300@34: rt300@34: int code[codeLength][P]; // start with normal array rt300@34: for(int j=0; j()); rt300@34: rt300@34: for(int j=0; j Hilbert::calculateParamsFromIndex(unsigned long long index){ rt300@34: // set %set start and direction of biggest cube rt300@34: unsigned int i; rt300@34: unsigned int mask = (1 << P) - 1; rt300@34: unsigned int entryPoint = 0; rt300@34: int direction = P - 1, directionInv = P-1; rt300@34: unsigned int vertex=0, subindex=0, newe=0, newd=0, entryPointInv = 0; rt300@34: rt300@34: unsigned int pbin[N]; rt300@34: rt300@34: vector params; rt300@34: for(i=0; i= 0; blev--){ rt300@34: // get next highest bits of index rt300@34: rt300@34: subindex = index >> blev*P; rt300@34: subindex = mask & subindex; rt300@34: rt300@35: //cout << "subindex: " << subindex << "\n"; rt300@34: // which vertex corresponds to this index? rt300@34: if(subindex < theGrayCode.size()) vertex = theGrayCodeD[subindex]; rt300@34: rt300@35: //cout << "rotated: " << vertex << "\n"; rt300@34: rt300@34: rt300@34: //% inverse rotate this T_e,d rt300@34: entryPointInv = rotr(entryPoint, direction+1,P); rt300@34: directionInv = (P - direction - 2); rt300@34: vertex = rotate(vertex,entryPointInv,directionInv); rt300@34: rt300@35: //cout << "vertex: " << vertex << "\n"; rt300@34: rt300@34: //% build up bits of params rt300@34: rt300@34: for(int j=0;j> P-j-1) & 1)*(1< theEntryVertices.size()){ rt300@43: cout << "ERROR: subindex too large for theEntryVertices\n"; rt300@34: } rt300@43: newe = theEntryVertices[subindex]; rt300@43: newd = theRotations[subindex]; rt300@34: // next rotations... rt300@34: int lse2 = rotr(newe, P-direction-1,P); rt300@34: entryPoint = entryPoint ^ lse2; rt300@34: direction = (direction + newd + 1) % P; rt300@35: //cout << "------------\n"; rt300@34: } rt300@34: rt300@34: return params; rt300@34: } rt300@34: //-------------------------------------------------------------------- rt300@34: int Hilbert::rotate(int vertex, int entryPoint, int direction){ rt300@34: vertex = vertex ^ entryPoint; rt300@34: vertex = rotr(vertex,direction+1,P); rt300@34: return vertex; rt300@34: } rt300@34: //-------------------------------------------------------------------- rt300@34: rt300@34: rt300@34: //-------------------------------------------------------------------- rt300@35: unsigned long long Hilbert::calculateIndexFromParams(vector params){ rt300@34: // set %set start and direction of biggest cube rt300@34: rt300@35: unsigned long long h = 0; rt300@34: rt300@34: unsigned int i; rt300@34: unsigned int entryPoint = 0; rt300@34: int direction = P - 1; rt300@35: unsigned int vertex=0, newe=0, newd=0; rt300@35: unsigned long long subindex; // needs to be long cos we lewt shift by alot rt300@34: vector subindices; rt300@34: rt300@34: rt300@34: // for loop thru bit levels rt300@36: rt300@34: for(int blev = N-1; blev >= 0; blev--){ rt300@34: //% get next highest bit of param rt300@34: rt300@34: vector vertexb; rt300@34: for(i=0;i theEntryVertices.size()){ rt300@43: cout << "ERROR: subindex too large for theEntryVertices\n"; rt300@43: } rt300@43: newe = theEntryVertices[subindex]; rt300@43: newd = theRotations[subindex]; rt300@34: rt300@34: // next rotations... rt300@34: int lse2 = rotr(newe, P-direction-1,P); rt300@34: entryPoint = entryPoint ^ lse2; rt300@34: direction = (direction + newd + 1) % P; rt300@34: rt300@34: // now build up h from subindices rt300@34: h += subindex << (blev*P); rt300@35: //cout << "------------\n"; rt300@34: } rt300@34: rt300@34: return h; rt300@34: } rt300@34: //--------------------------------------------------------------------