Files
ResInsight/ThirdParty/Ert/lib/util/util_endian.cpp
T
Magne Sjaastad 04091ad77d #4266 Update libecl
Use commit 0e1e780fd6f18ce93119061e36a4fca9711bc020

Excluded multibuild folder, as this caused git issues
2019-05-09 08:40:32 +02:00

158 lines
4.4 KiB
C++

/*
Copyright (C) 2012 Equinor ASA, Norway.
The file 'util_endian.c' is part of ERT - Ensemble based Reservoir Tool.
ERT is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
ERT is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE.
See the GNU General Public License at <http://www.gnu.org/licenses/gpl.html>
for more details.
*/
#include <stdint.h>
#include <stdio.h>
#if UINTPTR_MAX == 0xFFFFFFFF
#define ARCH32
#elif UINTPTR_MAX == 0xFFFFFFFFFFFFFFFF
#define ARCH64
#else
#error "Could not determine if this is a 32 bit or 64 bit computer?"
#endif
/*
Macros for endian flipping. The macros create a new endian-flipped
value, and should be used as:
flipped_value = FLIP32( value )
The macros are not exported and only available through the function
util_endian_flip_vector().
*/
#define FLIP16(var) (((var >> 8) & 0x00ff) | ((var << 8) & 0xff00))
#define FLIP32(var) (( (var >> 24) & 0x000000ff) | \
((var >> 8) & 0x0000ff00) | \
((var << 8) & 0x00ff0000) | \
((var << 24) & 0xff000000))
#define FLIP64(var) (((var >> 56) & 0x00000000000000ff) | \
((var >> 40) & 0x000000000000ff00) | \
((var >> 24) & 0x0000000000ff0000) | \
((var >> 8) & 0x00000000ff000000) | \
((var << 8) & 0x000000ff00000000) | \
((var << 24) & 0x0000ff0000000000) | \
((var << 40) & 0x00ff000000000000) | \
((var << 56) & 0xff00000000000000))
static uint16_t util_endian_convert16( uint16_t u ) {
return (( u >> 8U ) & 0xFFU) | (( u & 0xFFU) >> 8U);
}
static uint32_t util_endian_convert32( uint32_t u ) {
const uint32_t m8 = (uint32_t) 0x00FF00FFUL;
const uint32_t m16 = (uint32_t) 0x0000FFFFUL;
u = (( u >> 8U ) & m8) | ((u & m8) << 8U);
u = (( u >> 16U ) & m16) | ((u & m16) << 16U);
return u;
}
static uint64_t util_endian_convert64( uint64_t u ) {
const uint64_t m8 = (uint64_t) 0x00FF00FF00FF00FFULL;
const uint64_t m16 = (uint64_t) 0x0000FFFF0000FFFFULL;
const uint64_t m32 = (uint64_t) 0x00000000FFFFFFFFULL;
u = (( u >> 8U ) & m8) | ((u & m8) << 8U);
u = (( u >> 16U ) & m16) | ((u & m16) << 16U);
u = (( u >> 32U ) & m32) | ((u & m32) << 32U);
return u;
}
static uint64_t util_endian_convert32_64( uint64_t u ) {
const uint64_t m8 = (uint64_t) 0x00FF00FF00FF00FFULL;
const uint64_t m16 = (uint64_t) 0x0000FFFF0000FFFFULL;
u = (( u >> 8U ) & m8) | ((u & m8) << 8U);
u = (( u >> 16U ) & m16) | ((u & m16) << 16U);
return u;
}
void util_endian_flip_vector(void *data, int element_size , int elements) {
int i;
switch (element_size) {
case(1):
break;
case(2):
{
uint16_t *tmp16 = (uint16_t *) data;
for (i = 0; i <elements; i++)
tmp16[i] = util_endian_convert16(tmp16[i]);
break;
}
case(4):
{
#ifdef ARCH64
/*
In the case of a 64 bit CPU the fastest way to swap 32 bit
variables will be by swapping two elements in one operation;
this is provided by the util_endian_convert32_64() function. In the case
of binary ECLIPSE files this case is quite common, and
therefore worth supporting as a special case.
*/
uint64_t *tmp64 = (uint64_t *) data;
for (i = 0; i <elements/2; i++)
tmp64[i] = util_endian_convert32_64(tmp64[i]);
if ( elements & 1 ) {
// Odd number of elements - flip the last element as an ordinary 32 bit swap.
uint32_t *tmp32 = (uint32_t *) data;
tmp32[ elements - 1] = util_endian_convert32( tmp32[elements - 1] );
}
break;
#else
uint32_t *tmp32 = (uint32_t *) data;
for (i = 0; i <elements; i++)
tmp32[i] = util_endian_convert32(tmp32[i]);
break;
#endif
}
case(8):
{
uint64_t *tmp64 = (uint64_t *) data;
for (i = 0; i <elements; i++)
tmp64[i] = util_endian_convert64(tmp64[i]);
break;
}
default:
fprintf(stderr,"%s: current element size: %d \n",__func__ , element_size);
util_abort("%s: can only endian flip 1/2/4/8 byte variables - aborting \n",__func__);
}
}