mirror of
https://github.com/OPM/ResInsight.git
synced 2025-02-25 18:55:39 -06:00
2943 lines
104 KiB
C++
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"
|