/**************************************************
* unit:    struct            release 0.16         *
* purpose: test of functionality of struct lib    *
***************************************************/
#ifdef _MSC_VER
    #include <windows.h> 
#endif
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <math.h>

#ifdef __BORLANDC__
#include <alloc.h>
#else
#define heapcheck() 1
#endif

//#define LO_ENDIAN
#include "struct.h"

char Blob[32];
char *TEMP_FILE = "temp.tmp";

void Benchmark(void);

FILE *TempF;
int Pause = 0;


const char Struct1[] = "bwdDWB";
                       

typedef struct
	{
	char Name[20];
	int16_t Rows;
	int16_t Cols;
	int16_t TypSou;
	int32_t Zoom;
	int16_t Verze;
	int16_t Komprese;
	int16_t Stav;
	double xRasMin;
	double yRasMin;
	double xRasMax;
	double yRasMax;
	double Scale;
	uint16_t TileWidth;
	uint16_t TileHeight;
	int32_t TileOffsets;
	int32_t TileByteCounts;
	uint8_t TileCompression;
	uint8_t Dummy[423];
	} TopolRasHeader;

const char StructTopol[] = "a20wwwdwwweeeeewwddba423";

const char TEST_STRING_LONG[] = "Hello word from struct test";
const char TEST_STRING_SHORT[] = "Short Message*";

long SaveTopolHeader(FILE *f, const TopolRasHeader *SU)
{
 return(savestruct(f,StructTopol,
	 SU->Name,SU->Rows,SU->Cols,SU->TypSou,SU->Zoom,SU->Verze,
         SU->Komprese,SU->Stav,
         SU->xRasMin,SU->yRasMin,SU->xRasMax,SU->yRasMax,SU->Scale,	//from release 2
	 SU->TileWidth,SU->TileHeight,SU->TileOffsets,SU->TileByteCounts,
         SU->TileCompression,SU->Dummy));
}

long LoadTopolHeader(FILE *f, TopolRasHeader *SU)
{                                                   
 return(loadstruct(f,StructTopol,
	 &SU->Name,&SU->Rows,&SU->Cols,&SU->TypSou,&SU->Zoom,&SU->Verze,
         &SU->Komprese,&SU->Stav,
         &SU->xRasMin,&SU->yRasMin,&SU->xRasMax,&SU->yRasMax,&SU->Scale,	//from release 2
	 &SU->TileWidth,&SU->TileHeight,&SU->TileOffsets,&SU->TileByteCounts,
         &SU->TileCompression,&SU->Dummy));
}


