conversion byte -> float/int with 4/8 byte length

This commit is contained in:
Martin Diehl 2020-09-06 17:36:05 +02:00
parent de4587c52e
commit 54207760db
1 changed files with 77 additions and 4 deletions

View File

@ -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