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