int main(int argc, char *argv[])
{
uint8_t B, B1;
uint16_t W, W2;
uint32_t D, D2;
#ifdef uint64_t_defined
uint64_t Q, Q2;
#endif
float f, f2;
unsigned char a[8];
int i, rw, err;
int Ops;
TopolRasHeader SU;

puts("");
puts("<<<struct>>> (c)1998-2024 Jaroslav Fojtik");
puts("                 This program tests the struct.c library");
#ifdef LO_ENDIAN
 puts("***LO_ENDIAN defined***");
#endif
#ifdef HI_ENDIAN
 puts("***HI_ENDIAN defined***");
#endif
#ifdef EXPAND_OPS
 puts("***EXPAND_OPS defined***");
#endif
#ifdef NATIVE_ACCESS
 puts("***NATIVE access***");
#endif

 if(argc>1)
    {
    Ops=0;
    for(i=1; i<argc; i++)
      {
      if(!strcmp(argv[i],"-bench")) Ops|=3;
      if(!strcmp(argv[i],"-demo")) Ops|=4;
      if(!strcmp(argv[i],"-test")) Ops|=1;
      if(!strcmp(argv[i],"-pause")) Pause=1;
      if(!strcmp(argv[i],"-f"))
        {
        i++;
        TEMP_FILE = argv[i];
        }
      }
    }
 else Ops=3;

 err = 0;
 if(Ops & 1)
 {

 //////////////////////////////////
 puts(" Testing file operations");

 TempF = fopen(TEMP_FILE,"wb");
 if(TempF==NULL)
 {
   printf("Cannot open file \"temp.tmp\"!\n");
   err++;
   goto FileError;
 }

 W = 0x1122;
 rw = WrWORD_LoEnd(W, TempF);
 if(rw!=2)
   {printf("Problem in WrWORD_LoEnd, unexpected return value %d, expected 2\n",rw);err++;}

 W = 0x2233;
 rw = WrWORD_HiEnd(W, TempF);
 if(rw!=2)
   {printf("Problem in WrWORD_HiEnd, unexpected return value %d, expected 2\n",rw);err++;}

 D = 0x44556677;
 rw = WrDWORD_LoEnd(D, TempF);
 if(rw!=4)
   {printf("Problem in WrDWORD_LoEnd, unexpected return value %d\n",rw);err++;}

 D = 0x8899AABB;
 rw = WrDWORD_HiEnd(D, TempF);
 if(rw!=4)
   {printf("Problem in WrDWORD_HiEnd, unexpected return value %d\n",rw);err++;}

#if defined(uint64_t_defined)
 Q = 0x2468AC13579BDF;
 rw = WrQWORD_LoEnd(Q, TempF);
 if(rw!=8)
   {printf("Problem in WrQWORD_LoEnd, unexpected return value %d\n",rw);err++;}
 Q = 0x13579BDF02468AC;
 rw = WrQWORD_HiEnd(Q, TempF);
 if(rw!=8)
   {printf("Problem in WrQWORD_HiEnd, unexpected return value %d\n",rw);err++;}
#endif

 f = 20.5;
 rw = WrFLOAT_LoEnd(f, TempF);

 for(i=0; i<2048; i++) fputc(i,TempF);
 fclose(TempF);

 TempF = fopen(TEMP_FILE,"rb");
 if(TempF==NULL)
 {
   printf("Cannot reopen file \"temp.tmp\" for reading!\n");
   err++;
   goto FileError;
 }

 fseek(TempF,0,SEEK_SET);

 i = 0;

 fread(a,1,2,TempF);
 if(a[0]!=0x22 || a[1]!=0x11)
   {printf("Problem in WrWORD_LoEnd, value read 0x%X%2.2X\n",a[0],a[1]);err++;}

 fread(a,1,2,TempF);
 if(a[0]!=0x22 || a[1]!=0x33)
   {printf("Problem in WrWORD_HiEnd, value read 0x%X%2.2X\n",a[0],a[1]);err++;}

 fread(a,1,4,TempF);
 if(a[0]!=0x77 || a[1]!=0x66 || a[2]!=0x55 || a[3]!=0x44)
   {printf("Problem in WrDWORD_LoEnd, value read 0x%X%2.2X%2.2X%2.2X\n",a[0],a[1],a[2],a[3]);err++;}

 fread(a,1,4,TempF);
 if(a[0]!=0x88 || a[1]!=0x99 || a[2]!=0xAA || a[3]!=0xBB)
   {printf("Problem in WrDWORD_LoEnd, value read 0x%X%2.2X%2.2X%2.2X\n",a[0],a[1],a[2],a[3]);err++;}

#if defined(uint64_t_defined)
 fread(a,1,8,TempF);
//Q = 0x24 68 AC 13 57 9B DF;
 if(a[0]!=0xDF || a[1]!=0x9B || a[2]!=0x57 || a[3]!=0x13 || a[4]!=0xAC || a[5]!=0x68 || a[6]!=0x24 || a[7]!=0x00)
   {printf("Problem in WrQWORD_LoEnd, value read 0x%X%2.2X%2.2X%2.2X\n",a[0],a[1],a[2],a[3]);err++;}
 // Q = 0x1 35 79 BD F0 24 68 AC;
 fread(a,1,8,TempF);
 if(a[0]!=0x01 || a[1]!=0x35 || a[2]!=0x79 || a[3]!=0xBD || a[4]!=0xF0 || a[5]!=0x24 || a[6]!=0x68 || a[7]!=0xAC)
   {printf("Problem in WrQWORD_HiEnd, value read 0x%X%2.2X%2.2X%2.2X\n",a[0],a[1],a[2],a[3]);err++;}
#endif

 rw = RdFLOAT_LoEnd(&f2,TempF);
 if(rw!=4)
   {printf("Problem in RdDFLOAT_LoEnd, unexpected return value %d\n",rw);err++;}
 if(fabs(f2-f) >1e-5)
   {printf("Problem in RdDFLOAT_LoEnd, value read %f, expected %f\n",f2,f);err++;}


 rw = RdWORD_LoEnd(&W,TempF);
 if(rw!=2)
   {printf("\nProblem in RdWORD_LoEnd, unexpected return value %d",rw);err++;}
 if(W!=0x0100)
   {printf("\nProblem in RdWORD_LoEnd, value read %X",(int)W);err++;}

 rw = RdDWORD_LoEnd(&D,TempF);
 if(rw!=4)
   {printf("Problem in RdDWORD_LoEnd, unexpected return value %d\n",rw);err++;}
 if(D!=0x05040302)
   {printf("Problem in RdDWORD_LoEnd, value read %X\n",(int)D);err++;}

 rw = RdWORD_HiEnd(&W,TempF);
 if(rw!=2)
   {printf("Problem in RdWORD_HiEnd, unexpected return value %d\n",rw);err++;}
 if(W!=0x0607)
   {printf("Problem in RdWORD_HiEnd, value read %X\n",(int)W);err++;}

 rw = RdDWORD_HiEnd(&D,TempF);
 if(rw!=4)
   {printf("Problem in RdDWORD_HiEnd, unexpected return value %d\n",rw);err++;}
 if(D!=0x08090A0B)
   {printf("Problem in RdDWORD_HiEnd, value read %X\n",(int)D);err++;}

#if defined(uint64_t_defined)
 rw = RdQWORD_LoEnd(&Q,TempF);
 if(rw!=8)
   {printf("Problem in RdQWORD_LoEnd, unexpected return value %d\n",rw);err++;}
 if(Q!=0x131211100F0E0D0C)
   {printf("\nProblem in RdQWORD_LoEnd, value read %llX\n",Q);err++;}

 rw = RdQWORD_HiEnd(&Q,TempF);
 if(rw!=8)
   {printf("Problem in RdQWORD_HiEnd, unexpected return value %d\n",rw);err++;}
 if(Q!=0x1415161718191A1B)
   {printf("Problem in RdQWORD_HiEnd, value read %llXh, expected 1415161718191A1Bh\n",Q);err++;}
#endif

 fclose(TempF);


 //////////////////////////////////
 puts(" Testing struct manipulation");

 TempF = fopen(TEMP_FILE,"wb");
 if(TempF==NULL)
 {
   printf("\nCannot open file \"temp.tmp\"!");
   err++;
   goto FileError;
 }

 B = 0x23;
 B1 = 0x2F;
 W = 0x1234;
 W2 = 0x567;
 D = 0xABCDEF01;
 D2 = 0x44556677;
 rw = savestruct(TempF,Struct1, B, W, D, D2, W2, B1);
 if(rw!=14)
   {printf("14 bytes is expected to be stored in struct, %d reported\n",rw);err++;}
 rw = savestruct(TempF,Struct1, B1, W2, D2, D, W, B);
 if(rw!=14)
   {printf("14 bytes is expected to be stored in struct, %d reported\n",rw);err++;}

#if defined(uint64_t_defined)
 Q = 0xABCD0123456789; 
 Q2 = 0xBCD0123456789A;
 rw = savestruct(TempF, "Qwq", Q, W, Q2);
 if(rw!=18)
   {printf("18 bytes is expected to be stored in struct, %d reported\n",rw);err++;}
 rw = savestruct(TempF, "qWQ", Q, W, Q2);
 if(rw!=18)
   {printf("18 bytes is expected to be stored in struct, %d reported\n",rw);err++;}
#endif

 memset(&SU,45,sizeof(SU));
 SU.Rows = 107;
 SU.Cols = 105;
 SU.Stav = 0x4567;
 SU.xRasMin = -100.5;
 SU.TileCompression = 2;
 SU.TileByteCounts = 0x7BCDEF12;
 strcpy((char*)SU.Dummy,TEST_STRING_LONG);
 strcpy(SU.Name,TEST_STRING_SHORT);
 rw =SaveTopolHeader(TempF,&SU);
 if(rw != 512)
   {printf("Problem with struct saving %d, expected 512 bytes\n",rw);err++;} 

 fclose(TempF);


 TempF = fopen(TEMP_FILE,"rb");
 if(TempF==NULL)
 {
   printf("Cannot open file \"temp.tmp\" for reading!\n");
   err++;
   goto FileError;
 }

 rw = loadstruct(TempF,Struct1, &B1, &W2, &D2, &D, &W, &B);
 if(rw!=14)
   {printf("14 bytes is expected to be stored in struct, %d reported\n",rw);err++;}

 if(B1!=0x23)
   {printf("Expected to read 0x23, actually read %Xh\n", (unsigned)B1);err++;}
 if(B!=0x2F)
   {printf("Expected to read 0x2F, actually read %Xh\n", (unsigned)B);err++;}

 if(W2!=0x1234)
   {printf("Expected to read 0x1234, actually read %Xh\n", (unsigned)W2);err++;}
 if(W!=0x567)
   {printf("Expected to read 0x567, actually read %Xh\n", (unsigned)W);err++;}

 if(D2!=0xABCDEF01)
   {printf("Expected to read 0xABCDEF01, actually read %Xh\n", (unsigned)D2);err++;}
 if(D!=0x44556677)
   {printf("Expected to read 0x44556677, actually read %Xh\n", (unsigned)D);err++;}

 rw = loadstruct(TempF,Struct1, &B1, &W2, &D2, &D, &W, &B);
 if(rw!=14)
   {printf("14 bytes is expected to be stored in struct, %d reported\n",rw);err++;}

 if(B!=0x23)
   {printf("Expected to read 0x23, actually read %Xh\n", (unsigned)B);err++;}
 if(B1!=0x2F)
   {printf("Expected to read 0x2F, actually read %Xh\n", (unsigned)B1);err++;}

 if(W!=0x1234)
   {printf("Expected to read 0x1234, actually read %Xh\n", (unsigned)W);err++;}
 if(W2!=0x567)
   {printf("Expected to read 0x567, actually read %Xh\n", (unsigned)W2);err++;}

 if(D!=0xABCDEF01)
   {printf("Expected to read 0xABCDEF01, actually read %Xh\n", D);err++;}
 if(D2!=0x44556677)
   {printf("Expected to read 0x44556677, actually read %Xh\n", D2);err++;}

#if defined(uint64_t_defined)
 rw = loadstruct(TempF, "Qwq", &Q2, &W2, &Q);
 if(rw!=18)
   {printf("18 bytes is expected to be loaded from a struct, %d reported\n",rw);err++;}

 if(Q2 != 0xABCD0123456789)
   {printf("Expected to read 0xABCD0123456789, actually read %llXh\n", Q2);err++;}
 if(Q != 0xBCD0123456789A)
   {printf("Expected to read 0xBCD0123456789A, actually read %llXh\n", Q);err++;}
if(W2!=0x1234)
   {printf("Expected to read 0x1234, actually read %Xh\n", (unsigned)W2);err++;}

 rw = loadstruct(TempF, "qWQ", &Q, &W, &Q2);
 if(rw!=18)
   {printf("18 bytes is expected to be loaded from a struct, %d reported\n",rw);err++;}

 if(Q != 0xABCD0123456789)
   {printf("Expected to read 0xABCD0123456789, actually read %llXh\n", Q);err++;}
 if(Q2 != 0xBCD0123456789A)
   {printf("Expected to read 0xBCD0123456789A, actually read %llXh\n", Q2);err++;}
 if(W!=0x1234)
   {printf("Expected to read 0x1234, actually read %Xh\n", (unsigned)W2);err++;}

#endif

 memset(&SU,0xFF,sizeof(SU));
 rw =LoadTopolHeader(TempF,&SU);
 if(rw != 512)
   {printf("Problem with struct loading %d, expected 512 bytes to read.\n",rw);fflush(stdout);err++;} 
 if(SU.Rows != 107)
   {printf("Wrong value read from struct SU.Rows %d, expected %d\n",SU.Rows,107);fflush(stdout);err++;}    
 if(SU.Cols != 105)
   {printf("Wrong value read from struct SU.Cols %d, expected %d\n",SU.Cols,105);fflush(stdout);err++;}
 if(SU.TileCompression != 2)
   {printf("Wrong value read from struct SU.TileCompression %d, expected %d\n",SU.TileCompression,2);fflush(stdout);err++;}
 if(SU.TileByteCounts != 0x7BCDEF12)
   {printf("Wrong value read from struct SU.TileByteCounts %d, expected %d\n",SU.TileByteCounts,0x7BCDEF12);fflush(stdout);err++;}
 if(fabs(SU.xRasMin+100.5)>1e-5)
   {printf("Wrong value read from struct SU.xRasMin %f, expected %f\n",SU.xRasMin,-100.5);fflush(stdout);err++;}
 if(SU.Stav != 0x4567)
   {printf("Wrong value read from struct SU.Stav %d, expected %d\n",SU.TileByteCounts,0x4567);fflush(stdout);err++;}

 if(strcmp(SU.Name,TEST_STRING_SHORT)!=0)
   {printf("Wrong value read from struct SU.Name \"%s\", expected \"%s\".\n",SU.Name,TEST_STRING_SHORT);fflush(stdout);err++;}
 if(strcmp((char*)SU.Dummy,TEST_STRING_LONG)!=0)
   {printf("Wrong value read from struct SU.Dummy \"%s\", expected \"%s\".\n",SU.Dummy,TEST_STRING_LONG);fflush(stdout);err++;}

 fclose(TempF);


 //////////////////////////////////
FileError:
 puts(" Testing memory access macros");

 D = 0x55667788;
 W = 0x3456;
 for(i=0; i<7; i++)
   {
   ST_UINT16_LO(Blob+i,W);
   W2 = LD_UINT16_LO(Blob+i);
   if(W2!=W)
     {printf("\nProblem ST_UINT16_LO/LD_UINT16_LO, value read %X, expected %X",(unsigned)W2,(unsigned)W);err++;}

   ST_UINT16_HI(Blob+i,W);
   W2 = LD_UINT16_HI(Blob+i);
   if(W2!=W)
     {printf("\nProblem ST_UINT16_HI/LD_UINT16_HI, value read %X, expected %X",(unsigned)W2,(unsigned)W);err++;}

   ST_UINT32_LO(Blob+i,D);
   D2 = LD_UINT32_LO(Blob+i);
   if(D2!=D)
     {printf("\nProblem ST_UINT32_LO/LD_UINT32_LO, value read %X, expected %X",(unsigned)D2,(unsigned)D);err++;}

   ST_UINT32_HI(Blob+i,D);
   D2 = LD_UINT32_HI(Blob+i);
   if(D2!=D)
     {printf("\nProblem ST_UINT32_HI/LD_UINT32_HI, value read %X, expected %X",(unsigned)D2,(unsigned)D);err++;}

#if defined(uint64_t_defined)
   Q = 0x5566778899AABBCC;

   ST_UINT64_LO(Blob+i,Q);
   Q2 = LD_UINT64_LO(Blob+i);
   //Q2 = LD_UINT64_CPU(Blob+i);
   if(Q2!=Q)
     {printf("\nProblem ST_UINT64_LO/LD_UINT64_LO, value read %X, expected %X",(unsigned)Q2,(unsigned)Q);err++;}

   ST_UINT64_HI(Blob+i,Q);
   Q2 = LD_UINT64_HI(Blob+i);
   if(Q2!=Q)
     {printf("\nProblem ST_UINT64_HI/LD_UINT64_HI, value read %X, expected %X",(unsigned)Q2,(unsigned)Q);err++;}
#endif

   if(err>0) break;
   }
 }

 if(err==0 && (Ops & 2)) Benchmark();


 if(err!=0)
   {
   printf("\nUnit Error %d",err);
   return(-1);
   }
 puts(" .............. Test passed OK ..............");

 if(Pause)
 {
   puts("Hit any key to exit");
   getchar();
 }

return(0);
}


