Afivo  0.3
m_morton.f90
1 
7 module m_morton
8 
9  implicit none
10  private
11 
12  integer, parameter :: dp = kind(0.0d0)
13 
15  integer, parameter :: morton_k = selected_int_kind(15)
16 
17  ! Public types
18  public :: morton_k
19 
20  ! Public methods
21  public :: morton_from_ix2
22  public :: morton_from_ix3
23  public :: morton_to_ix2
24  public :: morton_to_ix3
25  public :: morton_bsearch
26  public :: morton_rank
27  public :: print_bits
28  public :: print_bits_morton
29 
30 contains
31 
33  function morton_from_ix2(ix) result(m_ix)
34  integer, intent(in) :: ix(2)
35  integer(morton_k) :: m_ix
36  integer(morton_k) :: a, b
37  a = bit_space_1(ix(1))
38  b = bit_space_1(ix(2))
39  m_ix = ior(a, ishft(b, 1))
40  end function morton_from_ix2
41 
43  function morton_to_ix2(m_ix) result(ix)
44  integer(morton_k), intent(in) :: m_ix
45  integer :: ix(2)
46  ix(1) = bit_despace_1(m_ix)
47  ix(2) = bit_despace_1(ishft(m_ix, -1))
48  end function morton_to_ix2
49 
51  function morton_from_ix3(ix) result(m_ix)
52  integer, intent(in) :: ix(3)
53  integer(morton_k) :: m_ix
54  integer(morton_k) :: a, b, c
55  a = bit_space_2(ix(1))
56  b = bit_space_2(ix(2))
57  c = bit_space_2(ix(3))
58  m_ix = ior(ior(a, ishft(b, 1)), ishft(c, 2))
59  end function morton_from_ix3
60 
62  function morton_to_ix3(m_ix) result(ix)
63  integer(morton_k), intent(in) :: m_ix
64  integer :: ix(3)
65  ix(1) = bit_despace_2(m_ix)
66  ix(2) = bit_despace_2(ishft(m_ix, -1))
67  ix(3) = bit_despace_2(ishft(m_ix, -2))
68  end function morton_to_ix3
69 
72  function morton_bsearch(list, val) result(ix)
73  integer(morton_k), intent(in) :: list(:)
74  integer(morton_k), intent(in) :: val
75  integer :: ix, i_min, i_max, i_middle
76 
77  i_min = 1
78  i_max = size(list)
79 
80  do while (i_min < i_max)
81  i_middle = i_min + (i_max - i_min) / 2
82 
83  if (val <= list(i_middle)) then
84  i_max = i_middle
85  else
86  i_min = i_middle + 1
87  end if
88  end do
89 
90  ix = i_min
91  if (val > list(ix)) ix = -1
92  end function morton_bsearch
93 
94  ! Add two "zero" bits between each bit of the input. Because the result has 64
95  ! bits available, only the first 21 bits from the input are spaced.
96  function bit_space_2(a) result(x)
97  integer, intent(in) :: a
98  integer(morton_k) :: x
99 
100  ! We only look at the first 21 bits
101  x = iand(int(a, morton_k), int(z'1fffff', morton_k))
102  x = iand(ior(x, ishft(x, 32)), int(z'1f00000000ffff', morton_k))
103  x = iand(ior(x, ishft(x, 16)), int(z'1f0000ff0000ff', morton_k))
104  x = iand(ior(x, ishft(x, 8)), int(z'100f00f00f00f00f', morton_k))
105  x = iand(ior(x, ishft(x, 4)), int(z'10c30c30c30c30c3', morton_k))
106  x = iand(ior(x, ishft(x, 2)), int(z'1249249249249249', morton_k))
107  end function bit_space_2
108 
109  ! Invert bit_space_2
110  function bit_despace_2(a) result(y)
111  integer(morton_k), intent(in) :: a
112  integer(morton_k) :: x
113  integer :: y
114 
115  x = iand(a, int(z'1249249249249249', morton_k))
116  x = iand(ior(x, ishft(x, -2)), int(z'10c30c30c30c30c3', morton_k))
117  x = iand(ior(x, ishft(x, -4)), int(z'100f00f00f00f00f', morton_k))
118  x = iand(ior(x, ishft(x, -8)), int(z'1f0000ff0000ff', morton_k))
119  x = iand(ior(x, ishft(x, -16)), int(z'1f00000000ffff', morton_k))
120  x = iand(ior(x, ishft(x, -32)), int(z'1fffff', morton_k))
121  y = int(x)
122  end function bit_despace_2
123 
124  ! Add one "zero" bit between each bit of the input.
125  function bit_space_1(a) result(x)
126  integer, intent(in) :: a
127  integer(morton_k) :: x
128 
129  x = a
130  x = iand(ior(x, ishft(x, 32)), int(z'00000000ffffffff', morton_k))
131  x = iand(ior(x, ishft(x, 16)), int(z'0000ffff0000ffff', morton_k))
132  x = iand(ior(x, ishft(x, 8)), int(z'00ff00ff00ff00ff', morton_k))
133  x = iand(ior(x, ishft(x, 4)), int(z'0f0f0f0f0f0f0f0f', morton_k))
134  x = iand(ior(x, ishft(x, 2)), int(z'3333333333333333', morton_k))
135  x = iand(ior(x, ishft(x, 1)), int(z'5555555555555555', morton_k))
136  end function bit_space_1
137 
138  ! Invert bit_space_1
139  function bit_despace_1(a) result(y)
140  integer(morton_k), intent(in) :: a
141  integer(morton_k) :: x
142  integer :: y
143 
144  x = a
145  x = iand(x, int(z'5555555555555555', morton_k))
146  x = iand(ior(x, ishft(x, -1)), int(z'3333333333333333', morton_k))
147  x = iand(ior(x, ishft(x, -2)), int(z'0f0f0f0f0f0f0f0f', morton_k))
148  x = iand(ior(x, ishft(x, -4)), int(z'00ff00ff00ff00ff', morton_k))
149  x = iand(ior(x, ishft(x, -8)), int(z'0000ffff0000ffff', morton_k))
150  x = iand(ior(x, ishft(x, -16)), int(z'00000000ffffffff', morton_k))
151  y = int(x)
152  end function bit_despace_1
153 
154  ! Jannis: This is taken from ORDERPACK and modified for morton_k
155  subroutine morton_rank (XDONT, IRNGT)
156  ! __________________________________________________________
157  ! MRGRNK = Merge-sort ranking of an array
158  ! For performance reasons, the first 2 passes are taken
159  ! out of the standard loop, and use dedicated coding.
160  ! __________________________________________________________
161  ! __________________________________________________________
162  Integer(morton_k), Dimension (:), Intent (In) :: XDONT
163  Integer, Dimension (:), Intent (Out) :: IRNGT
164  ! __________________________________________________________
165  Integer(morton_k) :: XVALA, XVALB
166  !
167  Integer, Dimension (SIZE(IRNGT)) :: JWRKT
168  Integer :: LMTNA, LMTNC, IRNG1, IRNG2
169  Integer :: NVAL, IIND, IWRKD, IWRK, IWRKF, JINDA, IINDA, IINDB
170  !
171  nval = min(SIZE(xdont), SIZE(irngt))
172  Select Case (nval)
173  Case (:0)
174  Return
175  Case (1)
176  irngt(1) = 1
177  Return
178  Case Default
179  Continue
180  End Select
181  !
182  ! Fill-in the index array, creating ordered couples
183  !
184  Do iind = 2, nval, 2
185  If (xdont(iind-1) <= xdont(iind)) Then
186  irngt(iind-1) = iind - 1
187  irngt(iind) = iind
188  Else
189  irngt(iind-1) = iind
190  irngt(iind) = iind - 1
191  End If
192  End Do
193  If (modulo(nval, 2) /= 0) Then
194  irngt(nval) = nval
195  End If
196  !
197  ! We will now have ordered subsets A - B - A - B - ...
198  ! and merge A and B couples into C - C - ...
199  !
200  lmtna = 2
201  lmtnc = 4
202  !
203  ! First iteration. The length of the ordered subsets goes from 2 to 4
204  !
205  Do
206  If (nval <= 2) Exit
207  !
208  ! Loop on merges of A and B into C
209  !
210  Do iwrkd = 0, nval - 1, 4
211  If ((iwrkd+4) > nval) Then
212  If ((iwrkd+2) >= nval) Exit
213  !
214  ! 1 2 3
215  !
216  If (xdont(irngt(iwrkd+2)) <= xdont(irngt(iwrkd+3))) Exit
217  !
218  ! 1 3 2
219  !
220  If (xdont(irngt(iwrkd+1)) <= xdont(irngt(iwrkd+3))) Then
221  irng2 = irngt(iwrkd+2)
222  irngt(iwrkd+2) = irngt(iwrkd+3)
223  irngt(iwrkd+3) = irng2
224  !
225  ! 3 1 2
226  !
227  Else
228  irng1 = irngt(iwrkd+1)
229  irngt(iwrkd+1) = irngt(iwrkd+3)
230  irngt(iwrkd+3) = irngt(iwrkd+2)
231  irngt(iwrkd+2) = irng1
232  End If
233  Exit
234  End If
235  !
236  ! 1 2 3 4
237  !
238  If (xdont(irngt(iwrkd+2)) <= xdont(irngt(iwrkd+3))) cycle
239  !
240  ! 1 3 x x
241  !
242  If (xdont(irngt(iwrkd+1)) <= xdont(irngt(iwrkd+3))) Then
243  irng2 = irngt(iwrkd+2)
244  irngt(iwrkd+2) = irngt(iwrkd+3)
245  If (xdont(irng2) <= xdont(irngt(iwrkd+4))) Then
246  ! 1 3 2 4
247  irngt(iwrkd+3) = irng2
248  Else
249  ! 1 3 4 2
250  irngt(iwrkd+3) = irngt(iwrkd+4)
251  irngt(iwrkd+4) = irng2
252  End If
253  !
254  ! 3 x x x
255  !
256  Else
257  irng1 = irngt(iwrkd+1)
258  irng2 = irngt(iwrkd+2)
259  irngt(iwrkd+1) = irngt(iwrkd+3)
260  If (xdont(irng1) <= xdont(irngt(iwrkd+4))) Then
261  irngt(iwrkd+2) = irng1
262  If (xdont(irng2) <= xdont(irngt(iwrkd+4))) Then
263  ! 3 1 2 4
264  irngt(iwrkd+3) = irng2
265  Else
266  ! 3 1 4 2
267  irngt(iwrkd+3) = irngt(iwrkd+4)
268  irngt(iwrkd+4) = irng2
269  End If
270  Else
271  ! 3 4 1 2
272  irngt(iwrkd+2) = irngt(iwrkd+4)
273  irngt(iwrkd+3) = irng1
274  irngt(iwrkd+4) = irng2
275  End If
276  End If
277  End Do
278  !
279  ! The Cs become As and Bs
280  !
281  lmtna = 4
282  Exit
283  End Do
284  !
285  ! Iteration loop. Each time, the length of the ordered subsets
286  ! is doubled.
287  !
288  Do
289  If (lmtna >= nval) Exit
290  iwrkf = 0
291  lmtnc = 2 * lmtnc
292  !
293  ! Loop on merges of A and B into C
294  !
295  Do
296  iwrk = iwrkf
297  iwrkd = iwrkf + 1
298  jinda = iwrkf + lmtna
299  iwrkf = iwrkf + lmtnc
300  If (iwrkf >= nval) Then
301  If (jinda >= nval) Exit
302  iwrkf = nval
303  End If
304  iinda = 1
305  iindb = jinda + 1
306  !
307  ! Shortcut for the case when the max of A is smaller
308  ! than the min of B. This line may be activated when the
309  ! initial set is already close to sorted.
310  !
311  ! IF (XDONT(IRNGT(JINDA)) <= XDONT(IRNGT(IINDB))) CYCLE
312  !
313  ! One steps in the C subset, that we build in the final rank array
314  !
315  ! Make a copy of the rank array for the merge iteration
316  !
317  jwrkt(1:lmtna) = irngt(iwrkd:jinda)
318  !
319  xvala = xdont(jwrkt(iinda))
320  xvalb = xdont(irngt(iindb))
321  !
322  Do
323  iwrk = iwrk + 1
324  !
325  ! We still have unprocessed values in both A and B
326  !
327  If (xvala > xvalb) Then
328  irngt(iwrk) = irngt(iindb)
329  iindb = iindb + 1
330  If (iindb > iwrkf) Then
331  ! Only A still with unprocessed values
332  irngt(iwrk+1:iwrkf) = jwrkt(iinda:lmtna)
333  Exit
334  End If
335  xvalb = xdont(irngt(iindb))
336  Else
337  irngt(iwrk) = jwrkt(iinda)
338  iinda = iinda + 1
339  If (iinda > lmtna) exit! Only B still with unprocessed values
340  xvala = xdont(jwrkt(iinda))
341  End If
342  !
343  End Do
344  End Do
345  !
346  ! The Cs become As and Bs
347  !
348  lmtna = 2 * lmtna
349  End Do
350  !
351  Return
352  !
353  end subroutine morton_rank
354 
355  subroutine print_bits(x)
356  integer, intent(in) :: x
357  integer :: n
358  do n = 0, bit_size(x)-1
359  if (btest(x, n)) then
360  write(*, "(A)", advance="NO") "1"
361  else
362  write(*, "(A)", advance="NO") "0"
363  end if
364  end do
365  write(*, *) ""
366  end subroutine print_bits
367 
368  subroutine print_bits_morton(x)
369  integer(morton_k), intent(in) :: x
370  integer :: n
371  do n = 0, bit_size(x)-1
372  if (btest(x, n)) then
373  write(*, "(A)", advance="NO") "1"
374  else
375  write(*, "(A)", advance="NO") "0"
376  end if
377  end do
378  write(*, *) ""
379  end subroutine print_bits_morton
380 
381 end module m_morton
This module contains methods to convert indices to morton numbers.
Definition: m_morton.f90:7