1
1
!!------------------------------------------------------------------------------
2
2
!! `NM_HASH32` and `NM_HASH32X` are translations to Fortran 2008 and signed
3
- !! two's complement arithmetic of the `nmhash32` and `nmhash32x` scalar
3
+ !! two's complement arithmetic of the `nmhash32` and `nmhash32x` V. 2 scalar
4
4
!! algorithms of James Z. M. Gao, copyright 2021. James Z. M. Gao's original
5
5
!! C++ code, `nmhash.h`, is available at the URL:
6
6
!! https://github.com/gzm55/hash-garage/blob/a8913138bdb3b7539c202edee30a7f0794bbd835/nmhash.h
9
9
!! The algorithms come in multiple versions, depending on whether the
10
10
!! vectorized instructions SSE2 or AVX2 are available. As neither instruction
11
11
!! is available in portable Fortran 2008, the algorithms that do not use these
12
- !! instructions are used .
12
+ !! instructions.
13
13
!!
14
14
!! The BSD 2-Clause license is as follows:
15
15
!!
@@ -93,7 +93,7 @@ contains
93
93
94
94
pure function nmh_readle32( p ) result( v )
95
95
integer(int32) :: v
96
- integer(int8), intent(in) :: p(: )
96
+ integer(int8), intent(in) :: p(1:4 )
97
97
98
98
if ( little_endian ) then
99
99
v = transfer( p(1:4), 0_int32 )
@@ -105,7 +105,7 @@ contains
105
105
106
106
pure function nmh_readle16( p ) result( v )
107
107
integer(int16) :: v
108
- integer(int8), intent(in) :: p(: )
108
+ integer(int8), intent(in) :: p(1:2 )
109
109
110
110
if ( little_endian ) then
111
111
v = transfer( p(1:2), 0_int16 )
@@ -125,11 +125,11 @@ contains
125
125
integer(int32), parameter :: m2 = int(z'3FB39C65', int32)
126
126
integer(int32), parameter :: m3 = int(z'E9139917', int32)
127
127
128
- integer(int16) :: vx16(2 )
128
+ integer(int16) :: vx16(0:1 )
129
129
integer(int16), parameter :: &
130
- m116(2 ) = transfer( m1, 0_int16, 2 ), &
131
- m216(2 ) = transfer( m2, 0_int16, 2 ), &
132
- m316(2 ) = transfer( m3, 0_int16, 2 )
130
+ m116(0:1 ) = transfer( m1, 0_int16, 2 ), &
131
+ m216(0:1 ) = transfer( m2, 0_int16, 2 ), &
132
+ m316(0:1 ) = transfer( m3, 0_int16, 2 )
133
133
134
134
vx32 = x
135
135
vx32 = ieor( vx32, ieor( ishft( vx32, -12 ), ishft( vx32, -6 ) ) )
@@ -149,11 +149,11 @@ contains
149
149
150
150
end function nmhash32_0to8
151
151
152
- pure function nmhash32_9to255( p, seed, full_avalanche ) result( result )
152
+ pure function nmhash32_9to255( p, seed, full_avalanche ) result( hash )
153
153
integer(int8), intent(in) :: p(0:)
154
154
integer(int32), intent(in) :: seed
155
155
logical, intent(in) :: full_avalanche
156
- integer(int32) :: result
156
+ integer(int32) :: hash
157
157
158
158
integer(int32) :: xu32(0:3), yu32(0:3)
159
159
integer(int16) :: xu16(0:1)
@@ -169,7 +169,6 @@ contains
169
169
! base mixer: [f0d9649b 5 -13 29a7935d -9 11 55d35831 -20 -10 ] =
170
170
! 0.93495901789135362
171
171
172
- result = 0
173
172
length = size( p, kind=int64 )
174
173
length32 = transfer(length, 0_int32, 2)
175
174
if (little_endian) then
@@ -268,7 +267,7 @@ contains
268
267
xu32(0) = transfer( xu16, 0_int32 )
269
268
xu32(0) = ieor(xu32(0), &
270
269
ieor(ishft(xu32(0), -10), ishft(xu32(0), -20) ) )
271
- result = xu32(0)
270
+ hash = xu32(0)
272
271
273
272
end function nmhash32_9to255
274
273
@@ -389,13 +388,11 @@ contains
389
388
u32 = x
390
389
u32 = ieor( u32, ieor( ishft( u32, -8 ), ishft( u32, -21 ) ) )
391
390
u16 = transfer( u32, 0_int16, 2 )
392
- u16(0) = u16(0) * m1_16(0)
393
- u16(1) = u16(1) * m1_16(1)
391
+ u16 = u16 * m1_16
394
392
u32 = transfer( u16, 0_int32 )
395
393
u32 = ieor( u32, ieor( ishft( u32, 12 ), ishft( u32, -7 ) ) )
396
394
u16 = transfer( u32, 0_int16, 2 )
397
- u16(0) = u16(0) * m2_16(0)
398
- u16(1) = u16(1) * m2_16(1)
395
+ u16 = u16 * m2_16
399
396
u32 = transfer( u16, 0_int32 )
400
397
u32 = ieor( u32, ieor( ishft( u32, -8 ), ishft( u32, -21 ) ) )
401
398
@@ -529,20 +526,24 @@ contains
529
526
integer(int32) :: x
530
527
531
528
integer(int64) :: len
532
- integer(int32) :: len32(0:1), len_base
529
+ integer(int32) :: len32(0:1)
530
+ integer(int8) :: len8(0:7)
531
+ integer(int32) :: len_base
533
532
integer(int32) :: y
534
533
integer(int32) :: a, b
535
534
integer(int64) :: i, r
536
535
537
- ! 5 to 9 bytes
538
- ! mixer: [11049a7d 23 bcccdc7b 12 065e9dad 12] = 0.16577596555667246
536
+ ! - at least 9 bytes
537
+ ! base mixer: [11049a7d 23 bcccdc7b 12 065e9dad 12] = 0.16577596555667246
538
+ ! tail mixer: [16 a52fb2cd 15 551e4d49 16] = 0.17162579707098322
539
539
540
540
len = size(p, kind=int64)
541
+ len8 = transfer(len, 0_int8, 8)
541
542
len32 = transfer(len, 0_int32, 2)
542
543
if (little_endian) then
543
- len_base = len32(0 )
544
+ len_base = transfer( [len8(0), 0_int8, 0_int8, 0_int8], 0_int32 )
544
545
else
545
- len_base = len32(1 )
546
+ len_base = transfer( [0_int8, 0_int8, 0_int8, len8(7)], 0_int32 )
546
547
end if
547
548
x = nmh_prime32_3
548
549
y = seed
@@ -618,7 +619,11 @@ contains
618
619
x = x * int(z'551E4D49', int32)
619
620
end if
620
621
621
- x = ieor(x, len_base )
622
+ if ( little_endian ) then
623
+ x = ieor(x, len32(0) )
624
+ else
625
+ x = ieor(x, len32(1) )
626
+ end if
622
627
x = ieor(x, ishftc(a, 27)) ! rotate one lane to pass Diff test
623
628
x = ieor(x, ishft(x,-14))
624
629
x = x * int(z'141CC535', int32 )
0 commit comments