#include "../test/bench.h"


void Read_Lo_EndianW(long i)
{
uint16_t W;

while(i-->0)
	{
	if((i & 0x7F)==0)
		fseek(TempF, 0, SEEK_SET);
	RdWORD_LoEnd(&W,TempF);
	RdWORD_LoEnd(&W,TempF);
	RdWORD_LoEnd(&W,TempF);
	RdWORD_LoEnd(&W,TempF);
	}
}

void Read_Hi_EndianW(long i)
{
uint16_t W;

while(i-->0)
	{
	if((i & 0x7F)==0)
		fseek(TempF, 0, SEEK_SET);
	RdWORD_HiEnd(&W,TempF);
	RdWORD_HiEnd(&W,TempF);
	RdWORD_HiEnd(&W,TempF);
	RdWORD_HiEnd(&W,TempF);
	}
}

void Read_Lo_EndianD(long i)
{
uint32_t D;

while(i-->0)
	{
	if((i & 0x7F)==0)
		fseek(TempF, 0, SEEK_SET);
	RdDWORD_LoEnd(&D,TempF);
	RdDWORD_LoEnd(&D,TempF);
	RdDWORD_LoEnd(&D,TempF);
	RdDWORD_LoEnd(&D,TempF);
	}
}

void Read_Hi_EndianD(long i)
{
uint32_t D;

while(i-->0)
	{
	if((i & 0x7F)==0)
		fseek(TempF, 0, SEEK_SET);
	RdDWORD_HiEnd(&D,TempF);
	RdDWORD_HiEnd(&D,TempF);
	RdDWORD_HiEnd(&D,TempF);
	RdDWORD_HiEnd(&D,TempF);
	}
}

