Running "CODESYS V3.5 SP16" here, I am trying to implement the hashcode algorithm mentioned in
Best implementation for hashCode method for a collection
and had to built my own solution to replicate Java's Float.floatToIntBits(f) which resulted in the following function
FUNCTION F_lrealToLintBits : LINT
VAR_INPUT
  lrVal : LREAL;
END_VAR
VAR
  arrBytes : ARRAY[0..7] OF BYTE; // LREAL contains 64 bits and each byte contains 8 bits
  pVal     : POINTER TO LREAL := ADR(arrBytes);
  diIndx   : DINT;
  uiExpt   : UINT := 0; // exponent goes from 0 to 63
END_VAR
pVal^ := lrVal; // maps LREAL to array of bytes
// little endian? cause it seems that least significant bit is at lowest address
FOR diIndx := LOWER_BOUND(arrBytes, 1) TO UPPER_BOUND(arrBytes, 1) BY 1 DO
  // bit access seems to be manual only so no loops
  IF arrBytes[diIndx].0 THEN
    F_lrealToLintBits := F_lrealToLintBits + LREAL_TO_LINT(EXPT(2, uiExpt));
  END_IF
  uiExpt := uiExpt + 1; // have to increment exponent after every bit
  IF arrBytes[diIndx].1 THEN
    F_lrealToLintBits := F_lrealToLintBits + LREAL_TO_LINT(EXPT(2, uiExpt));
  END_IF
  uiExpt := uiExpt + 1; // have to increment exponent after every bit
  IF arrBytes[diIndx].2 THEN
    F_lrealToLintBits := F_lrealToLintBits + LREAL_TO_LINT(EXPT(2, uiExpt));
  END_IF
  uiExpt := uiExpt + 1; // have to increment exponent after every bit
  IF arrBytes[diIndx].3 THEN
    F_lrealToLintBits := F_lrealToLintBits + LREAL_TO_LINT(EXPT(2, uiExpt));
  END_IF
  uiExpt := uiExpt + 1; // have to increment exponent after every bit
  IF arrBytes[diIndx].4 THEN
    F_lrealToLintBits := F_lrealToLintBits + LREAL_TO_LINT(EXPT(2, uiExpt));
  END_IF
  uiExpt := uiExpt + 1; // have to increment exponent after every bit
  IF arrBytes[diIndx].5 THEN
    F_lrealToLintBits := F_lrealToLintBits + LREAL_TO_LINT(EXPT(2, uiExpt));
  END_IF
  uiExpt := uiExpt + 1; // have to increment exponent after every bit
  IF arrBytes[diIndx].6 THEN
    F_lrealToLintBits := F_lrealToLintBits + LREAL_TO_LINT(EXPT(2, uiExpt));
  END_IF
  uiExpt := uiExpt + 1; // have to increment exponent after every bit
  IF arrBytes[diIndx].7 THEN
    F_lrealToLintBits := F_lrealToLintBits + LREAL_TO_LINT(EXPT(2, uiExpt));
  END_IF
  uiExpt := uiExpt + 1; // have to increment exponent after every bit
END_FOR
Firstly, I would like to know if there is an existing function in some library that does this already?
I looked in many places including in the OSCAT "Basic, 3.31" library but could not find anything similar (even a set of functions that I could chain together would be OK).
Secondly, can bit access only be done manually?
I would prefer to use a loop but it seems that is not possible? Is there a less copy-and-paste method of accessing the bits that would involve automatically detecting the number of bits if the data type in the array changes from BYTE to something else (e.g. DWORD)?
Potential alternative
Seems like this is where unions come in handy, as mentioned in https://forge.codesys.com/forge/talk/Engineering/thread/02a65a50b2/#e5f4/1911/c524 where if the value does not come from an external source (i.e. no need to check for endian-ness), Float.floatToIntBits(f) would be as simple as
TYPE
  U_lrealToRawLintBits :
  UNION
    lrVal : LREAL;
    liVal : LINT;
  END_UNION
END_TYPE
// supposed to replicate floatToIntBits() in Java at
// https://github.com/openjdk/jdk/blob/739769c8fc4b496f08a92225a12d07414537b6c0/src/java.base/share/classes/java/lang/Float.java#L775
FUNCTION F_lrealToLintBits : LINT
VAR_INPUT
    lrVal : LREAL;
END_VAR
VAR
    uLrealToLintBits : U_lrealToRawLintBits; // for interpreting LREAL as base 10 LINT
END_VAR
IF FPU.IsLRealPosInfinity(lrVal) THEN
  F_lrealToLintBits := 2139095040; // corresponds to 0x7f800000
ELSIF FPU.IsLRealNegInfinity(lrVal) THEN
  F_lrealToLintBits := 4286578688; // corresponds to 0xff800000
ELSIF FPU.IsLRealNaN(lrVal) THEN
  F_lrealToLintBits := 2143289344; // corresponds to 0x7fc00000
ELSE
  uLrealToLintBits.lrVal := lrVal;
  F_lrealToLintBits := uLrealToLintBits.liVal;
END_IF
 
    