Files
ResInsight/ThirdParty/Ert/lib/ecl/ecl_kw.cpp

2943 lines
104 KiB
C++

/*
Copyright (C) 2011 Statoil ASA, Norway.
The file 'ecl_kw.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 <stdlib.h>
#include <stdio.h>
#include <stdbool.h>
#include <string.h>
#include <math.h>
#include <ert/util/util.h>
#include <ert/util/buffer.hpp>
#include <ert/util/int_vector.hpp>
#include <ert/ecl/ecl_kw_magic.hpp>
#include <ert/ecl/ecl_kw.hpp>
#include <ert/ecl/fortio.h>
#include <ert/ecl/ecl_endian_flip.hpp>
#include <ert/ecl/ecl_type.hpp>
#define ECL_KW_TYPE_ID 6111098
struct ecl_kw_struct {
UTIL_TYPE_ID_DECLARATION;
int size;
ecl_data_type data_type;
char * header8; /* Header which is right padded with ' ' to become exactly 8 characters long. Should only be used internally.*/
char * header; /* Header which is trimmed to no-space. */
char * data; /* The actual data vector. */
bool shared_data; /* Whether this keyword has shared data or not. */
};
UTIL_IS_INSTANCE_FUNCTION(ecl_kw , ECL_KW_TYPE_ID )
/*****************************************************************/
/* For some peculiar reason the keyword data is written in blocks, all
numeric data is in blocks of 1000 elements, and character data is
in blocks of 105 elements.
*/
#define BLOCKSIZE_NUMERIC 1000
#define BLOCKSIZE_CHAR 105
/*****************************************************************/
/* When writing formatted data, the data comes in columns, with a
certain number of elements in each row, i.e. four columns for float
data:
0.000 0.000 0.000 0.000
0.000 0.000 0.000 0.000
0.000 0.000 0.000 0.000
....
These #define symbols define the number of columns for the
different datatypes.
*/
#define COLUMNS_CHAR 7
#define COLUMNS_FLOAT 4
#define COLUMNS_DOUBLE 3
#define COLUMNS_INT 6
#define COLUMNS_MESSAGE 1
#define COLUMNS_BOOL 25
/*****************************************************************/
/* Format string used when writing a formatted header. */
#define WRITE_HEADER_FMT " '%-8s' %11d '%-4s'\n"
/*****************************************************************/
/* Format string used when reading and writing formatted
files. Observe the following about these format strings:
1. The format string for reading double contains two '%'
identifiers, that is because doubles are read by parsing a
prefix and power separately.
2. For both double and float the write format contains two '%'
characters - that is because the values are split in a prefix
and a power prior to writing - see the function
__fprintf_scientific().
3. The logical type involves converting back and forth between 'T'
and 'F' and internal logical representation. The format strings
are therefore for reading/writing a character.
*/
#define READ_FMT_CHAR "%8c"
#define READ_FMT_FLOAT "%gE"
#define READ_FMT_INT "%d"
#define READ_FMT_MESS "%8c"
#define READ_FMT_BOOL " %c"
#define READ_FMT_DOUBLE "%lgD%d"
#define WRITE_FMT_CHAR " '%-8s'"
#define WRITE_FMT_INT " %11d"
#define WRITE_FMT_FLOAT " %11.8fE%+03d"
#define WRITE_FMT_DOUBLE " %17.14fD%+03d"
#define WRITE_FMT_MESS "%s"
#define WRITE_FMT_BOOL " %c"
/*****************************************************************/
/* The boolean type is not a native type which can be uniquely
identified between Fortran (ECLIPSE), C, formatted and unformatted
files:
o In the formatted ECLIPSE files the characters BOOL_TRUE_CHAR and
BOOL_FALSE_CHAR are used to represent true and false values
repsectively.
o In the unformatted ECLIPSE files the boolean values are
represented as integers with the values ECL_BOOL_TRUE_INT and
ECL_BOOL_FALSE_INT respectively.
Internally in an ecl_kw instance boolean values are represented as
integers (NOT bool), with the representation given by ECL_BOOL_TRUE_INT
and ECL_BOOL_FALSE_INT. This implies that read/write of unformatted
data can go transparently without between ECLIPSE and the ecl_kw
implementation, but exported set()/get() functions with bool must
intercept the bool values and convert to the appropriate integer
value.
*/
// For formatted files:
#define BOOL_TRUE_CHAR 'T'
#define BOOL_FALSE_CHAR 'F'
ecl_type_enum ecl_kw_get_type(const ecl_kw_type *);
void ecl_kw_set_data_type(ecl_kw_type * ecl_kw, ecl_data_type data_type);
static char * alloc_read_fmt_string(const ecl_data_type ecl_type) {
return util_alloc_sprintf(
"%%%dc",
ecl_type_get_sizeof_iotype(ecl_type)
);
}
static char * alloc_read_fmt(const ecl_data_type data_type ) {
switch(ecl_type_get_type(data_type)) {
case(ECL_CHAR_TYPE):
return util_alloc_string_copy(READ_FMT_CHAR);
case(ECL_INT_TYPE):
return util_alloc_string_copy(READ_FMT_INT);
case(ECL_FLOAT_TYPE):
return util_alloc_string_copy(READ_FMT_FLOAT);
case(ECL_DOUBLE_TYPE):
return util_alloc_string_copy(READ_FMT_DOUBLE);
case(ECL_BOOL_TYPE):
return util_alloc_string_copy(READ_FMT_BOOL);
case(ECL_MESS_TYPE):
return util_alloc_string_copy(READ_FMT_MESS);
case(ECL_STRING_TYPE):
return alloc_read_fmt_string(data_type);
default:
util_abort("%s: invalid ecl_type:%s \n",__func__ , ecl_type_alloc_name(data_type));
return NULL;
}
}
static char * alloc_write_fmt_string(const ecl_data_type ecl_type) {
return util_alloc_sprintf(
" '%%-%ds'",
ecl_type_get_sizeof_iotype(ecl_type)
);
}
static char * alloc_write_fmt(const ecl_data_type data_type) {
switch(ecl_type_get_type(data_type)) {
case(ECL_CHAR_TYPE):
return util_alloc_string_copy(WRITE_FMT_CHAR);
case(ECL_INT_TYPE):
return util_alloc_string_copy(WRITE_FMT_INT);
case(ECL_FLOAT_TYPE):
return util_alloc_string_copy(WRITE_FMT_FLOAT);
case(ECL_DOUBLE_TYPE):
return util_alloc_string_copy(WRITE_FMT_DOUBLE);
case(ECL_BOOL_TYPE):
return util_alloc_string_copy(WRITE_FMT_BOOL);
case(ECL_MESS_TYPE):
return util_alloc_string_copy(WRITE_FMT_MESS);
case(ECL_STRING_TYPE):
return alloc_write_fmt_string(data_type);
default:
util_abort("%s: invalid ecl_type: %s\n",__func__ , ecl_type_alloc_name(data_type));
return NULL;
}
}
static int get_blocksize( ecl_data_type data_type ) {
if (ecl_type_is_alpha(data_type))
return BLOCKSIZE_CHAR;
return BLOCKSIZE_NUMERIC;
}
static int get_columns(const ecl_data_type data_type) {
switch(ecl_type_get_type(data_type)) {
case(ECL_CHAR_TYPE):
return COLUMNS_CHAR;
case(ECL_INT_TYPE):
return COLUMNS_INT;
case(ECL_FLOAT_TYPE):
return COLUMNS_FLOAT;
case(ECL_DOUBLE_TYPE):
return COLUMNS_DOUBLE;
case(ECL_BOOL_TYPE):
return COLUMNS_BOOL;
case(ECL_MESS_TYPE):
return COLUMNS_MESSAGE;
case(ECL_STRING_TYPE):
return COLUMNS_CHAR; // TODO: Is this correct?
default:
util_abort("%s: invalid ecl_type: %s\n",__func__ , ecl_type_alloc_name(data_type));
return -1;
}
}
/******************************************************************/
static void ecl_kw_assert_index(const ecl_kw_type *ecl_kw , int index, const char *caller) {
if (index < 0 || index >= ecl_kw->size)
util_abort("%s: Invalid index lookup. kw:%s input_index:%d size:%d \n",caller , ecl_kw->header , index , ecl_kw->size);
}
static char * ecl_kw_alloc_output_buffer(const ecl_kw_type * ecl_kw) {
size_t sizeof_iotype = ecl_type_get_sizeof_iotype(ecl_kw->data_type);
size_t buffer_size = ecl_kw->size * sizeof_iotype;
char * buffer = (char*)util_malloc( buffer_size );
if (ecl_type_is_bool(ecl_kw->data_type)) {
int * int_data = (int *) buffer;
bool * bool_data = (bool *) ecl_kw->data;
for (int i=0; i < ecl_kw->size; i++)
if (bool_data[i])
int_data[i] = ECL_BOOL_TRUE_INT;
else
int_data[i] = ECL_BOOL_FALSE_INT;
util_endian_flip_vector(buffer, sizeof_iotype, ecl_kw->size);
return buffer;
}
if (ecl_type_is_char(ecl_kw->data_type) || ecl_type_is_string(ecl_kw->data_type)) {
size_t sizeof_ctype = ecl_type_get_sizeof_ctype(ecl_kw->data_type);
for (int i=0; i < ecl_kw->size; i++) {
size_t buffer_offset = i * sizeof_iotype;
size_t data_offset = i * sizeof_ctype;
memcpy(&buffer[buffer_offset], &ecl_kw->data[data_offset], sizeof_iotype);
}
return buffer;
}
if (ecl_type_is_mess(ecl_kw->data_type))
return buffer;
memcpy(buffer, ecl_kw->data, buffer_size);
util_endian_flip_vector(buffer, sizeof_iotype, ecl_kw->size);
return buffer;
}
static char * ecl_kw_alloc_input_buffer(const ecl_kw_type * ecl_kw) {
size_t buffer_size = ecl_kw->size * ecl_type_get_sizeof_iotype(ecl_kw->data_type);
char * buffer = (char*)util_malloc( buffer_size );
return buffer;
}
static void ecl_kw_load_from_input_buffer(ecl_kw_type * ecl_kw, char * buffer) {
size_t sizeof_iotype = ecl_type_get_sizeof_iotype(ecl_kw->data_type);
size_t sizeof_ctype = ecl_type_get_sizeof_ctype(ecl_kw->data_type);
size_t buffer_size = ecl_kw->size * sizeof_iotype;
if (ECL_ENDIAN_FLIP) {
if (ecl_type_is_numeric(ecl_kw->data_type) || ecl_type_is_bool(ecl_kw->data_type))
util_endian_flip_vector(buffer, sizeof_iotype, ecl_kw->size);
}
/*
Special case bool: Return Eclipse integer representation of bool to native bool.
*/
if (ecl_type_is_bool(ecl_kw->data_type)) {
int * int_data = (int *) buffer;
bool * bool_data = (bool *) ecl_kw->data;
for (int i=0; i < ecl_kw->size; i++) {
if (int_data[i] == ECL_BOOL_TRUE_INT)
bool_data[i] = true;
else
bool_data[i] = false;
}
return;
}
/*
Special case: insert '\0' termination at end of strings loaded from file.
*/
if (ecl_type_is_char(ecl_kw->data_type) || ecl_type_is_string(ecl_kw->data_type)) {
const char null_char = '\0';
for (int i=0; i < ecl_kw->size; i++) {
size_t buffer_offset = i * sizeof_iotype;
size_t data_offset = i * sizeof_ctype;
memcpy(&ecl_kw->data[data_offset], &buffer[buffer_offset], sizeof_iotype);
ecl_kw->data[data_offset + sizeof_iotype] = null_char;
}
return;
}
if (ecl_type_is_mess(ecl_kw->data_type))
return;
/*
Plain int, double, float data - that can be copied straight over to the ->data field.
*/
memcpy(ecl_kw->data, buffer, buffer_size);
}
const char * ecl_kw_get_header8(const ecl_kw_type *ecl_kw) {
return ecl_kw->header8;
}
/*
Return the header without the trailing spaces
*/
const char * ecl_kw_get_header(const ecl_kw_type * ecl_kw ) {
return ecl_kw->header;
}
bool ecl_kw_name_equal( const ecl_kw_type * ecl_kw , const char * name) {
return (strcmp( ecl_kw->header , name) == 0);
}
void ecl_kw_get_memcpy_data(const ecl_kw_type *ecl_kw , void *target) {
memcpy(target , ecl_kw->data , ecl_kw->size * ecl_type_get_sizeof_ctype(ecl_kw->data_type));
}
void ecl_kw_get_memcpy_int_data(const ecl_kw_type *ecl_kw , int * target) {
if (ecl_type_is_int(ecl_kw->data_type))
ecl_kw_get_memcpy_data( ecl_kw , target );
}
void ecl_kw_get_memcpy_float_data(const ecl_kw_type *ecl_kw , float *target) {
if (ecl_type_is_float(ecl_kw->data_type))
ecl_kw_get_memcpy_data( ecl_kw , target );
}
void ecl_kw_get_memcpy_double_data(const ecl_kw_type *ecl_kw , double *target) {
if (ecl_type_is_double(ecl_kw->data_type))
ecl_kw_get_memcpy_data( ecl_kw , target );
}
/** Allocates a untyped buffer with exactly the same content as the ecl_kw instances data. */
void * ecl_kw_alloc_data_copy(const ecl_kw_type * ecl_kw) {
void * buffer = util_alloc_copy( ecl_kw->data , ecl_kw->size * ecl_type_get_sizeof_ctype(ecl_kw->data_type) );
return buffer;
}
void ecl_kw_set_memcpy_data(ecl_kw_type *ecl_kw , const void *src) {
if (src != NULL)
memcpy(ecl_kw->data , src , ecl_kw->size * ecl_type_get_sizeof_ctype(ecl_kw->data_type));
}
static bool ecl_kw_string_eq(const char *s1 , const char *s2) {
const char space_char = ' ';
const char *long_kw = (strlen(s1) >= strlen(s2)) ? s1 : s2;
const char *short_kw = (strlen(s1) < strlen(s2)) ? s1 : s2;
const int len1 = strlen(long_kw);
const int len2 = strlen(short_kw);
int index;
bool eq = true;
if (len1 > ECL_STRING8_LENGTH)
util_abort("%s : eclipse keyword:%s is too long - aborting \n",__func__ , long_kw);
for (index = 0; index < len2; index++)
eq = eq & (long_kw[index] == short_kw[index]);
if (eq) {
for (index = len2; index < len1; index++)
eq = eq & (long_kw[index] == space_char);
}
return eq;
}
bool ecl_kw_ichar_eq(const ecl_kw_type *ecl_kw , int i , const char *value) {
char s1[ECL_STRING8_LENGTH + 1];
ecl_kw_iget(ecl_kw , i , s1);
return ecl_kw_string_eq(s1 , value);
}
bool ecl_kw_size_and_type_equal( const ecl_kw_type *ecl_kw1 , const ecl_kw_type * ecl_kw2 ) {
return (ecl_kw1->size == ecl_kw2->size &&
ecl_type_is_equal(ecl_kw1->data_type, ecl_kw2->data_type));
}
bool ecl_kw_header_eq(const ecl_kw_type *ecl_kw1 , const ecl_kw_type * ecl_kw2) {
bool equal = true;
if (strcmp(ecl_kw1->header8 , ecl_kw2->header8) != 0)
equal = false;
else
equal = ecl_kw_size_and_type_equal( ecl_kw1 , ecl_kw2 );
return equal;
}
static bool ecl_kw_data_equal__( const ecl_kw_type * ecl_kw , const void * data , int cmp_elements) {
int cmp = memcmp( ecl_kw->data , data , cmp_elements * ecl_type_get_sizeof_ctype(ecl_kw->data_type));
if (cmp == 0)
return true;
else
return false;
}
/**
Observe that the comparison is done with memcmp() -
i.e. "reasonably good" numerical agreement is *not* enough.
*/
bool ecl_kw_data_equal( const ecl_kw_type * ecl_kw , const void * data) {
return ecl_kw_data_equal__( ecl_kw , data , ecl_kw->size);
}
bool ecl_kw_content_equal( const ecl_kw_type * ecl_kw1 , const ecl_kw_type * ecl_kw2) {
if (ecl_kw_size_and_type_equal( ecl_kw1 , ecl_kw2))
return ecl_kw_data_equal__( ecl_kw1 , ecl_kw2->data , ecl_kw1->size);
else
return false;
}
/**
This function compares two ecl_kw instances, and returns true if they are equal.
*/
bool ecl_kw_equal(const ecl_kw_type *ecl_kw1, const ecl_kw_type *ecl_kw2) {
bool equal = ecl_kw_header_eq( ecl_kw1 , ecl_kw2 );
if (equal)
equal = ecl_kw_data_equal( ecl_kw1 , ecl_kw2->data );
return equal;
}
#define ECL_KW_NUMERIC_CMP(ctype) \
static bool ecl_kw_numeric_equal_ ## ctype( const ecl_kw_type * ecl_kw1 , const ecl_kw_type * ecl_kw2 , ctype abs_diff , ctype rel_diff) { \
int index; \
bool equal = true; \
{ \
const ctype * data1 = (const ctype *) ecl_kw1->data; \
const ctype * data2 = (const ctype *) ecl_kw2->data; \
for (index = 0; index < ecl_kw1->size; index++) { \
equal = util_ ## ctype ## _approx_equal__( data1[index], data2[index] , rel_diff , abs_diff); \
if (!equal) \
break; \
} \
} \
return equal; \
}
ECL_KW_NUMERIC_CMP( float )
ECL_KW_NUMERIC_CMP( double )
#undef ECL_KW_NUMERIC_CMP
/**
This function compares the data of two ecl_kw instances, and
returns true if the relative numerical difference is less than
@rel_diff. Does not consider consider the kw header.
*/
bool ecl_kw_numeric_equal(const ecl_kw_type *ecl_kw1, const ecl_kw_type *ecl_kw2 , double abs_diff , double rel_diff) {
if(!ecl_kw_size_and_type_equal(ecl_kw1, ecl_kw2))
return false;
if (ecl_type_is_float(ecl_kw1->data_type))
return ecl_kw_numeric_equal_float( ecl_kw1 , ecl_kw2 , abs_diff , rel_diff );
else if (ecl_type_is_double(ecl_kw1->data_type))
return ecl_kw_numeric_equal_double( ecl_kw1 , ecl_kw2 , abs_diff , rel_diff );
else
return ecl_kw_data_equal( ecl_kw1 , ecl_kw2->data );
}
bool ecl_kw_block_equal( const ecl_kw_type * ecl_kw1 , const ecl_kw_type * ecl_kw2 , int cmp_elements) {
if (ecl_kw_header_eq( ecl_kw1 , ecl_kw2)) {
if (cmp_elements == 0)
cmp_elements = ecl_kw1->size;
return ecl_kw_data_equal__( ecl_kw1 , ecl_kw2->data , cmp_elements );
} else
return false;
}
static void ecl_kw_set_shared_ref(ecl_kw_type * ecl_kw , void *data_ptr) {
if (!ecl_kw->shared_data) {
if (ecl_kw->data != NULL)
util_abort("%s: can not change to shared for keyword with allocated storage - aborting \n",__func__);
}
ecl_kw->shared_data = true;
ecl_kw->data = (char*)data_ptr;
}
static void ecl_kw_initialize(ecl_kw_type * ecl_kw , const char *header , int size , ecl_data_type data_type) {
ecl_kw_set_data_type(ecl_kw, data_type);
ecl_kw_set_header_name(ecl_kw , header);
ecl_kw->size = size;
}
static size_t ecl_kw_fortio_data_size( const ecl_kw_type * ecl_kw) {
const int blocksize = get_blocksize( ecl_kw->data_type );
const int num_blocks = ecl_kw->size / blocksize + (ecl_kw->size % blocksize == 0 ? 0 : 1);
return num_blocks * (4 + 4) + // Fortran fluff for each block
ecl_kw->size * ecl_type_get_sizeof_iotype( ecl_kw->data_type ); // Actual data
}
/**
Returns the number of bytes this ecl_kw instance would occupy in
BINARY file; we add 2*4 to the header size to include the size of
the fortran header and trailer combo.
*/
size_t ecl_kw_fortio_size( const ecl_kw_type * ecl_kw ) {
size_t size = ECL_KW_HEADER_FORTIO_SIZE;
size += ecl_kw_fortio_data_size(ecl_kw );
return size;
}
/**
The data is copied from the input argument to the ecl_kw; data can be NULL.
*/
ecl_kw_type * ecl_kw_alloc_new(const char * header , int size, ecl_data_type data_type , const void * data) {
ecl_kw_type *ecl_kw;
ecl_kw = ecl_kw_alloc_empty();
ecl_kw_initialize(ecl_kw , header , size , data_type);
if (data != NULL) {
ecl_kw_alloc_data(ecl_kw);
ecl_kw_set_memcpy_data(ecl_kw , data);
}
return ecl_kw;
}
ecl_kw_type * ecl_kw_alloc( const char * header , int size , ecl_data_type data_type ) {
ecl_kw_type *ecl_kw;
ecl_kw = ecl_kw_alloc_empty();
ecl_kw_initialize(ecl_kw , header , size , data_type);
ecl_kw_alloc_data(ecl_kw);
return ecl_kw;
}
ecl_kw_type * ecl_kw_alloc_new_shared(const char * header , int size, ecl_data_type data_type , void * data) {
ecl_kw_type *ecl_kw;
ecl_kw = ecl_kw_alloc_empty();
ecl_kw_initialize(ecl_kw , header , size , data_type);
ecl_kw_set_shared_ref(ecl_kw , data);
return ecl_kw;
}
ecl_kw_type * ecl_kw_alloc_empty() {
ecl_kw_type *ecl_kw;
ecl_kw = (ecl_kw_type*)util_malloc(sizeof *ecl_kw );
ecl_kw->header = NULL;
ecl_kw->header8 = NULL;
ecl_kw->data = NULL;
ecl_kw->shared_data = false;
ecl_kw->size = 0;
UTIL_TYPE_ID_INIT(ecl_kw , ECL_KW_TYPE_ID);
return ecl_kw;
}
void ecl_kw_free(ecl_kw_type *ecl_kw) {
free( ecl_kw->header );
free(ecl_kw->header8);
ecl_kw_free_data(ecl_kw);
free(ecl_kw);
}
void ecl_kw_free__(void *void_ecl_kw) {
ecl_kw_free((ecl_kw_type *) void_ecl_kw);
}
void ecl_kw_memcpy_data( ecl_kw_type * target , const ecl_kw_type * src) {
if (!ecl_kw_size_and_type_equal( target , src ))
util_abort("%s: type/size mismatch \n",__func__);
memcpy(target->data , src->data , target->size * ecl_type_get_sizeof_ctype(target->data_type));
}
void ecl_kw_memcpy(ecl_kw_type *target, const ecl_kw_type *src) {
target->size = src->size;
ecl_kw_set_data_type(target, src->data_type);
ecl_kw_set_header_name( target , src->header );
ecl_kw_alloc_data(target);
ecl_kw_memcpy_data( target , src );
}
ecl_kw_type *ecl_kw_alloc_copy(const ecl_kw_type *src) {
ecl_kw_type *new_;
new_ = ecl_kw_alloc_empty();
ecl_kw_memcpy(new_ , src);
return new_;
}
/**
This function will allocate a new copy of @src, where only the
elements corresponding to the slice [index1:index2) is included.
The input parameters @index1 and @index2 can to some extent be
out-of-range:
index1 = max( index1 , 0 );
index2 = min( index2 , size );
If index1 > index2 it will fail hard; the same applies if stride is
<= 0.
*/
ecl_kw_type * ecl_kw_alloc_slice_copy( const ecl_kw_type * src, int index1, int index2, int stride) {
if (index1 < 0) index1 = 0;
if (index2 > src->size) index2 = src->size;
if (index1 >= src->size) util_abort("%s: index1=%d > size:%d \n",__func__ , index1 , src->size);
if (stride <= 0) util_abort("%s: stride:%d completely broken ...\n",__func__ , stride);
{
ecl_kw_type * new_kw = NULL;
int src_index = index1;
/* 1: Determine size of the sliced copy. */
{
int new_size = 0;
while (src_index < index2) {
new_size++;
src_index += stride;
}
if (new_size > 0) {
new_kw = ecl_kw_alloc_empty();
ecl_kw_initialize(new_kw , src->header , new_size , src->data_type);
ecl_kw_alloc_data(new_kw);
/* 2: Copy over the elements. */
src_index = index1;
{
int target_index = 0;
const char * src_ptr = src->data;
char * new_ptr = new_kw->data;
int sizeof_ctype = ecl_type_get_sizeof_ctype(new_kw->data_type);
while ( src_index < index2 ) {
memcpy( &new_ptr[ target_index * sizeof_ctype ] , &src_ptr[ src_index * sizeof_ctype ] , sizeof_ctype );
src_index += stride;
target_index += 1;
}
}
}
}
return new_kw;
}
}
void ecl_kw_resize( ecl_kw_type * ecl_kw, int new_size) {
if (ecl_kw->shared_data)
util_abort("%s: trying to allocate data for ecl_kw object which has been declared with shared storage - aborting \n",__func__);
if (new_size != ecl_kw->size) {
size_t old_byte_size = ecl_kw->size * ecl_type_get_sizeof_ctype(ecl_kw->data_type);
size_t new_byte_size = new_size * ecl_type_get_sizeof_ctype(ecl_kw->data_type);
ecl_kw->data = (char*)util_realloc(ecl_kw->data , new_byte_size );
if (new_byte_size > old_byte_size) {
size_t offset = old_byte_size;
memset(&ecl_kw->data[offset] , 0 , new_byte_size - old_byte_size);
}
ecl_kw->size = new_size;
}
}
/**
Will allocate a copy of the src_kw. Will copy @count elements
starting at @offset. If @count < 0 all remaining elements from
@offset will be copied. If new_kw == NULL the new keyword will have
the same header as the @src, otherwise the value @new_kw will be
used.
*/
ecl_kw_type * ecl_kw_alloc_sub_copy( const ecl_kw_type * src, const char * new_kw , int offset , int count) {
if (new_kw == NULL)
new_kw = src->header;
if (count < 0)
count = src->size - offset;
if ((offset < 0) || (offset >= src->size)) util_abort("%s: invalid offset - limits: [%d,%d) \n",__func__ , 0 , src->size);
if ((count + offset) > src->size) util_abort("%s: invalid count value: %d \n",__func__ , count);
{
void * src_data = ecl_kw_iget_ptr( src , offset );
return ecl_kw_alloc_new( new_kw , count , src->data_type , src_data );
}
}
const void * ecl_kw_copyc__(const void * void_kw) {
return ecl_kw_alloc_copy((const ecl_kw_type *) void_kw);
}
static void * ecl_kw_iget_ptr_static(const ecl_kw_type *ecl_kw , int i) {
ecl_kw_assert_index(ecl_kw , i , __func__);
return &ecl_kw->data[i * ecl_type_get_sizeof_ctype(ecl_kw->data_type)];
}
static void ecl_kw_iget_static(const ecl_kw_type *ecl_kw , int i , void *iptr) {
memcpy(iptr , ecl_kw_iget_ptr_static(ecl_kw , i) , ecl_type_get_sizeof_ctype(ecl_kw->data_type));
}
static void ecl_kw_iset_static(ecl_kw_type *ecl_kw , int i , const void *iptr) {
size_t sizeof_ctype = ecl_type_get_sizeof_ctype(ecl_kw->data_type);
ecl_kw_assert_index(ecl_kw , i , __func__);
memcpy(&ecl_kw->data[i * sizeof_ctype] , iptr, sizeof_ctype);
}
void ecl_kw_iget(const ecl_kw_type *ecl_kw , int i , void *iptr) {
ecl_kw_iget_static(ecl_kw , i , iptr);
}
/**
Will return a double value for underlying data types of double,
float and int.
*/
double ecl_kw_iget_as_double(const ecl_kw_type * ecl_kw , int index) {
if (ecl_type_is_float(ecl_kw->data_type))
return ecl_kw_iget_float( ecl_kw , index); /* Here the compiler will silently insert a float -> double conversion. */
else if (ecl_type_is_double(ecl_kw->data_type))
return ecl_kw_iget_double( ecl_kw, index);
else if (ecl_type_is_int(ecl_kw->data_type))
return ecl_kw_iget_int( ecl_kw, index); /* */
else {
util_abort("%s: can not be converted to double - no data for you! \n",__func__);
return -1;
}
}
/**
Will return a float value for underlying data types of double and float.
*/
float ecl_kw_iget_as_float(const ecl_kw_type * ecl_kw , int i) {
if (ecl_type_is_float(ecl_kw->data_type))
return ecl_kw_iget_float( ecl_kw , i);
else if (ecl_type_is_double(ecl_kw->data_type))
return (float) ecl_kw_iget_double( ecl_kw, i);
else {
util_abort("%s: can not be converted to float - no data for you! \n",__func__);
return -1;
}
}
#define ECL_KW_IGET_TYPED(ctype , ECL_TYPE) \
ctype ecl_kw_iget_ ## ctype(const ecl_kw_type * ecl_kw, int i) { \
ctype value; \
if (ecl_kw_get_type(ecl_kw) != ECL_TYPE) \
util_abort("%s: Keyword: %s is wrong type - aborting \n",__func__ , ecl_kw_get_header8(ecl_kw)); \
ecl_kw_iget_static(ecl_kw , i , &value); \
return value; \
} \
ECL_KW_IGET_TYPED(double , ECL_DOUBLE_TYPE);
ECL_KW_IGET_TYPED(float , ECL_FLOAT_TYPE);
ECL_KW_IGET_TYPED(int , ECL_INT_TYPE);
ECL_KW_IGET_TYPED(bool , ECL_BOOL_TYPE);
#undef ECL_KW_IGET_TYPED
const char * ecl_kw_iget_char_ptr( const ecl_kw_type * ecl_kw , int i) {
if (ecl_kw_get_type(ecl_kw) != ECL_CHAR_TYPE)
util_abort("%s: Keyword: %s is wrong type - aborting \n",__func__ , ecl_kw_get_header8(ecl_kw));
return (const char *)ecl_kw_iget_ptr( ecl_kw , i );
}
const char * ecl_kw_iget_string_ptr( const ecl_kw_type * ecl_kw, int i) {
if (ecl_kw_get_type(ecl_kw) != ECL_STRING_TYPE)
util_abort("%s: Keyword: %s is wrong type - aborting \n",__func__ , ecl_kw_get_header8(ecl_kw));
return (const char *)ecl_kw_iget_ptr( ecl_kw , i );
}
/**
This will set the elemnts of the ecl_kw data storage in index to
the value of s8; if s8 is shorter than 8 characters the result will
be padded, if s8 is longer than 8 characters the characters from 9
and out will be ignored.
*/
void ecl_kw_iset_string8(ecl_kw_type * ecl_kw , int index , const char *s8) {
char * ecl_string = (char *) ecl_kw_iget_ptr( ecl_kw , index );
if (strlen( s8 ) >= ECL_STRING8_LENGTH) {
/* The whole string goes in - possibly loosing content at the end. */
int i;
for (i=0; i < ECL_STRING8_LENGTH; i++)
ecl_string[i] = s8[i];
} else {
/* The string is padded with trailing spaces. */
int string_length = strlen( s8 );
int i;
for (i=0; i < string_length; i++)
ecl_string[i] = s8[i];
for (i=string_length; i < ECL_STRING8_LENGTH; i++)
ecl_string[i] = ' ';
}
ecl_string[ ECL_STRING8_LENGTH ] = '\0';
}
/**
This function will set the string @index in the ecl_kw string array
to @s. IFF @s is longer than 8 characters, the first part will go
in element @index, and then we will continue writing into the next
elements. If the resulting index goes beyond the length of the
keyword - WhamBang!
You should know what you are doing when sending in a string of
length greater than 8 - maybe the overwriting of consecutive
elements is not what you want?
*/
void ecl_kw_iset_char_ptr( ecl_kw_type * ecl_kw , int index, const char * s) {
int strings = strlen( s ) / ECL_STRING8_LENGTH;
if ((strlen( s ) % ECL_STRING8_LENGTH) != 0)
strings++;
{
int sub_index;
for (sub_index = 0; sub_index < strings; sub_index++)
ecl_kw_iset_string8( ecl_kw , index + sub_index , &s[ sub_index * ECL_STRING8_LENGTH ]);
}
}
/**
This function will verify that the given string is of approperiate
length (0 <= lenght <= data_type.element_size). If so, the elements
of @s will be written to the @ecl_kw string array starting at
@index. If the input string is shorter than the type length the
string will be padded with trailing spaces.
*/
void ecl_kw_iset_string_ptr( ecl_kw_type * ecl_kw, int index, const char * s) {
if(!ecl_type_is_alpha(ecl_kw_get_data_type(ecl_kw))) {
char * type_name = ecl_type_alloc_name(ecl_kw_get_data_type(ecl_kw));
util_abort("%s: Expected alphabetic data type (CHAR, CXXX or MESS), was %s\n", __func__, type_name);
}
size_t input_len = strlen(s);
size_t type_len = ecl_type_get_sizeof_iotype(ecl_kw->data_type);
if(input_len > type_len)
util_abort("%s: String of length %d cannot hold input string of length %d\n", __func__, type_len, input_len);
{
char * ecl_string = (char *) ecl_kw_iget_ptr(ecl_kw, index);
size_t i;
for(i = 0; i < input_len; ++i)
ecl_string[i] = s[i];
for (i=input_len; i < type_len; ++i)
ecl_string[i] = ' ';
ecl_string[type_len] = '\0';
}
}
/**
This function will compare the string at position @index with the
input @other string. The comparison will be done in a
'space-tolerant', i.e. trailing spaces are ignored in the
comparison. If the strings are considered equal true is returned.
*/
bool ecl_kw_icmp_string( const ecl_kw_type * ecl_kw , int index, const char * other_string) {
const char * kw_string = (const char *)ecl_kw_iget_char_ptr( ecl_kw , index );
if (strlen(other_string)) {
const char * match = strstr( kw_string , other_string);
if (match == kw_string)
return true;
}
return false;
}
#define ECL_KW_ISET_TYPED(ctype , ECL_TYPE) \
void ecl_kw_iset_ ## ctype(ecl_kw_type * ecl_kw, int i, ctype value) { \
if (ecl_kw_get_type(ecl_kw) != ECL_TYPE) \
util_abort("%s: Keyword: %s is wrong type - aborting \n",__func__ , ecl_kw_get_header8(ecl_kw)); \
ecl_kw_iset_static(ecl_kw , i , &value); \
} \
ECL_KW_ISET_TYPED(double , ECL_DOUBLE_TYPE);
ECL_KW_ISET_TYPED(float , ECL_FLOAT_TYPE);
ECL_KW_ISET_TYPED(int , ECL_INT_TYPE);
ECL_KW_ISET_TYPED(bool , ECL_BOOL_TYPE);
#undef ECL_KW_ISET_TYPED
#define ECL_KW_SET_INDEXED(ctype , ECL_TYPE) \
void ecl_kw_set_indexed_ ## ctype( ecl_kw_type * ecl_kw, const int_vector_type * index_list , ctype value) { \
if (ecl_kw_get_type(ecl_kw) != ECL_TYPE) \
util_abort("%s: Keyword: %s is wrong type - aborting \n",__func__ , ecl_kw_get_header8(ecl_kw)); \
{ \
ctype * data = (ctype *) ecl_kw->data; \
int size = int_vector_size( index_list ); \
const int * index_ptr = int_vector_get_const_ptr( index_list ); \
int i; \
for (i = 0; i < size; i++) \
data[index_ptr[i]] = value; \
} \
}
ECL_KW_SET_INDEXED( double , ECL_DOUBLE_TYPE);
ECL_KW_SET_INDEXED( float , ECL_FLOAT_TYPE);
ECL_KW_SET_INDEXED( int , ECL_INT_TYPE);
#undef ECL_KW_SET_INDEXED
#define ECL_KW_SHIFT_INDEXED(ctype , ECL_TYPE) \
void ecl_kw_shift_indexed_ ## ctype( ecl_kw_type * ecl_kw, const int_vector_type * index_list , ctype shift) { \
if (ecl_kw_get_type(ecl_kw) != ECL_TYPE) \
util_abort("%s: Keyword: %s is wrong type - aborting \n",__func__ , ecl_kw_get_header8(ecl_kw)); \
{ \
ctype * data = (ctype *) ecl_kw->data; \
int size = int_vector_size( index_list ); \
const int * index_ptr = int_vector_get_const_ptr( index_list ); \
int i; \
for (i = 0; i < size; i++) \
data[index_ptr[i]] += shift; \
} \
}
ECL_KW_SHIFT_INDEXED( double , ECL_DOUBLE_TYPE);
ECL_KW_SHIFT_INDEXED( float , ECL_FLOAT_TYPE);
ECL_KW_SHIFT_INDEXED( int , ECL_INT_TYPE);
#undef ECL_KW_SHIFT_INDEXED
#define ECL_KW_SCALE_INDEXED(ctype , ECL_TYPE) \
void ecl_kw_scale_indexed_ ## ctype( ecl_kw_type * ecl_kw, const int_vector_type * index_list , ctype scale) { \
if (ecl_kw_get_type(ecl_kw) != ECL_TYPE) \
util_abort("%s: Keyword: %s is wrong type - aborting \n",__func__ , ecl_kw_get_header8(ecl_kw)); \
{ \
ctype * data = (ctype *) ecl_kw->data; \
int size = int_vector_size( index_list ); \
const int * index_ptr = int_vector_get_const_ptr( index_list ); \
int i; \
for (i = 0; i < size; i++) \
data[index_ptr[i]] *= scale; \
} \
}
ECL_KW_SCALE_INDEXED( double , ECL_DOUBLE_TYPE);
ECL_KW_SCALE_INDEXED( float , ECL_FLOAT_TYPE);
ECL_KW_SCALE_INDEXED( int , ECL_INT_TYPE);
#undef ECL_KW_SCALE_INDEXED
/*****************************************************************/
/* Various ways to get pointers to the underlying data. */
#define ECL_KW_GET_TYPED_PTR(ctype , ECL_TYPE) \
ctype * ecl_kw_get_ ## ctype ## _ptr(const ecl_kw_type * ecl_kw) { \
if (ecl_kw_get_type(ecl_kw) != ECL_TYPE) \
util_abort("%s: Keyword: %s is wrong type - aborting \n",__func__ , ecl_kw_get_header8(ecl_kw)); \
return (ctype *) ecl_kw->data; \
}
ECL_KW_GET_TYPED_PTR(double , ECL_DOUBLE_TYPE);
ECL_KW_GET_TYPED_PTR(float , ECL_FLOAT_TYPE);
ECL_KW_GET_TYPED_PTR(int , ECL_INT_TYPE);
ECL_KW_GET_TYPED_PTR(bool , ECL_BOOL_TYPE);
#undef ECL_KW_GET_TYPED_PTR
void * ecl_kw_get_void_ptr(const ecl_kw_type * ecl_kw) {
return ecl_kw->data;
}
/*****************************************************************/
void * ecl_kw_iget_ptr(const ecl_kw_type *ecl_kw , int i) {
return ecl_kw_iget_ptr_static(ecl_kw , i);
}
void ecl_kw_iset(ecl_kw_type *ecl_kw , int i , const void *iptr) {
ecl_kw_iset_static(ecl_kw , i , iptr);
}
static bool ecl_kw_qskip(FILE *stream) {
const char sep = '\'';
const char space = ' ';
const char newline = '\n';
const char tab = '\t';
bool OK = true;
char c;
bool cont = true;
while (cont) {
c = fgetc(stream);
if (c == EOF) {
cont = false;
OK = false;
} else {
if (c == space || c == newline || c == tab)
cont = true;
else if (c == sep)
cont = false;
}
}
return OK;
}
static bool ecl_kw_fscanf_qstring(char *s , const char *fmt , int len, FILE *stream) {
const char null_char = '\0';
char last_sep;
bool OK;
OK = ecl_kw_qskip(stream);
if (OK) {
int read_count = 0;
read_count += fscanf(stream , fmt , s);
s[len] = null_char;
read_count += fscanf(stream , "%c" , &last_sep);
if (read_count != 2)
util_abort("%s: reading \'xxxxxxxx\' formatted string failed \n",__func__);
}
return OK;
}
/*
This rather painful parsing is because formatted eclipse double
format : 0.ddddD+01 - difficult to parse the 'D';
*/
/** Should be: NESTED */
static double __fscanf_ECL_double( FILE * stream , const char * fmt) {
int read_count , power;
double value , arg;
read_count = fscanf( stream , fmt , &arg , &power);
if (read_count == 2)
value = arg * pow(10 , power );
else {
util_abort("%s: read failed \n",__func__);
value = -1;
}
return value;
}
bool ecl_kw_fread_data(ecl_kw_type *ecl_kw, fortio_type *fortio) {
bool fmt_file = fortio_fmt_file( fortio );
if (ecl_kw->size > 0) {
const int blocksize = get_blocksize( ecl_kw->data_type );
if (fmt_file) {
const int blocks = ecl_kw->size / blocksize + (ecl_kw->size % blocksize == 0 ? 0 : 1);
char * read_fmt = alloc_read_fmt( ecl_kw->data_type );
FILE * stream = fortio_get_FILE(fortio);
int offset = 0;
int index = 0;
int ib,ir;
for (ib = 0; ib < blocks; ib++) {
int read_elm = util_int_min((ib + 1) * blocksize , ecl_kw->size) - ib * blocksize;
for (ir = 0; ir < read_elm; ir++) {
switch(ecl_kw_get_type(ecl_kw)) {
case(ECL_CHAR_TYPE):
ecl_kw_fscanf_qstring(&ecl_kw->data[offset] , read_fmt , 8, stream);
break;
case(ECL_STRING_TYPE):
ecl_kw_fscanf_qstring(
&ecl_kw->data[offset],
read_fmt,
ecl_type_get_sizeof_iotype(ecl_kw_get_data_type(ecl_kw)),
stream
);
break;
case(ECL_INT_TYPE):
{
int iread = fscanf(stream , read_fmt , (int *) &ecl_kw->data[offset]);
if (iread != 1)
util_abort("%s: after reading %d values reading of keyword:%s from:%s failed - aborting \n",__func__,
offset / ecl_type_get_sizeof_ctype(ecl_kw->data_type),
ecl_kw->header8,
fortio_filename_ref(fortio));
}
break;
case(ECL_FLOAT_TYPE):
{
int iread = fscanf(stream , read_fmt , (float *) &ecl_kw->data[offset]);
if (iread != 1) {
util_abort("%s: after reading %d values reading of keyword:%s from:%s failed - aborting \n",__func__,
offset / ecl_type_get_sizeof_ctype(ecl_kw->data_type),
ecl_kw->header8,
fortio_filename_ref(fortio));
}
}
break;
case(ECL_DOUBLE_TYPE):
{
double value = __fscanf_ECL_double( stream , read_fmt );
ecl_kw_iset(ecl_kw , index , &value);
}
break;
case(ECL_BOOL_TYPE):
{
char bool_char;
if (fscanf(stream , read_fmt , &bool_char) == 1) {
if (bool_char == BOOL_TRUE_CHAR)
ecl_kw_iset_bool(ecl_kw , index , true);
else if (bool_char == BOOL_FALSE_CHAR)
ecl_kw_iset_bool(ecl_kw , index , false);
else
util_abort("%s: Logical value: [%c] not recogniced - aborting \n", __func__ , bool_char);
} else
util_abort("%s: read failed - premature file end? \n",__func__ );
}
break;
case(ECL_MESS_TYPE):
ecl_kw_fscanf_qstring(&ecl_kw->data[offset] , read_fmt , 8 , stream);
break;
default:
util_abort("%s: Internal error: internal eclipse_type: %d not recognized - aborting \n",__func__ , ecl_kw_get_type(ecl_kw));
}
offset += ecl_type_get_sizeof_ctype(ecl_kw->data_type);
index++;
}
}
/* Skip the trailing newline */
fortio_fseek( fortio , 1 , SEEK_CUR);
free(read_fmt);
return true;
} else {
char * buffer = ecl_kw_alloc_input_buffer(ecl_kw);
const int sizeof_iotype = ecl_type_get_sizeof_iotype(ecl_kw->data_type);
bool read_ok = fortio_fread_buffer(fortio, buffer, ecl_kw->size * sizeof_iotype);
if (read_ok)
ecl_kw_load_from_input_buffer(ecl_kw, buffer);
free(buffer);
return read_ok;
}
} else
/* The keyword has zero size - and reading data is trivially OK. */
return true;
}
void ecl_kw_fread_indexed_data(fortio_type * fortio, offset_type data_offset, ecl_data_type data_type, int element_count, const int_vector_type* index_map, char* io_buffer) {
const int block_size = get_blocksize(data_type);
FILE *stream = fortio_get_FILE( fortio );
int index;
int sizeof_iotype = ecl_type_get_sizeof_iotype(data_type);
for(index = 0; index < int_vector_size(index_map); index++) {
int element_index = int_vector_iget(index_map, index);
if(element_index < 0 || element_index >= element_count)
util_abort("%s: Element index is out of range 0 <= %d < %d\n", __func__, element_index, element_count);
fortio_data_fseek(fortio, data_offset, element_index, sizeof_iotype, element_count, block_size);
util_fread(&io_buffer[index * sizeof_iotype], sizeof_iotype, 1, stream, __func__);
}
if (ECL_ENDIAN_FLIP)
util_endian_flip_vector(io_buffer, sizeof_iotype, int_vector_size(index_map));
}
/**
Allocates storage and reads data.
*/
bool ecl_kw_fread_realloc_data(ecl_kw_type *ecl_kw, fortio_type *fortio) {
ecl_kw_alloc_data(ecl_kw);
return ecl_kw_fread_data(ecl_kw , fortio);
}
/**
Static method without a class instance.
*/
bool ecl_kw_fskip_data__( ecl_data_type data_type , const int element_count , fortio_type * fortio) {
if (element_count <= 0)
return true;
bool fmt_file = fortio_fmt_file(fortio);
if (fmt_file) {
/* Formatted skipping actually involves reading the data - nice ??? */
ecl_kw_type * tmp_kw = ecl_kw_alloc_empty( );
ecl_kw_initialize( tmp_kw , "WORK" , element_count , data_type );
ecl_kw_alloc_data(tmp_kw);
ecl_kw_fread_data(tmp_kw , fortio);
ecl_kw_free( tmp_kw );
} else {
const int blocksize = get_blocksize( data_type );
const int block_count = element_count / blocksize + (element_count % blocksize != 0);
int element_size = ecl_type_get_sizeof_iotype(data_type);
if(!fortio_data_fskip(fortio, element_size, element_count, block_count))
return false;
}
return true;
}
bool ecl_kw_fskip_data(ecl_kw_type *ecl_kw, fortio_type *fortio) {
return ecl_kw_fskip_data__( ecl_kw_get_data_type(ecl_kw) , ecl_kw->size , fortio );
}
/**
This function will skip the header part of an ecl_kw instance. The
function will read the file content at the current position, it is
therefore essential that the file pointer is positioned at the
beginning of a keyword when this function is called; otherwise it
will be complete crash and burn.
*/
void ecl_kw_fskip_header( fortio_type * fortio) {
bool fmt_file = fortio_fmt_file( fortio );
if (fmt_file) {
ecl_kw_type * ecl_kw = ecl_kw_alloc_empty( );
ecl_kw_fread_header( ecl_kw , fortio );
ecl_kw_free( ecl_kw );
} else
fortio_fskip_record( fortio );
}
ecl_read_status_enum ecl_kw_fread_header(ecl_kw_type *ecl_kw , fortio_type * fortio) {
const char null_char = '\0';
FILE *stream = fortio_get_FILE( fortio );
bool fmt_file = fortio_fmt_file( fortio );
char header[ECL_STRING8_LENGTH + 1];
char ecl_type_str[ECL_TYPE_LENGTH + 1];
int record_size;
int size;
if (fmt_file) {
if(!ecl_kw_fscanf_qstring(header , "%8c" , 8 , stream))
return ECL_KW_READ_FAIL;
int read_count = fscanf(stream , "%d" , &size);
if (read_count != 1)
return ECL_KW_READ_FAIL;
if (!ecl_kw_fscanf_qstring(ecl_type_str , "%4c" , 4 , stream))
return ECL_KW_READ_FAIL;
fgetc(stream); /* Reading the trailing newline ... */
}
else {
header[ECL_STRING8_LENGTH] = null_char;
ecl_type_str[ECL_TYPE_LENGTH] = null_char;
record_size = fortio_init_read(fortio);
if (record_size <= 0)
return ECL_KW_READ_FAIL;
char buffer[ECL_KW_HEADER_DATA_SIZE];
size_t read_bytes = fread(buffer , 1 , ECL_KW_HEADER_DATA_SIZE , stream);
if (read_bytes != ECL_KW_HEADER_DATA_SIZE)
return ECL_KW_READ_FAIL;
memcpy( header , &buffer[0] , ECL_STRING8_LENGTH);
void * ptr = &buffer[ECL_STRING8_LENGTH];
size = *((int*)ptr);
memcpy( ecl_type_str , &buffer[ECL_STRING8_LENGTH + sizeof(size)] , ECL_TYPE_LENGTH);
if(!fortio_complete_read(fortio , record_size))
return ECL_KW_READ_FAIL;
if (ECL_ENDIAN_FLIP)
util_endian_flip_vector(&size , sizeof size , 1);
}
ecl_data_type data_type = ecl_type_create_from_name( ecl_type_str );
ecl_kw_initialize( ecl_kw , header , size , data_type);
return ECL_KW_READ_OK;
}
/**
Will seek through the open fortio file and search for a keyword with
header 'kw'. It will always start the search from the present
position in the file, but if rewind is true it will rewind the
fortio file if not finding 'kw' between current offset and EOF.
If the kw is found the fortio pointer is positioned at the
beginning of the keyword, and the function returns true. If the the
'kw' is NOT found the file will be repositioned to the initial
position, and the function will return false; unless abort_on_error
== true in which case the function will abort if the 'kw' is not
found.
*/
bool ecl_kw_fseek_kw(const char * kw , bool rewind , bool abort_on_error , fortio_type *fortio) {
ecl_kw_type *tmp_kw = ecl_kw_alloc_empty();
long int init_pos = fortio_ftell( fortio );
bool cont, kw_found;
cont = true;
kw_found = false;
while (cont) {
long current_pos = fortio_ftell( fortio );
if (ecl_kw_fread_header(tmp_kw , fortio) == ECL_KW_READ_OK) {
if (ecl_kw_string_eq(ecl_kw_get_header8(tmp_kw) , kw)) {
fortio_fseek( fortio , current_pos , SEEK_SET );
kw_found = true;
cont = false;
} else
ecl_kw_fskip_data(tmp_kw , fortio);
} else {
if (rewind) {
fortio_rewind(fortio);
rewind = false;
} else
cont = false;
}
}
if (!kw_found) {
if (abort_on_error)
util_abort("%s: failed to locate keyword:%s in file:%s - aborting \n",__func__ , kw , fortio_filename_ref(fortio));
fortio_fseek(fortio , init_pos , SEEK_SET);
}
ecl_kw_free(tmp_kw);
return kw_found;
}
bool ecl_kw_ifseek_kw(const char * kw , fortio_type * fortio , int index) {
int i = 0;
do {
ecl_kw_fseek_kw(kw , false , true , fortio);
i++;
} while (i <= index);
return true;
}
bool ecl_kw_fseek_last_kw(const char * kw , bool abort_on_error , fortio_type *fortio) {
long int init_pos = fortio_ftell( fortio );
bool kw_found = false;
fortio_fseek(fortio , 0L , SEEK_SET);
kw_found = ecl_kw_fseek_kw(kw , false , false , fortio);
if (kw_found) {
bool cont = true;
do {
long int current_pos = fortio_ftell( fortio );
ecl_kw_fskip(fortio);
cont = ecl_kw_fseek_kw(kw , false , false , fortio);
if (!cont) fortio_fseek(fortio , current_pos , SEEK_SET);
} while (cont);
} else {
if (abort_on_error)
util_abort("%s: could not locate keyword:%s - aborting \n",__func__ , kw);
else
fortio_fseek(fortio , init_pos , SEEK_SET);
}
return kw_found;
}
void ecl_kw_set_data_ptr(ecl_kw_type * ecl_kw , void * data) {
if (!ecl_kw->shared_data)
free( ecl_kw->data );
ecl_kw->data = (char*)data;
}
/**
This is where the storage buffer of the ecl_kw is allocated.
*/
void ecl_kw_alloc_data(ecl_kw_type *ecl_kw) {
if (ecl_kw->shared_data)
util_abort("%s: trying to allocate data for ecl_kw object which has been declared with shared storage - aborting \n",__func__);
{
size_t byte_size = ecl_kw->size * ecl_type_get_sizeof_ctype(ecl_kw->data_type);
ecl_kw->data = (char*)util_realloc(ecl_kw->data , byte_size );
memset(ecl_kw->data , 0 , byte_size);
}
}
void ecl_kw_free_data(ecl_kw_type *ecl_kw) {
if (!ecl_kw->shared_data)
free(ecl_kw->data);
ecl_kw->data = NULL;
}
void ecl_kw_set_header_name(ecl_kw_type * ecl_kw , const char * header) {
ecl_kw->header8 = (char*)realloc(ecl_kw->header8 , ECL_STRING8_LENGTH + 1);
if (strlen(header) <= 8) {
sprintf(ecl_kw->header8 , "%-8s" , header);
/* Internalizing a header without the trailing spaces as well. */
free( ecl_kw->header );
ecl_kw->header = util_alloc_strip_copy( ecl_kw->header8 );
}
else {
ecl_kw->header = (char*)util_alloc_copy(header, strlen( header ) + 1);
}
}
void ecl_kw_set_data_type(ecl_kw_type * ecl_kw, ecl_data_type data_type) {
memcpy(&ecl_kw->data_type, &data_type, sizeof data_type);
}
bool ecl_kw_fread_realloc(ecl_kw_type *ecl_kw , fortio_type *fortio) {
if (ecl_kw_fread_header(ecl_kw , fortio) == ECL_KW_READ_OK)
return ecl_kw_fread_realloc_data( ecl_kw , fortio );
else
return false;
}
void ecl_kw_fread(ecl_kw_type * ecl_kw , fortio_type * fortio) {
int current_size = ecl_kw->size;
if (ecl_kw_fread_header(ecl_kw , fortio) != ECL_KW_READ_OK)
util_abort("%s: failed to read header for ecl_kw - aborting \n",__func__);
if (ecl_kw->size == current_size)
ecl_kw_fread_data(ecl_kw , fortio);
else
util_abort("%s: size mismatch - aborting \n",__func__);
}
ecl_kw_type *ecl_kw_fread_alloc(fortio_type *fortio) {
bool OK;
ecl_kw_type *ecl_kw = ecl_kw_alloc_empty();
OK = ecl_kw_fread_realloc(ecl_kw , fortio);
if (!OK) {
free(ecl_kw);
ecl_kw = NULL;
}
return ecl_kw;
}
void ecl_kw_fskip(fortio_type *fortio) {
ecl_kw_type *tmp_kw;
tmp_kw = ecl_kw_fread_alloc(fortio );
ecl_kw_free(tmp_kw);
}
static void ecl_kw_fwrite_data_unformatted( const ecl_kw_type * ecl_kw , fortio_type * fortio ) {
char * iobuffer = ecl_kw_alloc_output_buffer(ecl_kw);
int sizeof_iotype = ecl_type_get_sizeof_iotype(ecl_kw->data_type);
{
const int blocksize = get_blocksize( ecl_kw->data_type );
const int num_blocks = ecl_kw->size / blocksize + (ecl_kw->size % blocksize == 0 ? 0 : 1);
int block_nr;
for (block_nr = 0; block_nr < num_blocks; block_nr++) {
int this_blocksize = util_int_min((block_nr + 1)*blocksize , ecl_kw->size) - block_nr*blocksize;
int record_size = this_blocksize * sizeof_iotype; /* The total size in bytes of the record written by the fortio layer. */
fortio_fwrite_record(fortio , &iobuffer[block_nr * blocksize * sizeof_iotype] , record_size);
}
}
free(iobuffer);
}
/**
The point of this awkward function is that I have not managed to
use C fprintf() syntax to reproduce the ECLIPSE
formatting. ECLIPSE expects the following formatting for float
and double values:
0.ddddddddE+03 (float)
0.ddddddddddddddD+03 (double)
The problem with printf have been:
1. To force the radix part to start with 0.
2. To use 'D' as the exponent start for double values.
If you are more proficient with C fprintf() format strings than I
am, the __fprintf_scientific() function should be removed, and
the WRITE_FMT_DOUBLE and WRITE_FMT_FLOAT format specifiers
updated accordingly.
*/
static void __fprintf_scientific(FILE * stream, const char * fmt , double x) {
double pow_x = ceil(log10(fabs(x)));
double arg_x = x / pow(10.0 , pow_x);
if (x != 0.0) {
if (fabs(arg_x) == 1.0) {
arg_x *= 0.10;
pow_x += 1;
}
} else {
arg_x = 0.0;
pow_x = 0.0;
}
fprintf(stream , fmt , arg_x , (int) pow_x);
}
static void ecl_kw_fwrite_data_formatted( ecl_kw_type * ecl_kw , fortio_type * fortio ) {
{
FILE * stream = fortio_get_FILE( fortio );
const int blocksize = get_blocksize( ecl_kw->data_type );
const int columns = get_columns( ecl_kw->data_type );
char * write_fmt = alloc_write_fmt( ecl_kw->data_type );
const int num_blocks = ecl_kw->size / blocksize + (ecl_kw->size % blocksize == 0 ? 0 : 1);
int block_nr;
for (block_nr = 0; block_nr < num_blocks; block_nr++) {
int this_blocksize = util_int_min((block_nr + 1)*blocksize , ecl_kw->size) - block_nr*blocksize;
int num_lines = this_blocksize / columns + ( this_blocksize % columns == 0 ? 0 : 1);
int line_nr;
for (line_nr = 0; line_nr < num_lines; line_nr++) {
int num_columns = util_int_min( (line_nr + 1)*columns , this_blocksize) - columns * line_nr;
int col_nr;
for (col_nr =0; col_nr < num_columns; col_nr++) {
int data_index = block_nr * blocksize + line_nr * columns + col_nr;
void * data_ptr = ecl_kw_iget_ptr_static( ecl_kw , data_index );
switch (ecl_kw_get_type(ecl_kw)) {
case(ECL_CHAR_TYPE):
fprintf(stream , write_fmt , data_ptr);
break;
case(ECL_STRING_TYPE):
fprintf(stream , write_fmt , data_ptr);
break;
case(ECL_INT_TYPE):
{
int int_value = ((int *) data_ptr)[0];
fprintf(stream , write_fmt , int_value);
}
break;
case(ECL_BOOL_TYPE):
{
bool bool_value = ((bool *) data_ptr)[0];
if (bool_value)
fprintf(stream , write_fmt , BOOL_TRUE_CHAR);
else
fprintf(stream , write_fmt , BOOL_FALSE_CHAR);
}
break;
case(ECL_FLOAT_TYPE):
{
float float_value = ((float *) data_ptr)[0];
__fprintf_scientific( stream , write_fmt , float_value );
}
break;
case(ECL_DOUBLE_TYPE):
{
double double_value = ((double *) data_ptr)[0];
__fprintf_scientific( stream , write_fmt , double_value );
}
break;
case(ECL_MESS_TYPE):
util_abort("%s: internal fuckup : message type keywords should NOT have data ??\n",__func__);
break;
}
}
fprintf(stream , "\n");
}
}
free(write_fmt);
}
}
void ecl_kw_fwrite_data(const ecl_kw_type *_ecl_kw , fortio_type *fortio) {
ecl_kw_type *ecl_kw = (ecl_kw_type *) _ecl_kw;
bool fmt_file = fortio_fmt_file( fortio );
if (fmt_file)
ecl_kw_fwrite_data_formatted( ecl_kw , fortio );
else
ecl_kw_fwrite_data_unformatted( ecl_kw ,fortio );
}
void ecl_kw_fwrite_header(const ecl_kw_type *ecl_kw , fortio_type *fortio) {
FILE *stream = fortio_get_FILE(fortio);
bool fmt_file = fortio_fmt_file(fortio);
char * type_name = ecl_type_alloc_name(ecl_kw->data_type);
if (fmt_file)
fprintf(stream , WRITE_HEADER_FMT , ecl_kw->header8 , ecl_kw->size , type_name);
else {
int size = ecl_kw->size;
if (ECL_ENDIAN_FLIP)
util_endian_flip_vector(&size , sizeof size , 1);
fortio_init_write(fortio , ECL_KW_HEADER_DATA_SIZE );
fwrite(ecl_kw->header8 , sizeof(char) , ECL_STRING8_LENGTH , stream);
fwrite(&size , sizeof(int) , 1 , stream);
fwrite(type_name , sizeof(char) , ECL_TYPE_LENGTH , stream);
fortio_complete_write(fortio , ECL_KW_HEADER_DATA_SIZE);
}
free(type_name);
}
bool ecl_kw_fwrite(const ecl_kw_type *ecl_kw , fortio_type *fortio) {
if (strlen(ecl_kw_get_header( ecl_kw)) > ECL_STRING8_LENGTH) {
fortio_fwrite_error(fortio);
return false;
}
ecl_kw_fwrite_header(ecl_kw , fortio);
ecl_kw_fwrite_data(ecl_kw , fortio);
return true;
}
static void * ecl_kw_get_data_ref(const ecl_kw_type *ecl_kw) {
return ecl_kw->data;
}
void * ecl_kw_get_ptr(const ecl_kw_type *ecl_kw) {
return ecl_kw_get_data_ref( ecl_kw );
}
int ecl_kw_get_size(const ecl_kw_type * ecl_kw) {
return ecl_kw->size;
}
ecl_type_enum ecl_kw_get_type(const ecl_kw_type * ecl_kw) {
return ecl_type_get_type(ecl_kw->data_type);
}
ecl_data_type ecl_kw_get_data_type(const ecl_kw_type * ecl_kw) {
return ecl_kw->data_type;
}
/******************************************************************/
ecl_kw_type * ecl_kw_buffer_alloc(buffer_type * buffer) {
const char * header = buffer_fread_string( buffer );
int size = buffer_fread_int( buffer );
ecl_type_enum ecl_type = (ecl_type_enum)buffer_fread_int( buffer );
size_t element_size = buffer_fread_int( buffer );
ecl_data_type data_type = ecl_type_create(ecl_type, element_size);
ecl_kw_type * ecl_kw = ecl_kw_alloc_empty();
ecl_kw_initialize( ecl_kw , header , size , data_type );
ecl_kw_alloc_data(ecl_kw);
buffer_fread(buffer , ecl_kw->data , ecl_type_get_sizeof_ctype(ecl_kw->data_type) , ecl_kw->size);
return ecl_kw;
}
void ecl_kw_buffer_store(const ecl_kw_type * ecl_kw , buffer_type * buffer) {
buffer_fwrite_string( buffer , ecl_kw->header8 );
buffer_fwrite_int( buffer , ecl_kw->size );
buffer_fwrite_int( buffer , ecl_type_get_type(ecl_kw->data_type) );
buffer_fwrite_int( buffer , ecl_type_get_sizeof_ctype(ecl_kw->data_type));
buffer_fwrite( buffer , ecl_kw->data , ecl_type_get_sizeof_ctype(ecl_kw->data_type) , ecl_kw->size);
}
void ecl_kw_fwrite_param_fortio(fortio_type * fortio, const char * header , ecl_data_type data_type , int size, void * data) {
ecl_kw_type * ecl_kw = ecl_kw_alloc_new_shared(header , size , data_type , data);
ecl_kw_fwrite(ecl_kw , fortio);
ecl_kw_free(ecl_kw);
}
void ecl_kw_fwrite_param(const char * filename , bool fmt_file , const char * header , ecl_data_type data_type , int size, void * data) {
fortio_type * fortio = fortio_open_writer(filename , fmt_file , ECL_ENDIAN_FLIP);
ecl_kw_fwrite_param_fortio(fortio , header , data_type , size , data);
fortio_fclose(fortio);
}
void ecl_kw_get_data_as_double(const ecl_kw_type * ecl_kw , double * double_data) {
if (ecl_type_is_double(ecl_kw->data_type))
// Direct memcpy - no conversion
ecl_kw_get_memcpy_data(ecl_kw , double_data);
else {
if (ecl_type_is_float(ecl_kw->data_type)) {
const float * float_data = (const float *) ecl_kw->data;
util_float_to_double(double_data , float_data , ecl_kw->size);
} else if (ecl_type_is_int(ecl_kw->data_type)) {
const int * int_data = (const int *) ecl_kw->data;
int i;
for (i=0; i < ecl_kw->size; i++)
double_data[i] = int_data[i];
} else {
fprintf(stderr,"%s: type can not be converted to double - aborting \n",__func__);
ecl_kw_summarize(ecl_kw);
util_abort("%s: Aborting \n",__func__);
}
}
}
void ecl_kw_get_data_as_float(const ecl_kw_type * ecl_kw , float * float_data) {
if (ecl_type_is_float(ecl_kw->data_type))
// Direct memcpy - no conversion
ecl_kw_get_memcpy_data(ecl_kw , float_data);
else {
if (ecl_type_is_double(ecl_kw->data_type)) {
const double * double_data = (const double *) ecl_kw->data;
util_double_to_float(float_data , double_data , ecl_kw->size);
} else if (ecl_type_is_int(ecl_kw->data_type)) {
const int * int_data = (const int *) ecl_kw->data;
int i;
for (i=0; i < ecl_kw->size; i++)
float_data[i] = (float) int_data[i];
} else {
fprintf(stderr,"%s: type can not be converted to float - aborting \n",__func__);
ecl_kw_summarize(ecl_kw);
util_abort("%s: Aborting \n",__func__);
}
}
}
/**
Will create a new keyword of the same type as src_kw, and size
@target_size. The integer array mapping is a list sizeof(src_kw)
elements, where each element is the new index, i.e.
new_kw[ mapping[i] ] = src_kw[i]
For all inactive elements in new kw are set as follows:
0 - For float / int / double
False - For logical
"" - For char
*/
ecl_kw_type * ecl_kw_alloc_scatter_copy( const ecl_kw_type * src_kw , int target_size , const int * mapping, void * def_value) {
int default_int = 0;
double default_double = 0;
float default_float = 0;
bool default_bool = false;
const char * default_char = "";
ecl_kw_type * new_kw = ecl_kw_alloc( src_kw->header , target_size , src_kw->data_type );
if (def_value != NULL)
ecl_kw_scalar_set__( new_kw , def_value );
else {
/** Initialize with defaults .*/
switch (ecl_kw_get_type(src_kw)) {
case(ECL_INT_TYPE):
ecl_kw_scalar_set__( new_kw , &default_int );
break;
case(ECL_FLOAT_TYPE):
ecl_kw_scalar_set__( new_kw , &default_float );
break;
case(ECL_DOUBLE_TYPE):
ecl_kw_scalar_set__( new_kw , &default_double );
break;
case(ECL_BOOL_TYPE):
ecl_kw_scalar_set__( new_kw , &default_bool );
break;
case(ECL_CHAR_TYPE):
ecl_kw_scalar_set__( new_kw , default_char );
break;
default:
util_abort("%s: unsupported type:%d \n", __func__ , ecl_kw_get_type(src_kw));
}
}
{
int sizeof_ctype = ecl_type_get_sizeof_ctype( src_kw->data_type );
int i;
for( i =0; i < src_kw->size; i++) {
int target_index = mapping[i];
memcpy( &new_kw->data[ target_index * sizeof_ctype ] , &src_kw->data[ i * sizeof_ctype] , sizeof_ctype);
}
}
return new_kw;
}
ecl_kw_type * ecl_kw_alloc_global_copy(const ecl_kw_type * src, const ecl_kw_type * actnum) {
if (ecl_kw_get_type(actnum) != ECL_INT_TYPE)
return NULL;
const int global_size = ecl_kw_get_size(actnum);
ecl_kw_type * global_copy = ecl_kw_alloc( ecl_kw_get_header(src), global_size, src->data_type);
const int * mapping = ecl_kw_get_int_ptr(actnum);
const int src_size = ecl_kw_get_size(src);
int src_index = 0;
for (int global_index=0; global_index < global_size; global_index++) {
if (mapping[global_index]) {
/* We ran through and beyond the size of the src keyword. */
if (src_index >= src_size) {
ecl_kw_free(global_copy);
global_copy = NULL;
break;
}
const void * value_ptr = ecl_kw_iget_ptr(src, src_index);
ecl_kw_iset_static(global_copy, global_index, value_ptr);
src_index++;
}
}
/* Not all the src data was distributed. */
if (src_index < src_size) {
ecl_kw_free(global_copy);
global_copy = NULL;
}
return global_copy;
}
void ecl_kw_fread_double_param(const char * filename , bool fmt_file , double * double_data) {
fortio_type * fortio = fortio_open_reader(filename , fmt_file , ECL_ENDIAN_FLIP);
ecl_kw_type * ecl_kw = ecl_kw_fread_alloc(fortio);
fortio_fclose(fortio);
if (ecl_kw == NULL)
util_abort("%s: fatal error: loading parameter from: %s failed - aborting \n",__func__ , filename);
ecl_kw_get_data_as_double(ecl_kw , double_data);
ecl_kw_free(ecl_kw);
}
void ecl_kw_summarize(const ecl_kw_type * ecl_kw) {
char * type_name = ecl_type_alloc_name(ecl_kw->data_type);
printf("%8s %10d:%4s \n",ecl_kw_get_header8(ecl_kw),
ecl_kw_get_size(ecl_kw),
type_name);
free(type_name);
}
/*****************************************************************/
#define ECL_KW_SCALAR_SET_TYPED( ctype , ECL_TYPE ) \
void ecl_kw_scalar_set_ ## ctype( ecl_kw_type * ecl_kw , ctype value){ \
if (ecl_kw_get_type(ecl_kw) == ECL_TYPE) { \
ctype * data = (ctype *)ecl_kw_get_data_ref(ecl_kw); \
int i; \
for (i=0;i < ecl_kw->size; i++) \
data[i] = value; \
} else util_abort("%s: wrong type\n",__func__); \
}
ECL_KW_SCALAR_SET_TYPED( int , ECL_INT_TYPE )
ECL_KW_SCALAR_SET_TYPED( float , ECL_FLOAT_TYPE )
ECL_KW_SCALAR_SET_TYPED( double , ECL_DOUBLE_TYPE )
ECL_KW_SCALAR_SET_TYPED( bool , ECL_BOOL_TYPE )
#undef ECL_KW_SCALAR_SET_TYPED
void ecl_kw_scalar_set_float_or_double( ecl_kw_type * ecl_kw , double value ) {
ecl_type_enum ecl_type = ecl_kw_get_type(ecl_kw);
if (ecl_type == ECL_FLOAT_TYPE)
ecl_kw_scalar_set_float( ecl_kw , (float) value);
else if (ecl_type == ECL_DOUBLE_TYPE)
ecl_kw_scalar_set_double( ecl_kw , value);
else
util_abort("%s: wrong type \n",__func__);
}
/*
Untyped - low level alternative.
*/
void ecl_kw_scalar_set__(ecl_kw_type * ecl_kw , const void * value) {
int sizeof_ctype = ecl_type_get_sizeof_ctype( ecl_kw->data_type );
int i;
for (i=0;i < ecl_kw->size; i++)
memcpy( &ecl_kw->data[ i * sizeof_ctype ] , value , sizeof_ctype);
}
/*****************************************************************/
void ecl_kw_alloc_double_data(ecl_kw_type * ecl_kw , double * values) {
ecl_kw_alloc_data(ecl_kw);
memcpy(ecl_kw->data , values , ecl_kw->size * ecl_type_get_sizeof_ctype(ecl_kw->data_type));
}
void ecl_kw_alloc_float_data(ecl_kw_type * ecl_kw , float * values) {
ecl_kw_alloc_data(ecl_kw);
memcpy(ecl_kw->data , values , ecl_kw->size * ecl_type_get_sizeof_ctype(ecl_kw->data_type));
}
/*****************************************************************/
/* Macros for typed mathematical functions. */
#define ECL_KW_SCALE_TYPED( ctype , ECL_TYPE ) \
void ecl_kw_scale_ ## ctype (ecl_kw_type * ecl_kw , ctype scale_factor) { \
if (ecl_kw_get_type(ecl_kw) != ECL_TYPE) \
util_abort("%s: Keyword: %s is wrong type - aborting \n",__func__ , ecl_kw_get_header8(ecl_kw)); \
{ \
ctype * data = (ctype *)ecl_kw_get_data_ref(ecl_kw); \
int size = ecl_kw_get_size(ecl_kw); \
int i; \
for (i=0; i < size; i++) \
data[i] *= scale_factor; \
} \
}
ECL_KW_SCALE_TYPED( int , ECL_INT_TYPE)
ECL_KW_SCALE_TYPED( float , ECL_FLOAT_TYPE)
ECL_KW_SCALE_TYPED( double , ECL_DOUBLE_TYPE )
#undef ECL_KW_SCALE_TYPED
void ecl_kw_scale_float_or_double( ecl_kw_type * ecl_kw , double scale_factor ) {
ecl_type_enum ecl_type = ecl_kw_get_type(ecl_kw);
if (ecl_type == ECL_FLOAT_TYPE)
ecl_kw_scale_float( ecl_kw , (float) scale_factor);
else if (ecl_type == ECL_DOUBLE_TYPE)
ecl_kw_scale_double( ecl_kw , scale_factor);
else
util_abort("%s: wrong type \n",__func__);
}
#define ECL_KW_SHIFT_TYPED( ctype , ECL_TYPE ) \
void ecl_kw_shift_ ## ctype (ecl_kw_type * ecl_kw , ctype shift_value) { \
if (ecl_kw_get_type(ecl_kw) != ECL_TYPE) \
util_abort("%s: Keyword: %s is wrong type - aborting \n",__func__ , ecl_kw_get_header8(ecl_kw)); \
{ \
ctype * data = (ctype *)ecl_kw_get_data_ref(ecl_kw); \
int size = ecl_kw_get_size(ecl_kw); \
int i; \
for (i=0; i < size; i++) \
data[i] += shift_value; \
} \
}
ECL_KW_SHIFT_TYPED( int , ECL_INT_TYPE)
ECL_KW_SHIFT_TYPED( float , ECL_FLOAT_TYPE)
ECL_KW_SHIFT_TYPED( double , ECL_DOUBLE_TYPE )
#undef ECL_KW_SHIFT_TYPED
void ecl_kw_shift_float_or_double( ecl_kw_type * ecl_kw , double shift_value ) {
ecl_type_enum ecl_type = ecl_kw_get_type(ecl_kw);
if (ecl_type == ECL_FLOAT_TYPE)
ecl_kw_shift_float( ecl_kw , (float) shift_value );
else if (ecl_type == ECL_DOUBLE_TYPE)
ecl_kw_shift_double( ecl_kw , shift_value );
else
util_abort("%s: wrong type \n",__func__);
}
bool ecl_kw_size_and_numeric_type_equal( const ecl_kw_type * kw1, const ecl_kw_type * kw2) {
return ecl_kw_size_and_type_equal(kw1, kw2) && ecl_type_is_numeric(kw1->data_type);
}
#define ECL_KW_ASSERT_TYPED_BINARY_OP( ctype , ECL_TYPE ) \
bool ecl_kw_assert_binary_ ## ctype( const ecl_kw_type * kw1 , const ecl_kw_type * kw2) { \
if (!ecl_kw_size_and_numeric_type_equal( kw1 , kw2)) \
return false; \
if (ecl_kw_get_type(kw1) != ECL_TYPE) \
return false; /* Type mismatch */ \
return true; \
}
ECL_KW_ASSERT_TYPED_BINARY_OP( int , ECL_INT_TYPE )
ECL_KW_ASSERT_TYPED_BINARY_OP( float , ECL_FLOAT_TYPE )
ECL_KW_ASSERT_TYPED_BINARY_OP( double , ECL_DOUBLE_TYPE )
#undef ECL_KW_ASSERT_TYPED_BINARY_OP
void ecl_kw_copy_indexed( ecl_kw_type * target_kw , const int_vector_type * index_set , const ecl_kw_type * src_kw) {
if (!ecl_kw_size_and_type_equal( target_kw , src_kw ))
util_abort("%s: type/size mismatch\n",__func__);
{
char * target_data = (char *)ecl_kw_get_data_ref( target_kw );
const char * src_data = (const char *)ecl_kw_get_data_ref( src_kw );
int sizeof_ctype = ecl_type_get_sizeof_ctype(target_kw->data_type);
int set_size = int_vector_size( index_set );
const int * index_data = int_vector_get_const_ptr( index_set );
int i;
for (i=0; i < set_size; i++) {
int index = index_data[i];
memcpy( &target_data[ index * sizeof_ctype ] , &src_data[ index * sizeof_ctype] , sizeof_ctype);
}
}
}
#define ECL_KW_TYPED_INPLACE_ADD_INDEXED( ctype ) \
static void ecl_kw_inplace_add_indexed_ ## ctype( ecl_kw_type * target_kw , const int_vector_type * index_set , const ecl_kw_type * add_kw) { \
if (!ecl_kw_assert_binary_ ## ctype( target_kw , add_kw )) \
util_abort("%s: type/size mismatch\n",__func__); \
{ \
ctype * target_data = (ctype *)ecl_kw_get_data_ref( target_kw ); \
const ctype * add_data = (const ctype *)ecl_kw_get_data_ref( add_kw ); \
int set_size = int_vector_size( index_set ); \
const int * index_data = int_vector_get_const_ptr( index_set ); \
int i; \
for (i=0; i < set_size; i++) { \
int index = index_data[i]; \
target_data[index] += add_data[index]; \
} \
} \
}
ECL_KW_TYPED_INPLACE_ADD_INDEXED( int )
ECL_KW_TYPED_INPLACE_ADD_INDEXED( double )
ECL_KW_TYPED_INPLACE_ADD_INDEXED( float )
#undef ECL_KW_TYPED_INPLACE_ADD
void ecl_kw_inplace_add_indexed( ecl_kw_type * target_kw , const int_vector_type * index_set , const ecl_kw_type * add_kw) {
ecl_type_enum type = ecl_kw_get_type(target_kw);
switch (type) {
case(ECL_FLOAT_TYPE):
ecl_kw_inplace_add_indexed_float( target_kw , index_set , add_kw );
break;
case(ECL_DOUBLE_TYPE):
ecl_kw_inplace_add_indexed_double( target_kw , index_set , add_kw );
break;
case(ECL_INT_TYPE):
ecl_kw_inplace_add_indexed_int( target_kw , index_set , add_kw );
break;
default:
util_abort("%s: inplace add not implemented for type:%s \n",__func__ , ecl_type_alloc_name( ecl_kw_get_data_type(target_kw) ));
}
}
#define ECL_KW_TYPED_INPLACE_ADD( ctype ) \
static void ecl_kw_inplace_add_ ## ctype( ecl_kw_type * target_kw , const ecl_kw_type * add_kw) { \
if (!ecl_kw_assert_binary_ ## ctype( target_kw , add_kw )) \
util_abort("%s: type/size mismatch\n",__func__); \
{ \
ctype * target_data = (ctype *)ecl_kw_get_data_ref( target_kw ); \
const ctype * add_data = (const ctype *)ecl_kw_get_data_ref( add_kw ); \
int i; \
for (i=0; i < target_kw->size; i++) \
target_data[i] += add_data[i]; \
} \
}
ECL_KW_TYPED_INPLACE_ADD( int )
ECL_KW_TYPED_INPLACE_ADD( double )
ECL_KW_TYPED_INPLACE_ADD( float )
#undef ECL_KW_TYPED_INPLACE_ADD
void ecl_kw_inplace_add( ecl_kw_type * target_kw , const ecl_kw_type * add_kw) {
ecl_type_enum type = ecl_kw_get_type(target_kw);
switch (type) {
case(ECL_FLOAT_TYPE):
ecl_kw_inplace_add_float( target_kw , add_kw );
break;
case(ECL_DOUBLE_TYPE):
ecl_kw_inplace_add_double( target_kw , add_kw );
break;
case(ECL_INT_TYPE):
ecl_kw_inplace_add_int( target_kw , add_kw );
break;
default:
util_abort("%s: inplace add not implemented for type:%s \n",__func__ , ecl_type_alloc_name( ecl_kw_get_data_type(target_kw) ));
}
}
#define ECL_KW_TYPED_INPLACE_ADD_SQUARED( ctype ) \
static void ecl_kw_inplace_add_squared_ ## ctype( ecl_kw_type * target_kw , const ecl_kw_type * add_kw) { \
if (!ecl_kw_assert_binary_ ## ctype( target_kw , add_kw )) \
util_abort("%s: type/size mismatch\n",__func__); \
{ \
ctype * target_data = (ctype *)ecl_kw_get_data_ref( target_kw ); \
const ctype * add_data = (const ctype *)ecl_kw_get_data_ref( add_kw ); \
int i; \
for (i=0; i < target_kw->size; i++) \
target_data[i] += add_data[i] * add_data[i]; \
} \
}
ECL_KW_TYPED_INPLACE_ADD_SQUARED( int )
ECL_KW_TYPED_INPLACE_ADD_SQUARED( double )
ECL_KW_TYPED_INPLACE_ADD_SQUARED( float )
#undef ECL_KW_TYPED_INPLACE_ADD
void ecl_kw_inplace_add_squared( ecl_kw_type * target_kw , const ecl_kw_type * add_kw) {
ecl_type_enum type = ecl_kw_get_type(target_kw);
switch (type) {
case(ECL_FLOAT_TYPE):
ecl_kw_inplace_add_squared_float( target_kw , add_kw );
break;
case(ECL_DOUBLE_TYPE):
ecl_kw_inplace_add_squared_double( target_kw , add_kw );
break;
case(ECL_INT_TYPE):
ecl_kw_inplace_add_squared_int( target_kw , add_kw );
break;
default:
util_abort("%s: inplace add not implemented for type:%s \n",__func__ , ecl_type_alloc_name( ecl_kw_get_data_type(target_kw) ));
}
}
#define ECL_KW_TYPED_INPLACE_SUB( ctype ) \
void ecl_kw_inplace_sub_ ## ctype( ecl_kw_type * target_kw , const ecl_kw_type * sub_kw) { \
if (!ecl_kw_assert_binary_ ## ctype( target_kw , sub_kw )) \
util_abort("%s: type/size mismatch\n",__func__); \
{ \
ctype * target_data = (ctype *)ecl_kw_get_data_ref( target_kw ); \
const ctype * sub_data = (const ctype *)ecl_kw_get_data_ref( sub_kw ); \
int i; \
for (i=0; i < target_kw->size; i++) \
target_data[i] -= sub_data[i]; \
} \
}
ECL_KW_TYPED_INPLACE_SUB( int )
ECL_KW_TYPED_INPLACE_SUB( double )
ECL_KW_TYPED_INPLACE_SUB( float )
#undef ECL_KW_TYPED_INPLACE_SUB
void ecl_kw_inplace_sub( ecl_kw_type * target_kw , const ecl_kw_type * sub_kw) {
ecl_type_enum type = ecl_kw_get_type(target_kw);
switch (type) {
case(ECL_FLOAT_TYPE):
ecl_kw_inplace_sub_float( target_kw , sub_kw );
break;
case(ECL_DOUBLE_TYPE):
ecl_kw_inplace_sub_double( target_kw , sub_kw );
break;
case(ECL_INT_TYPE):
ecl_kw_inplace_sub_int( target_kw , sub_kw );
break;
default:
util_abort("%s: inplace sub not implemented for type:%s \n",__func__ , ecl_type_alloc_name( ecl_kw_get_data_type(target_kw) ));
}
}
#define ECL_KW_TYPED_INPLACE_SUB_INDEXED( ctype ) \
static void ecl_kw_inplace_sub_indexed_ ## ctype( ecl_kw_type * target_kw , const int_vector_type * index_set , const ecl_kw_type * sub_kw) { \
if (!ecl_kw_assert_binary_ ## ctype( target_kw , sub_kw )) \
util_abort("%s: type/size mismatch\n",__func__); \
{ \
ctype * target_data = (ctype *)ecl_kw_get_data_ref( target_kw ); \
const ctype * sub_data = (const ctype *)ecl_kw_get_data_ref( sub_kw ); \
int set_size = int_vector_size( index_set ); \
const int * index_data = int_vector_get_const_ptr( index_set ); \
int i; \
for (i=0; i < set_size; i++) { \
int index = index_data[i]; \
target_data[index] -= sub_data[index]; \
} \
} \
}
ECL_KW_TYPED_INPLACE_SUB_INDEXED( int )
ECL_KW_TYPED_INPLACE_SUB_INDEXED( double )
ECL_KW_TYPED_INPLACE_SUB_INDEXED( float )
#undef ECL_KW_TYPED_INPLACE_SUB
void ecl_kw_inplace_sub_indexed( ecl_kw_type * target_kw , const int_vector_type * index_set , const ecl_kw_type * sub_kw) {
ecl_type_enum type = ecl_kw_get_type(target_kw);
switch (type) {
case(ECL_FLOAT_TYPE):
ecl_kw_inplace_sub_indexed_float( target_kw , index_set , sub_kw );
break;
case(ECL_DOUBLE_TYPE):
ecl_kw_inplace_sub_indexed_double( target_kw , index_set , sub_kw );
break;
case(ECL_INT_TYPE):
ecl_kw_inplace_sub_indexed_int( target_kw , index_set , sub_kw );
break;
default:
util_abort("%s: inplace sub not implemented for type:%s \n",__func__ , ecl_type_alloc_name( ecl_kw_get_data_type(target_kw) ));
}
}
/*****************************************************************/
#define ECL_KW_TYPED_INPLACE_ABS( ctype , abs_func) \
void ecl_kw_inplace_abs_ ## ctype( ecl_kw_type * kw ) { \
ctype * data = (ctype *)ecl_kw_get_data_ref( kw ); \
int i; \
for (i=0; i < kw->size; i++) \
data[i] = abs_func(data[i]); \
}
ECL_KW_TYPED_INPLACE_ABS( int , abs )
ECL_KW_TYPED_INPLACE_ABS( double , fabs )
ECL_KW_TYPED_INPLACE_ABS( float , fabsf )
#undef ECL_KW_TYPED_INPLACE_ABS
void ecl_kw_inplace_abs( ecl_kw_type * kw ) {
ecl_type_enum type = ecl_kw_get_type(kw);
switch (type) {
case(ECL_FLOAT_TYPE):
ecl_kw_inplace_abs_float( kw );
break;
case(ECL_DOUBLE_TYPE):
ecl_kw_inplace_abs_double( kw );
break;
case(ECL_INT_TYPE):
ecl_kw_inplace_abs_int( kw );
break;
default:
util_abort("%s: inplace abs not implemented for type:%s \n",__func__ , ecl_type_alloc_name( ecl_kw_get_data_type(kw) ));
}
}
/*****************************************************************/
static int sqrti(int x) {
return round( sqrt(x) );
}
#define ECL_KW_TYPED_INPLACE_SQRT( ctype, sqrt_func ) \
void ecl_kw_inplace_sqrt_ ## ctype( ecl_kw_type * kw ) { \
ctype * data = (ctype *)ecl_kw_get_data_ref( kw ); \
int i; \
for (i=0; i < kw->size; i++) \
data[i] = sqrt_func(data[i]); \
}
ECL_KW_TYPED_INPLACE_SQRT( double , sqrt )
ECL_KW_TYPED_INPLACE_SQRT( float , sqrtf )
ECL_KW_TYPED_INPLACE_SQRT( int, sqrti)
#undef ECL_KW_TYPED_INPLACE_SQRT
void ecl_kw_inplace_sqrt( ecl_kw_type * kw ) {
ecl_type_enum type = ecl_kw_get_type(kw);
switch (type) {
case(ECL_FLOAT_TYPE):
ecl_kw_inplace_sqrt_float( kw );
break;
case(ECL_DOUBLE_TYPE):
ecl_kw_inplace_sqrt_double( kw );
break;
case(ECL_INT_TYPE):
ecl_kw_inplace_sqrt_int( kw );
break;
default:
util_abort("%s: inplace sqrt not implemented for type:%s \n",__func__ , ecl_type_alloc_name( ecl_kw_get_data_type(kw) ));
}
}
/*****************************************************************/
#define ECL_KW_TYPED_INPLACE_MUL( ctype ) \
void ecl_kw_inplace_mul_ ## ctype( ecl_kw_type * target_kw , const ecl_kw_type * mul_kw) { \
if (!ecl_kw_assert_binary_ ## ctype( target_kw , mul_kw )) \
util_abort("%s: type/size mismatch\n",__func__); \
{ \
ctype * target_data = (ctype *)ecl_kw_get_data_ref( target_kw ); \
const ctype * mul_data = (const ctype *)ecl_kw_get_data_ref( mul_kw ); \
int i; \
for (i=0; i < target_kw->size; i++) \
target_data[i] *= mul_data[i]; \
} \
}
ECL_KW_TYPED_INPLACE_MUL( int )
ECL_KW_TYPED_INPLACE_MUL( double )
ECL_KW_TYPED_INPLACE_MUL( float )
#undef ECL_KW_TYPED_INPLACE_MUL
void ecl_kw_inplace_mul( ecl_kw_type * target_kw , const ecl_kw_type * mul_kw) {
ecl_type_enum type = ecl_kw_get_type(target_kw);
switch (type) {
case(ECL_FLOAT_TYPE):
ecl_kw_inplace_mul_float( target_kw , mul_kw );
break;
case(ECL_DOUBLE_TYPE):
ecl_kw_inplace_mul_double( target_kw , mul_kw );
break;
case(ECL_INT_TYPE):
ecl_kw_inplace_mul_int( target_kw , mul_kw );
break;
default:
util_abort("%s: inplace mul not implemented for type:%s \n",__func__ , ecl_type_alloc_name( ecl_kw_get_data_type(target_kw) ));
}
}
#define ECL_KW_TYPED_INPLACE_MUL_INDEXED( ctype ) \
static void ecl_kw_inplace_mul_indexed_ ## ctype( ecl_kw_type * target_kw , const int_vector_type * index_set , const ecl_kw_type * mul_kw) { \
if (!ecl_kw_assert_binary_ ## ctype( target_kw , mul_kw )) \
util_abort("%s: type/size mismatch\n",__func__); \
{ \
ctype * target_data = (ctype *)ecl_kw_get_data_ref( target_kw ); \
const ctype * mul_data = (const ctype *)ecl_kw_get_data_ref( mul_kw ); \
int set_size = int_vector_size( index_set ); \
const int * index_data = int_vector_get_const_ptr( index_set ); \
int i; \
for (i=0; i < set_size; i++) { \
int index = index_data[i]; \
target_data[index] *= mul_data[index]; \
} \
} \
}
ECL_KW_TYPED_INPLACE_MUL_INDEXED( int )
ECL_KW_TYPED_INPLACE_MUL_INDEXED( double )
ECL_KW_TYPED_INPLACE_MUL_INDEXED( float )
#undef ECL_KW_TYPED_INPLACE_MUL
void ecl_kw_inplace_mul_indexed( ecl_kw_type * target_kw , const int_vector_type * index_set , const ecl_kw_type * mul_kw) {
ecl_type_enum type = ecl_kw_get_type(target_kw);
switch (type) {
case(ECL_FLOAT_TYPE):
ecl_kw_inplace_mul_indexed_float( target_kw , index_set , mul_kw );
break;
case(ECL_DOUBLE_TYPE):
ecl_kw_inplace_mul_indexed_double( target_kw , index_set , mul_kw );
break;
case(ECL_INT_TYPE):
ecl_kw_inplace_mul_indexed_int( target_kw , index_set , mul_kw );
break;
default:
util_abort("%s: inplace mul not implemented for type:%s \n",__func__ , ecl_type_alloc_name( ecl_kw_get_data_type(target_kw) ));
}
}
/*****************************************************************/
#define ECL_KW_TYPED_INPLACE_DIV( ctype ) \
void ecl_kw_inplace_div_ ## ctype( ecl_kw_type * target_kw , const ecl_kw_type * div_kw) { \
if (!ecl_kw_assert_binary_ ## ctype( target_kw , div_kw )) \
util_abort("%s: type/size mismatch\n",__func__); \
{ \
ctype * target_data = (ctype *)ecl_kw_get_data_ref( target_kw ); \
const ctype * div_data = (const ctype *)ecl_kw_get_data_ref( div_kw ); \
int i; \
for (i=0; i < target_kw->size; i++) \
target_data[i] /= div_data[i]; \
} \
}
ECL_KW_TYPED_INPLACE_DIV( int )
ECL_KW_TYPED_INPLACE_DIV( double )
ECL_KW_TYPED_INPLACE_DIV( float )
#undef ECL_KW_TYPED_INPLACE_DIV
void ecl_kw_inplace_div( ecl_kw_type * target_kw , const ecl_kw_type * div_kw) {
ecl_type_enum type = ecl_kw_get_type(target_kw);
switch (type) {
case(ECL_FLOAT_TYPE):
ecl_kw_inplace_div_float( target_kw , div_kw );
break;
case(ECL_DOUBLE_TYPE):
ecl_kw_inplace_div_double( target_kw , div_kw );
break;
case(ECL_INT_TYPE):
ecl_kw_inplace_div_int( target_kw , div_kw );
break;
default:
util_abort("%s: inplace div not implemented for type:%s \n",__func__ , ecl_type_alloc_name( ecl_kw_get_data_type(target_kw) ));
}
}
#define ECL_KW_TYPED_INPLACE_DIV_INDEXED( ctype ) \
static void ecl_kw_inplace_div_indexed_ ## ctype( ecl_kw_type * target_kw , const int_vector_type * index_set , const ecl_kw_type * div_kw) { \
if (!ecl_kw_assert_binary_ ## ctype( target_kw , div_kw )) \
util_abort("%s: type/size mismatch\n",__func__); \
{ \
ctype * target_data = (ctype *)ecl_kw_get_data_ref( target_kw ); \
const ctype * div_data = (const ctype *)ecl_kw_get_data_ref( div_kw ); \
int set_size = int_vector_size( index_set ); \
const int * index_data = int_vector_get_const_ptr( index_set ); \
int i; \
for (i=0; i < set_size; i++) { \
int index = index_data[i]; \
target_data[index] *= div_data[index]; \
} \
} \
}
ECL_KW_TYPED_INPLACE_DIV_INDEXED( int )
ECL_KW_TYPED_INPLACE_DIV_INDEXED( double )
ECL_KW_TYPED_INPLACE_DIV_INDEXED( float )
#undef ECL_KW_TYPED_INPLACE_DIV
void ecl_kw_inplace_div_indexed( ecl_kw_type * target_kw , const int_vector_type * index_set , const ecl_kw_type * div_kw) {
ecl_type_enum type = ecl_kw_get_type(target_kw);
switch (type) {
case(ECL_FLOAT_TYPE):
ecl_kw_inplace_div_indexed_float( target_kw , index_set , div_kw );
break;
case(ECL_DOUBLE_TYPE):
ecl_kw_inplace_div_indexed_double( target_kw , index_set , div_kw );
break;
case(ECL_INT_TYPE):
ecl_kw_inplace_div_indexed_int( target_kw , index_set , div_kw );
break;
default:
util_abort("%s: inplace div not implemented for type:%s \n",__func__ , ecl_type_alloc_name( ecl_kw_get_data_type(target_kw) ));
}
}
bool ecl_kw_inplace_safe_div(ecl_kw_type * target_kw, const ecl_kw_type * divisor) {
if (ecl_kw_get_type(target_kw) != ECL_FLOAT_TYPE)
return false;
if (ecl_kw_get_type(divisor) != ECL_INT_TYPE)
return false;
float * target_data = (float*)ecl_kw_get_data_ref( target_kw );
const int* div_data = (const int*)ecl_kw_get_data_ref( divisor );
for (int i=0; i < target_kw->size; i++) {
if (div_data[i] != 0)
target_data[i] /= div_data[i];
}
return true;
}
/*****************************************************************/
void ecl_kw_inplace_inv(ecl_kw_type * my_kw) {
int size = ecl_kw_get_size(my_kw);
ecl_type_enum type = ecl_kw_get_type(my_kw);
{
int i;
void * my_data = ecl_kw_get_data_ref(my_kw);
switch (type) {
case(ECL_DOUBLE_TYPE):
{
double *my_double = (double *) my_data;
for (i=0; i < size; i++)
my_double[i] = 1.0/ my_double[i];
break;
}
case(ECL_FLOAT_TYPE):
{
float *my_float = (float *) my_data;
for (i=0; i < size; i++)
my_float[i] = 1.0f / my_float[i];
break;
}
default:
util_abort("%s: can only be called on ECL_FLOAT_TYPE and ECL_DOUBLE_TYPE - aborting \n",__func__);
}
}
}
void ecl_kw_inplace_update_file(const ecl_kw_type * ecl_kw , const char * filename, int index) {
if (util_file_exists(filename)) {
bool fmt_file = util_fmt_bit8(filename);
{
fortio_type * fortio = fortio_open_readwrite(filename , fmt_file , ECL_ENDIAN_FLIP);
ecl_kw_ifseek_kw(ecl_kw_get_header8(ecl_kw) , fortio , index);
{
ecl_kw_type * file_kw = ecl_kw_alloc_empty();
long int current_pos = fortio_ftell( fortio );
ecl_kw_fread_header(file_kw , fortio);
fortio_fseek( fortio , current_pos , SEEK_SET );
if (!ecl_kw_size_and_type_equal(ecl_kw, file_kw))
util_abort("%s: header mismatch when trying to update:%s in %s \n",__func__ , ecl_kw_get_header8(ecl_kw) , filename);
ecl_kw_free(file_kw);
}
fortio_fflush(fortio);
ecl_kw_fwrite(ecl_kw , fortio);
fortio_fclose(fortio);
}
}
}
/******************************************************************/
bool ecl_kw_is_kw_file(fortio_type * fortio) {
const long int init_pos = fortio_ftell( fortio );
bool kw_file;
{
ecl_kw_type * ecl_kw = ecl_kw_alloc_empty();
if (fortio_fmt_file( fortio ))
kw_file = (ecl_kw_fread_header(ecl_kw , fortio) != ECL_KW_READ_FAIL);
else {
if (fortio_is_fortio_file(fortio))
kw_file = (ecl_kw_fread_header(ecl_kw , fortio) != ECL_KW_READ_FAIL);
else
kw_file = false;
}
ecl_kw_free(ecl_kw);
}
fortio_fseek(fortio , init_pos , SEEK_SET);
return kw_file;
}
#define KW_MAX_MIN(type) \
{ \
type * data = (type*)ecl_kw_get_data_ref(ecl_kw); \
type max = data[0]; \
type min = data[0]; \
int i; \
for (i=1; i < ecl_kw_get_size(ecl_kw); i++) \
util_update_ ## type ## _max_min(data[i] , &max , &min); \
memcpy(_max , &max , ecl_type_get_sizeof_ctype(ecl_kw->data_type)); \
memcpy(_min , &min , ecl_type_get_sizeof_ctype(ecl_kw->data_type)); \
}
void ecl_kw_max_min(const ecl_kw_type * ecl_kw , void * _max , void *_min) {
switch (ecl_kw_get_type(ecl_kw)) {
case(ECL_FLOAT_TYPE):
KW_MAX_MIN(float);
break;
case(ECL_DOUBLE_TYPE):
KW_MAX_MIN(double);
break;
case(ECL_INT_TYPE):
KW_MAX_MIN(int);
break;
default:
util_abort("%s: invalid type for element sum \n",__func__);
}
}
#define ECL_KW_MAX_MIN( ctype ) \
void ecl_kw_max_min_ ## ctype ( const ecl_kw_type * ecl_kw , ctype * _max , ctype * _min) { \
KW_MAX_MIN( ctype ); \
}
#define ECL_KW_MAX( ctype ) \
ctype ecl_kw_ ## ctype ## _max( const ecl_kw_type * ecl_kw ) { \
ctype max,min; \
ecl_kw_max_min_ ## ctype( ecl_kw , &max , &min); \
return max; \
}
#define ECL_KW_MIN( ctype ) \
ctype ecl_kw_ ## ctype ## _min( const ecl_kw_type * ecl_kw ) { \
ctype max,min; \
ecl_kw_max_min_ ## ctype( ecl_kw , &max , &min); \
return min; \
}
ECL_KW_MAX_MIN( int )
ECL_KW_MAX_MIN( float )
ECL_KW_MAX_MIN( double )
ECL_KW_MAX( int )
ECL_KW_MAX( float )
ECL_KW_MAX( double )
ECL_KW_MIN( int )
ECL_KW_MIN( float )
ECL_KW_MIN( double )
#undef ECL_KW_MAX
#undef ECL_KW_MIN
#undef KW_MAX_MIN
#undef ECL_KW_MAX_MIN
#define KW_SUM_INDEXED(type) \
{ \
const type * data = (const type *)ecl_kw_get_data_ref(ecl_kw); \
type sum = 0; \
int size = int_vector_size( index_list ); \
const int * index_ptr = int_vector_get_const_ptr( index_list ); \
for (int i = 0; i < size; i++) \
sum += data[index_ptr[i]]; \
memcpy(_sum , &sum , ecl_type_get_sizeof_ctype(ecl_kw->data_type)); \
}
void ecl_kw_element_sum_indexed(const ecl_kw_type * ecl_kw , const int_vector_type * index_list, void * _sum) {
switch (ecl_kw_get_type(ecl_kw)) {
case(ECL_FLOAT_TYPE):
KW_SUM_INDEXED(float);
break;
case(ECL_DOUBLE_TYPE):
KW_SUM_INDEXED(double);
break;
case(ECL_INT_TYPE):
KW_SUM_INDEXED(int);
break;
case(ECL_BOOL_TYPE):
{
const bool * data = (const bool *)ecl_kw_get_data_ref(ecl_kw);
const int * index_ptr = int_vector_get_const_ptr( index_list );
const int size = int_vector_size( index_list );
int sum = 0;
for (int i = 0; i < size; i++)
sum += (data[index_ptr[i]]);
memcpy(_sum , &sum , sizeof sum);
}
break;
default:
util_abort("%s: invalid type for element sum \n",__func__);
}
}
#undef KW_SUM
#define KW_SUM(type) \
{ \
const type * data = (const type *)ecl_kw_get_data_ref(ecl_kw); \
type sum = 0; \
for (int i=0; i < ecl_kw_get_size(ecl_kw); i++) \
sum += data[i]; \
memcpy(_sum , &sum , ecl_type_get_sizeof_ctype(ecl_kw->data_type)); \
}
void ecl_kw_element_sum(const ecl_kw_type * ecl_kw , void * _sum) {
switch (ecl_kw_get_type(ecl_kw)) {
case(ECL_FLOAT_TYPE):
KW_SUM(float);
break;
case(ECL_DOUBLE_TYPE):
KW_SUM(double);
break;
case(ECL_INT_TYPE):
KW_SUM(int);
break;
default:
util_abort("%s: invalid type for element sum \n",__func__);
}
}
#undef KW_SUM
double ecl_kw_element_sum_float( const ecl_kw_type * ecl_kw ) {
float float_sum;
double double_sum;
void * sum_ptr = NULL;
if (ecl_type_is_double(ecl_kw->data_type))
sum_ptr = &double_sum;
else if (ecl_type_is_float(ecl_kw->data_type))
sum_ptr = &float_sum;
else
util_abort("%s: invalid type: \n",__func__);
ecl_kw_element_sum( ecl_kw , sum_ptr );
if (ecl_type_is_double(ecl_kw->data_type))
return double_sum;
else if (ecl_type_is_float(ecl_kw->data_type))
return float_sum;
else
return 0;
}
int ecl_kw_element_sum_int( const ecl_kw_type * ecl_kw ) {
int int_sum;
ecl_kw_element_sum( ecl_kw , &int_sum);
return int_sum;
}
/*****************************************************************/
#define ECL_KW_FPRINTF_DATA(ctype) \
static void ecl_kw_fprintf_data_ ## ctype(const ecl_kw_type * ecl_kw , const char * fmt , FILE * stream) \
{ \
const ctype * data = (const ctype *) ecl_kw->data; \
int i; \
for (i=0; i < ecl_kw->size; i++) \
fprintf(stream , fmt , data[i]); \
}
ECL_KW_FPRINTF_DATA( int )
ECL_KW_FPRINTF_DATA( float )
ECL_KW_FPRINTF_DATA( double )
ECL_KW_FPRINTF_DATA( bool )
#undef ECL_KW_FPRINTF_DATA
static void ecl_kw_fprintf_data_string( const ecl_kw_type * ecl_kw , const char * fmt , FILE * stream) {
int i;
for (i=0; i < ecl_kw->size; i++)
fprintf(stream , fmt , &ecl_kw->data[ i * ecl_type_get_sizeof_ctype(ecl_kw->data_type)]);
}
void ecl_kw_fprintf_data( const ecl_kw_type * ecl_kw , const char * fmt , FILE * stream) {
if (ecl_type_is_double(ecl_kw->data_type))
ecl_kw_fprintf_data_double( ecl_kw , fmt , stream );
else if (ecl_type_is_float(ecl_kw->data_type))
ecl_kw_fprintf_data_float( ecl_kw , fmt , stream );
else if (ecl_type_is_int(ecl_kw->data_type))
ecl_kw_fprintf_data_int( ecl_kw , fmt , stream );
else if (ecl_type_is_bool(ecl_kw->data_type))
ecl_kw_fprintf_data_bool( ecl_kw , fmt , stream );
else if (ecl_type_is_char(ecl_kw->data_type) || ecl_type_is_string(ecl_kw->data_type))
ecl_kw_fprintf_data_string( ecl_kw , fmt , stream );
}
static bool ecl_kw_elm_equal_numeric__( const ecl_kw_type * ecl_kw1 , const ecl_kw_type * ecl_kw2 , int offset, double abs_epsilon, double rel_epsilon) {
double v1 = ecl_kw_iget_as_double( ecl_kw1 , offset );
double v2 = ecl_kw_iget_as_double( ecl_kw2 , offset );
return util_double_approx_equal__( v1, v2 , rel_epsilon , abs_epsilon );
}
static bool ecl_kw_elm_equal__( const ecl_kw_type * ecl_kw1 , const ecl_kw_type * ecl_kw2 , int offset) {
size_t data_offset = ecl_type_get_sizeof_ctype(ecl_kw1->data_type) * offset;
int cmp = memcmp( &ecl_kw1->data[ data_offset ] , &ecl_kw2->data[ data_offset ] , ecl_type_get_sizeof_ctype(ecl_kw1->data_type));
if (cmp == 0)
return true;
else
return false;
}
int ecl_kw_first_different( const ecl_kw_type * ecl_kw1 , const ecl_kw_type * ecl_kw2 , int offset, double abs_epsilon, double rel_epsilon) {
if (!ecl_kw_size_and_type_equal( ecl_kw1 , ecl_kw2))
util_abort("%s: sorry invalid comparison\n",__func__);
if (offset >= ecl_kw_get_size( ecl_kw1 ))
util_abort("%s: sorry - invalid offset value\n",__func__);
{
bool numeric_compare = false;
if (((abs_epsilon > 0) || (rel_epsilon > 0)) && ((ecl_kw_get_type( ecl_kw1 ) == ECL_FLOAT_TYPE) || (ecl_kw_get_type( ecl_kw1 ) == ECL_DOUBLE_TYPE)))
numeric_compare = true;
{
int index = offset;
while (true) {
bool equal = (numeric_compare) ? ecl_kw_elm_equal_numeric__( ecl_kw1 , ecl_kw2, index , abs_epsilon, rel_epsilon) : ecl_kw_elm_equal__( ecl_kw1 , ecl_kw2 , index );
if (!equal)
break;
index++;
if (index == ecl_kw_get_size( ecl_kw1 ))
break;
}
return index;
}
}
}
#include "ecl_kw_functions.cpp"