void Write_Lo_EndianW(long i)
{
uint16_t W = 12345;

while(i-->0)
	{
	if(i > 0x1000) fseek(TempF, 0, SEEK_SET);
	WrWORD_LoEnd(W,TempF);
	WrWORD_LoEnd(W,TempF);
	WrWORD_LoEnd(W,TempF);
	WrWORD_LoEnd(W,TempF);
	}
}

void Write_Hi_EndianW(long i)
{
uint16_t W = 12345;

while(i-->0)
	{
	if(i > 0x1000) fseek(TempF, 0, SEEK_SET);
	WrWORD_HiEnd(W,TempF);
	WrWORD_HiEnd(W,TempF);
	WrWORD_HiEnd(W,TempF);
	WrWORD_HiEnd(W,TempF);
	}
}

void Write_Lo_EndianD(long i)
{
uint32_t D = 123456;

while(i-->0)
	{
	if(i > 0x1000) fseek(TempF, 0, SEEK_SET);
	WrDWORD_LoEnd(D,TempF);
	WrDWORD_LoEnd(D,TempF);
	WrDWORD_LoEnd(D,TempF);
	WrDWORD_LoEnd(D,TempF);
	}
}

void Write_Hi_EndianD(long i)
{
uint32_t D = 123456;

while(i-->0)
	{
	if(i > 0x1000) fseek(TempF, 0, SEEK_SET);
	WrDWORD_HiEnd(D,TempF);
	WrDWORD_HiEnd(D,TempF);
	WrDWORD_HiEnd(D,TempF);
	WrDWORD_HiEnd(D,TempF);
	}
}


