1 /* hilbert.c -
2 $Id$
3    Author - Eric Bylaska
4 
5    This file contains 2d hilbert mapping routines
6 
7 */
8 
9 #include <stdio.h>
10 #include <stdlib.h>
11 #include <math.h>
12 #include "typesf2c.h"
13 #include "olist.h"
14 
15 #if defined(WIN32) && !defined(__MINGW32__)
16 #define hilbert2d_map_ HILBERT2D_MAP
17 #endif
18 
19 
20 #define bottom_left     0
21 #define bottom_right    1
22 #define top_left        2
23 #define top_right       3
24 
25 #define right   0
26 #define left    1
27 #define up      2
28 #define down    3
29 
30 int     hilbert2d(int i, int j, int level);
31 int     hilbert_dir(int i, int j, int level, int high, int* start);
32 
33 #if (defined(CRAY) || defined(WIN32)) && !defined(__crayx1) &&!defined(__MINGW32__)
34 #define pspsolve_ PSPSOLVE
35 #endif
36 
hilbert2d_map_(sizex_ptr,sizey_ptr,map)37 void FATR hilbert2d_map_(sizex_ptr,sizey_ptr,map)
38 Integer     *sizex_ptr,*sizey_ptr;
39 Integer     map[];
40 {
41     int i,j,size,sizex,sizey;
42     int ii,jj,iii,jjj;
43     int level,count;
44     double dx,dy,x2,y2,dx2,dy2;
45     OList_Type olist2;
46     int *map2,*mapii,*mapjj;
47 
48    sizex = *sizex_ptr;
49    sizey = *sizey_ptr;
50 
51 
52    size = sizex;
53    if (sizey>size) size = sizey;
54 
55    /* get the level of map */
56    count = 1;
57    level = 0;
58    while (count < size)
59    {
60       ++level;
61       count = count*2;
62    }
63 
64    map2  = (int *) malloc(count*count*sizeof(int));
65    mapii = (int *) malloc(count*count*sizeof(int));
66    mapjj = (int *) malloc(count*count*sizeof(int));
67 
68 
69    //create_olist(&olist2,count*count);
70    //for (jj=0; jj<count; ++jj)
71    //for (ii=0; ii<count; ++ii)
72    //{
73    //
74    //   map2[ii+jj*count] = hilbert2d(ii,jj,level);
75    //   insert_olist(&olist2,map2[ii+jj*count]);
76    //}
77 
78    for (jj=0; jj<count; ++jj)
79    for (ii=0; ii<count; ++ii)
80       map2[ii+jj*count] = hilbert2d(ii,jj,level);
81 
82    create_olist(&olist2,count*count);
83    for (jj=0; jj<count; ++jj)
84    for (ii=0; ii<count; ++ii)
85       insert_olist(&olist2,map2[ii+jj*count]);
86 
87 
88    for (jj=0; jj<count; ++jj)
89    for (ii=0; ii<count; ++ii)
90       map2[ii+jj*count] = index_olist(&olist2,map2[ii+jj*count]);
91 
92    destroy_olist(&olist2);
93 
94    for (jj=0; jj<count; ++jj)
95    for (ii=0; ii<count; ++ii)
96    {
97       mapii[map2[ii+jj*count]] = ii;
98       mapjj[map2[ii+jj*count]] = jj;
99    }
100 
101 
102    dx2 = 1.0/((double) count);
103    dy2 = 1.0/((double) count);
104    dx =  1.0/((double) sizex);
105    dy =  1.0/((double) sizey);
106 
107    for (j=0; j<sizex*sizey; ++j) map[j] = -9;
108 
109    iii = 0;
110    for (jjj=0; jjj<count*count; ++jjj)
111    {
112       ii = mapii[jjj];
113       jj = mapjj[jjj];
114 
115       x2 = dx2*(ii+0.5);
116       y2 = dy2*(jj+0.5);
117       i = rint((x2/dx) - 0.5);
118       j = rint((y2/dy) - 0.5);
119 
120       if (map[i+j*sizex] == -9)
121       {
122         map[i+j*sizex] = iii;
123         ++iii;
124       }
125    }
126    free(mapii);
127    free(mapjj);
128    free(map2);
129 
130 }
131 
132 
hilbert2d(i,j,level)133 int     hilbert2d(i,j,level)
134 int     i,j;
135 int     level;
136 {
137    int  start,direction;
138 
139    direction = hilbert_dir(i,j,level,level,&start);
140 
141    return start;
142 }
143 
144 
parent(i)145 int     parent(i)
146 int     i;
147 {
148    return(i/2);
149 }
150 
corner(i,j)151 int     corner(i,j)
152 int     i,j;
153 {
154    return(2*(j%2) + (i%2));
155 }
156 
hilbert_dir(i,j,level,high,start)157 int     hilbert_dir(i,j,level,high,start)
158 int     i,j;
159 int     level,high;
160 int     *start;
161 {
162    int  direction,parent_direction,
163         crnr,length,
164         count;
165 
166    length = 1;
167    for (count=0; count<(high-level); ++count)
168       length = length*4;
169 
170    if (level == 0)
171    {
172       direction = right;
173       *start    = 0;
174    }
175    else
176    {
177       parent_direction = hilbert_dir(parent(i),parent(j),
178                                      level-1,high,
179                                      start);
180       crnr = corner(i,j);
181 
182 
183       if (parent_direction == right)
184       {
185          if (crnr == bottom_left)
186          {
187             direction = up;
188             *start    = *start + 0*length;
189          }
190          if (crnr == bottom_right)
191          {
192             direction = down;
193             *start    = *start + 3*length;
194          }
195          if (crnr == top_left)
196          {
197             direction = right;
198             *start    = *start + 1*length;
199          }
200          if (crnr == top_right)
201          {
202             direction = right;
203             *start    = *start + 2*length;
204          }
205       }
206 
207       if (parent_direction == left)
208       {
209          if (crnr == bottom_left)
210          {
211             direction = left;
212             *start    = *start + 2*length;
213          }
214          if (crnr == bottom_right)
215          {
216             direction = left;
217             *start    = *start + 1*length;
218          }
219          if (crnr == top_left)
220          {
221             direction = up;
222             *start    = *start + 3*length;
223          }
224          if (crnr == top_right)
225          {
226             direction = down;
227             *start    = *start + 0*length;
228          }
229       }
230 
231       if (parent_direction == up)
232       {
233          if (crnr == bottom_left)
234          {
235             direction = right;
236             *start    = *start + 0*length;
237          }
238          if (crnr == bottom_right)
239          {
240             direction = up;
241             *start    = *start + 1*length;
242          }
243          if (crnr == top_left)
244          {
245             direction = left;
246             *start    = *start + 3*length;
247          }
248          if (crnr == top_right)
249          {
250             direction = up;
251             *start    = *start + 2*length;
252          }
253       }
254 
255       if (parent_direction == down)
256       {
257          if (crnr == bottom_left)
258          {
259             direction = down;
260             *start    = *start + 2*length;
261          }
262          if (crnr == bottom_right)
263          {
264             direction = right;
265             *start    = *start + 3*length;
266          }
267          if (crnr == top_left)
268          {
269             direction = down;
270             *start    = *start + 1*length;
271          }
272          if (crnr == top_right)
273          {
274             direction = left;
275             *start    = *start + 0*length;
276          }
277       }
278    }
279 
280    return direction;
281 }
282