diff --git a/doc/specs/stdlib_io.md b/doc/specs/stdlib_io.md index 40cb2b426..0fa0d30b6 100644 --- a/doc/specs/stdlib_io.md +++ b/doc/specs/stdlib_io.md @@ -131,3 +131,130 @@ program demo_savetxt call savetxt('example.dat', x) end program demo_savetxt ``` + +## `disp` - display your data + +### Status + +Experimental + +### Class + +Impure subroutine. + +### Description + +Outputs a `logical/integer/real/complex/character/string_type` scalar or `logical/integer/real/complex` and rank-1/rank-2 array to the screen or a file `unit`. + +#### More details + +```fortran +call disp( A(i, j, 2, :, 1:10) [, header, unit, brief] ) !! `i, j, ...` can be determined by `do` loop. +``` + +For `complex` type, the output format is `*(A25, 1X)`; +For other types, the output format is `*(A12, 1X)`. + +To prevent users from accidentally passing large-length arrays to `disp`, causing unnecessary io blockage: +1. If the `brief` argument is not specified, `disp` will print **the brief array content with a length of `10*50` by default**. +2. Specify `brief=.true.`, `disp` will print **the brief array content with a length of `5*5`**; +3. Specify `brief=.false.`, `disp` will print **`all` the contents of the array**. + +### Syntax + +`call [[stdlib_io(module):disp(interface)]]([x, header, unit, brief])` + +### Arguments + +`x`: Shall be a `logical/integer/real/complex/string_type` scalar or `logical/integer/real/complex` and rank-1/rank-2 array. +This argument is `intent(in)` and `optional`. + +`header`: Shall be a `character(len=*)` scalar. +This argument is `intent(in)` and `optional`. + +`unit`: Shall be an `integer` scalar linked to an IO stream. +This argument is `intent(in)` and `optional`. + +`brief`: Shall be a `logical` scalar. +This argument is `intent(in)` and `optional`. +Controls an abridged version of the `x` object is printed. + +### Output + +The result is to print `header` and `x` on the screen (or another output `unit/file`) in this order. +If `x` is a rank-1/rank-2 `array` type, the dimension length information of the `array` will also be outputted. + +If `disp` is not passed any arguments, a blank line is printed. + +If the `x` is present and of `real/complex` type, the data will retain four significant decimal places, like `(g0.4)`. + +### Example + +```fortran +program test_io_disp + + use stdlib_io, only: disp + + real(8) :: r(2, 3) + complex :: c(2, 3), c_3d(2, 100, 20) + integer :: i(2, 3) + logical :: l(10, 10) + r = 1.; c = 1.; c_3d = 2.; i = 1; l = .true. + r(1, 1) = -1.e-11 + r(1, 2) = -1.e10 + c(2, 2) = (-1.e10,-1.e10) + c_3d(1,3,1) = (1000, 0.001) + c_3d(1,3,2) = (1.e4, 100.) + call disp('string', header='disp(string):') + call disp('It is a note.') + call disp() + call disp(r, header='disp(r):') + call disp(r(1,:), header='disp(r(1,:))') + call disp(c, header='disp(c):') + call disp(i, header='disp(i):') + call disp(l, header='disp(l):', brief=.true.) + call disp(c_3d(:,:,3), header='disp(c_3d(:,:,3)):', brief=.true.) + call disp(c_3d(2,:,:), header='disp(c_3d(2,:,:)):', brief=.true.) + +end program test_io_disp +``` +**Results:** +```fortran + disp(string): + string + It is a note. + + disp(r): + [matrix size: 2×3] + -0.1000E-10 -0.1000E+11 1.000 + 1.000 1.000 1.000 + disp(r(1,:)) + [vector size: 3] + -0.1000E-10 -0.1000E+11 1.000 + disp(c): + [matrix size: 2×3] + (1.000,0.000) (1.000,0.000) (1.000,0.000) + (1.000,0.000) (-0.1000E+11,-0.1000E+11) (1.000,0.000) + disp(i): + [matrix size: 2×3] + 1 1 1 + 1 1 1 + disp(l): + [matrix size: 10×10] + T T T ... T + T T T ... T + T T T ... T + : : : : : + T T T ... T + disp(c_3d(:,:,3)): + [matrix size: 2×100] + (2.000,0.000) (2.000,0.000) (2.000,0.000) ... (2.000,0.000) + (2.000,0.000) (2.000,0.000) (2.000,0.000) ... (2.000,0.000) + disp(c_3d(2,:,:)): + [matrix size: 100×20] + (2.000,0.000) (2.000,0.000) (2.000,0.000) ... (2.000,0.000) + (2.000,0.000) (2.000,0.000) (2.000,0.000) ... (2.000,0.000) + (2.000,0.000) (2.000,0.000) (2.000,0.000) ... (2.000,0.000) + : : : : : + (2.000,0.000) (2.000,0.000) (2.000,0.000) ... (2.000,0.000) +``` \ No newline at end of file diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index b56d75b0e..08eb00dac 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -7,6 +7,7 @@ set(fppFiles stdlib_bitsets_64.fypp stdlib_bitsets_large.fypp stdlib_io.fypp + stdlib_io_disp.fypp stdlib_linalg.fypp stdlib_linalg_diag.fypp stdlib_linalg_outer_product.fypp diff --git a/src/Makefile.manual b/src/Makefile.manual index 7576cf3d8..2ee03fc57 100644 --- a/src/Makefile.manual +++ b/src/Makefile.manual @@ -4,6 +4,7 @@ SRCFYPP = \ stdlib_bitsets_large.fypp \ stdlib_bitsets.fypp \ stdlib_io.fypp \ + stdlib_io_disp.fypp \ stdlib_linalg.fypp \ stdlib_linalg_diag.fypp \ stdlib_linalg_outer_product.fypp \ @@ -27,8 +28,8 @@ SRCFYPP = \ stdlib_stats_moment_scalar.fypp \ stdlib_stats_var.fypp \ stdlib_math.fypp \ - stdlib_math_linspace.fypp \ - stdlib_math_logspace.fypp \ + stdlib_math_linspace.fypp \ + stdlib_math_logspace.fypp \ stdlib_stats_distribution_PRNG.fypp \ stdlib_string_type.fypp \ stdlib_string_type_constructor.fypp \ @@ -85,7 +86,12 @@ stdlib_io.o: \ stdlib_error.o \ stdlib_optval.o \ stdlib_kinds.o \ - stdlib_ascii.o + stdlib_ascii.o \ + stdlib_string_type.o +stdlib_io_disp.o: \ + stdlib_strings.o \ + stdlib_string_type.o \ + stdlib_io.o stdlib_linalg.o: \ stdlib_kinds.o stdlib_linalg_diag.o: \ diff --git a/src/stdlib_io.fypp b/src/stdlib_io.fypp index dcacaa644..4e56f00a9 100644 --- a/src/stdlib_io.fypp +++ b/src/stdlib_io.fypp @@ -7,18 +7,52 @@ module stdlib_io !! ([Specification](../page/specs/stdlib_io.html)) use stdlib_kinds, only: sp, dp, qp, & - int8, int16, int32, int64 + int8, int16, int32, int64, lk, c_bool use stdlib_error, only: error_stop use stdlib_optval, only: optval use stdlib_ascii, only: is_blank + use stdlib_string_type, only: string_type implicit none private ! Public API - public :: loadtxt, savetxt, open + public :: loadtxt, savetxt, open, disp ! Private API that is exposed so that we can test it in tests public :: parse_mode + + !> version: experimental + !> + !> Display a scalar, vector or matrix. + !> ([Specification](../page/specs/stdlib_io.html#disp-display-your-data-to-the-screen-or-another-output-unit)) + interface disp + #:set DISP_KINDS_TYPES = REAL_KINDS_TYPES + INT_KINDS_TYPES & + & + CMPLX_KINDS_TYPES + LOG_KINDS_TYPES + #:set DISP_RANKS = range(0, 3) + #:for k1, t1 in DISP_KINDS_TYPES + #:for rank in DISP_RANKS + module subroutine disp_${rank}$_${t1[0]}$${k1}$(x, header, unit, brief) + ${t1}$, intent(in) :: x${ranksuffix(rank)}$ + character(len=*), intent(in), optional :: header + integer, intent(in), optional :: unit + logical, intent(in), optional :: brief + end subroutine disp_${rank}$_${t1[0]}$${k1}$ + #:endfor + #:endfor + module subroutine disp_character(x, header, unit, brief) + character(len=*), intent(in), optional :: x + character(len=*), intent(in), optional :: header + integer, intent(in), optional :: unit + logical, intent(in), optional :: brief + end subroutine disp_character + module subroutine disp_string_type(x, header, unit, brief) + type(string_type), intent(in) :: x + character(len=*), intent(in), optional :: header + integer, intent(in), optional :: unit + logical, intent(in), optional :: brief + end subroutine disp_string_type + end interface disp + interface loadtxt !! version: experimental !! diff --git a/src/stdlib_io_disp.fypp b/src/stdlib_io_disp.fypp new file mode 100644 index 000000000..5dee5337c --- /dev/null +++ b/src/stdlib_io_disp.fypp @@ -0,0 +1,213 @@ +#:include "common.fypp" +#:set RIL_KINDS_TYPES = REAL_KINDS_TYPES + INT_KINDS_TYPES + LOG_KINDS_TYPES + +submodule (stdlib_io) stdlib_io_disp + + use, intrinsic :: iso_fortran_env, only: output_unit + use stdlib_strings, only: to_string + use stdlib_string_type, only: char + implicit none + + character(len=*), parameter :: rfmt = '(*(g12.4, 1x))' + character(len=*), parameter :: cfmt = '(*(g25.0, 1x))' + character(len=*), parameter :: fmt_ = 'g0.4' + integer, parameter :: brief_col = 5 + integer, parameter :: brief_row = 5 + integer, parameter :: default_col = 10 + integer, parameter :: default_row = 50 + +contains + + #:for k1, t1 in RIL_KINDS_TYPES + #! Display a/an ${t1}$ scalar. + module procedure disp_0_${t1[0]}$${k1}$ + integer :: unit_ + + unit_ = optval(unit, output_unit) + + if (present(header)) write(unit_, *) header + write(unit_, rfmt) x + + end procedure disp_0_${t1[0]}$${k1}$ + + #! Display a/an ${t1}$ vector. + module procedure disp_1_${t1[0]}$${k1}$ + integer :: unit_ + logical :: brief_ + integer :: m, col + + unit_ = optval(unit, output_unit) + brief_ = optval(brief, .true.) + col = merge(brief_col, default_col, present(brief) .and. brief_) + m = size(x, 1) + + if (present(header)) write(unit_, *) header + write(unit_, *) '[vector size: ' // to_string(m) // ']' + + if (brief_ .and. m > col) then + #! Brief Print. + write(unit_, rfmt) x(1:col-2), '...', x(m) + else + #! Full Print. + write(unit_, rfmt) x(:) + end if + + end procedure disp_1_${t1[0]}$${k1}$ + + #! Display a/an ${t1}$ matrix. + module procedure disp_2_${t1[0]}$${k1}$ + integer :: unit_ + logical :: brief_ + integer :: i, m, n + integer :: col, row + character(len=1) :: colon(default_col) + + unit_ = optval(unit, output_unit) + brief_ = optval(brief, .true.) + col = merge(brief_col, default_col, present(brief) .and. brief_) + row = merge(brief_row, default_row, present(brief) .and. brief_) + m = size(x, 1) + n = size(x, 2) + + if (present(header)) write(unit_, *) header + write(unit_, *) '[matrix size: ' // to_string(m) // '×' // to_string(n) // ']' + + if (brief_ .and. (m > col .or. n > row)) then + #! Brief Print. + colon = ':' + if (m > col .and. n > row) then + do i = 1, row-2 + write(unit_, rfmt) x(i,1:col-2), '...', x(i,n) + end do + write(unit_, rfmt) colon(1:col) + write(unit_, rfmt) x(m,1:col-2), '...', x(m,n) + elseif (m > col .and. n <= row) then + do i = 1, 3 + write(unit_, rfmt) x(i,:) + end do + write(unit_, rfmt) colon(1:n) + write(unit_, rfmt) x(m,:) + elseif (m <= col .and. n > row) then + do i = 1, m + write(unit_, rfmt) x(i,1:col-2), '...', x(i,n) + end do + end if + else + #! Full Print. + do i = 1, m + write(unit_, rfmt) x(i,:) + end do + end if + + end procedure disp_2_${t1[0]}$${k1}$ + #:endfor + + #:for k1, t1 in CMPLX_KINDS_TYPES + #! Display a ${t1}$ scalar. + module procedure disp_0_${t1[0]}$${k1}$ + integer :: unit_ + + unit_ = optval(unit, output_unit) + + if (present(header)) write(unit_, *) header + write(unit_, cfmt) to_string(x, fmt_) + + end procedure disp_0_${t1[0]}$${k1}$ + + #! Display a ${t1}$ vector. + module procedure disp_1_${t1[0]}$${k1}$ + integer :: unit_ + logical :: brief_ + integer :: i, m, col + + unit_ = optval(unit, output_unit) + brief_ = optval(brief, .true.) + col = merge(brief_col, default_col, present(brief) .and. brief_) + m = size(x, 1) + + if (present(header)) write(unit_, *) header + write(unit_, *) '[vector size: ' // to_string(m) // ']' + + if (brief_ .and. m > col) then + #! Brief Print. + write(unit_, cfmt) (to_string(x(i), fmt_), i=1, col-2), '...', to_string(x(m), fmt_) + else + #! Full Print. + write(unit_, cfmt) (to_string(x(i), fmt_), i=1, m) + end if + + end procedure disp_1_${t1[0]}$${k1}$ + + #! Display a ${t1}$ matrix. + module procedure disp_2_${t1[0]}$${k1}$ + integer :: unit_ + logical :: brief_ + integer :: i, j, m, n + integer :: col, row + character(len=1) :: colon(default_col) + + unit_ = optval(unit, output_unit) + brief_ = optval(brief, .true.) + col = merge(brief_col, default_col, present(brief) .and. brief_) + row = merge(brief_row, default_row, present(brief) .and. brief_) + m = size(x, 1) + n = size(x, 2) + + if (present(header)) write(unit_, *) header + write(unit_, *) '[matrix size: ' // to_string(m) // '×' // to_string(n) // ']' + + if (brief_ .and. (m > col .or. n > row)) then + #! Brief Print. + colon = ':' + if (m > col .and. n > row) then + do i = 1, col-2 + write(unit_, cfmt) (to_string(x(i,j), fmt_), j=1, col-2), '...', to_string(x(i,n), fmt_) + end do + write(unit_, cfmt) colon(1:col) + write(unit_, cfmt) (to_string(x(m,j), fmt_), j=1, col-2), '...', to_string(x(m,n), fmt_) + elseif (m > col .and. n <= row) then + do i = 1, col-2 + write(unit_, cfmt) (to_string(x(i,j), fmt_), j=1, n) + end do + write(unit_, cfmt) colon(1:n) + write(unit_, cfmt) (to_string(x(m,j), fmt_), j=1, n) + elseif (m <= col .and. n > row) then + do i = 1, m + write(unit_, cfmt) (to_string(x(m,j), fmt_), j=1, col-2), '...', to_string(x(m,n), fmt_) + end do + end if + else + #! Full Print. + do i = 1, m + write(unit_, cfmt) (to_string(x(i,j), fmt_), j=1, n) + end do + end if + + end procedure disp_2_${t1[0]}$${k1}$ + #:endfor + + #! Display a `character` scalar. + module procedure disp_character + character(len=:), allocatable :: x_ + integer :: unit_ + + x_ = optval(x, '') + unit_ = optval(unit, output_unit) + + if (present(header)) write(unit_, *) header + write(unit_, *) x_ + + end procedure disp_character + + #! Display a `string_type` scalar + module procedure disp_string_type + integer :: unit_ + + unit_ = optval(unit, output_unit) + + if (present(header)) write(unit_, *) header + write(unit_, *) char(x) + + end procedure disp_string_type + +end submodule stdlib_io_disp \ No newline at end of file diff --git a/src/tests/io/CMakeLists.txt b/src/tests/io/CMakeLists.txt index 68388a5e5..8963859e5 100644 --- a/src/tests/io/CMakeLists.txt +++ b/src/tests/io/CMakeLists.txt @@ -8,3 +8,4 @@ set_tests_properties(savetxt_qp PROPERTIES LABELS quadruple_precision) ADDTEST(open) ADDTEST(parse_mode) +ADDTEST(disp) diff --git a/src/tests/io/Makefile.manual b/src/tests/io/Makefile.manual index 3bbce9db7..cb7122ff1 100644 --- a/src/tests/io/Makefile.manual +++ b/src/tests/io/Makefile.manual @@ -3,7 +3,8 @@ PROGS_SRC = test_loadtxt.f90 \ test_loadtxt_qp.f90 \ test_savetxt_qp.f90 \ test_parse_mode.f90 \ - test_open.f90 + test_open.f90 \ + test_disp.f90 CLEAN_FILES = tmp.dat tmp_qp.dat io_open.dat io_open.stream diff --git a/src/tests/io/test_disp.f90 b/src/tests/io/test_disp.f90 new file mode 100644 index 000000000..dc3268fe1 --- /dev/null +++ b/src/tests/io/test_disp.f90 @@ -0,0 +1,410 @@ +module test_io_disp + + use stdlib_strings, only: starts_with + use stdlib_string_type, only: string_type, assignment(=) + use stdlib_error, only: check + use stdlib_io, only: disp + use stdlib_optval, only: optval + implicit none + + integer :: unit + character(len=200) :: string + +contains + + subroutine check_formatter(actual, expected, description, partial) + character(len=*), intent(in) :: actual, expected, description + logical, intent(in), optional :: partial + logical :: stat + character(len=:), allocatable :: msg + + if (optval(partial, .false.)) then + stat = starts_with(actual, expected) + else + stat = actual == expected + end if + + if (.not. stat) then + msg = description//new_line("a")// & + & "Expected: '"//expected//"' but got '"//actual//"'" + else + print '(" - ", a, /, " Result: ''", a, "''")', description, actual + end if + + call check(stat, msg) + + end subroutine check_formatter + + subroutine test_io_disp_complex + complex :: c(6,6) = (1.0, 1.0) + + open(newunit=unit, status='scratch') + call disp(c(1,1), header='Test_io_disp_complex_scalar (brief) : ', brief=.true.) + call disp(c(1,1), unit=unit, header='Test_io_disp_complex_scalar (brief) : ', brief=.true.) + + call disp(c(1,:), header='Test_io_disp_complex_vector (brief) : ', brief=.true.) + call disp(c(1,:), unit=unit, header='Test_io_disp_complex_vector (brief) : ', brief=.true.) + + call disp(c(:,1), header='Test_io_disp_complex_vector : ', brief=.false.) + call disp(c(:,1), unit=unit, header='Test_io_disp_complex_vector : ', brief=.false.) + + call disp(c(1:2,1:2), header='Test_io_disp_complex_matrix : ', brief=.false.) + call disp(c(1:2,1:2), unit=unit, header='Test_io_disp_complex_matrix : ', brief=.false.) + + call disp(c(:,:), header='Test_io_disp_complex_matrix (brief) : ', brief=.true.) + call disp(c(:,:), unit=unit, header='Test_io_disp_complex_matrix (brief) : ', brief=.true.) + + !! Checks + rewind(unit) + read(unit, '(A200)') string + call check_formatter(trim(adjustl(string)), 'Test_io_disp_complex_scalar (brief) :', 'Header') + read(unit, '(A200)') string + call check_formatter(trim(adjustl(string)), '(1.000,1.000)', 'Value') + + read(unit, '(A200)') string + call check_formatter(trim(adjustl(string)), 'Test_io_disp_complex_vector (brief) :', 'Header') + read(unit, '(A200)') string + call check_formatter(trim(adjustl(string)), '[vector size: 6]', 'Vector Info') + read(unit, '(A200)') string + call check_formatter(trim(adjustl(string)), & + '(1.000,1.000) (1.000,1.000) (1.000,1.000) & + & ... (1.000,1.000)', 'Brief Vector') + + read(unit, '(A200)') string + call check_formatter(trim(adjustl(string)), 'Test_io_disp_complex_vector :', 'Header') + read(unit, '(A200)') string + call check_formatter(trim(adjustl(string)), '[vector size: 6]', 'Vector Info') + read(unit, '(A200)') string + call check_formatter(trim(adjustl(string)), & + '(1.000,1.000) (1.000,1.000) (1.000,1.000) & + & (1.000,1.000) (1.000,1.000) (1.000,1.000)', 'Brief Vector') + + read(unit, '(A200)') string + call check_formatter(trim(adjustl(string)), 'Test_io_disp_complex_matrix :', 'Header') + read(unit, '(A200)') string + call check_formatter(trim(adjustl(string)), '[matrix size: 2×2]', 'Matrix Info') + read(unit, '(A200)') string + call check_formatter(trim(adjustl(string)), & + '(1.000,1.000) (1.000,1.000)', 'Matrix Vector 1') + read(unit, '(A200)') string + call check_formatter(trim(adjustl(string)), & + '(1.000,1.000) (1.000,1.000)', 'Matrix Vector 2') + + read(unit, '(A200)') string + call check_formatter(trim(adjustl(string)), 'Test_io_disp_complex_matrix (brief) :', 'Header') + read(unit, '(A200)') string + call check_formatter(trim(adjustl(string)), '[matrix size: 6×6]', 'Matrix Info') + read(unit, '(A200)') string + call check_formatter(trim(adjustl(string)), & + '(1.000,1.000) (1.000,1.000) (1.000,1.000) & + & ... (1.000,1.000)', 'Matrix Vector 1') + read(unit, '(A200)') string + call check_formatter(trim(adjustl(string)), & + '(1.000,1.000) (1.000,1.000) (1.000,1.000) & + & ... (1.000,1.000)', 'Matrix Vector 2') + read(unit, '(A200)') string + call check_formatter(trim(adjustl(string)), & + '(1.000,1.000) (1.000,1.000) (1.000,1.000) & + & ... (1.000,1.000)', 'Matrix Vector 3') + read(unit, '(A200)') string + call check_formatter(trim(adjustl(string)), & + ': : : & + & : :', 'Matrix Vector ..') + read(unit, '(A200)') string + call check_formatter(trim(adjustl(string)), & + '(1.000,1.000) (1.000,1.000) (1.000,1.000) & + & ... (1.000,1.000)', 'Matrix Vector Size(Matrix, 1)') + close(unit) + + end subroutine test_io_disp_complex + + subroutine test_io_disp_real + + real :: r(6,6) = 1.0 + + open(newunit=unit, status='scratch') + call disp(r(1,1), header='Test_io_disp_real_scalar (brief) : ', brief=.true.) + call disp(r(1,1), unit=unit, header='Test_io_disp_real_scalar (brief) : ', brief=.true.) + + call disp(r(1,:), header='Test_io_disp_real_vector (brief) : ', brief=.true.) + call disp(r(1,:), unit=unit, header='Test_io_disp_real_vector (brief) : ', brief=.true.) + + call disp(r(:,1), header='Test_io_disp_real_vector : ', brief=.false.) + call disp(r(:,1), unit=unit, header='Test_io_disp_real_vector : ', brief=.false.) + + call disp(r(1:2,1:2), header='Test_io_disp_real_matrix : ', brief=.false.) + call disp(r(1:2,1:2), unit=unit, header='Test_io_disp_real_matrix : ', brief=.false.) + + call disp(r(:,:), header='Test_io_disp_real_matrix (brief) : ', brief=.true.) + call disp(r(:,:), unit=unit, header='Test_io_disp_real_matrix (brief) : ', brief=.true.) + + !! Checks + rewind(unit) + read(unit, '(A200)') string + call check_formatter(trim(adjustl(string)), 'Test_io_disp_real_scalar (brief) :', 'Header') + read(unit, '(A200)') string + call check_formatter(trim(adjustl(string)), '1.000', 'Value') + + read(unit, '(A200)') string + call check_formatter(trim(adjustl(string)), 'Test_io_disp_real_vector (brief) :', 'Header') + read(unit, '(A200)') string + call check_formatter(trim(adjustl(string)), '[vector size: 6]', 'Vector Info') + read(unit, '(A200)') string + call check_formatter(trim(adjustl(string)), & + '1.000 1.000 1.000 ... 1.000', 'Brief Vector') + + read(unit, '(A200)') string + call check_formatter(trim(adjustl(string)), 'Test_io_disp_real_vector :', 'Header') + read(unit, '(A200)') string + call check_formatter(trim(adjustl(string)), '[vector size: 6]', 'Vector Info') + read(unit, '(A200)') string + call check_formatter(trim(adjustl(string)), & + '1.000 1.000 1.000 1.000 1.000 1.000', 'Brief Vector') + + read(unit, '(A200)') string + call check_formatter(trim(adjustl(string)), 'Test_io_disp_real_matrix :', 'Header') + read(unit, '(A200)') string + call check_formatter(trim(adjustl(string)), '[matrix size: 2×2]', 'Matrix Info') + read(unit, '(A200)') string + call check_formatter(trim(adjustl(string)), & + '1.000 1.000', 'Matrix Vector 1') + read(unit, '(A200)') string + call check_formatter(trim(adjustl(string)), & + '1.000 1.000', 'Matrix Vector 2') + + read(unit, '(A200)') string + call check_formatter(trim(adjustl(string)), 'Test_io_disp_real_matrix (brief) :', 'Header') + read(unit, '(A200)') string + call check_formatter(trim(adjustl(string)), '[matrix size: 6×6]', 'Matrix Info') + read(unit, '(A200)') string + call check_formatter(trim(adjustl(string)), & + '1.000 1.000 1.000 ... 1.000', 'Matrix Vector 1') + read(unit, '(A200)') string + call check_formatter(trim(adjustl(string)), & + '1.000 1.000 1.000 ... 1.000', 'Matrix Vector 2') + read(unit, '(A200)') string + call check_formatter(trim(adjustl(string)), & + '1.000 1.000 1.000 ... 1.000', 'Matrix Vector 3') + read(unit, '(A200)') string + call check_formatter(trim(adjustl(string)), & + ': : : : :', 'Matrix Vector ..') + read(unit, '(A200)') string + call check_formatter(trim(adjustl(string)), & + '1.000 1.000 1.000 ... 1.000', 'Matrix Vector Size(Matrix, 1)') + close(unit) + + end subroutine test_io_disp_real + + subroutine test_io_disp_integer + + integer :: i(6,6) = 1 + + open(newunit=unit, status='scratch') + call disp(i(1,1), header='Test_io_disp_integer_scalar (brief) : ', brief=.true.) + call disp(i(1,1), unit=unit, header='Test_io_disp_integer_scalar (brief) : ', brief=.true.) + + call disp(i(1,:), header='Test_io_disp_integer_vector (brief) : ', brief=.true.) + call disp(i(1,:), unit=unit, header='Test_io_disp_integer_vector (brief) : ', brief=.true.) + + call disp(i(:,1), header='Test_io_disp_integer_vector : ', brief=.false.) + call disp(i(:,1), unit=unit, header='Test_io_disp_integer_vector : ', brief=.false.) + + call disp(i(1:2,1:2), header='Test_io_disp_integer_matrix : ', brief=.false.) + call disp(i(1:2,1:2), unit=unit, header='Test_io_disp_integer_matrix : ', brief=.false.) + + call disp(i(:,:), header='Test_io_disp_integer_matrix (brief) : ', brief=.true.) + call disp(i(:,:), unit=unit, header='Test_io_disp_integer_matrix (brief) : ', brief=.true.) + + !! Checks + rewind(unit) + read(unit, '(A200)') string + call check_formatter(trim(adjustl(string)), 'Test_io_disp_integer_scalar (brief) :', 'Header') + read(unit, '(A200)') string + call check_formatter(trim(adjustl(string)), '1', 'Value') + + read(unit, '(A200)') string + call check_formatter(trim(adjustl(string)), 'Test_io_disp_integer_vector (brief) :', 'Header') + read(unit, '(A200)') string + call check_formatter(trim(adjustl(string)), '[vector size: 6]', 'Vector Info') + read(unit, '(A200)') string + call check_formatter(trim(adjustl(string)), & + '1 1 1 ... 1', 'Brief Vector') + + read(unit, '(A200)') string + call check_formatter(trim(adjustl(string)), 'Test_io_disp_integer_vector :', 'Header') + read(unit, '(A200)') string + call check_formatter(trim(adjustl(string)), '[vector size: 6]', 'Vector Info') + read(unit, '(A200)') string + call check_formatter(trim(adjustl(string)), & + '1 1 1 1 1 1', 'Brief Vector') + + read(unit, '(A200)') string + call check_formatter(trim(adjustl(string)), 'Test_io_disp_integer_matrix :', 'Header') + read(unit, '(A200)') string + call check_formatter(trim(adjustl(string)), '[matrix size: 2×2]', 'Matrix Info') + read(unit, '(A200)') string + call check_formatter(trim(adjustl(string)), & + '1 1', 'Matrix Vector 1') + read(unit, '(A200)') string + call check_formatter(trim(adjustl(string)), & + '1 1', 'Matrix Vector 2') + + read(unit, '(A200)') string + call check_formatter(trim(adjustl(string)), 'Test_io_disp_integer_matrix (brief) :', 'Header') + read(unit, '(A200)') string + call check_formatter(trim(adjustl(string)), '[matrix size: 6×6]', 'Matrix Info') + read(unit, '(A200)') string + call check_formatter(trim(adjustl(string)), & + '1 1 1 ... 1', 'Matrix Vector 1') + read(unit, '(A200)') string + call check_formatter(trim(adjustl(string)), & + '1 1 1 ... 1', 'Matrix Vector 2') + read(unit, '(A200)') string + call check_formatter(trim(adjustl(string)), & + '1 1 1 ... 1', 'Matrix Vector 3') + read(unit, '(A200)') string + call check_formatter(trim(adjustl(string)), & + ': : : : :', 'Matrix Vector ..') + read(unit, '(A200)') string + call check_formatter(trim(adjustl(string)), & + '1 1 1 ... 1', 'Matrix Vector Size(Matrix, 1)') + close(unit) + + end subroutine test_io_disp_integer + + subroutine test_io_disp_logical + + logical :: l(6,6) = .true. + ! unit = open(filenanme, 'w+t') + open(newunit=unit, status='scratch') + call disp(l(1,1), header='Test_io_disp_logical_scalar (brief) : ', brief=.true.) + call disp(l(1,1), unit=unit, header='Test_io_disp_logical_scalar (brief) : ', brief=.true.) + + call disp(l(1,:), header='Test_io_disp_logical_vector (brief) : ', brief=.true.) + call disp(l(1,:), unit=unit, header='Test_io_disp_logical_vector (brief) : ', brief=.true.) + + call disp(l(:,1), header='Test_io_disp_logical_vector : ', brief=.false.) + call disp(l(:,1), unit=unit, header='Test_io_disp_logical_vector : ', brief=.false.) + + call disp(l(1:2,1:2), header='Test_io_disp_logical_matrix : ', brief=.false.) + call disp(l(1:2,1:2), unit=unit, header='Test_io_disp_logical_matrix : ', brief=.false.) + + call disp(l(:,:), header='Test_io_disp_logical_matrix (brief) : ', brief=.true.) + call disp(l(:,:), unit=unit, header='Test_io_disp_logical_matrix (brief) : ', brief=.true.) + + !! Checks + rewind(unit) + read(unit, '(A200)') string + call check_formatter(trim(adjustl(string)), 'Test_io_disp_logical_scalar (brief) :', 'Header') + read(unit, '(A200)') string + call check_formatter(trim(adjustl(string)), 'T', 'Value') + + read(unit, '(A200)') string + call check_formatter(trim(adjustl(string)), 'Test_io_disp_logical_vector (brief) :', 'Header') + read(unit, '(A200)') string + call check_formatter(trim(adjustl(string)), '[vector size: 6]', 'Vector Info') + read(unit, '(A200)') string + call check_formatter(trim(adjustl(string)), & + 'T T T ... T', 'Brief Vector') + + read(unit, '(A200)') string + call check_formatter(trim(adjustl(string)), 'Test_io_disp_logical_vector :', 'Header') + read(unit, '(A200)') string + call check_formatter(trim(adjustl(string)), '[vector size: 6]', 'Vector Info') + read(unit, '(A200)') string + call check_formatter(trim(adjustl(string)), & + 'T T T T T T', 'Brief Vector') + + read(unit, '(A200)') string + call check_formatter(trim(adjustl(string)), 'Test_io_disp_logical_matrix :', 'Header') + read(unit, '(A200)') string + call check_formatter(trim(adjustl(string)), '[matrix size: 2×2]', 'Matrix Info') + read(unit, '(A200)') string + call check_formatter(trim(adjustl(string)), & + 'T T', 'Matrix Vector 1') + read(unit, '(A200)') string + call check_formatter(trim(adjustl(string)), & + 'T T', 'Matrix Vector 2') + + read(unit, '(A200)') string + call check_formatter(trim(adjustl(string)), 'Test_io_disp_logical_matrix (brief) :', 'Header') + read(unit, '(A200)') string + call check_formatter(trim(adjustl(string)), '[matrix size: 6×6]', 'Matrix Info') + read(unit, '(A200)') string + call check_formatter(trim(adjustl(string)), & + 'T T T ... T', 'Matrix Vector 1') + read(unit, '(A200)') string + call check_formatter(trim(adjustl(string)), & + 'T T T ... T', 'Matrix Vector 2') + read(unit, '(A200)') string + call check_formatter(trim(adjustl(string)), & + 'T T T ... T', 'Matrix Vector 3') + read(unit, '(A200)') string + call check_formatter(trim(adjustl(string)), & + ': : : : :', 'Matrix Vector ..') + read(unit, '(A200)') string + call check_formatter(trim(adjustl(string)), & + 'T T T ... T', 'Matrix Vector Size(Matrix, 1)') + close(unit) + + end subroutine test_io_disp_logical + + subroutine test_io_disp_character + + character(*), parameter :: str = 'It is a character.' + ! unit = open(filenanme, 'w+t') + open(newunit=unit, status='scratch') + call disp(str, header='Test_io_disp_character_scalar (brief) : ', brief=.true.) + call disp(str, unit=unit, header='Test_io_disp_character_scalar (brief) : ', brief=.true.) + + !! Checks + rewind(unit) + read(unit, '(A200)') string + call check_formatter(trim(adjustl(string)), 'Test_io_disp_character_scalar (brief) :', 'Header') + read(unit, '(A200)') string + call check_formatter(trim(adjustl(string)), 'It is a character.', 'Value') + close(unit) + + end subroutine test_io_disp_character + + subroutine test_io_disp_string_type + + type(string_type) :: str + + str = 'It is a string_type.' + open(newunit=unit, status='scratch') + call disp(str, header='Test_io_disp_string_type_scalar (brief) : ', brief=.true.) + call disp(str, unit=unit, header='Test_io_disp_string_type_scalar (brief) : ', brief=.true.) + + !! Checks + rewind(unit) + read(unit, '(A200)') string + call check_formatter(trim(adjustl(string)), 'Test_io_disp_string_type_scalar (brief) :', 'Header') + read(unit, '(A200)') string + call check_formatter(trim(adjustl(string)), 'It is a string_type.', 'Value') + close(unit) + + end subroutine test_io_disp_string_type + +end module test_io_disp + +program tester + + use test_io_disp + ! real(4) :: x(51,51) + + call test_io_disp_complex + call test_io_disp_real + call test_io_disp_integer + call test_io_disp_logical + call test_io_disp_character + call test_io_disp_string_type + + !> Content that is difficult to test: The length of the dimension is too large + !> to print and check by a test program. + ! x = 0.0 + ! call disp(x, header="Test_io_disp_real_matrix (51×51)(default) : [10×50]") + ! call disp(x, header="Test_io_disp_real_matrix (51×51)(brief=.true.) : [5×5]", brief=.true.) + ! call disp(x, header="Test_io_disp_real_matrix (51×51)(brief=.false.) : [all]", brief=.false.) + +end program tester \ No newline at end of file