#if defined(uint64_t_defined)
void Write_Lo_EndianQ(long i)
{
uint64_t Q = 0x123456789ABCD0;

while(i-->0)
	{
	if(i > 0x800) fseek(TempF, 0, SEEK_SET);
	WrQWORD_LoEnd(Q,TempF);
	WrQWORD_LoEnd(Q,TempF);
	WrQWORD_LoEnd(Q,TempF);
	WrQWORD_LoEnd(Q,TempF);
	}
}

void Write_Hi_EndianQ(long i)
{
uint64_t Q = 0x123456789ABCD0;

while(i-->0)
	{
	if(i > 0x800) fseek(TempF, 0, SEEK_SET);
	WrQWORD_HiEnd(Q,TempF);
	WrQWORD_HiEnd(Q,TempF);
	WrQWORD_HiEnd(Q,TempF);
	WrQWORD_HiEnd(Q,TempF);
	}
}

void Read_Lo_EndianQ(long i)
{
uint64_t Q;

while(i-->0)
	{
	if((i & 0x7F)==0)
		fseek(TempF, 0, SEEK_SET);
	RdQWORD_LoEnd(&Q,TempF);
	RdQWORD_LoEnd(&Q,TempF);
	RdQWORD_LoEnd(&Q,TempF);
	RdQWORD_LoEnd(&Q,TempF);
	}
}

