Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
53 changes: 53 additions & 0 deletions Test/FMI3/fmi3_import_variable_types_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
#include <stdint.h>
#include <limits.h>
#include <float.h>
#include <cmath>

#include "fmilib.h"
#include "config_test.h"
Expand Down Expand Up @@ -129,3 +130,55 @@ TEST_CASE("Varibles types testing") {
REQUIRE(fmi3_testutil_get_num_problems(tfmu) == 0);
fmi3_testutil_import_free(tfmu);
}

/* Parse INF start values */
static void test_inf_float64_positive(fmi3_import_t* xml) {
fmi3_import_variable_t* v = fmi3_import_get_variable_by_name(xml, "var1");
REQUIRE(v != nullptr);
fmi3_import_float64_variable_t* var = fmi3_import_get_variable_as_float64(v);
REQUIRE(var != nullptr);
REQUIRE(std::isinf(fmi3_import_get_float64_variable_start(var)));
REQUIRE(fmi3_import_get_float64_variable_start(var) > 0);
}

static void test_inf_float64_negative(fmi3_import_t* xml) {
fmi3_import_variable_t* v = fmi3_import_get_variable_by_name(xml, "var2");
REQUIRE(v != nullptr);
fmi3_import_float64_variable_t* var = fmi3_import_get_variable_as_float64(v);
REQUIRE(var != nullptr);
REQUIRE(std::isinf(fmi3_import_get_float64_variable_start(var)));
REQUIRE(fmi3_import_get_float64_variable_start(var) < 0);
}

static void test_inf_float32_positive(fmi3_import_t* xml) {
fmi3_import_variable_t* v = fmi3_import_get_variable_by_name(xml, "var3");
REQUIRE(v != nullptr);
fmi3_import_float32_variable_t* var = fmi3_import_get_variable_as_float32(v);
REQUIRE(var != nullptr);
REQUIRE(std::isinf(fmi3_import_get_float32_variable_start(var)));
REQUIRE(fmi3_import_get_float32_variable_start(var) > 0);
}

static void test_inf_float32_negative(fmi3_import_t* xml) {
fmi3_import_variable_t* v = fmi3_import_get_variable_by_name(xml, "var4");
REQUIRE(v != nullptr);
fmi3_import_float32_variable_t* var = fmi3_import_get_variable_as_float32(v);
REQUIRE(var != nullptr);
REQUIRE(std::isinf(fmi3_import_get_float32_variable_start(var)));
REQUIRE(fmi3_import_get_float32_variable_start(var) < 0);
}

TEST_CASE("INF start values") {
const char* xmldir = FMI3_TEST_XML_DIR "/variable_types/inf_start";
fmi3_testutil_import_t* tfmu = fmi3_testutil_parse_xml_with_log(xmldir);
fmi3_import_t* fmu = tfmu->fmu;
REQUIRE(fmu != nullptr);

test_inf_float64_positive(fmu);
test_inf_float64_negative(fmu);
test_inf_float32_positive(fmu);
test_inf_float32_negative(fmu);

REQUIRE(fmi3_testutil_get_num_problems(tfmu) == 0);
fmi3_testutil_import_free(tfmu);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<?xml version="1.0" encoding="UTF-8"?>
<fmiModelDescription fmiVersion="3.0" modelName="" instantiationToken="">
<CoSimulation modelIdentifier="id"/>

<ModelVariables>
<Float64 name="var1" valueReference="1" start="INF" initial="exact"/>
<Float64 name="var2" valueReference="2" start="-INF" initial="exact"/>
<Float32 name="var3" valueReference="3" start="INF" initial="exact"/>
<Float32 name="var4" valueReference="4" start="-INF" initial="exact"/>
</ModelVariables>

<ModelStructure/>
</fmiModelDescription>
19 changes: 19 additions & 0 deletions src/XML/src/FMI3/fmi3_xml_parser.c
Original file line number Diff line number Diff line change
Expand Up @@ -623,6 +623,12 @@ static int fmi3_xml_str_to_floatXX(fmi3_xml_parser_context_t* context, int requi
void* value = NULL; /* points to the buffer that holds the value: default or read */
int status = 0; /* status flag for value boundary check */

/* detect INF values - allow them to skip the boundary check */
int isInf = 0;
if (strVal) {
isInf = (strcmp(strVal, "INF") == 0 || strcmp(strVal, "+INF") == 0 || strcmp(strVal, "-INF") == 0);
}

/* get the value */
if (!strVal && !required) {
value = defaultVal;
Expand All @@ -634,6 +640,19 @@ static int fmi3_xml_str_to_floatXX(fmi3_xml_parser_context_t* context, int requi
value = &valReadBuff;
}

if (isInf) {
/* INF values are valid per FMI spec; assign directly without boundary check */
switch(primType->bitness) {
case fmi3_bitness_64:
*(fmi3_float64_t*)field = (fmi3_float64_t)valReadBuff; break;
case fmi3_bitness_32:
*(fmi3_float32_t*)field = (fmi3_float32_t)valReadBuff; break;
default:
assert(0); /* impl. error */
}
return 0;
}

/* downcast */
switch(primType->bitness) {
case fmi3_bitness_64:
Expand Down
Loading