-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy path1brc_lcrs.f90
150 lines (137 loc) · 4.06 KB
/
1brc_lcrs.f90
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
module trie_types
implicit none
type :: trie
character(len=1) :: key = '!'
real :: min = 1000
real :: max = -1000
real :: sum = 0
integer :: count = 0
type(trie), pointer :: child => null()
type(trie), pointer :: sibling => null()
end type trie
end module trie_types
module builder
use trie_types
implicit none
contains
function str2real (str) result(f)
character(len=*), intent(in) :: str
integer :: i, off
integer :: zero
real :: f
zero = ichar('0')
off = merge (2, 1, str(1:1)=='-')
i = index(str(off:),'.')
if (i==2) then
f = ichar(str(off:off)) - zero
else
f = (ichar(str(off:off)) - zero)*10 + ichar(str(off+1:off+1)) - zero
end if
f = f + (ichar(str(off+i:off+i)) - zero) / 10.0
f = merge(-f,f,off==2)
end function str2real
subroutine update(buffer, root)
character(len=*), intent(in) :: buffer
type(trie), pointer, intent(inout) :: root
type(trie), pointer :: current
integer :: i, j, k
character(len=1) :: c
real :: f
i = 1
current => root
do while (i <= len(buffer))
c = buffer(i:i)
if (c == ';') then
j = i+1
k = index(buffer(j:), achar(10))
f = str2real (buffer(j:j+k-2))
i = j+k
call update_stats(current, f)
current => root
else if (.not. associated(current%child)) then
allocate(current%child)
current => current%child
current%key = c
i = i + 1
else if (current%child%key == c) then
current => current%child
i = i + 1
else
current => current%child
call find_sibling (current, c)
i = i + 1
end if
end do
end subroutine update
subroutine update_stats(current, f)
type(trie), pointer, intent(inout) :: current
real, intent(in) :: f
if (f < current%min) current%min = f
if (f > current%max) current%max = f
current%sum = current%sum + f
current%count = current%count + 1
end subroutine update_stats
subroutine find_sibling(current, c)
character(len=1), intent(in) :: c
type(trie), pointer, intent(inout) :: current
do
if (.not. associated(current%sibling)) then
allocate(current%sibling)
current => current%sibling
current%key = c
exit
endif
current => current%sibling
if (current%key == c) exit
end do
end subroutine find_sibling
recursive subroutine display(tree, prefix)
type(trie), pointer, intent(in) :: tree
character(len=*), intent(in), optional :: prefix
character(len=:), allocatable :: new_prefix
if (.not. associated(tree)) return
if (present(prefix)) then
new_prefix = prefix // tree%key
else
new_prefix = tree%key
end if
if (tree%min < 100) then
print '(A,A,F5.1,F5.1,F5.1)', new_prefix, ";", &
tree%min, tree%max, tree%sum / tree%count
end if
if (associated(tree%child)) then
call display(tree%child, new_prefix)
end if
if (associated(tree%sibling)) then
call display(tree%sibling, prefix)
end if
end subroutine display
end module builder
program one_brc
use trie_types
use builder
implicit none
integer, parameter :: buffer_size = 102400, tail_len=100
character(len=:), allocatable :: buffer
integer(kind=8) :: fd, read_size, off, start
type(trie), pointer :: tree
open(newunit=fd, file='measurements.txt', access='stream', &
form='unformatted', status='old')
inquire(unit=fd, size=read_size)
allocate(tree)
do while (read_size > 0)
allocate(character(len=min(read_size, buffer_size)) :: buffer)
read(fd) buffer
if (read_size <= buffer_size) then
call update(buffer, tree)
exit
end if
start = len(buffer)-tail_len
off = start + index(buffer(start:), achar(10))-1
call update(buffer(1:off), tree)
call fseek(fd, off - len(buffer), 1)
read_size = read_size - off
deallocate(buffer)
end do
call display(tree%child)
end program one_brc