void Read_Hi_EndianQ(long i)
{
uint64_t Q;

while(i-->0)
	{
	if((i & 0x7F)==0)
		fseek(TempF, 0, SEEK_SET);
	RdQWORD_HiEnd(&Q,TempF);
	RdQWORD_HiEnd(&Q,TempF);
	RdQWORD_HiEnd(&Q,TempF);
	RdQWORD_HiEnd(&Q,TempF);
	}
}
#endif


char TestArray[128];
volatile uint16_t w=0;
volatile uint32_t d=0;

void ReadMem_Lo_W(long i)
{
while(i-->0)
	{
	w += LD_UINT16_LO(&TestArray[0]);
	w += LD_UINT16_LO(&TestArray[2]);
	w += LD_UINT16_LO(&TestArray[4]);
	w += LD_UINT16_LO(&TestArray[6]);
	w += LD_UINT16_LO(&TestArray[8]);
	w += LD_UINT16_LO(&TestArray[10]);
	w += LD_UINT16_LO(&TestArray[12]);
	w += LD_UINT16_LO(&TestArray[16]);
	}
}


void ReadMem_Lo_Wp1(long i)
{
while(i-->0)
	{
	w += LD_UINT16_LO(&TestArray[1]);
	w += LD_UINT16_LO(&TestArray[3]);
	w += LD_UINT16_LO(&TestArray[5]);
	w += LD_UINT16_LO(&TestArray[7]);
	w += LD_UINT16_LO(&TestArray[9]);
	w += LD_UINT16_LO(&TestArray[11]);
	w += LD_UINT16_LO(&TestArray[13]);
	w += LD_UINT16_LO(&TestArray[15]);
	}
}


void ReadMem_Hi_W(long i)
{
while(i-->0)
	{
	w += LD_UINT16_HI(&TestArray[0]);
	w += LD_UINT16_HI(&TestArray[2]);
	w += LD_UINT16_HI(&TestArray[4]);
	w += LD_UINT16_HI(&TestArray[6]);
	w += LD_UINT16_HI(&TestArray[8]);
	w += LD_UINT16_HI(&TestArray[10]);
	w += LD_UINT16_HI(&TestArray[12]);
	w += LD_UINT16_HI(&TestArray[16]);
	}
}


void ReadMem_Hi_Wp1(long i)
{
while(i-->0)
	{
	w += LD_UINT16_HI(&TestArray[1]);
	w += LD_UINT16_HI(&TestArray[3]);
	w += LD_UINT16_HI(&TestArray[5]);
	w += LD_UINT16_HI(&TestArray[7]);
	w += LD_UINT16_HI(&TestArray[9]);
	w += LD_UINT16_HI(&TestArray[11]);
	w += LD_UINT16_HI(&TestArray[13]);
	w += LD_UINT16_HI(&TestArray[15]);
	}
}


void ReadMem_Lo_D(long i)
{
while(i-->0)
	{
	d += LD_UINT32_LO(&TestArray[0]);
	d += LD_UINT32_LO(&TestArray[4]);
	d += LD_UINT32_LO(&TestArray[8]);
	d += LD_UINT32_LO(&TestArray[12]);
	d += LD_UINT32_LO(&TestArray[16]);
	d += LD_UINT32_LO(&TestArray[20]);
	d += LD_UINT32_LO(&TestArray[24]);
	d += LD_UINT32_LO(&TestArray[28]);
	}
}


