From 54207760db9c78a8fd37ed8b9b284cdcc0ae9d59 Mon Sep 17 00:00:00 2001 From: Martin Diehl Date: Sun, 6 Sep 2020 17:36:05 +0200 Subject: [PATCH] conversion byte -> float/int with 4/8 byte length --- src/prec.f90 | 81 +++++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 77 insertions(+), 4 deletions(-) diff --git a/src/prec.f90 b/src/prec.f90 index 73649f76b..6f0a2ab3d 100644 --- a/src/prec.f90 +++ b/src/prec.f90 @@ -8,6 +8,7 @@ !-------------------------------------------------------------------------------------------------- module prec use, intrinsic :: IEEE_arithmetic + use, intrinsic :: ISO_C_Binding implicit none public @@ -81,7 +82,7 @@ contains !-------------------------------------------------------------------------------------------------- -!> @brief reporting precision +!> @brief report precision and do self test !-------------------------------------------------------------------------------------------------- subroutine prec_init @@ -230,24 +231,96 @@ logical elemental pure function cNeq(a,b,tol) end function cNeq +!-------------------------------------------------------------------------------------------------- +!> @brief interprete array of bytes (C_SIGNED_CHAR) as C_FLOAT (4 byte float) +!-------------------------------------------------------------------------------------------------- +pure function bytes_to_C_FLOAT(bytes) + + integer(C_SIGNED_CHAR), dimension(:), intent(in) :: bytes !< byte-wise representation of a C_FLOAT array + real(C_FLOAT), dimension(size(bytes,kind=pLongInt)/(storage_size(0._C_FLOAT,pLongInt)/8_pLongInt)) :: & + bytes_to_C_FLOAT + + bytes_to_C_FLOAT = transfer(bytes,bytes_to_C_FLOAT,size(bytes_to_C_FLOAT)) + +end function bytes_to_C_FLOAT + + +!-------------------------------------------------------------------------------------------------- +!> @brief interprete array of bytes (C_SIGNED_CHAR) as C_DOUBLE (8 byte float) +!-------------------------------------------------------------------------------------------------- +pure function bytes_to_C_DOUBLE(bytes) + + integer(C_SIGNED_CHAR), dimension(:), intent(in) :: bytes !< byte-wise representation of a C_DOUBLE array + real(C_DOUBLE), dimension(size(bytes,kind=pLongInt)/(storage_size(0._C_DOUBLE,pLongInt)/8_pLongInt)) :: & + bytes_to_C_DOUBLE + + bytes_to_C_DOUBLE = transfer(bytes,bytes_to_C_DOUBLE,size(bytes_to_C_DOUBLE)) + +end function bytes_to_C_DOUBLE + + +!-------------------------------------------------------------------------------------------------- +!> @brief interprete array of bytes (C_SIGNED_CHAR) as C_INT32_T (4 byte signed integer) +!-------------------------------------------------------------------------------------------------- +pure function bytes_to_C_INT32_T(bytes) + + integer(C_SIGNED_CHAR), dimension(:), intent(in) :: bytes !< byte-wise representation of a C_INT32_T array + integer(C_INT32_T), dimension(size(bytes,kind=pLongInt)/(storage_size(0_C_INT32_T,pLongInt)/8_pLongInt)) :: & + bytes_to_C_INT32_T + + bytes_to_C_INT32_T = transfer(bytes,bytes_to_C_INT32_T,size(bytes_to_C_INT32_T)) + +end function bytes_to_C_INT32_T + + +!-------------------------------------------------------------------------------------------------- +!> @brief interprete array of bytes (C_SIGNED_CHAR) as C_INT64_T (8 byte signed integer) +!-------------------------------------------------------------------------------------------------- +pure function bytes_to_C_INT64_T(bytes) + + integer(C_SIGNED_CHAR), dimension(:), intent(in) :: bytes !< byte-wise representation of a C_INT64_T array + integer(C_INT64_T), dimension(size(bytes,kind=pLongInt)/(storage_size(0_C_INT64_T,pLongInt)/8_pLongInt)) :: & + bytes_to_C_INT64_T + + bytes_to_C_INT64_T = transfer(bytes,bytes_to_C_INT64_T,size(bytes_to_C_INT64_T)) + +end function bytes_to_C_INT64_T + + !-------------------------------------------------------------------------------------------------- !> @brief check correctness of some prec functions !-------------------------------------------------------------------------------------------------- subroutine selfTest integer, allocatable, dimension(:) :: realloc_lhs_test - real(pReal), dimension(2) :: r + real(pReal), dimension(1) :: f + integer(pInt), dimension(1) :: i + real(pReal), dimension(2) :: r external :: & quit + realloc_lhs_test = [1,2] + if (any(realloc_lhs_test/=[1,2])) call quit(9000) + call random_number(r) r = r/minval(r) if(.not. all(dEq(r,r+PREAL_EPSILON))) call quit(9000) if(dEq(r(1),r(2)) .and. dNeq(r(1),r(2))) call quit(9000) if(.not. all(dEq0(r-(r+PREAL_MIN)))) call quit(9000) - realloc_lhs_test = [1,2] - if (any(realloc_lhs_test/=[1,2])) call quit(9000) + ! https://www.binaryconvert.com + ! https://www.rapidtables.com/convert/number/binary-to-decimal.html + f = real(bytes_to_C_FLOAT(int([-65,+11,-102,+75],C_SIGNED_CHAR)),pReal) + if(dNeq(f(1),20191102.0_pReal,0.0_pReal)) call quit(9000) + + f = real(bytes_to_C_DOUBLE(int([0,0,0,-32,+119,+65,+115,65],C_SIGNED_CHAR)),pReal) + if(dNeq(f(1),20191102.0_pReal,0.0_pReal)) call quit(9000) + + i = int(bytes_to_C_INT32_T(int([+126,+23,+52,+1],C_SIGNED_CHAR)),pInt) + if(i(1) /= 20191102_pInt) call quit(9000) + + i = int(bytes_to_C_INT64_T(int([+126,+23,+52,+1,0,0,0,0],C_SIGNED_CHAR)),pInt) + if(i(1) /= 20191102_pInt) call quit(9000) end subroutine selfTest