Scrambler
1
|
00001 //######################################################################### 00002 // 00003 // Copyright (C) 2003-2012 Department of Physics and Astronomy, 00004 // University of Rochester, 00005 // Rochester, NY 00006 // 00007 // hilbert.c is part of AstroBEAR. 00008 // 00009 // AstroBEAR is free software: you can redistribute it and/or modify 00010 // it under the terms of the GNU General Public License as published by 00011 // the Free Software Foundation, either version 3 of the License, or 00012 // (at your option) any later version. 00013 // 00014 // AstroBEAR is distributed in the hope that it will be useful, 00015 // but WITHOUT ANY WARRANTY; without even the implied warranty of 00016 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00017 // GNU General Public License for more details. 00018 // 00019 // You should have received a copy of the GNU General Public License 00020 // along with AstroBEAR. If not, see <http://www.gnu.org/licenses/>. 00021 // 00022 //######################################################################### 00026 #include <stdio.h> 00027 #include <math.h> 00028 00029 00030 void closedformhilbert2d_(int * nn, int * rr, int * cc, int * hh) { 00031 unsigned h=0; 00032 unsigned ri=0; 00033 unsigned ci=0; 00034 unsigned pos; 00035 unsigned mask; 00036 unsigned i, tmp; 00037 unsigned n; 00038 unsigned r; 00039 unsigned c; 00040 n = *nn; 00041 r = *rr; 00042 c = *cc; 00043 00044 // In 2D the hilbert curve looks like 00045 // ___ 00046 // | | Ordering for cases 2 4 Hilbert Order 1 2 00047 // | | -----------------> 1 3 -----------------> 0 3 00048 00049 // 00050 // __ __ __ __ 00051 // | |__| | 4 sub pieces | | | | 2 4 | 2 is in standard orientation 00052 // |__ __| --------> __ __ | 4 is also instandard orientation 00053 // __| |__ __| |__ 1 3 | 1 needs to be flipped about x=y 00054 // | 3 needs to be flipped about x=-y 00055 00056 // Basic idea is to coarsen hilbert curve out to get the 00057 // meta position which determins the case and the coarse "meta" hilbert value 00058 // Then depending on which case, re-orient the sub grid so that it is in standard 00059 // orientation. Then multiply the meta hilbert value by 4 before adding the next 00060 // level value and so on... 00061 00062 // example n=3, r=4=100 ,c=5=101 00063 // pos=100 00064 // mask=011 00065 00066 // i=0-> ri=001, ci=001 -> case 4 (meta hilbert value = 2) 00067 // ri->1, ci->0 00068 // r=000, c=001 00069 // h=10 00070 // pos=010 00071 // mask=001 00072 00073 // i=1-> ri=000, ci=000 -> case 1 (meta hilbert value = 0) 00074 // ri->0, ci->0 00075 // r=001, c=000 00076 // h=1000 00077 // pos=001 00078 // mask=000 00079 00080 // i=2-> ri=1, ci=0 -> case 3 (meta hilbert value = 3) 00081 // ri->1, ci->1 00082 // r=000, c=000 00083 // h=100011 00084 // pos=000 00085 // mask=000 00086 00087 //hilbert value = 100011 = 35 00088 00089 pos = 1 << (n-1); // bit mask used to extract ri and ci which are meta positions of the coarsened hilbert curve 00090 mask = pow(2,(n-1))-1; // 0001111111 mask used to subtract off ci and ri to get relative positions within the coarsened hilbert curve 00091 for (i=0; i<n; i++) { 00092 00093 ri = (r & pos) >> (n-i-1); // meta row position of coarsened hilbert curve 00094 ci = (c & pos) >> (n-i-1); // meta column position of coarsened hilbert curve 00095 r = r & mask; c = c & mask; // local row and column positions within the current section of the meta hilbert curve 00096 00097 if (ri==0 && ci==0) { // Case 1 (Lower left corner) 00098 ri = 0; ci = 0; // meta hilbert value = 0 -> 00 in binary 00099 tmp = r; r = c; c = tmp; } // In order to rotate the next meta hilbert tree into standard order we need to reflect about x=y or swap r and c 00100 else if (ri==0 && ci==1) { // Case 2 (Upper Left corner) 00101 ri = 0; ci = 1; } // meta hilbert value = 1 -> 01 in binary (already in standard order) 00102 else if (ri==1 && ci==0) { // Case 3 (Lower right corner) 00103 ri = 1; ci = 1; // meta hilbert value = 3 -> 11 in binary 00104 tmp = r; r = c; c = tmp; // Need to rotate -90 and reflect in x (x->-y->-y, y->x->-x) or (x=-y, y=-x) 00105 r = ~r & mask; c = ~c & mask; } // to arrange in standard order 00106 else { // Case 4 (Upper right corner) 00107 ri = 1; ci = 0; } // meta hilbert value = 2 -> 10 in binary (Already in standard order) 00108 00109 pos = pos >> 1; mask = mask >> 1; // shift pos and mask to next finer level of hilbert fractal 00110 h = (((h << 1) | ri) << 1) | ci; // multiply h by 4 and add contribution from meta hilbert value 00111 } 00112 *hh=h; 00113 } 00114 00115 00116 void closedformhilbert3d_(int * nn, int * rr, int * cc, int * dd, int * hh) { 00117 unsigned h=0; 00118 unsigned ri; 00119 unsigned ci; 00120 unsigned di; 00121 unsigned pos; 00122 unsigned mask; 00123 unsigned i, tmp; 00124 unsigned n; 00125 unsigned r; 00126 unsigned c; 00127 unsigned d; 00128 n = *nn; 00129 r = *rr; 00130 c = *cc; 00131 d = *dd; 00132 00133 // And In 3D the hilbert curve looks like 00134 // ____ 00135 // / / Ordering for cases 5 7 Hilbert Order 6 5 00136 // / __/_ -----------------> 4 6 -----------------> 7 4 00137 // / | / -----------------> 1 3 -----------------> 1 2 00138 // / |/ 0 2 0 3 00139 00140 00141 // I won't draw the second generation hilbert curve - but basic idea is the same for 2D. 00142 // For each case add the appropriate hilbert value based on the hilbert order 00143 // Then reorient the subsection into standard orientation using flips/rotations etc... 00144 // The second generation hilbert curve was taken from Space Filling Curves by ... 00145 00146 h=0; 00147 00148 pos = 1 << (n-1); // bit mask used to extract ri and ci which are meta positions of the coarsened hilbert curve 00149 mask = pow(2,(n-1))-1; // 0001111111 mask used to subtract off ci and ri to get relative positions within the coarsened hilbert curve 00150 for (i=0; i<n; i++) { 00151 ri = (r & pos) >> (n-i-1); // meta row position of coarsened hilbert curve 00152 ci = (c & pos) >> (n-i-1); // meta column position of coarsened hilbert curve 00153 di = (d & pos) >> (n-i-1); // meta depth position 00154 r = r & mask; c = c & mask; d = d & mask; // local row and column positions within the current section of the meta hilbert curve 00155 if (di==0 && ri==0 && ci==0) { // Case 1 (Bottom-Front-Left corner) 00156 di = 0; ri = 0; ci = 0; // meta hilbert value = 0 -> 000 in binary 00157 tmp = c; c = d; d = tmp; } // Need to reflect around c=d 00158 00159 else if (di==0 && ri==0 && ci==1) { // Case 2 (Bottom-Back-Left corner) 00160 di = 0; ri = 0; ci = 1; // meta hilbert value = 1 -> 001 in binary (already in standard order) 00161 tmp = r; r = d; d = tmp; } // Need to reflect about r=d 00162 00163 else if (di==0 && ri==1 && ci==0) { // Case 3 (Bottom-Front-Right corner) 00164 di = 0; ri = 1; ci = 1; // meta hilbert value = 3 -> 011 in binary 00165 tmp = r; r = ~c & mask; c = ~d & mask ; d = tmp;} // need to rotate about [r,-c,d] 00166 00167 else if (di==0 && ri==1 && ci==1) { // Case 4 (Bottom-Back-Right) 00168 di = 0; ri = 1; ci = 0; } // meta hilbert value = 2 -> 010 in binary (Already in standard order) 00169 00170 else if (di==1 && ri==0 && ci==0) { // Case 5 (Top-Front-Left corner) 00171 di = 1; ri = 1; ci = 1; // meta hilbert value = 7 -> 111 in binary 00172 tmp = c; c = ~d & mask; d = ~tmp & mask;} // Need to reflect about c=-d 00173 00174 00175 else if (di==1 && ri==0 && ci==1) { // Case 6 (Top-Back-Left) 00176 di = 1; ri = 1; ci = 0; // meta hilbert value = 6 -> 110 in binary (already in standard order) 00177 tmp = r; r=~d & mask; d=~tmp & mask; } // Need to reflect about d=-r 00178 00179 else if (di==1 && ri==1 && ci==0) { // Case 7 (Top-Front-Right corner) 00180 di = 1; ri = 0; ci = 0; // meta hilbert value = 4 -> 100 in binary 00181 tmp = d; d = ~r & mask; r = ~c & mask; c = tmp;} // Need to reflect about c=-r and then reflect about c=d 00182 00183 else {// (di==1 && ri==1 && ci==1) // Case 8 (Top-Back-Right corner) 00184 di = 1; ri = 0; ci = 1; } // meta hilbert value = 5 -> 101 in binary (Already in standard order) 00185 00186 pos = pos >> 1; mask = mask >> 1; // shift pos and mask to next finer level of hilbert fractal 00187 h = ((((h << 1) | di) << 1) | ri) << 1 | ci; // multiply h by 8 and add contribution from meta hilbert value 00188 } 00189 *hh=h; 00190 }