void ReadMem_Lo_Dp1(long i)
{
while(i-->0)
	{
	d += LD_UINT32_LO(&TestArray[1]);
	d += LD_UINT32_LO(&TestArray[3]);
	d += LD_UINT32_LO(&TestArray[5]);
	d += LD_UINT32_LO(&TestArray[7]);
	d += LD_UINT32_LO(&TestArray[9]);
	d += LD_UINT32_LO(&TestArray[11]);
	d += LD_UINT32_LO(&TestArray[13]);
	d += LD_UINT32_LO(&TestArray[15]);
	}
}


void ReadMem_Hi_D(long i)
{
while(i-->0)
	{
	d += LD_UINT32_HI(&TestArray[0]);
	d += LD_UINT32_HI(&TestArray[4]);
	d += LD_UINT32_HI(&TestArray[8]);
	d += LD_UINT32_HI(&TestArray[12]);
	d += LD_UINT32_HI(&TestArray[16]);
	d += LD_UINT32_HI(&TestArray[20]);
	d += LD_UINT32_HI(&TestArray[24]);
	d += LD_UINT32_HI(&TestArray[28]);
	}
}


void ReadMem_Hi_Dp1(long i)
{
while(i-->0)
	{
	d += LD_UINT32_HI(&TestArray[1]);
	d += LD_UINT32_HI(&TestArray[3]);
	d += LD_UINT32_HI(&TestArray[5]);
	d += LD_UINT32_HI(&TestArray[7]);
	d += LD_UINT32_HI(&TestArray[9]);
	d += LD_UINT32_HI(&TestArray[11]);
	d += LD_UINT32_HI(&TestArray[13]);
	d += LD_UINT32_HI(&TestArray[15]);
	}
}


#if defined(uint64_t_defined)

volatile uint64_t q=0;

void ReadMem_Lo_Q(long i)
{
while(i-->0)
	{
	q += LD_UINT64_LO(&TestArray[0]);
	q += LD_UINT64_LO(&TestArray[4]);
	q += LD_UINT64_LO(&TestArray[8]);
	q += LD_UINT64_LO(&TestArray[12]);
	q += LD_UINT64_LO(&TestArray[16]);
	q += LD_UINT64_LO(&TestArray[20]);
	q += LD_UINT64_LO(&TestArray[24]);
	q += LD_UINT64_LO(&TestArray[28]);
	}
}


void ReadMem_Lo_Qp1(long i)
{
while(i-->0)
	{
	q += LD_UINT64_LO(&TestArray[1]);
	q += LD_UINT64_LO(&TestArray[3]);
	q += LD_UINT64_LO(&TestArray[5]);
	q += LD_UINT64_LO(&TestArray[7]);
	q += LD_UINT64_LO(&TestArray[9]);
	q += LD_UINT64_LO(&TestArray[11]);
	q += LD_UINT64_LO(&TestArray[13]);
	q += LD_UINT64_LO(&TestArray[15]);
	}
}


void ReadMem_Hi_Q(long i)
{
while(i-->0)
	{
	q += LD_UINT64_HI(&TestArray[0]);
	q += LD_UINT64_HI(&TestArray[4]);
	q += LD_UINT64_HI(&TestArray[8]);
	q += LD_UINT64_HI(&TestArray[12]);
	q += LD_UINT64_HI(&TestArray[16]);
	q += LD_UINT64_HI(&TestArray[20]);
	q += LD_UINT64_HI(&TestArray[24]);
	q += LD_UINT64_HI(&TestArray[28]);
	}
}


void ReadMem_Hi_Qp1(long i)
{
while(i-->0)
	{
	q += LD_UINT64_HI(&TestArray[1]);
	q += LD_UINT64_HI(&TestArray[3]);
	q += LD_UINT64_HI(&TestArray[5]);
	q += LD_UINT64_HI(&TestArray[7]);
	q += LD_UINT64_HI(&TestArray[9]);
	q += LD_UINT64_HI(&TestArray[11]);
	q += LD_UINT64_HI(&TestArray[13]);
	q += LD_UINT64_HI(&TestArray[15]);
	}
}

#endif


