IODA Bundle
encode.f90
Go to the documentation of this file.
1 
3 
4  use odc
5  use odc_config
6  use, intrinsic :: iso_fortran_env
7  implicit none
8 
9  integer(8), parameter :: col1_data(7) = [1, 2, 3, 4, 5, 6, 7]
10  integer(8), parameter :: col2_data(7) = [0, 0, 0, 0, 0, 0, 0]
11  integer(8), parameter :: col3_data(7) = [73, 73, 73, 73, 73, 73, 73]
12  real(8), parameter :: col4_data(7) = [1.432, 1.432, 1.432, 1.432, 1.432, 1.432, 1.432]
13  integer(8), parameter :: col5_data(7) = [-17, -7, -7, 999999, 1, 4, 4]
14  character(16), parameter :: col6_data(7) = [character(16) :: "aoeu", "aoeu", "abcdefghijkl", "None", "boo", "squiggle", "a"]
15  character(8), parameter :: col7_data(7) = [character(8) :: "abcd", "abcd", "abcd", "abcd", "abcd", "abcd", "abcd"]
16  real(8), parameter :: col8_data(7) = [2.345, 2.345, 2.345, 2.345, 2.345, 2.345, 2.345]
17  real(8), parameter :: col9_data(7) = [999.99, 888.88, 777.77, 666.66, 999999.0, 444.44, 333.33]
18  real(8), parameter :: col10_data(7) = [999.99, 888.88, 777.77, 666.66, 999999.0, 444.44, 333.33]
19  integer(8), parameter :: col11_data(7) = [1, 999999, 3, 4, 5, 999999, 8]
20  integer(8), parameter :: col12_data(7) = [-512, 999999, 3, 7623, -22000, 999999, 7]
21  integer(8), parameter :: col13_data(7) = [-1234567, 8765432, 999999, 22, 2222222, -81222323, 999999]
22  integer(8), parameter :: col14_data(7) = [999999, 999999, 999999, 999999, 999999, 999999, 999999]
23 
24 contains
25 
26  ! TODO: Test missing doubles
27  ! TODO: Test missing REAL
28  ! TODO: Encoding NaN?
29 
30  subroutine check_call(err, msg, success)
31  integer, intent(in) :: err
32  character(*), intent(in) :: msg
33  logical, intent(inout) :: success
34 
35  if (err /= odc_success) then
36  write(error_unit, *) 'Failed API call: ', msg
37  write(error_unit, *) 'Error: ', odc_error_string(err)
38  success = .false.
39  end if
40  end subroutine
41 
42  subroutine check_decoded_column_major(data, success)
43  real(8), intent(in) :: data(:, :)
44  integer :: row
45  character(16) :: str16
46  character(8) :: str8
47  logical, intent(inout) :: success
48 
49  if (size(data, 1) /= 7 .or. size(data, 2) /= 15) then
50  write(error_unit, *) 'did not get data shape [7, 15]'
51  success = .false.
52  end if
53 
54  if (any(col1_data /= data(:, 1))) then
55  write(error_unit, *) 'Col 1 differs: ', col1_data, ' vs ', data(:, 1)
56  success = .false.
57  end if
58 
59  if (any(col2_data /= data(:, 2))) then
60  write(error_unit, *) 'Col 2 differs: ', col2_data, ' vs ', data(:, 2)
61  success = .false.
62  end if
63 
64  if (any(col3_data /= data(:, 3))) then
65  write(error_unit, *) 'Col 3 differs: ', col3_data, ' vs ', data(:, 3)
66  success = .false.
67  end if
68 
69  if (any(abs(col4_data - data(:, 4)) > 1.0e-10)) then
70  write(error_unit, *) 'Col 4 differs: ', col4_data, ' vs ', data(:, 4)
71  success = .false.
72  end if
73 
74  if (any(col5_data /= data(:, 5))) then
75  write(error_unit, *) 'Col 5 differs: ', col5_data, ' vs ', data(:, 5)
76  success = .false.
77  end if
78 
79  do row = 1, 7
80  if (trim(col6_data(row)) /= trim(transfer(data(row, 6:7), str16))) then
81  write(error_unit, *) 'Col 6 differs: ', trim(col6_data(row)), ' vs ', &
82  transfer(data(row, 6:7), str16)
83  success = .false.
84  end if
85 
86  if (trim(col7_data(row)) /= trim(transfer(data(row, 8), str8))) then
87  write(error_unit, *) 'Col 7 differs: ', trim(col6_data(row)), ' vs ', &
88  transfer(data(row, 8), str8)
89  success = .false.
90  end if
91  end do
92 
93  if (any(abs(col8_data - data(:, 9)) > 1.0e-10)) then
94  write(error_unit, *) 'Col 8 differs: ', col8_data, ' vs ', data(:, 9)
95  success = .false.
96  end if
97 
98  if (any(abs(col9_data - data(:, 10)) > 1.0e-10)) then
99  write(error_unit, *) 'Col 9 differs: ', col9_data, ' vs ', data(:, 10)
100  success = .false.
101  end if
102 
103  if (any(abs(col10_data - data(:, 11)) > 1.0e-10)) then
104  write(error_unit, *) 'Col 10 differs: ', col10_data, ' vs ', data(:, 11)
105  success = .false.
106  end if
107 
108  if (any(col11_data /= data(:, 12))) then
109  write(error_unit, *) 'Col 11 differs: ', col11_data, ' vs ', data(:, 12)
110  success = .false.
111  end if
112 
113  if (any(col12_data /= data(:, 13))) then
114  write(error_unit, *) 'Col 12 differs: ', col12_data, ' vs ', data(:, 13)
115  success = .false.
116  end if
117 
118  if (any(col13_data /= data(:, 14))) then
119  write(error_unit, *) 'Col 13 differs: ', col13_data, ' vs ', data(:, 14)
120  success = .false.
121  end if
122 
123  if (any(col14_data /= data(:, 15))) then
124  write(error_unit, *) 'Col 14 differs: ', col14_data, ' vs ', data(:, 15)
125  success = .false.
126  end if
127  end subroutine
128 
129  function construct_data_column_major() result(data)
130  real(8) :: data(7, 15)
131  integer :: row
132 
133  data(:, 1) = col1_data
134  data(:, 2) = col2_data
135  data(:, 3) = col3_data
136  data(:, 4) = col4_data
137  data(:, 5) = col5_data
138  do row = 1, 7
139  data(row, 6:7) = transfer(col6_data(row), 1.0_8, 2)
140  data(row, 8) = transfer(col7_data(row), 1.0_8)
141  end do
142  data(:, 9) = col8_data
143  data(:, 10) = col9_data
144  data(:, 11) = col10_data
145  data(:, 12) = col11_data
146  data(:, 13) = col12_data
147  data(:, 14) = col13_data
148  data(:, 15) = col14_data
149  end function
150 
151  subroutine initialise_encoder(encoder, success)
152  type(odc_encoder) :: encoder
153  logical, intent(inout) :: success
154 
155  call check_call(encoder%initialise(), "initialise encoder", success)
156 
157  call check_call(encoder%add_column("col1", odc_integer), "add col1", success)
158  call check_call(encoder%add_column("col2", odc_integer), "add col2", success)
159  call check_call(encoder%add_column("col3", odc_bitfield), "add col3", success)
160  call check_call(encoder%add_column("col4", odc_double), "add col4", success)
161  call check_call(encoder%add_column("col5", odc_integer), "add col5", success)
162  call check_call(encoder%add_column("col6", odc_string), "add col6", success)
163  call check_call(encoder%add_column("col7", odc_string), "add col7", success)
164  call check_call(encoder%add_column("col8", odc_real), "add col8", success)
165  call check_call(encoder%add_column("col9", odc_double), "add col9", success)
166  call check_call(encoder%add_column("col10", odc_real), "add col10", success)
167  call check_call(encoder%add_column("col11", odc_bitfield), "add col11", success)
168  call check_call(encoder%add_column("col12", odc_integer), "add col12", success)
169  call check_call(encoder%add_column("col13", odc_integer), "add col13", success)
170  call check_call(encoder%add_column("col14", odc_integer), "add col14", success)
171 
172  call check_call(encoder%column_set_data_size(6, element_size_doubles=2), "column attrs", success)
173 
174  call check_call(encoder%column_add_bitfield(11, "bf1", 3), "add bitfield 1", success)
175  call check_call(encoder%column_add_bitfield(11, "bf2", 2), "add bitfield 2", success)
176  call check_call(encoder%column_add_bitfield(11, "bf3", 1), "add bitfield 3", success)
177  end subroutine
178 
179  function test_encode_column_major() result(success)
180 
181  real(8) :: data(7, 15)
182  integer :: outunit, iter
183  integer(8) :: bytes_written
184  type(odc_encoder) :: encoder
185  character(*), parameter :: test_filename = 'f90_test_encode_column.odb'
186  logical :: success
187  success = .true.
188 
190 
191  call check_decoded_column_major(data, success)
192  call initialise_encoder(encoder, success)
193 
194  ! Put encoding in a loop. Do the encoding twice, to demonstrate that
195  ! we can iterate through tables of data.
196 
197  open(newunit=outunit, file=test_filename, access='stream', form='unformatted')
198 
199  do iter = 0, 1
200  call check_call(encoder%set_data(data), "set encoder data", success)
201  call check_call(encoder%encode(outunit, bytes_written), "do encode", success)
202  end do
203 
204  close(outunit)
205  call check_call(encoder%free(), "free encoder", success)
206 
207  call check_encoded_odb(test_filename, success)
208 
209  end function
210 
211  function test_encode_row_major() result(success)
212 
213  real(8) :: data(15, 7)
214  integer :: row, outunit, iter
215  integer(8) :: bytes_written
216  type(odc_encoder) :: encoder
217  character(*), parameter :: test_filename = 'f90_test_encode_row.odb'
218  logical :: success
219  success = .true.
220 
221  data = transpose(construct_data_column_major())
222 
223  call check_decoded_column_major(transpose(data), success)
224  call initialise_encoder(encoder, success)
225 
226  ! Put encoding in a loop. Do the encoding twice, to demonstrate that
227  ! we can iterate through tables of data.
228 
229  open(newunit=outunit, file=test_filename, access='stream', form='unformatted')
230 
231  do iter = 0, 1
232  call check_call(encoder%set_data(data, column_major=.false.), "set encoder data", success)
233  call check_call(encoder%encode(outunit, bytes_written), "do encode", success)
234  end do
235 
236  close(outunit)
237  call check_call(encoder%free(), "free encoder", success)
238 
239  call check_encoded_odb(test_filename, success)
240 
241  end function
242 
243  subroutine check_frame_column(frame, col, name, type, success)
244  type(odc_frame), intent(in) :: frame
245  integer, intent(in) :: col, type
246  character(*), intent(in) :: name
247  logical, intent(inout) :: success
248 
249  character(:), allocatable :: column_name, nm
250  integer :: ncols, column_type, element_size, element_size_doubles, bitfield_count
251  integer :: sz, off, i
252  integer :: expected_count, expected_sz
253 
254  character(3) :: expected_bf_names(3) = ['bf1', 'bf2', 'bf3']
255  integer :: expected_bf_sizes(3) = [3, 2, 1]
256  integer :: expected_bf_offsets(3) = [0, 3, 5]
257 
258  call check_call(frame%column_count(ncols), "column count", success)
259  if (ncols /= 14) then
260  write(error_unit, *) 'Unexpected column count. got ', ncols, ', expected 14'
261  success = .false.
262  end if
263 
264  call check_call(frame%column_attributes(col, &
265  name=column_name, &
266  type=column_type, &
267  element_size=element_size, &
268  element_size_doubles=element_size_doubles, &
269  bitfield_count=bitfield_count), "column attrs", success)
270 
271  if (column_name /= name) then
272  write(error_unit, '(a,i2,4a)') 'Unexpected column name for column ', col, &
273  '. Got ', column_name, ', expected ', name
274  success = .false.
275  end if
276 
277  if (column_type /= type) then
278  write(error_unit, '(3(a,i2))') 'Unexpected column type for column ', col, &
279  '. Got ', column_name, ', expected ', name
280  success = .false.
281  end if
282 
283  if (col == 6) then
284  expected_sz = 2
285  else
286  expected_sz = 1
287  end if
288 
289  if (element_size_doubles /= expected_sz) then
290  write(error_unit, '(3(a,i2))') 'Unexpected column element size for column ', col, &
291  '. Got ', element_size_doubles, ', expected ', expected_sz
292  success = .false.
293  end if
294 
295  if (element_size /= 8*expected_sz) then
296  write(error_unit, '(3(a,i2))') 'Unexpected column element size for column ', col, &
297  '. Got ', element_size, ', expected ', 8*expected_sz
298  success = .false.
299  end if
300 
301  if (col == 11) then
302  expected_count = 3
303  else
304  expected_count = 0
305  end if
306 
307  if (bitfield_count /= expected_count) then
308  write(error_unit, '(3(a,i2))') 'Unexpected column bitfield_count for column ', col, &
309  '. Got ', bitfield_count, ', expected ', expected_count
310  success = .false.
311  end if
312 
313  if (col == 11) then
314  do i = 1, 3
315  call check_call(frame%bitfield_attributes(11, i, name=nm, offset=off, size=sz), 'bitfield attrs', success)
316 
317  if (sz /= expected_bf_sizes(i)) then
318  write(error_unit, '(3(a,i2))') 'Unexpected bitfield size for field ', i, &
319  '. Got ', sz, ', expected ', expected_bf_sizes(i)
320  success = .false.
321  end if
322 
323  if (off /= expected_bf_offsets(i)) then
324  write(error_unit, '(3(a,i2))') 'Unexpected bitfield offset for field ', i, &
325  '. Got ', off, ', expected ', expected_bf_offsets(i)
326  success = .false.
327  end if
328 
329  if (nm /= expected_bf_names(i)) then
330  write(error_unit, '(a,i2,4a)') 'Unexpected bitfield name for field ', i, &
331  '. Got ', nm, ', expected ', expected_bf_names(i)
332  success = .false.
333  end if
334 
335  end do
336  end if
337 
338  end subroutine
339 
340  subroutine check_encoded_odb(path, success)
341  character(*), intent(in) :: path
342  logical, intent(inout) :: success
343 
344  type(odc_reader) :: reader
345  type(odc_frame) :: frame
346  type(odc_decoder) :: decoder
347  real(8), pointer :: data(:,:)
348  logical :: column_major
349  integer :: err, iter
350  integer(8) :: nrows
351 
352  call check_call(reader%open_path(path), "open " // path, success)
353  call check_call(frame%initialise(reader), "initialise frame", success)
354 
355  ! We are expecting two frames
356 
357  do iter = 0, 1
358 
359  call check_call(frame%next(), "get first frame", success)
360 
361  call check_frame_column(frame, 1, "col1", odc_integer, success)
362  call check_frame_column(frame, 2, "col2", odc_integer, success)
363  call check_frame_column(frame, 3, "col3", odc_bitfield, success)
364  call check_frame_column(frame, 4, "col4", odc_double, success)
365  call check_frame_column(frame, 5, "col5", odc_integer, success)
366  call check_frame_column(frame, 6, "col6", odc_string, success)
367  call check_frame_column(frame, 7, "col7", odc_string, success)
368  call check_frame_column(frame, 8, "col8", odc_real, success)
369  call check_frame_column(frame, 9, "col9", odc_double, success)
370  call check_frame_column(frame, 10, "col10", odc_real, success)
371  call check_frame_column(frame, 11, "col11", odc_bitfield, success)
372  call check_frame_column(frame, 12, "col12", odc_integer, success)
373  call check_frame_column(frame, 13, "col13", odc_integer, success)
374  call check_frame_column(frame, 14, "col14", odc_integer, success)
375 
376  ! Decode the data
377 
378  call check_call(decoder%initialise(), "initialise decoder", success)
379  call check_call(decoder%defaults_from_frame(frame), "defaults from frame", success)
380  call check_call(decoder%decode(frame, nrows), "decode", success)
381  call check_call(decoder%data(data, column_major), "get data", success)
382 
383  if (.not. column_major) then
384  write(error_unit, *) 'expected column major'
385  success = .false.
386  end if
387 
388  call check_decoded_column_major(data, success)
389  call check_call(decoder%free(), "free decoder", success)
390 
391  end do
392 
393  ! And iterations done
394 
395  err = frame%next()
396  if (err /= odc_iteration_complete) then
397  write(error_unit, *) 'expected iteration complete'
398  success = .false.
399  end if
400 
401  ! Cleanup
402 
403  call check_call(frame%free(), "free frame", success)
404  call check_call(reader%close(), "free frame", success)
405 
406  end subroutine
407 
408  !funcion test_encode_integers() result(success)
409  ! logical :: success
410  ! success = .true.
411  !end function
412 
413  !function test_encode_columns() result(success)
414  ! logical :: success
415  ! success = .true.
416  !end function
417 
418 end module
419 
420 
422 
424  implicit none
425 
426  logical :: success
427 
428  success = .true.
429  call check_call(odc_initialise_api(), "initialise api", success)
430  call check_call(odc_set_missing_integer(999999_8), "set missing integer", success)
431  call check_call(odc_set_missing_double(999999.0_8), "set missing double", success)
432 
433  success = test_encode_column_major() .and. success
434  success = test_encode_row_major() .and. success
435  !success = test_encode_integers() .and. success
436  !success = test_encode_columns() .and. success
437 
438  if (.not. success) stop -1
439 
440 end program
int odc_set_missing_integer(long missing_integer)
Definition: api/odc.cc:257
int odc_initialise_api()
Definition: api/odc.cc:203
const char * odc_error_string(int err)
Definition: api/odc.cc:93
int odc_set_missing_double(double missing_double)
Definition: api/odc.cc:263
program fapi_general
Definition: encode.f90:421
subroutine check_call(err, msg, success)
Definition: encode.f90:31
real(8), dimension(7), parameter col4_data
Definition: encode.f90:12
subroutine initialise_encoder(encoder, success)
Definition: encode.f90:152
character(8), dimension(7), parameter col7_data
Definition: encode.f90:15
real(8) function, dimension(7, 15) construct_data_column_major()
Definition: encode.f90:130
integer(8), dimension(7), parameter col11_data
Definition: encode.f90:19
subroutine check_encoded_odb(path, success)
Definition: encode.f90:341
subroutine check_decoded_column_major(data, success)
Definition: encode.f90:43
integer(8), dimension(7), parameter col3_data
Definition: encode.f90:11
integer(8), dimension(7), parameter col12_data
Definition: encode.f90:20
logical function test_encode_row_major()
Definition: encode.f90:212
subroutine check_frame_column(frame, col, name, type, success)
Definition: encode.f90:244
real(8), dimension(7), parameter col10_data
Definition: encode.f90:18
integer(8), dimension(7), parameter col14_data
Definition: encode.f90:22
real(8), dimension(7), parameter col9_data
Definition: encode.f90:17
integer(8), dimension(7), parameter col2_data
Definition: encode.f90:10
real(8), dimension(7), parameter col8_data
Definition: encode.f90:16
integer(8), dimension(7), parameter col5_data
Definition: encode.f90:13
character(16), dimension(7), parameter col6_data
Definition: encode.f90:14
integer(8), dimension(7), parameter col1_data
Definition: encode.f90:9
logical function test_encode_column_major()
Definition: encode.f90:180
integer(8), dimension(7), parameter col13_data
Definition: encode.f90:21
Definition: ColumnInfo.h:23
integer(c_int), parameter, public odc_real
Definition: odc.f90:9
integer, parameter, public odc_iteration_complete
Definition: odc.f90:17
integer(c_int), parameter, public odc_string
Definition: odc.f90:10
integer(c_int), parameter, public odc_double
Definition: odc.f90:12
integer(c_int), parameter, public odc_bitfield
Definition: odc.f90:11
integer(c_int), parameter, public odc_integer
Definition: odc.f90:8
integer, parameter, public odc_success
Definition: odc.f90:16