! Tests packing and unpacking data from a BLUE file with different byte orders.
!
! @author  J. Czechowski IV
!
startmacro
  call setDatDir

  call testScalarValues
  call testVector8      ! VD, VX, 3D, 3X
  call testVector4      ! VF, VL, 3F, 3L
  call testVector2      ! VI, 3I
  
  call testLocalCopy ^{datDir}.sinewave.prm           ! Type 1000
  call testLocalCopy ^{datDir}.fftdemo.prm            ! Type 1000
  call testLocalCopy ^{datDir}.apenny.prm             ! Type 2000
  call testLocalCopy ^{datDir}.testxy3000.prm         ! Type 3000
  call testLocalCopy ^{datDir}.test3000_ieee.prm      ! Type 3000
  call testLocalCopy ^{datDir}.test3000_eeei.prm      ! Type 3000
  call testLocalCopy ^{datDir}.coneflags5000.prm      ! Type 5000
  call testLocalCopy ^{datDir}.ellipseflags5000.prm   ! Type 5000
endmacro

!******************************************************************************!
! Set the dat directory
!******************************************************************************!
procedure setDatDir
  invoke nxmMajor env.nmversion.subString(0,1)
  invoke major java.lang.Integer.valueOf(nxmMajor)
  if major GE 4 then
    invoke s:datDir           nxm.sys.test.DatLocator.getDatDirLocation()
    invoke s:datDirSlash      nxm.sys.test.DatLocator.getDatDirSlashLocation()
    invoke z:sysDatFull       nxm.sys.test.DatLocator.sysDatFull()
    invoke z:sysTestDatExists nxm.sys.test.DatLocator.sysTestDatExists()
  else
    set s:datDir           "nxm.sys.dat"
    set s:datDirSlash      "nxm/sys/dat"
    set z:sysDatFull       true
    set z:sysTestDatExists false
  endif
return

! Tests copying a file to a local copy. Copying with COPY/L will fail if the initial
! byte order differs from the local platform and it has VD data, until Bug ???? is
! resolved.
!
! The primary difference between NOOP and COPY/L is that NOOP uses byte buffers during
! the copy and COPY/L uses the methods from ListFile which hold each row as a Table.
! COPY/B should always work since it is a direct binary copy.
!
! @param fname The file to copy to RAM
!
procedure testLocalCopy fn:fname
  res name "^{fname.root}.^{fname.ext}"

  noop fname ram:tempN
  file copy/l fname ram:tempL
  file copy/b fname ram:tempB
  
  ! Do not do FEQ/H with NOOP or COPY/L since byte ordering differs
  assert/text="^reg.main.name: Copy ^name using NOOP"   ram:tempN FEQ/D fname
  assert/text="^reg.main.name: Copy ^name using COPY/L" ram:tempL FEQ/D fname
  assert/text="^reg.main.name: Copy ^name using COPY/B" ram:tempB FEQ/D fname
  erase/all ram:tempN ram:tempL ram:tempB
return


! Tests packing/unpacking scalar values
procedure testScalarValues
  set fname ram:testfile
  call createByteFile fname 15
  
  file open/w tag ^{fname}
    ! All values must be < 128 to prevent problems with NaNs after converting to double
    !                      | DOUBLE/XLONG                          | FLOAT/LONG           | INT       | BYTE
    set tag.insertData(-1) {F1=1,F2=2,F3=3,F4=4,F5=5,F6=6,F7=7,F8=8,F9=1,F10=2,F11=3,F12=4,F13=1,F14=2,F15=1}
    set tag.insertData(-1) {F1=8,F2=7,F3=6,F4=5,F5=4,F6=3,F7=2,F8=1,F9=4,F10=3,F11=2,F12=1,F13=2,F14=1,F15=1}
  file close tag
  
  call testScalarFormat "SX" "SL" "SI" "SB"
  call testScalarFormat "SD" "SF" "SI" "SB"
  call testScalarFormat "1X" "1L" "1I" "1B"
  call testScalarFormat "1D" "1F" "1I" "1B"
return


! Tests unpacking a vector of 8-byte values
procedure testVector8
  set fname ram:testfile
  call createByteFile fname 24
  
  file open/w tag ^{fname}
    ! All values must be < 128 to prevent problems with NaNs after converting to double
    !                      | DOUBLE/XLONG                          | DOUBLE/XLONG                                 | DOUBLE/XLONG
    set tag.insertData(-1) {F1=1,F2=2,F3=3,F4=4,F5=5,F6=6,F7=7,F8=8,F9=1,F10=2,F11=3,F12=4,F13=5,F14=6,F15=7,F16=8,F17=1,F18=2,F19=3,F20=4,F21=5,F22=6,F23=7,F24=8}
    set tag.insertData(-1) {F1=8,F2=7,F3=6,F4=5,F5=4,F6=3,F7=2,F8=1,F9=8,F10=7,F11=6,F12=5,F13=4,F14=3,F15=2,F16=1,F17=8,F18=7,F19=6,F20=5,F21=4,F22=3,F23=2,F24=1}
  file close tag

  call testVectorValues fname "VD"
  call testVectorValues fname "VX"
  call testVectorValues fname "3D"
  call testVectorValues fname "3X"
return


