00001 #include "hilbert.h"
00002
00003 #ifdef __cplusplus
00004 #include <queue>
00005 #include <vector>
00006 #include <iostream>
00007 #include <sstream>
00008 #include <algorithm>
00009 #include <math.h>
00010
00011 using namespace std;
00012
00013 #ifndef PARTITION_TOPOLOGY_VERBOSE
00014 #define PARTITION_TOPOLOGY_VERBOSE 0
00015 #endif
00016
00025 static int gray_encode(int i) {
00026
00027 return i ^ (i/2);
00028 }
00029
00030 static int gray_decode(int n) {
00031 int sh = 1;
00032 int div;
00033 while (true) {
00034 div = n >> sh;
00035 n ^= div;
00036 if (div <= 1) {
00037 return n;
00038 }
00039 sh <<=1;
00040 }
00041 }
00042
00043 static void initial_start_end(int nChunks, int dim, int& start, int& end) {
00044 start = 0;
00046 int mod_val = (-nChunks - 1) % dim;
00047 if (mod_val < 0) {
00048 mod_val += dim;
00049 }
00050 end = pow((double)2, (double)mod_val);
00051 }
00052
00053 static int pack_index(vector<int> chunks, int dim) {
00054 int p = pow((double)2, (double)dim);
00055 int chunk_size = chunks.size();
00056 int val = 0;
00057 for (int i = 0;i < chunk_size; i++) {
00058 val = val*p + chunks[i] ;
00059 }
00060 return val;
00061 }
00062
00063 static vector<int> transpose_bits(vector<int> srcs, int nDests) {
00064 int nSrcs = srcs.size();
00065 vector<int> dests;
00066 dests.resize(nDests);
00067 int dest = 0;
00068 for (int j = nDests - 1; j > -1; j--) {
00069 dest = 0;
00071 for (int k = 0; k < nSrcs; k++) {
00072 dest = dest * 2 + srcs[k] % 2;
00073 srcs[k] /= 2;
00075 }
00076 dests[j] = dest;
00077 }
00078 return dests;
00079 }
00080
00081 static vector<int> pack_coords(vector<int> coord_chunks, int dim) {
00082 return transpose_bits(coord_chunks, dim);
00083 }
00084
00085 static vector<int> unpack_coords(const vector<int> &coords, int dim) {
00086 int biggest = 0;
00087 for(int i=0; i<coords.size(); i++)
00088 {
00089 if(coords[i] > biggest)
00090 biggest = coords[i];
00091 }
00092 int nChunks = max(1, int( ceil( log( (double)biggest + 1)/log(2.0f) ) ) );
00093 return transpose_bits( coords, nChunks );
00094 }
00095
00096
00097 static void unpack_index(int i, int dim, vector<int>& chunks) {
00098 int p = pow((double)2, (double)dim);
00099 int nChunks = max(1, int(ceil(double(log((double)i+1))/log((double)p))));
00100
00101 chunks.resize(nChunks);
00102 for (int j = nChunks-1; j > -1; j--) {
00103 chunks[j] = i % p;
00104 i /= p;
00106 }
00107
00108 }
00109
00110 static int gray_encode_travel(int start, int end, int mask, int i) {
00111 int travel_bit = start ^ end;
00112 int modulus = mask + 1;
00113 int g = gray_encode(i) * (travel_bit * 2);
00114
00115 return ((g | (g/modulus) ) & mask) ^ start;
00116 }
00117
00118 static int gray_decode_travel(int start, int end, int mask, int i) {
00119 int travel_bit = start ^ end;
00120 int modulus = mask + 1;
00121 int rg = (i ^ start) * ( modulus/(travel_bit * 2));
00122 return gray_decode((rg | (rg / modulus)) & mask);
00123 }
00124
00125 static void child_start_end(int parent_start, int parent_end, int mask, int i, int&
00126 child_start, int& child_end) {
00127 int start_i = max(0, (i-1)&~1);
00128
00129 int end_i = min(mask, (i+1)|1);
00130
00131 child_start = gray_encode_travel(parent_start, parent_end, mask, start_i);
00132 child_end = gray_encode_travel(parent_start, parent_end, mask, end_i);
00133
00134 }
00135
00136 vector<int> int_to_Hilbert(int i, int dim) {
00137 int nChunks, mask, start, end;
00138 vector<int> index_chunks;
00139 unpack_index(i, dim, index_chunks);
00140 nChunks = index_chunks.size();
00141
00142 mask = pow((double)2, (double)dim) - 1;
00143
00144 initial_start_end(nChunks, dim, start, end);
00145
00146 vector<int> coord_chunks;
00147 coord_chunks.resize(nChunks);
00148 for (int j = 0; j < nChunks; j++) {
00149 i = index_chunks[j];
00150 coord_chunks[j] = gray_encode_travel(start, end, mask, i);
00151
00153 child_start_end(start, end, mask, i, start, end);
00154
00155 }
00156 return pack_coords(coord_chunks, dim);
00157 }
00158
00159 int Hilbert_to_int(const vector<int>& coords, int dim)
00160 {
00161 vector<int> coord_chunks = unpack_coords( coords, dim );
00162 int i;
00163 int nChunks = coord_chunks.size();
00164 int mask = pow((double)2, (double)dim) - 1;
00165 int start, end;
00166 initial_start_end(nChunks, dim, start, end);
00167 vector<int> index_chunks;
00168 index_chunks.resize(nChunks);
00169 for (int j = 0; j < nChunks; j++) {
00170 i = gray_decode_travel( start, end, mask, coord_chunks[ j ] );
00171 index_chunks[ j ] = i;
00172 child_start_end(start, end, mask, i, start, end);
00173 }
00174
00175 return pack_index( index_chunks, dim );
00176 }
00177
00178 #endif