void Benchmark(void)
{
double f, f2;
int i;

puts(" .............. Benchmarks ..............");

for(i=0; i<sizeof(TestArray); i++)
  TestArray[i] = i;

f = AutoMeasure(ReadMem_Lo_W);
f2 = AutoMeasure(ReadMem_Lo_Wp1);
printf(" Read memory Lo Endian WORD:\t%.3f[ns]\tunalligned %.3f[ns]\n", 1000*f/8, 1000*f2/8);

f = AutoMeasure(ReadMem_Hi_W);
f2 = AutoMeasure(ReadMem_Hi_Wp1);
printf(" Read memory Hi Endian WORD:\t%.3f[ns]\tunalligned %.3f[ns]\n", 1000*f/8, 1000*f2/8);

f = AutoMeasure(ReadMem_Lo_D);
f2 = AutoMeasure(ReadMem_Lo_Dp1);
printf(" Read memory Lo Endian DWORD:\t%.3f[ns]\tunalligned %.3f[ns]\n", 1000*f/8, 1000*f2/8);

f = AutoMeasure(ReadMem_Hi_D);
f2 = AutoMeasure(ReadMem_Hi_Dp1);
printf(" Read memory Hi Endian DWORD:\t%.3f[ns]\tunalligned %.3f[ns]\n", 1000*f/8, 1000*f2/8);


#if defined(uint64_t_defined)
f = AutoMeasure(ReadMem_Lo_Q);
f2 = AutoMeasure(ReadMem_Lo_Qp1);
printf(" Read memory Lo Endian QWORD:\t%.3f[ns]\tunalligned %.3f[ns]\n", 1000*f/8, 1000*f2/8);

f = AutoMeasure(ReadMem_Hi_Q);
f2 = AutoMeasure(ReadMem_Hi_Qp1);
printf(" Read memory Hi Endian QWORD:\t%.3f[ns]\tunalligned %.3f[ns]\n", 1000*f/8, 1000*f2/8);
#endif


TempF=fopen(TEMP_FILE,"wb");
for(i=0; i<16384; i++)
    fputc(i,TempF);
fflush(TempF);
fclose(TempF);

TempF = fopen(TEMP_FILE,"rb");
if(TempF==NULL)
  {
  printf("\nCannot open file \"%s\" for reading!", TEMP_FILE);
  return;
  }


fseek(TempF,0,SEEK_SET);
f = AutoMeasure(Read_Lo_EndianW);
printf(" Read file Lo Endian WORD:\t%.3f[ns]\n",1000*f/4);

fseek(TempF,0,SEEK_SET);
f = AutoMeasure(Read_Hi_EndianW);
printf(" Read file Hi Endian WORD:\t%.3f[ns]\n",1000*f/4);

fseek(TempF,0,SEEK_SET);
f = AutoMeasure(Read_Lo_EndianD);
printf(" Read file Lo Endian DWORD:\t%.3f[ns]\n",1000*f/4);

fseek(TempF,0,SEEK_SET);
f = AutoMeasure(Read_Hi_EndianD);
printf(" Read file Hi Endian DWORD:\t%.3f[ns]\n",1000*f/4);

#if defined(uint64_t_defined)
fseek(TempF,0,SEEK_SET);
f = AutoMeasure(Read_Lo_EndianQ);
printf(" Read file Lo Endian QWORD:\t%.3f[ns]\n",1000*f/4);

fseek(TempF,0,SEEK_SET);
f = AutoMeasure(Read_Hi_EndianQ);
printf(" Read file Hi Endian QWORD:\t%.3f[ns]\n",1000*f/4);
#endif

fclose(TempF);

//////////////////////////////////////////////

TempF = fopen(TEMP_FILE,"wb");
if(TempF==NULL)
  {
  printf("\nCannot open file \"%s\" for writing!", TEMP_FILE);
  return;
  }

f = AutoMeasure(Write_Lo_EndianW);
fflush(TempF);
printf(" Write file Lo Endian WORD:\t%.3f[ns]\n",1000*f/4);

fseek(TempF,0,SEEK_SET);
f = AutoMeasure(Write_Hi_EndianW);
fflush(TempF);
printf(" Write file Hi Endian WORD:\t%.3f[ns]\n",1000*f/4);

fseek(TempF,0,SEEK_SET);
f = AutoMeasure(Write_Lo_EndianD);
fflush(TempF);
printf(" Write file Lo Endian DWORD:\t%.3f[ns]\n",1000*f/4);

fseek(TempF,0,SEEK_SET);
f = AutoMeasure(Write_Hi_EndianD);
fflush(TempF);
printf(" Write file Hi Endian DWORD:\t%.3f[ns]\n",1000*f/4);

#if defined(uint64_t_defined)
fseek(TempF,0,SEEK_SET);
f = AutoMeasure(Write_Lo_EndianQ);
fflush(TempF);
printf(" Write file Lo Endian QWORD:\t%.3f[ns]\n",1000*f/4);

fseek(TempF,0,SEEK_SET);
f = AutoMeasure(Write_Hi_EndianQ);
fflush(TempF);
printf(" Write file Hi Endian QWORD:\t%.3f[ns]\n",1000*f/4);
#endif

fclose(TempF);
}