! Tests unpacking a vector of 4-byte values
procedure testVector4
  set fname ram:testfile
  call createByteFile fname 12
  
  file open/w tag ^{fname}
    ! All values must be < 128 to prevent problems with NaNs after converting to double
    !                      | FLOAT/LONG        | FLOAT/LONG        | FLOAT/LONG
    set tag.insertData(-1) {F1=1,F2=2,F3=3,F4=4,F5=1,F6=2,F7=3,F8=4,F9=1,F10=2,F11=3,F12=4}
    set tag.insertData(-1) {F1=4,F2=3,F3=2,F4=1,F5=4,F6=3,F7=2,F8=1,F9=4,F10=3,F11=2,F12=1}
  file close tag

  call testVectorValues fname "VF"
  call testVectorValues fname "VL"
  call testVectorValues fname "3F"
  call testVectorValues fname "3L"
return


! Tests unpacking a vector of 2-byte values
procedure testVector2
  set fname ram:testfile
  call createByteFile fname 6
  
  file open/w tag ^{fname}
    ! All values must be < 128 to prevent problems with NaNs after converting to double
    !                      | INT     | INT     | INT
    set tag.insertData(-1) {F1=1,F2=2,F3=1,F4=2,F5=1,F6=2}
    set tag.insertData(-1) {F1=2,F2=1,F3=2,F4=1,F5=2,F6=1}
  file close tag

  call testVectorValues fname "VI"
  call testVectorValues fname "3I"
return


! Used by testVector8, testVector4, testVector2
procedure testVectorValues fn:filename s:form
  file open ieee ^{filename}{SR=(VAL/^{form}),DATAREP=IEEE}
    res ieee_row0 ieee.getDataTable(0)
    res ieee_row1 ieee.getDataTable(1)
  file close ieee
  
  file open eeei ^{filename}{SR=(VAL/^{form}),DATAREP=EEEI}
    res eeei_row0 eeei.getDataTable(0)
    res eeei_row1 eeei.getDataTable(1)
  file close eeei
  
  assert/text="^reg.main.name: FORM=^{form}: Row 0 (IEEE) = Row 1 (EEEI) VAL(0)" ieee_row0.VAL(0) EQ eeei_row1.VAL(0)
  assert/text="^reg.main.name: FORM=^{form}: Row 0 (IEEE) = Row 1 (EEEI) VAL(1)" ieee_row0.VAL(1) EQ eeei_row1.VAL(1)
  assert/text="^reg.main.name: FORM=^{form}: Row 0 (IEEE) = Row 1 (EEEI) VAL(2)" ieee_row0.VAL(2) EQ eeei_row1.VAL(2)

  assert/text="^reg.main.name: FORM=^{form}: Row 1 (IEEE) = Row 0 (EEEI) VAL(0)" ieee_row1.VAL(0) EQ eeei_row0.VAL(0)
  assert/text="^reg.main.name: FORM=^{form}: Row 1 (IEEE) = Row 0 (EEEI) VAL(1)" ieee_row1.VAL(1) EQ eeei_row0.VAL(1)
  assert/text="^reg.main.name: FORM=^{form}: Row 1 (IEEE) = Row 0 (EEEI) VAL(2)" ieee_row1.VAL(2) EQ eeei_row0.VAL(2)
return


! Used by testScalarValues
procedure testScalarFormat s:form8 s:form4 s:form2 s:form1
  set subrec "DAT8/^{form8},DAT4/^{form4},DAT2/^{form2},DAT1/^{form1}"


  file open ieee ^{fname}{SR=(^{subrec}),DATAREP=IEEE}
    res ieee_row0 ieee.getDataTable(0)
    res ieee_row1 ieee.getDataTable(1)
  file close ieee
  
  file open eeei ^{fname}{SR=(^{subrec}),DATAREP=EEEI}
    res eeei_row0 eeei.getDataTable(0)
    res eeei_row1 eeei.getDataTable(1)
  file close eeei
  
  assert/text="^reg.main.name: FORM=^{form8}: Row 0 (IEEE) = Row 1 (EEEI)" ieee_row0.dat8 EQ eeei_row1.dat8
  assert/text="^reg.main.name: FORM=^{form8}: Row 1 (IEEE) = Row 0 (EEEI)" ieee_row1.dat8 EQ eeei_row0.dat8
  
  assert/text="^reg.main.name: FORM=^{form4}: Row 0 (IEEE) = Row 1 (EEEI)" ieee_row0.dat4 EQ eeei_row1.dat4
  assert/text="^reg.main.name: FORM=^{form4}: Row 1 (IEEE) = Row 0 (EEEI)" ieee_row1.dat4 EQ eeei_row0.dat4

  assert/text="^reg.main.name: FORM=^{form2}: Row 0 (IEEE) = Row 1 (EEEI)" ieee_row0.dat2 EQ eeei_row1.dat2
  assert/text="^reg.main.name: FORM=^{form2}: Row 1 (IEEE) = Row 0 (EEEI)" ieee_row1.dat2 EQ eeei_row0.dat2

  assert/text="^reg.main.name: FORM=^{form1}: Row 0 (IEEE) = Row 1 (EEEI)" ieee_row0.dat1 EQ eeei_row1.dat1
  assert/text="^reg.main.name: FORM=^{form1}: Row 1 (IEEE) = Row 0 (EEEI)" ieee_row1.dat1 EQ eeei_row0.dat1
return


! Crestes a new Type 3000 file with the given number of columns each with SB data
!
!  @param cbf_fileName  The file name
!  @param cbf_numBytes  The number of columns
!
procedure createByteFile FN:cbf_fileName L:cbf_numBytes
  if cbf_numBytes gt 0 then
    set cbf_rows "F1/SB"
    do i 2 cbf_numBytes 1
      set cbf_rows "^{cbf_rows},F^{i}/SB"
    enddo
    
    header/create ^{fname} type=3000 SR=(^{cbf_rows})
  endif
return
