commit 07105c9726f8146f972f6435bc67e1d1ac27cd0f
parent c58e6d34fb67f63bb4ed510e3bcd10688a4a6273
Author: Christophe Coustet <christophe.coustet@meso-star.com>
Date: Thu, 13 Feb 2020 15:16:05 +0100
Get rid of expressions in initial/boundary conditions
Diffstat:
15 files changed, 246 insertions(+), 1756 deletions(-)
diff --git a/cmake/CMakeLists.txt b/cmake/CMakeLists.txt
@@ -28,16 +28,12 @@ find_package(StarEnc3D 0.3.1 REQUIRED)
find_package(Stardis 0.7.1 REQUIRED)
find_package(StarSTL 0.3 REQUIRED)
-set(TINYEXPR_SOURCE_DIR "${PROJECT_SOURCE_DIR}/../tinyexpr"
- CACHE PATH "Directory for TinyExpr source files")
-
include_directories(
${RSys_INCLUDE_DIR}
${StarGeom3D_INCLUDE_DIR}
${StarEnc3D_INCLUDE_DIR}
${Stardis_INCLUDE_DIR}
- ${StarSTL_INCLUDE_DIR}
- ${TINYEXPR_SOURCE_DIR})
+ ${StarSTL_INCLUDE_DIR})
if(MSVC)
find_package(MuslGetopt REQUIRED)
include_directories(${MuslGetopt_INCLUDE_DIR})
@@ -83,25 +79,6 @@ rcmake_prepend_path(SDIS_FILES_SRC ${SDIS_SOURCE_DIR})
rcmake_prepend_path(SDIS_FILES_INC ${SDIS_SOURCE_DIR})
rcmake_prepend_path(SDIS_FILES_DOC ${PROJECT_SOURCE_DIR}/../)
-# Default is right to left pow and log is natural log
-# Build tinyExpr without closure support and with function_1 to function_3
-# support only (these ones cannot be disabled as predefined functions require
-# them).
-set(TE_DEFAULTS
- "-DTE_POW_FROM_RIGHT -DTE_NAT_LOG -DTE_WITHOUT_CLOSURES \
- -DTE_WITHOUT_FUNCTION_0 -DTE_MAX_FUNCTION_ARITY=3")
-
-ADD_LIBRARY(tinyexpr STATIC
- ${TINYEXPR_SOURCE_DIR}/tinyexpr.c ${TINYEXPR_SOURCE_DIR}/tinyexpr.h)
-
-if(CMAKE_COMPILER_IS_GNUCC)
- set_target_properties(tinyexpr PROPERTIES
- COMPILE_FLAGS "-std=c99 ${TE_DEFAULTS}")
-elseif(MSVC)
- set_target_properties(tinyexpr PROPERTIES
- COMPILE_FLAGS ${TE_DEFAULTS})
-endif()
-
add_executable(sdis-app
${SDIS_FILES_SRC}
${SDIS_FILES_INC})
@@ -111,13 +88,13 @@ if(CMAKE_COMPILER_IS_GNUCC)
COMPILE_FLAGS "-std=c99 ${TE_DEFAULTS}"
VERSION ${VERSION})
target_link_libraries(sdis-app
- Stardis StarGeom3D StarEnc3D StarSTL RSys tinyexpr m)
+ Stardis StarGeom3D StarEnc3D StarSTL RSys m)
elseif(MSVC)
set_target_properties(sdis-app PROPERTIES
COMPILE_FLAGS "${TE_DEFAULTS}"
VERSION ${VERSION})
target_link_libraries(sdis-app
- Stardis StarGeom3D StarEnc3D StarSTL RSys tinyexpr MuslGetopt)
+ Stardis StarGeom3D StarEnc3D StarSTL RSys MuslGetopt)
endif()
rcmake_copy_runtime_libraries(sdis-app)
diff --git a/src/stardis-app.c b/src/stardis-app.c
@@ -11,8 +11,6 @@
#define HTABLE_KEY_FUNCTOR_HASH hash_description
#define HTABLE_KEY_FUNCTOR_INIT init_description
#define HTABLE_KEY_FUNCTOR_COPY cp_description
-#define HTABLE_KEY_FUNCTOR_RELEASE release_description
-#define HTABLE_KEY_FUNCTOR_COPY_AND_RELEASE cp_release_description
#include <rsys/hash_table.h>
#include <string.h>
@@ -498,8 +496,6 @@ stardis_release(struct stardis* stardis)
}
sa_release(stardis->geometry.interf_bytrg);
stardis->geometry.interf_bytrg = NULL;
- for (i=0; i<sa_size(stardis->descriptions); ++i)
- release_description(stardis->descriptions + i);
sa_release(stardis->descriptions);
release_geometry(&stardis->geometry);
sa_release(stardis->boundary.primitives);
diff --git a/src/stardis-app.h b/src/stardis-app.h
@@ -11,7 +11,6 @@
#include <rsys/stretchy_array.h>
#include <rsys/hash_table.h>
#include <sdis.h>
-#include <tinyexpr.h>
#include <limits.h>
@@ -116,10 +115,10 @@ struct mat_fluid {
unsigned fluid_id;
double rho;
double cp;
- char* Tinit;
- char* Temp;
+ double tinit;
+ double imposed_temperature;
};
-#define NULL_FLUID__ { "", UINT_MAX, 0, 0, NULL, NULL }
+#define NULL_FLUID__ { "", UINT_MAX, 0, 0, -1, -1 }
static const struct mat_fluid NULL_FLUID = NULL_FLUID__;
static void
@@ -128,20 +127,19 @@ print_fluid(FILE* stream, const struct mat_fluid* f)
ASSERT(stream && f);
fprintf(stream, "Fluid '%s': cp=%g rho=%g",
f->name, f->cp, f->rho);
- if (f->Tinit) fprintf(stream, " Tinit='%s'", f->Tinit);
- if (f->Temp) fprintf(stream, " Temp='%s'", f->Temp);
+ if (f->tinit >= 0) fprintf(stream, " Tinit=%f", f->tinit);
+ if (f->imposed_temperature >= 0) fprintf(stream, " Temp=%f", f->imposed_temperature);
fprintf(stream, "\n");
-}
+}static char
-static char
eq_fluid(const struct mat_fluid* a, const struct mat_fluid* b)
{
if (strcmp(a->name, b->name)
|| a->fluid_id != b->fluid_id
|| a->rho != b->rho
|| a->cp != b->cp
- || strcmp(a->Tinit, b->Tinit)
- || strcmp(a->Temp, b->Temp))
+ || a->tinit != b->tinit
+ || a->imposed_temperature != b->imposed_temperature)
return 0;
return 1;
}
@@ -153,38 +151,8 @@ cp_fluid(struct mat_fluid* dst, const struct mat_fluid* src)
dst->fluid_id = src->fluid_id;
dst->rho = src->rho;
dst->cp = src->cp;
- if (!src->Tinit) dst->Tinit = NULL;
- else {
- dst->Tinit = malloc(sizeof(src->Tinit) + 1);
- if (!dst->Tinit) return RES_MEM_ERR;
- strcpy(dst->Tinit, src->Tinit);
- }
- if (!src->Temp) dst->Temp = NULL;
- else {
- dst->Temp = malloc(sizeof(src->Temp) + 1);
- if (!dst->Temp) return RES_MEM_ERR;
- strcpy(dst->Temp, src->Temp);
- }
- return RES_OK;
-}
-
-static FINLINE res_T
-cp_release_fluid(struct mat_fluid* dst, struct mat_fluid* src)
-{
- strcpy(dst->name, src->name);
- dst->fluid_id = src->fluid_id;
- dst->rho = src->rho;
- dst->cp = src->cp;
- dst->Tinit = src->Tinit; src->Tinit = NULL;
- dst->Temp = src->Temp; src->Temp = NULL;
- return RES_OK;
-}
-
-static FINLINE res_T
-release_fluid(struct mat_fluid* a)
-{
- free(a->Tinit);
- free(a->Temp);
+ dst->tinit = src->tinit;
+ dst->imposed_temperature = src->imposed_temperature;
return RES_OK;
}
@@ -193,8 +161,8 @@ hash_fluid(const struct mat_fluid* key)
{
/* 64-bits Fowler/Noll/Vo hash function */
const uint64_t FNV64_PRIME =
- (uint64_t) (((uint64_t) 1 << 40) + ((uint64_t) 1 << 8) + 0xB3);
- const uint64_t OFFSET64_BASIS = (uint64_t) 14695981039346656037u;
+ (uint64_t)(((uint64_t)1 << 40) + ((uint64_t)1 << 8) + 0xB3);
+ const uint64_t OFFSET64_BASIS = (uint64_t)14695981039346656037u;
uint64_t hash = OFFSET64_BASIS;
size_t i;
ASSERT(key);
@@ -207,23 +175,23 @@ hash_fluid(const struct mat_fluid* key)
hash = hash * FNV64_PRIME;
}
FOR_EACH(i, 0, sizeof(key->rho)) {
- hash = hash ^ (uint64_t) ((unsigned char)((const char*)&key->rho)[i]);
+ hash = hash ^ (uint64_t)((unsigned char)((const char*)&key->rho)[i]);
hash = hash * FNV64_PRIME;
}
FOR_EACH(i, 0, sizeof(key->cp)) {
hash = hash ^ (uint64_t)((unsigned char)((const char*)&key->cp)[i]);
hash = hash * FNV64_PRIME;
}
- hash = hash ^ (uint64_t)((unsigned char)(key->Tinit == 0));
+ hash = hash ^ (uint64_t)((unsigned char)(key->tinit == 0));
hash = hash * FNV64_PRIME;
- FOR_EACH(i, 0, key->Tinit ? strlen(key->Tinit)*sizeof(*key->Tinit) : 0) {
- hash = hash ^ (uint64_t)((unsigned char) ((const char*)key->Tinit)[i]);
+ FOR_EACH(i, 0, sizeof(key->tinit)) {
+ hash = hash ^ (uint64_t)((unsigned char)((const char*)&key->tinit)[i]);
hash = hash * FNV64_PRIME;
}
- hash = hash ^ (uint64_t)((unsigned char)(key->Temp == 0));
+ hash = hash ^ (uint64_t)((unsigned char)(key->imposed_temperature == 0));
hash = hash * FNV64_PRIME;
- FOR_EACH(i, 0, key->Temp ? strlen(key->Temp) * sizeof(*key->Temp) : 0) {
- hash = hash ^ (uint64_t)((unsigned char)((const char*)key->Temp)[i]);
+ FOR_EACH(i, 0, sizeof(key->imposed_temperature)) {
+ hash = hash ^ (uint64_t)((unsigned char)((const char*)&key->imposed_temperature)[i]);
hash = hash * FNV64_PRIME;
}
return hash;
@@ -236,12 +204,11 @@ struct mat_solid {
double rho;
double cp;
double delta;
- char* Tinit;
- char* Temp;
- char* power;
- int has_power;
+ double tinit;
+ double imposed_temperature;
+ double vpower;
};
-#define NULL_SOLID__ { "", UINT_MAX, 0, 0, 0, 0, NULL, NULL, NULL, 0}
+#define NULL_SOLID__ { "", UINT_MAX, 0, 0, 0, 0, -1, -1, 0 }
static const struct mat_solid NULL_SOLID = NULL_SOLID__;
static void
@@ -249,11 +216,11 @@ print_solid(FILE* stream, const struct mat_solid* s)
{
ASSERT(stream && s);
fprintf(stream,
- "Solid '%s': lambda=%g cp=%g rho=%g delta=%g Power='%s'",
- s->name, s->lambda, s->cp, s->rho, s->delta,
- (s->has_power ? s->power : "0"));
- if (s->Tinit) fprintf(stream, " Tinit='%s'", s->Tinit);
- if (s->Temp) fprintf(stream, " Temp='%s'", s->Temp);
+ "Solid '%s': lambda=%g cp=%g rho=%g delta=%g Power=%f",
+ s->name, s->lambda, s->cp, s->rho, s->delta, s->vpower);
+ if (s->tinit >= 0) fprintf(stream, " Tinit=%f", s->tinit);
+ if (s->imposed_temperature >= 0)
+ fprintf(stream, " Temp=%f", s->imposed_temperature);
fprintf(stream, "\n");
}
@@ -266,11 +233,9 @@ eq_solid(const struct mat_solid* a, const struct mat_solid* b)
|| a->rho != b->rho
|| a->cp != b->cp
|| a->delta != b->delta
- || strcmp(a->Tinit, b->Tinit)
- || strcmp(a->Temp, b->Temp)
- || a->has_power != b->has_power)
+ || a->tinit != b->tinit
+ || a->imposed_temperature != b->imposed_temperature)
return 0;
- if (a->has_power && a->power != b->power) return 0;
return 1;
}
@@ -283,50 +248,8 @@ cp_solid(struct mat_solid* dst, const struct mat_solid* src)
dst->rho = src->rho;
dst->cp = src->cp;
dst->delta = src->delta;
- if (!src->Tinit) dst->Tinit = NULL;
- else {
- dst->Tinit = malloc(sizeof(src->Tinit) + 1);
- if (!dst->Tinit) return RES_MEM_ERR;
- strcpy(dst->Tinit, src->Tinit);
- }
- if (!src->Temp) dst->Temp = NULL;
- else {
- dst->Temp = malloc(sizeof(src->Temp) + 1);
- if (!dst->Temp) return RES_MEM_ERR;
- strcpy(dst->Temp, src->Temp);
- }
- dst->has_power = src->has_power;
- if (!src->power) dst->power = NULL;
- else {
- dst->power = malloc(sizeof(src->power) + 1);
- if (!dst->power) return RES_MEM_ERR;
- strcpy(dst->power, src->power);
- }
- return RES_OK;
-}
-
-static FINLINE res_T
-cp_release_solid(struct mat_solid* dst, struct mat_solid* src)
-{
- strcpy(dst->name, src->name);
- dst->solid_id = src->solid_id;
- dst->lambda = src->lambda;
- dst->rho = src->rho;
- dst->cp = src->cp;
- dst->delta = src->delta;
- dst->Tinit = src->Tinit; src->Tinit = NULL;
- dst->Temp = src->Temp; src->Temp = NULL;
- dst->has_power = src->has_power;
- dst->power = src->power; src->power = NULL;
- return RES_OK;
-}
-
-static FINLINE res_T
-release_solid(struct mat_solid* a)
-{
- free(a->power);
- free(a->Tinit);
- free(a->Temp);
+ dst->tinit = src->tinit;
+ dst->imposed_temperature = src->imposed_temperature;
return RES_OK;
}
@@ -335,8 +258,8 @@ hash_solid(const struct mat_solid* key)
{
/* 64-bits Fowler/Noll/Vo hash function */
const uint64_t FNV64_PRIME =
- (uint64_t) (((uint64_t) 1 << 40) + ((uint64_t) 1 << 8) + 0xB3);
- const uint64_t OFFSET64_BASIS = (uint64_t) 14695981039346656037u;
+ (uint64_t)(((uint64_t)1 << 40) + ((uint64_t)1 << 8) + 0xB3);
+ const uint64_t OFFSET64_BASIS = (uint64_t)14695981039346656037u;
uint64_t hash = OFFSET64_BASIS;
size_t i;
ASSERT(key);
@@ -364,25 +287,21 @@ hash_solid(const struct mat_solid* key)
hash = hash ^ (uint64_t)((unsigned char)((const char*)&key->delta)[i]);
hash = hash * FNV64_PRIME;
}
- hash = hash ^ (uint64_t)((unsigned char)(key->Tinit == 0));
+ hash = hash ^ (uint64_t)((unsigned char)(key->tinit == 0));
hash = hash * FNV64_PRIME;
- FOR_EACH(i, 0, key->Tinit ? strlen(key->Tinit) * sizeof(*key->Tinit) : 0) {
- hash = hash ^ (uint64_t)((unsigned char)((const char*)key->Tinit)[i]);
+ FOR_EACH(i, 0,sizeof(key->tinit)) {
+ hash = hash ^ (uint64_t)((unsigned char)((const char*)&key->tinit)[i]);
hash = hash * FNV64_PRIME;
}
- hash = hash ^ (uint64_t)((unsigned char)(key->Temp == 0));
+ hash = hash ^ (uint64_t)((unsigned char)(key->imposed_temperature == 0));
hash = hash * FNV64_PRIME;
- FOR_EACH(i, 0, key->Temp ? strlen(key->Temp) * sizeof(*key->Temp) : 0) {
- hash = hash ^ (uint64_t)((unsigned char)((const char*)key->Temp)[i]);
- hash = hash * FNV64_PRIME;
- }
- FOR_EACH(i, 0, sizeof(key->has_power)) {
- hash = hash ^ (uint64_t) ((unsigned char) ((const char*) &key->has_power)[i]);
+ FOR_EACH(i, 0, sizeof(key->imposed_temperature)) {
+ hash = hash ^ (uint64_t)((unsigned char)
+ ((const char*)&key->imposed_temperature)[i]);
hash = hash * FNV64_PRIME;
}
- if (!key->has_power) return hash;
- FOR_EACH(i, 0, strlen(key->power) * sizeof(*key->power)) {
- hash = hash ^ (uint64_t)((unsigned char)((const char*)key->power)[i]);
+ FOR_EACH(i, 0, sizeof(key->vpower)) {
+ hash = hash ^ (uint64_t)((unsigned char)((const char*)&key->vpower)[i]);
hash = hash * FNV64_PRIME;
}
return hash;
@@ -395,10 +314,10 @@ struct h_boundary {
double specular_fraction;
double hc;
double hc_max;
- char* T;
+ double imposed_temperature;
int has_emissivity, has_hc;
};
-#define NULL_HBOUND__ { "", UINT_MAX, 0, 0, 0, 0, NULL, 0, 0}
+#define NULL_HBOUND__ { "", UINT_MAX, 0, 0, 0, -1, 0, 0 }
static const struct h_boundary NULL_HBOUND = NULL_HBOUND__;
static void
@@ -410,25 +329,23 @@ print_h_boundary
ASSERT(stream && b
&& (type == DESC_BOUND_H_FOR_SOLID || type == DESC_BOUND_H_FOR_FLUID));
fprintf(stream,
- "H boundary %s for %s: emissivity=%g specular_fraction=%g hc=%g hc_max=%g T='%s'\n",
+ "H boundary %s for %s: emissivity=%g specular_fraction=%g hc=%g hc_max=%g T=%f\n",
b->name,
(type == DESC_BOUND_H_FOR_SOLID ? "solid" : "fluid"),
(b->has_emissivity ? b->emissivity : 0),
(b->has_emissivity ? b->specular_fraction : 0),
(b->has_hc ? b->hc : 0),
(b->has_hc ? b->hc_max : 0),
- (b->T ? b->T : "0"));
+ b->imposed_temperature);
}
static char
-eq_h_boundary
- (const struct h_boundary* a,
- const struct h_boundary* b)
+eq_h_boundary(const struct h_boundary* a, const struct h_boundary* b)
{
if (a->mat_id != b->mat_id
|| strcmp(a->name, b->name)
|| a->specular_fraction != b->specular_fraction
- || strcmp(a->T, b->T)
+ || a->imposed_temperature != b->imposed_temperature
|| a->has_emissivity != b->has_emissivity
|| a->has_hc != b->has_hc)
return 0;
@@ -443,12 +360,7 @@ cp_h_boundary(struct h_boundary* dst, const struct h_boundary* src)
strcpy(dst->name, src->name);
dst->mat_id = src->mat_id;
dst->specular_fraction = src->specular_fraction;
- if (!src->T) dst->T = NULL;
- else {
- dst->T = malloc(sizeof(src->T) + 1);
- if (!dst->T) return RES_MEM_ERR;
- strcpy(dst->T, src->T);
- }
+ dst->imposed_temperature = src->imposed_temperature;
dst->has_emissivity = src->has_emissivity;
dst->has_hc = src->has_hc;
dst->emissivity = src->emissivity;
@@ -457,35 +369,13 @@ cp_h_boundary(struct h_boundary* dst, const struct h_boundary* src)
return RES_OK;
}
-static FINLINE res_T
-cp_release_h_boundary(struct h_boundary* dst, struct h_boundary* src)
-{
- strcpy(dst->name, src->name);
- dst->mat_id = src->mat_id;
- dst->specular_fraction = src->specular_fraction;
- dst->T = src->T; src->T = NULL;
- dst->has_emissivity = src->has_emissivity;
- dst->has_hc = src->has_hc;
- dst->emissivity = src->emissivity;
- dst->hc_max = src->hc_max;
- dst->hc = src->hc;
- return RES_OK;
-}
-
-static FINLINE res_T
-release_h_boundary(struct h_boundary* a)
-{
- free(a->T);
- return RES_OK;
-}
-
static size_t
hash_h_boundary(const struct h_boundary* key)
{
/* 64-bits Fowler/Noll/Vo hash function */
const uint64_t FNV64_PRIME =
- (uint64_t) (((uint64_t) 1 << 40) + ((uint64_t) 1 << 8) + 0xB3);
- const uint64_t OFFSET64_BASIS = (uint64_t) 14695981039346656037u;
+ (uint64_t)(((uint64_t)1 << 40) + ((uint64_t)1 << 8) + 0xB3);
+ const uint64_t OFFSET64_BASIS = (uint64_t)14695981039346656037u;
uint64_t hash = OFFSET64_BASIS;
size_t i;
ASSERT(key);
@@ -502,11 +392,13 @@ hash_h_boundary(const struct h_boundary* key)
hash = hash * FNV64_PRIME;
}
FOR_EACH(i, 0, sizeof(key->specular_fraction)) {
- hash = hash ^ (uint32_t)((unsigned char)((const char*)&key->specular_fraction)[i]);
+ hash = hash ^ (uint32_t)((unsigned char)
+ ((const char*)&key->specular_fraction)[i]);
hash = hash * FNV64_PRIME;
}
- FOR_EACH(i, 0, strlen(key->T) * sizeof(*key->T)) {
- hash = hash ^ (uint32_t)((unsigned char)((const char*)key->T)[i]);
+ FOR_EACH(i, 0, sizeof(key->imposed_temperature)) {
+ hash = hash ^ (uint32_t)((unsigned char)
+ ((const char*)&key->imposed_temperature)[i]);
hash = hash * FNV64_PRIME;
}
FOR_EACH(i, 0, sizeof(key->has_emissivity)) {
@@ -514,16 +406,16 @@ hash_h_boundary(const struct h_boundary* key)
hash = hash * FNV64_PRIME;
}
FOR_EACH(i, 0, sizeof(key->has_hc)) {
- hash = hash ^ (uint32_t) ((unsigned char) ((const char*) &key->has_hc)[i]);
+ hash = hash ^ (uint32_t)((unsigned char)((const char*)&key->has_hc)[i]);
hash = hash * FNV64_PRIME;
}
if (!key->has_hc) return hash;
FOR_EACH(i, 0, sizeof(key->hc)) {
- hash = hash ^ (uint32_t) ((unsigned char) ((const char*) &key->hc)[i]);
+ hash = hash ^ (uint32_t)((unsigned char)((const char*)&key->hc)[i]);
hash = hash * FNV64_PRIME;
}
FOR_EACH(i, 0, sizeof(key->hc_max)) {
- hash = hash ^ (uint32_t) ((unsigned char) ((const char*) &key->hc_max)[i]);
+ hash = hash ^ (uint32_t)((unsigned char)((const char*)&key->hc_max)[i]);
hash = hash * FNV64_PRIME;
}
return hash;
@@ -532,13 +424,12 @@ hash_h_boundary(const struct h_boundary* key)
struct t_boundary {
char name[32];
unsigned mat_id;
- char* T;
- struct te_expr* te_temperature;
+ double imposed_temperature;
double hc;
double hc_max;
int has_hc;
};
-#define NULL_TBOUND__ { "", UINT_MAX, NULL, NULL, 0, 0, 0}
+#define NULL_TBOUND__ { "", UINT_MAX, -1, 0, 0, 0 }
static const struct t_boundary NULL_TBOUND = NULL_TBOUND__;
static void
@@ -550,12 +441,12 @@ print_t_boundary
ASSERT(stream && b
&& (type == DESC_BOUND_T_FOR_SOLID || type == DESC_BOUND_T_FOR_FLUID));
fprintf(stream,
- "T boundary %s for %s: hc=%g hc_max=%g T='%s'\n",
+ "T boundary %s for %s: hc=%g hc_max=%g T=%f\n",
b->name,
(type == DESC_BOUND_T_FOR_SOLID ? "solid" : "fluid"),
(b->has_hc ? b->hc : 0),
(b->has_hc ? b->hc_max : 0),
- (b->T ? b->T : "0"));
+ b->imposed_temperature);
}
static char
@@ -568,7 +459,7 @@ eq_t_boundary
/* These fields are meaningful by both types */
if (strcmp(a->name, b->name))
return 0;
- if (a->mat_id != b->mat_id || strcmp(a->T, b->T))
+ if (a->mat_id != b->mat_id || a->imposed_temperature != b->imposed_temperature)
return 0;
if (type != DESC_BOUND_T_FOR_FLUID)
return 1;
@@ -585,55 +476,24 @@ cp_t_boundary(struct t_boundary* dst, const struct t_boundary* src)
{
strcpy(dst->name, src->name);
dst->mat_id = src->mat_id;
- if (!src->T) dst->T = NULL;
- else {
- dst->T = malloc(sizeof(src->T) + 1);
- if (!dst->T) return RES_MEM_ERR;
- strcpy(dst->T, src->T);
- }
- dst->has_hc = src->has_hc;
- dst->hc_max = src->hc_max;
- dst->hc = src->hc;
- if (!src->te_temperature) dst->te_temperature = NULL;
- else {
- dst->te_temperature = te_duplicate(src->te_temperature);
- if (!dst->te_temperature) return RES_MEM_ERR;
- }
- return RES_OK;
-}
-
-static FINLINE res_T
-cp_release_t_boundary(struct t_boundary* dst, struct t_boundary* src)
-{
- strcpy(dst->name, src->name);
- dst->mat_id = src->mat_id;
- dst->T = src->T; src->T = NULL;
+ dst->imposed_temperature = src->imposed_temperature;
dst->has_hc = src->has_hc;
dst->hc_max = src->hc_max;
dst->hc = src->hc;
- dst->te_temperature = src->te_temperature; src->te_temperature = NULL;
- return RES_OK;
-}
-
-static FINLINE res_T
-release_t_boundary(struct t_boundary* a)
-{
- free(a->T);
- te_free(a->te_temperature);
return RES_OK;
}
static size_t
hash_t_boundary
- (const struct t_boundary* key,
- const enum description_type type)
+(const struct t_boundary* key,
+ const enum description_type type)
{
(void)type;
ASSERT(type == DESC_BOUND_T_FOR_SOLID || type == DESC_BOUND_T_FOR_FLUID);
/* 64-bits Fowler/Noll/Vo hash function */
const uint64_t FNV64_PRIME =
- (uint64_t) (((uint64_t) 1 << 40) + ((uint64_t) 1 << 8) + 0xB3);
- const uint64_t OFFSET64_BASIS = (uint64_t) 14695981039346656037u;
+ (uint64_t)(((uint64_t)1 << 40) + ((uint64_t)1 << 8) + 0xB3);
+ const uint64_t OFFSET64_BASIS = (uint64_t)14695981039346656037u;
uint64_t hash = OFFSET64_BASIS;
size_t i;
ASSERT(key);
@@ -646,11 +506,12 @@ hash_t_boundary
hash = hash * FNV64_PRIME;
}
FOR_EACH(i, 0, sizeof(key->has_hc)) {
- hash = hash ^ (uint32_t) ((unsigned char) ((const char*) &key->has_hc)[i]);
+ hash = hash ^ (uint32_t)((unsigned char)((const char*)&key->has_hc)[i]);
hash = hash * FNV64_PRIME;
}
- FOR_EACH(i, 0, strlen(key->T) * sizeof(*key->T)) {
- hash = hash ^ (uint32_t) ((unsigned char) ((const char*) key->T)[i]);
+ FOR_EACH(i, 0, sizeof(key->imposed_temperature)) {
+ hash = hash ^ (uint32_t)((unsigned char)
+ ((const char*)&key->imposed_temperature)[i]);
hash = hash * FNV64_PRIME;
}
if (!key->has_hc) return hash;
@@ -668,23 +529,21 @@ hash_t_boundary
struct f_boundary {
char name[32];
unsigned mat_id;
- char* flux;
- struct te_expr* te_flux;
+ double imposed_flux;
};
-#define NULL_FBOUND__ { "", UINT_MAX, NULL, NULL}
+#define NULL_FBOUND__ { "", UINT_MAX, SDIS_FLUX_NONE }
static const struct f_boundary NULL_FBOUND = NULL_FBOUND__;
static void
print_f_boundary
(FILE* stream,
- const struct f_boundary* b,
- const enum description_type type)
+ const struct f_boundary* b)
{
- ASSERT(stream && b && type == DESC_BOUND_F_FOR_SOLID); (void)type;
+ ASSERT(stream && b);
fprintf(stream,
- "F boundary %s for SOLID: flux='%s'\n",
+ "F boundary %s for SOLID: flux=%f\n",
b->name,
- (b->flux ? b->flux : "0"));
+ b->imposed_flux);
}
static char
@@ -692,7 +551,7 @@ eq_f_boundary(const struct f_boundary* a, const struct f_boundary* b)
{
return (a->mat_id == b->mat_id
&& 0 == strcmp(a->name, b->name)
- && 0 == strcmp(a->flux, b->flux));
+ && a->imposed_flux == b->imposed_flux);
}
static FINLINE res_T
@@ -700,36 +559,7 @@ cp_f_boundary(struct f_boundary* dst, const struct f_boundary* src)
{
strcpy(dst->name, src->name);
dst->mat_id = src->mat_id;
- if (!src->flux) dst->flux = NULL;
- else {
- dst->flux = malloc(sizeof(src->flux) + 1);
- if (!dst->flux) return RES_MEM_ERR;
- strcpy(dst->flux, src->flux);
- }
- if (!src->te_flux) dst->te_flux = NULL;
- else {
- dst->te_flux = te_duplicate(src->te_flux);
- if (!dst->te_flux) return RES_MEM_ERR;
- }
- return RES_OK;
-}
-
-static FINLINE res_T
-cp_release_f_boundary(struct f_boundary* dst, struct f_boundary* src)
-{
- strcpy(dst->name, src->name);
- dst->mat_id = src->mat_id;
- dst->flux = malloc(sizeof(src->flux) + 1);
- dst->flux = src->flux; src->flux = NULL;
- dst->te_flux = src->te_flux; src->te_flux = NULL;
- return RES_OK;
-}
-
-static FINLINE res_T
-release_f_boundary(struct f_boundary* a)
-{
- free(a->flux);
- te_free(a->te_flux);
+ dst->imposed_flux = src->imposed_flux;
return RES_OK;
}
@@ -738,8 +568,8 @@ hash_f_boundary(const struct f_boundary* key)
{
/* 64-bits Fowler/Noll/Vo hash function */
const uint64_t FNV64_PRIME =
- (uint64_t) (((uint64_t) 1 << 40) + ((uint64_t) 1 << 8) + 0xB3);
- const uint64_t OFFSET64_BASIS = (uint64_t) 14695981039346656037u;
+ (uint64_t)(((uint64_t)1 << 40) + ((uint64_t)1 << 8) + 0xB3);
+ const uint64_t OFFSET64_BASIS = (uint64_t)14695981039346656037u;
uint64_t hash = OFFSET64_BASIS;
size_t i;
ASSERT(key);
@@ -751,8 +581,8 @@ hash_f_boundary(const struct f_boundary* key)
hash = hash ^ (uint32_t)((unsigned char)((const char*)&key->mat_id)[i]);
hash = hash * FNV64_PRIME;
}
- FOR_EACH(i, 0, strlen(key->flux) * sizeof(*key->flux)) {
- hash = hash ^ (uint32_t)((unsigned char)((const char*)key->flux)[i]);
+ FOR_EACH(i, 0, sizeof(key->imposed_flux)) {
+ hash = hash ^ (uint32_t)((unsigned char)((const char*)&key->imposed_flux)[i]);
hash = hash * FNV64_PRIME;
}
return hash;
@@ -769,6 +599,20 @@ struct solid_fluid_connect {
#define NULL_SFCONNECT__ { "", 0, 0, 0, 0, 0, 0}
static const struct solid_fluid_connect NULL_SFCONNECT = NULL_SFCONNECT__;
+static void
+print_sf_connect
+ (FILE* stream,
+ const struct solid_fluid_connect* c)
+{
+ ASSERT(stream && c);
+ fprintf(stream, "Solid-Fluid connection %s:", c->name);
+ if(c->has_emissivity)
+ fprintf(stream, " emissivity=%f, specular_fraction=%f",
+ c->emissivity, c->specular_fraction);
+ if (c->has_hc) fprintf(stream, " hc=%f", c->hc);
+ fprintf(stream, "\n");
+}
+
static char
eq_sf_connect(const struct solid_fluid_connect* a, const struct solid_fluid_connect* b)
{
@@ -812,8 +656,8 @@ hash_sf_connect(const struct solid_fluid_connect* key)
{
/* 64-bits Fowler/Noll/Vo hash function */
const uint64_t FNV64_PRIME =
- (uint64_t) (((uint64_t) 1 << 40) + ((uint64_t) 1 << 8) + 0xB3);
- const uint64_t OFFSET64_BASIS = (uint64_t) 14695981039346656037u;
+ (uint64_t)(((uint64_t)1 << 40) + ((uint64_t)1 << 8) + 0xB3);
+ const uint64_t OFFSET64_BASIS = (uint64_t)14695981039346656037u;
uint64_t hash = OFFSET64_BASIS;
size_t i;
ASSERT(key);
@@ -847,7 +691,6 @@ hash_sf_connect(const struct solid_fluid_connect* key)
}
return hash;
}
-
struct description {
enum description_type type;
union d {
@@ -882,7 +725,10 @@ print_description
print_h_boundary(stream, &desc->d.h_boundary, desc->type);
break;
case DESC_BOUND_F_FOR_SOLID:
- print_f_boundary(stream, &desc->d.f_boundary, desc->type);
+ print_f_boundary(stream, &desc->d.f_boundary);
+ break;
+ case DESC_SOLID_FLUID_CONNECT:
+ print_sf_connect(stream, &desc->d.sf_connect);
break;
default:
FATAL("error:" STR(__FILE__) ":" STR(__LINE__)": Invalid type.\n");
@@ -913,110 +759,57 @@ eq_description(const struct description* a, const struct description* b)
}
}
-static FINLINE res_T
-init_description(struct mem_allocator* alloc, struct description* key)
-{
- (void)alloc;
- key->type = DESCRIPTION_TYPE_COUNT__;
- return RES_OK;
-}
-
-static FINLINE res_T
-cp_description(struct description* dst, const struct description* src)
+static INLINE size_t
+hash_description(const struct description* key)
{
- ASSERT(src && dst);
- dst->type = src->type;
- switch (dst->type) {
+ switch (key->type) {
case DESC_MAT_SOLID:
- return cp_solid(&dst->d.solid, &src->d.solid);
+ return hash_solid(&key->d.solid);
case DESC_MAT_FLUID:
- return cp_fluid(&dst->d.fluid, &src->d.fluid);
+ return hash_fluid(&key->d.fluid);
case DESC_BOUND_H_FOR_SOLID:
case DESC_BOUND_H_FOR_FLUID:
- return cp_h_boundary(&dst->d.h_boundary, &src->d.h_boundary);
+ return hash_h_boundary(&key->d.h_boundary);
case DESC_BOUND_T_FOR_SOLID:
case DESC_BOUND_T_FOR_FLUID:
- return cp_t_boundary(&dst->d.t_boundary, &src->d.t_boundary);
+ return hash_t_boundary(&key->d.t_boundary, key->type);
case DESC_BOUND_F_FOR_SOLID:
- return cp_f_boundary(&dst->d.f_boundary, &src->d.f_boundary);
+ return hash_f_boundary(&key->d.f_boundary);
case DESC_SOLID_FLUID_CONNECT:
- return cp_sf_connect(&dst->d.sf_connect, &src->d.sf_connect);
+ return hash_sf_connect(&key->d.sf_connect);
default:
FATAL("error:" STR(__FILE__) ":" STR(__LINE__)": Invalid type.\n");
}
}
static FINLINE res_T
-cp_release_description(struct description* dst, struct description* src)
+init_description(struct mem_allocator* alloc, struct description* key)
{
- ASSERT(src && dst);
- dst->type = src->type;
- switch (dst->type) {
- case DESC_MAT_SOLID:
- return cp_release_solid(&dst->d.solid, &src->d.solid);
- case DESC_MAT_FLUID:
- return cp_release_fluid(&dst->d.fluid, &src->d.fluid);
- case DESC_BOUND_H_FOR_SOLID:
- case DESC_BOUND_H_FOR_FLUID:
- return cp_release_h_boundary(&dst->d.h_boundary, &src->d.h_boundary);
- case DESC_BOUND_T_FOR_SOLID:
- case DESC_BOUND_T_FOR_FLUID:
- return cp_release_t_boundary(&dst->d.t_boundary, &src->d.t_boundary);
- case DESC_BOUND_F_FOR_SOLID:
- return cp_release_f_boundary(&dst->d.f_boundary, &src->d.f_boundary);
- case DESC_SOLID_FLUID_CONNECT:
- return cp_release_sf_connect(&dst->d.sf_connect, &src->d.sf_connect);
- case DESCRIPTION_TYPE_COUNT__:
- return RES_OK;
- default:
- FATAL("error:" STR(__FILE__) ":" STR(__LINE__)": Invalid type.\n");
- }
+ (void)alloc;
+ key->type = DESCRIPTION_TYPE_COUNT__;
+ return RES_OK;
}
static FINLINE res_T
-release_description(struct description* a)
-{
- ASSERT(a);
- switch (a->type) {
- case DESC_MAT_SOLID:
- return release_solid(&a->d.solid);
- case DESC_MAT_FLUID:
- return release_fluid(&a->d.fluid);
- case DESC_BOUND_H_FOR_SOLID:
- case DESC_BOUND_H_FOR_FLUID:
- return release_h_boundary(&a->d.h_boundary);
- case DESC_BOUND_T_FOR_SOLID:
- case DESC_BOUND_T_FOR_FLUID:
- return release_t_boundary(&a->d.t_boundary);
- case DESC_BOUND_F_FOR_SOLID:
- return release_f_boundary(&a->d.f_boundary);
- case DESC_SOLID_FLUID_CONNECT:
- return release_sf_connect(&a->d.sf_connect);
- case DESCRIPTION_TYPE_COUNT__:
- return RES_OK;
- default:
- FATAL("error:" STR(__FILE__) ":" STR(__LINE__)": Invalid type.\n");
- }
-}
-
-static INLINE size_t
-hash_description(const struct description* key)
+cp_description(struct description* dst, const struct description* src)
{
- switch (key->type) {
+ ASSERT(src && dst);
+ dst->type = src->type;
+ switch (dst->type) {
case DESC_MAT_SOLID:
- return hash_solid(&key->d.solid);
+ return cp_solid(&dst->d.solid, &src->d.solid);
case DESC_MAT_FLUID:
- return hash_fluid(&key->d.fluid);
+ return cp_fluid(&dst->d.fluid, &src->d.fluid);
case DESC_BOUND_H_FOR_SOLID:
case DESC_BOUND_H_FOR_FLUID:
- return hash_h_boundary(&key->d.h_boundary);
+ return cp_h_boundary(&dst->d.h_boundary, &src->d.h_boundary);
case DESC_BOUND_T_FOR_SOLID:
case DESC_BOUND_T_FOR_FLUID:
- return hash_t_boundary(&key->d.t_boundary, key->type);
+ return cp_t_boundary(&dst->d.t_boundary, &src->d.t_boundary);
case DESC_BOUND_F_FOR_SOLID:
- return hash_f_boundary(&key->d.f_boundary);
+ return cp_f_boundary(&dst->d.f_boundary, &src->d.f_boundary);
case DESC_SOLID_FLUID_CONNECT:
- return hash_sf_connect(&key->d.sf_connect);
+ return cp_sf_connect(&dst->d.sf_connect, &src->d.sf_connect);
default:
FATAL("error:" STR(__FILE__) ":" STR(__LINE__)": Invalid type.\n");
}
diff --git a/src/stardis-compute.c b/src/stardis-compute.c
@@ -194,42 +194,33 @@ create_holder
const int is_green)
{
res_T res = RES_OK;
- /* Could be less restrictive if green output included positions/dates */
- int prohibited = is_green ? NO_VAR_ALLOWED : ALL_VARS_ALLOWED;
switch (description->type) {
case DESC_BOUND_H_FOR_SOLID:
counts->hbound_count++;
/* Create an external fluid with bound temp as fluid temp */
- res = create_fluid(dev, NULL, 1, 1, is_green, 1, NULL,
- description->d.h_boundary.T, media, &description->d.h_boundary.mat_id);
+ res = create_fluid(dev, NULL, 1, 1, is_green, 1, -1,
+ description->d.h_boundary.imposed_temperature, media,
+ &description->d.h_boundary.mat_id);
if (res != RES_OK) goto error;
break;
case DESC_BOUND_H_FOR_FLUID:
/* Create an external solid with bound temp as solid temp */
counts->hbound_count++;
- res = create_solid(dev, NULL, INF, 1, 1, 1, is_green, 1, NULL,
- description->d.h_boundary.T, NULL, media, NULL,
+ res = create_solid(dev, NULL, INF, 1, 1, 1, is_green, 1, -1,
+ description->d.h_boundary.imposed_temperature, 0, media,
&description->d.h_boundary.mat_id);
if (res != RES_OK) goto error;
break;
case DESC_BOUND_T_FOR_SOLID:
counts->tbound_count++;
- ASSERT(description->d.t_boundary.T != NULL);
- res = compile_expr_to_fn(&description->d.t_boundary.te_temperature,
- description->d.t_boundary.T, prohibited, NULL);
- if (res != RES_OK) {
- fprintf(stderr, "Invalid boundary temperature expression: %s\n",
- description->d.t_boundary.T);
- goto error;
- }
if (dummies->dummy_fluid) {
/* Reuse external dummy fluid */
description->d.t_boundary.mat_id = dummies->dummy_fluid_id;
} else {
/* Create dummy fluid */
- res = create_fluid(dev, NULL, 1, 1, is_green, 1, NULL,
- NULL, media, &description->d.t_boundary.mat_id);
+ res = create_fluid(dev, NULL, 1, 1, is_green, 1, -1,
+ -1, media, &description->d.t_boundary.mat_id);
if (res != RES_OK) goto error;
dummies->dummy_fluid = sa_last(*media);
dummies->dummy_fluid_id = description->d.t_boundary.mat_id;
@@ -237,21 +228,13 @@ create_holder
break;
case DESC_BOUND_T_FOR_FLUID:
counts->tbound_count++;
- ASSERT(description->d.t_boundary.T != NULL);
- res = compile_expr_to_fn(&description->d.t_boundary.te_temperature,
- description->d.t_boundary.T, prohibited, NULL);
- if (res != RES_OK) {
- fprintf(stderr, "Invalid boundary temperature expression: %s\n",
- description->d.t_boundary.T);
- goto error;
- }
if (dummies->dummy_solid) {
/* Reuse external dummy solid */
description->d.t_boundary.mat_id = dummies->dummy_solid_id;
} else {
/* Create dummy solid */
- res = create_solid(dev, NULL, 1, 1, 1, 1, is_green, 1, NULL,
- NULL, NULL, media, NULL, &description->d.t_boundary.mat_id);
+ res = create_solid(dev, NULL, 1, 1, 1, 1, is_green, 1, -1,
+ -1, 0, media, &description->d.t_boundary.mat_id);
if (res != RES_OK) goto error;
dummies->dummy_solid = sa_last(*media);
dummies->dummy_solid_id = description->d.t_boundary.mat_id;
@@ -259,20 +242,12 @@ create_holder
break;
case DESC_BOUND_F_FOR_SOLID:
counts->fbound_count++;
- ASSERT(description->d.f_boundary.flux != NULL);
- res = compile_expr_to_fn(&description->d.f_boundary.te_flux,
- description->d.f_boundary.flux, 1, NULL);
- if (res != RES_OK) {
- fprintf(stderr, "Invalid boundary flux expression: %s\n",
- description->d.f_boundary.flux);
- goto error;
- }
if (dummies->dummy_fluid) {
/* Reuse external dummy fluid */
description->d.f_boundary.mat_id = dummies->dummy_fluid_id;
} else {
/* Create dummy fluid */
- res = create_fluid(dev, NULL, 1, 1, is_green, 1, NULL, NULL,
+ res = create_fluid(dev, NULL, 1, 1, is_green, 1, -1, -1,
media, &description->d.f_boundary.mat_id);
if (res != RES_OK) goto error;
dummies->dummy_fluid = sa_last(*media);
@@ -296,11 +271,10 @@ create_holder
description->d.solid.delta,
is_green,
0,
- description->d.solid.Tinit,
- description->d.solid.Temp,
- description->d.solid.power,
+ description->d.solid.tinit,
+ description->d.solid.imposed_temperature,
+ description->d.solid.vpower,
media,
- &description->d.solid.has_power,
&description->d.solid.solid_id);
if (res != RES_OK) goto error;
break;
@@ -312,8 +286,8 @@ create_holder
description->d.fluid.cp,
is_green,
0,
- description->d.fluid.Tinit,
- description->d.fluid.Temp,
+ description->d.fluid.tinit,
+ description->d.fluid.imposed_temperature,
media,
&description->d.fluid.fluid_id);
if (res != RES_OK) goto error;
@@ -744,47 +718,6 @@ error:
******************************************************************************/
res_T
-compile_expr_to_fn
- (struct te_expr** f,
- const char* math_expr,
- const int prohibited,
- int* is_zero)
-{
- te_variable vars[4] = {
- TE_DEF_OFFSET("x", offsetof(struct sdis_rwalk_vertex, P[0])),
- TE_DEF_OFFSET("y", offsetof(struct sdis_rwalk_vertex, P[1])),
- TE_DEF_OFFSET("z", offsetof(struct sdis_rwalk_vertex, P[2])),
- TE_DEF_OFFSET("t", offsetof(struct sdis_rwalk_vertex, time))
- };
- int fst = 0, lst = 4;
-
- ASSERT(f && math_expr);
- ASSERT(prohibited == (prohibited & NO_VAR_ALLOWED)); /* Use only defined flags */
-
- if (prohibited & XYZ_PROHIBITED) fst = 3;
- if (prohibited & T_PROHIBITED) lst = 3;
- *f = te_compile(math_expr, vars + fst, lst - fst, NULL);
- if (!*f) {
- if (!te_compile(math_expr, vars, 4, NULL))
- return RES_BAD_ARG; /* Expr is not valid */
- /* Expr is valid */
- if (prohibited != ALL_VARS_ALLOWED)
- fprintf(stderr, "Expression \"%s\" use a probibited variable ", math_expr);
- if (prohibited == NO_VAR_ALLOWED)
- fprintf(stderr, "(no variable allowed)\n");
- else if (prohibited == XYZ_PROHIBITED)
- fprintf(stderr, "(xyz prohibited)\n");
- else {
- ASSERT(prohibited == T_PROHIBITED);
- fprintf(stderr, "(t prohibited)\n");
- }
- return RES_BAD_OP; /* Expr is valid, but use a forbidden var */
- }
- if (is_zero) *is_zero = !((*f)->type == TE_CONSTANT && (*f)->v.value == 0);
- return RES_OK;
-}
-
-res_T
stardis_compute
(struct stardis* stardis,
const int mode)
diff --git a/src/stardis-compute.h b/src/stardis-compute.h
@@ -11,7 +11,6 @@
#define HTABLE_KEY unsigned
#include <rsys/hash_table.h>
-struct te_expr;
struct stardis;
struct counts {
@@ -23,21 +22,6 @@ struct counts {
}
static const struct counts COUNTS_NULL = COUNTS_NULL__;
-/* A type to limit variable use in tinyexpr expressions */
-enum var_prohibited_t {
- ALL_VARS_ALLOWED = 0,
- T_PROHIBITED = BIT(4),
- XYZ_PROHIBITED = BIT(5),
- NO_VAR_ALLOWED = T_PROHIBITED | XYZ_PROHIBITED
-};
-
-extern res_T
-compile_expr_to_fn
- (struct te_expr** f,
- const char* math_expr,
- const int prohibited,
- int* is_zero);
-
extern res_T
stardis_compute
(struct stardis* stardis,
diff --git a/src/stardis-fluid.c b/src/stardis-fluid.c
@@ -2,7 +2,6 @@
#include "stardis-compute.h"
#include <sdis.h>
-#include <tinyexpr.h>
#include<rsys/stretchy_array.h>
#include <limits.h>
@@ -37,17 +36,15 @@ fluid_get_temperature
struct sdis_data* data)
{
const struct fluid* fluid_props = sdis_data_cget(data);
- ASSERT(fluid_props->t_init || fluid_props->temp);
if (fluid_props->is_green || vtx->time > fluid_props->t0) {
/* Always use temp for Green mode, regardless of time */
- if (fluid_props->temp)
- return te_eval(fluid_props->temp, vtx);
+ if (fluid_props->imposed_temperature >= 0)
+ return fluid_props->imposed_temperature;
else return -1;
}
- /* Time is t0: use t_init */
- if (fluid_props->t_init)
- return te_eval(fluid_props->t_init, vtx);
- /* Must have had t_init defined: error! */
+ /* Time is <= 0: use tinit */
+ if (fluid_props->tinit >= 0) return fluid_props->tinit;
+ /* Must have had tinit defined: error! */
if (fluid_props->name[0]) {
fprintf(stderr,
"fluid_get_temperature: getting undefined Tinit (fluid '%s')\n",
@@ -58,15 +55,6 @@ fluid_get_temperature
FATAL("fluid_get_temperature: getting undefined Tinit\n");
}
-static void
-release_fluid_data
- (void* f)
-{
- struct fluid* fluid = (struct fluid*)f;
- te_free(fluid->t_init);
- te_free(fluid->temp);
-}
-
/*******************************************************************************
* Public Functions
******************************************************************************/
@@ -79,8 +67,8 @@ create_fluid
const double cp,
const int is_green,
const int is_outside,
- const char* tinit_expr,
- const char* t_expr,
+ const double tinit,
+ const double imposed_temperature,
struct sdis_medium*** media_ptr,
unsigned* out_id)
{
@@ -89,15 +77,14 @@ create_fluid
struct sdis_data* data = NULL;
struct fluid* fluid_props;
size_t sz;
- /* Could be less restrictive if green output included positions/dates */
- int prohibited = is_green ? NO_VAR_ALLOWED : ALL_VARS_ALLOWED;
ASSERT(dev && rho >= 0 && cp >= 0 && media_ptr && out_id);
+ ASSERT(tinit >= 0 || imposed_temperature >= 0);
fluid_shader.calorific_capacity = fluid_get_calorific_capacity;
fluid_shader.volumic_mass = fluid_get_volumic_mass;
fluid_shader.temperature = fluid_get_temperature;
res = sdis_data_create(dev, sizeof(struct fluid), ALIGNOF(struct fluid),
- release_fluid_data, &data);
+ NULL, &data);
if (res != RES_OK) goto error;
sz = sa_size(*media_ptr);
@@ -107,31 +94,12 @@ create_fluid
else fluid_props->name[0] = '\0';
fluid_props->cp = cp;
fluid_props->rho = rho;
- fluid_props->t_init = NULL;
- fluid_props->temp = NULL;
+ fluid_props->tinit = tinit;
+ fluid_props->imposed_temperature = imposed_temperature;
fluid_props->is_green = is_green;
fluid_props->is_outside = is_outside;
- fluid_props->t0 = 0;
fluid_props->id = (unsigned)sz;
- if (tinit_expr) {
- res = compile_expr_to_fn(&fluid_props->t_init, tinit_expr,
- prohibited | T_PROHIBITED, NULL);
- if (res != RES_OK) {
- if (res == RES_BAD_ARG)
- fprintf(stderr, "Invalid initial temperature expression: %s\n",
- tinit_expr);
- goto error;
- }
- }
- if (t_expr) {
- res = compile_expr_to_fn(&fluid_props->temp, t_expr, prohibited, NULL);
- if (res != RES_OK) {
- fprintf(stderr, "Invalid temperature expression: %s\n",
- t_expr);
- goto error;
- }
- }
res = sdis_fluid_create(dev, &fluid_shader, data, sa_add(*media_ptr, 1));
if (res != RES_OK) goto error;
*out_id = fluid_props->id;
diff --git a/src/stardis-fluid.h b/src/stardis-fluid.h
@@ -6,7 +6,6 @@
#include <sdis.h>
#include <rsys/rsys.h>
-struct te_expr;
struct sdis_device;
struct sdis_medium;
@@ -19,10 +18,9 @@ struct fluid {
double rho; /* Volumic mass */
/* Compute mode */
int is_green, is_outside;
- double t0;
- /* TinyExpr stuff to compute temperature */
- struct te_expr *temp;
- struct te_expr *t_init;
+ double t0; /* End time of tinit */
+ double tinit;
+ double imposed_temperature;
/* ID */
unsigned id;
};
@@ -35,8 +33,8 @@ create_fluid
const double cp,
const int is_green,
const int is_outside,
- const char* tinit_expr,
- const char* t_expr,
+ const double tinit,
+ const double imposed_temperature,
struct sdis_medium*** media_ptr,
unsigned* out_id);
diff --git a/src/stardis-intface.c b/src/stardis-intface.c
@@ -2,7 +2,6 @@
#include "stardis-app.h"
#include "stardis-output.h"
-#include <tinyexpr.h>
#include <sdis.h>
#include <rsys/stretchy_array.h>
@@ -26,11 +25,8 @@ interface_get_temperature
struct sdis_data* data)
{
const struct intface* interface_props = sdis_data_cget(data);
-
- if (interface_props->temperature == NULL)
- return -1;
-
- return te_eval(interface_props->temperature, frag);
+ (void)frag;
+ return interface_props->imposed_temperature;
}
static double
@@ -39,11 +35,8 @@ interface_get_flux
struct sdis_data* data)
{
const struct intface* interface_props = sdis_data_cget(data);
-
- if (interface_props->flux == NULL)
- return SDIS_FLUX_NONE;
-
- return te_eval(interface_props->flux, frag);
+ (void)frag;
+ return interface_props->imposed_flux;
}
static double
@@ -66,15 +59,6 @@ interface_get_alpha
return interface_props->alpha;
}
-static void
-release_interface_data
- (void* s)
-{
- struct intface* intface = (struct intface*)s;
- te_free(intface->temperature);
- te_free(intface->flux);
-}
-
/*******************************************************************************
* Public Functions
******************************************************************************/
@@ -127,10 +111,10 @@ create_intface
int connect_defined = (cd != UINT_MAX);
SDIS(data_create(dev, sizeof(struct intface), ALIGNOF(struct intface),
- release_interface_data, &data));
+ NULL, &data));
interface_props = sdis_data_get(data);
- interface_props->temperature = NULL;
- interface_props->flux = NULL;
+ interface_props->imposed_temperature = -1;
+ interface_props->imposed_flux = SDIS_FLUX_NONE;
interface_props->front_boundary_id = UINT_MAX;
interface_props->back_boundary_id = UINT_MAX;
@@ -266,9 +250,9 @@ create_intface
* TODO: should be outside to allow contact resistances */
interface_shader.back.temperature = interface_get_temperature;
}
- ASSERT(connect->d.t_boundary.te_temperature);
- interface_props->temperature
- = te_duplicate(connect->d.t_boundary.te_temperature);
+ ASSERT(connect->d.t_boundary.imposed_temperature >= 0);
+ interface_props->imposed_temperature
+ = connect->d.t_boundary.imposed_temperature;
if (connect->d.t_boundary.has_hc) {
ASSERT(connect->type == DESC_BOUND_T_FOR_FLUID);
interface_shader.convection_coef = interface_get_convection_coef;
@@ -292,8 +276,8 @@ create_intface
front_med = media[connect->d.f_boundary.mat_id];
interface_shader.back.flux = interface_get_flux;
}
- ASSERT(connect->d.f_boundary.te_flux);
- interface_props->flux = te_duplicate(connect->d.f_boundary.te_flux);
+ ASSERT(connect->d.f_boundary.imposed_flux != SDIS_FLUX_NONE);
+ interface_props->imposed_flux = connect->d.f_boundary.imposed_flux;
break;
case DESC_SOLID_FLUID_CONNECT:
/* Both front and back should be defined;
diff --git a/src/stardis-intface.h b/src/stardis-intface.h
@@ -7,7 +7,6 @@
#include <limits.h>
-struct te_expr;
struct sdis_data;
struct sdis_device;
struct geometry;
@@ -21,9 +20,9 @@ struct intface {
double hc; /* Convection coefficient */
double emissivity;
double alpha;
- /* TinyExpr stuff to compute temperature & flux */
- struct te_expr *temperature;
- struct te_expr *flux;
+ /* Imposed compute temperature & flux */
+ double imposed_temperature;
+ double imposed_flux;
/* IDs */
unsigned front_boundary_id, back_boundary_id;
};
diff --git a/src/stardis-output.c b/src/stardis-output.c
@@ -440,8 +440,8 @@ dump_green
const struct mat_solid* sl;
if (desc->type != DESC_MAT_SOLID) continue;
sl = &desc->d.solid;
- printf("%u\t%s\t%g\t%g\t%g\t%s\n",
- i, sl->name, sl->lambda, sl->rho, sl->cp, (sl->has_power ? sl->power : "0"));
+ printf("%u\t%s\t%g\t%g\t%g\t%g\n",
+ i, sl->name, sl->lambda, sl->rho, sl->cp, sl->vpower);
}
}
if (counts->fmed_count) {
@@ -465,7 +465,7 @@ dump_green
if (desc->type != DESC_BOUND_T_FOR_SOLID
&& desc->type != DESC_BOUND_T_FOR_FLUID) continue;
bd = &desc->d.t_boundary;
- printf("%u\t%s\t%s\n", i, bd->name, bd->T);
+ printf("%u\t%s\t%g\n", i, bd->name, bd->imposed_temperature);
}
}
if (counts->hbound_count) {
@@ -477,10 +477,11 @@ dump_green
if (desc->type != DESC_BOUND_H_FOR_SOLID
&& desc->type != DESC_BOUND_H_FOR_FLUID) continue;
bd = &desc->d.h_boundary;
- printf("%u\t%s\t%g\t%g\t%g\t%g\t%s\n",
+ printf("%u\t%s\t%g\t%g\t%g\t%g\t%g\n",
i, bd->name, (bd->has_emissivity ? bd->emissivity : 0),
(bd->has_emissivity ? bd->specular_fraction : 0),
- (bd->has_hc ? bd->hc : 0), (bd->has_hc ? bd->hc_max : 0), bd->T);
+ (bd->has_hc ? bd->hc : 0), (bd->has_hc ? bd->hc_max : 0),
+ bd->imposed_temperature);
}
}
if (counts->fbound_count) {
@@ -491,8 +492,8 @@ dump_green
const struct f_boundary* bd;
if (desc->type != DESC_BOUND_F_FOR_SOLID) continue;
bd = &desc->d.f_boundary;
- printf("%u\t%s\t%s\n",
- i, bd->name, bd->flux);
+ printf("%u\t%s\t%g\n",
+ i, bd->name, bd->imposed_flux);
}
}
diff --git a/src/stardis-parsing.c b/src/stardis-parsing.c
@@ -625,29 +625,25 @@ parse_medium_line
res = RES_BAD_ARG;
goto exit;
}
- /* Depending of the number of spaces before '"' strtok should
- * be called once or twice */
- CHK_TOK(strtok(NULL, "\""), "Tinit");
- if (*(tk + strspn(tk, " \t")) == '\0') {
- CHK_TOK(strtok(NULL, "\""), "Tinit");
+ CHK_TOK(strtok(NULL, " "), "Tinit");
+ res = cstr_to_double(tk, &desc->d.solid.tinit);
+ if (res != RES_OK || desc->d.solid.tinit < 0) {
+ fprintf(stderr, "Invalid Tinit: %s\n", tk);
+ res = RES_BAD_ARG;
+ goto exit;
}
- desc->d.solid.Tinit = malloc(strlen(tk) + 1);
- strcpy(desc->d.solid.Tinit, tk);
- /* Closing " fot Tinit; can return NULL if line ends just after "Tinit" */
- tk = strtok(NULL, "\"");
/* Volumic Power is optional */
- if (tk && *(tk + strspn(tk, " \t")) == '\0') {
- /* Depending of the number of spaces before '"' strtok should
- * be called once or twice */
- tk = strtok(NULL, "\"");
- }
+ tk = strtok(NULL, " ");
if (tk) {
- desc->d.solid.power = malloc(strlen(tk) + 1);
- strcpy(desc->d.solid.power, tk);
- /* Can be changed aftwerwards if compiled to constant 0 */
- desc->d.solid.has_power = 1;
+ res = cstr_to_double(tk, &desc->d.solid.vpower);
+ if (res != RES_OK) {
+ fprintf(stderr, "Invalid volumic power: %s\n", tk);
+ res = RES_BAD_ARG;
+ goto exit;
+ }
}
+ else desc->d.solid.vpower = SDIS_VOLUMIC_POWER_NONE;
}
else if (strcmp(tk, "FLUID") == 0) {
desc->type = DESC_MAT_FLUID;
@@ -681,12 +677,13 @@ parse_medium_line
}
/* Depending of the number of spaces before '"' strtok should
* be called once or twice */
- CHK_TOK(strtok(NULL, "\""), "Tinit");
- if (*(tk + strspn(tk, " \t")) == '\0') {
- CHK_TOK(strtok(NULL, "\""), "Tinit");
+ CHK_TOK(strtok(NULL, " "), "Tinit");
+ res = cstr_to_double(tk, &desc->d.fluid.tinit);
+ if (res != RES_OK || desc->d.fluid.tinit < 0) {
+ fprintf(stderr, "Invalid Tinit: %s\n", tk);
+ res = RES_BAD_ARG;
+ goto exit;
}
- desc->d.fluid.Tinit = malloc(strlen(tk) + 1);
- strcpy(desc->d.fluid.Tinit, tk);
} else {
res = RES_BAD_ARG;
fprintf(stderr, "Invalid medium type: %s\n", tk);
@@ -796,14 +793,13 @@ parse_boundary_line
res = RES_BAD_ARG;
goto exit;
}
- /* Depending of the number of spaces before '"' strtok should
- * be called once or twice */
- CHK_TOK(strtok(NULL, "\""), "temperature");
- if (*(tk + strspn(tk, " \t")) == '\0') {
- CHK_TOK(strtok(NULL, "\""), "temperature");
+ CHK_TOK(strtok(NULL, " "), "temperature");
+ res = cstr_to_double(tk, &desc->d.h_boundary.imposed_temperature);
+ if (res != RES_OK || desc->d.h_boundary.imposed_temperature < 0) {
+ fprintf(stderr, "Invalid temperature value: %s\n", tk);
+ res = RES_BAD_ARG;
+ goto exit;
}
- desc->d.h_boundary.T = malloc(strlen(tk) + 1);
- strcpy(desc->d.h_boundary.T, tk);
}
else if (t_solid || t_fluid) {
desc->type = t_solid ? DESC_BOUND_T_FOR_SOLID : DESC_BOUND_T_FOR_FLUID;
@@ -822,14 +818,13 @@ parse_boundary_line
*stl_filename = malloc(strlen(tk) + 1);
strcpy(*stl_filename, tk);
- /* Depending of the number of spaces before '"' strtok should
- * be called once or twice */
- CHK_TOK(strtok(NULL, "\""), "temperature");
- if (*(tk + strspn(tk, " \t")) == '\0') {
- CHK_TOK(strtok(NULL, "\""), "temperature");
+ CHK_TOK(strtok(NULL, " "), "temperature");
+ res = cstr_to_double(tk, &desc->d.t_boundary.imposed_temperature);
+ if (res != RES_OK || desc->d.t_boundary.imposed_temperature < 0) {
+ fprintf(stderr, "Invalid temperature value: %s\n", tk);
+ res = RES_BAD_ARG;
+ goto exit;
}
- desc->d.t_boundary.T = malloc(strlen(tk) + 1);
- strcpy(desc->d.t_boundary.T, tk);
/* Parse hc + hc_max only if fluid */
if (t_fluid) {
@@ -871,12 +866,13 @@ parse_boundary_line
/* Depending of the number of spaces before '"' strtok should
* be called once or twice */
- CHK_TOK(strtok(NULL, "\""), "flux");
- if (*(tk + strspn(tk, " \t")) == '\0') {
- CHK_TOK(strtok(NULL, "\""), "flux");
+ CHK_TOK(strtok(NULL, " "), "flux");
+ res = cstr_to_double(tk, &desc->d.f_boundary.imposed_flux);
+ if (res != RES_OK) {
+ fprintf(stderr, "Invalid flux value: %s\n", tk);
+ res = RES_BAD_ARG;
+ goto exit;
}
- desc->d.f_boundary.flux = malloc(strlen(tk) + 1);
- strcpy(desc->d.f_boundary.flux, tk);
}
else if (sf_connect) {
desc->type = DESC_SOLID_FLUID_CONNECT;
diff --git a/src/stardis-solid.c b/src/stardis-solid.c
@@ -2,7 +2,6 @@
#include "stardis-compute.h"
#include <sdis.h>
-#include <tinyexpr.h>
#include<rsys/stretchy_array.h>
#include <limits.h>
@@ -58,10 +57,7 @@ solid_get_delta_boundary
struct sdis_data* data)
{
const struct solid* solid_props = sdis_data_cget(data);
- return solid_props->delta
- /* Emperical scale factor that ensures that delta_boundary > delta withouht
- * being an exact multiple of delta. */
- /** 2.1 */;
+ return solid_props->delta;
}
#endif
@@ -71,17 +67,14 @@ solid_get_temperature
struct sdis_data* data)
{
const struct solid* solid_props = sdis_data_cget(data);
- char msg[128];
- ASSERT(solid_props->t_init || solid_props->temp);
if (solid_props->is_green || vtx->time > solid_props->t0) {
/* Always use temp for Green mode, regardless of time */
- if (solid_props->temp)
- return te_eval(solid_props->temp, vtx);
+ if (solid_props->imposed_temperature >= 0)
+ return solid_props->imposed_temperature;
else return -1;
}
- /* Time is t0: use t_init */
- if (solid_props->t_init)
- return te_eval(solid_props->t_init, vtx);
+ /* Time is <= 0: use tinit */
+ if (solid_props->tinit >= 0) return solid_props->tinit;
/* Must have had t_init defined: error! */
if (solid_props->name[0]) {
fprintf(stderr,
@@ -99,16 +92,8 @@ solid_get_power
struct sdis_data* data)
{
const struct solid* solid_props = sdis_data_cget(data);
- return te_eval(solid_props->power, vtx);
-}
-
-static void
-release_solid_data
- (void* s)
-{
- struct solid* solid = (struct solid*)s;
- te_free(solid->t_init);
- te_free(solid->power);
+ (void)vtx;
+ return solid_props->vpower;
}
/*******************************************************************************
@@ -125,11 +110,10 @@ create_solid
const double delta,
const int is_green,
const int is_outside,
- const char* tinit_expr, /* Can be NULL if not used by getter */
- const char* t_expr, /* Can be NULL if not used by getter */
- const char* power_expr, /* Can be NULL */
+ const double tinit,
+ const double imposed_temperature,
+ const double vpower,
struct sdis_medium*** media_ptr,
- int* out_has_power, /* Can be NULL */
unsigned* out_id)
{
res_T res = RES_OK;
@@ -138,7 +122,6 @@ create_solid
struct solid* solid_props;
size_t sz;
/* Could be less restrictive if green output included positions/dates */
- int prohibited = is_green ? NO_VAR_ALLOWED : ALL_VARS_ALLOWED;
ASSERT(dev && lambda >= 0 && rho >= 0 && cp >= 0 && delta > 0
&& media_ptr && out_id);
@@ -151,7 +134,7 @@ create_solid
#endif
solid_shader.temperature = solid_get_temperature;
res = sdis_data_create(dev, sizeof(struct solid), ALIGNOF(struct solid),
- release_solid_data, &data);
+ NULL, &data);
if (res != RES_OK) goto error;
sz = sa_size(*media_ptr);
@@ -163,44 +146,13 @@ create_solid
solid_props->rho = rho;
solid_props->cp = cp;
solid_props->delta = delta;
- solid_props->t_init = NULL;
- solid_props->temp = NULL;
- solid_props->power = NULL;
+ solid_props->tinit = tinit;
+ solid_props->imposed_temperature = imposed_temperature;
+ solid_props->vpower = vpower;
solid_props->is_green = is_green;
solid_props->is_outside = is_outside;
- solid_props->t0 = 0;
solid_props->id = (unsigned)sz;
- if (tinit_expr) {
- res = compile_expr_to_fn(&solid_props->t_init, tinit_expr,
- prohibited | T_PROHIBITED, NULL);
- if (res != RES_OK) {
- if (res == RES_BAD_ARG)
- fprintf(stderr, "Invalid initial temperature expression: %s\n",
- tinit_expr);
- goto error;
- }
- }
- if (t_expr) {
- res = compile_expr_to_fn(&solid_props->temp, t_expr, prohibited, NULL);
- if (res != RES_OK) {
- fprintf(stderr, "Invalid temperature expression: %s\n",
- t_expr);
- goto error;
- }
- }
- if (power_expr) {
- int has_power;
- res = compile_expr_to_fn(&solid_props->power, power_expr, prohibited, &has_power);
- if (res != RES_OK) {
- fprintf(stderr, "Invalid volumic power expression: %s\n",
- power_expr);
- goto error;
- }
- if (out_has_power) *out_has_power = has_power;
- if (has_power) solid_shader.volumic_power = solid_get_power;
- } else {
- if (out_has_power) *out_has_power = 0;
- }
+ if (vpower != 0) solid_shader.volumic_power = solid_get_power;
res = sdis_solid_create(dev, &solid_shader, data, sa_add(*media_ptr, 1));
if (res != RES_OK) goto error;
*out_id = solid_props->id;
diff --git a/src/stardis-solid.h b/src/stardis-solid.h
@@ -5,7 +5,6 @@
#include <rsys/rsys.h>
-struct te_expr;
struct sdis_device;
struct sdis_medium;
@@ -18,13 +17,12 @@ struct solid {
double lambda; /* Conductivity */
double rho; /* Volumic mass */
double delta; /* Numerical parameter */
+ double tinit; /* Initial temperature */
+ double imposed_temperature; /* allow to impose a T; -1 if unset */
+ double vpower;
/* Compute mode */
int is_green, is_outside;
- double t0;
- /* TinyExpr stuff to compute temperature & power */
- struct te_expr *temp;
- struct te_expr *t_init;
- struct te_expr *power;
+ double t0; /* End time of tinit */
/* ID */
unsigned id;
};
@@ -39,11 +37,10 @@ create_solid
const double delta,
const int is_green,
const int is_outside,
- const char* tinit_expr, /* Can be NULL if not used by getter */
- const char* t_expr, /* Can be NULL if not used by getter */
- const char* power_expr, /* Can be NULL */
+ const double tinit,
+ const double imposed_temperature,
+ const double vpower,
struct sdis_medium*** media_ptr,
- int* out_has_power, /* Can be NULL */
unsigned* out_id);
#endif
diff --git a/tinyexpr/tinyexpr.c b/tinyexpr/tinyexpr.c
@@ -1,891 +0,0 @@
-/*
- * TINYEXPR - Tiny recursive descent parser and evaluation engine in C
- *
- * Copyright (c) 2015-2018 Lewis Van Winkle
- *
- * http://CodePlea.com
- *
- * This software is provided 'as-is', without any express or implied
- * warranty. In no event will the authors be held liable for any damages
- * arising from the use of this software.
- *
- * Permission is granted to anyone to use this software for any purpose,
- * including commercial applications, and to alter it and redistribute it
- * freely, subject to the following restrictions:
- *
- * 1. The origin of this software must not be misrepresented; you must not
- * claim that you wrote the original software. If you use this software
- * in a product, an acknowledgement in the product documentation would be
- * appreciated but is not required.
- * 2. Altered source versions must be plainly marked as such, and must not be
- * misrepresented as being the original software.
- * 3. This notice may not be removed or altered from any source distribution.
- */
-
-/* COMPILE TIME OPTIONS */
-
-/* Exponentiation associativity:
-For a^b^c = (a^b)^c and -a^b = (-a)^b do nothing.
-For a^b^c = a^(b^c) and -a^b = -(a^b) uncomment the next line.*/
-/* #define TE_POW_FROM_RIGHT */
-
-/* Logarithms
-For log = base 10 log do nothing
-For log = natural log uncomment the next line. */
-/* #define TE_NAT_LOG */
-
-#include "tinyexpr.h"
-#include <stdlib.h>
-#include <math.h>
-#include <string.h>
-#include <stdio.h>
-#include <limits.h>
-#include <assert.h>
-
-#ifndef M_E
-#define M_E 2.71828182845904523536 // e
-#endif
-
-#ifndef M_PI
-#define M_PI 3.14159265358979323846 // pi
-#endif
-
-#ifndef NAN
-#define NAN (0.0/0.0)
-#endif
-
-#ifndef INFINITY
-#define INFINITY (1.0/0.0)
-#endif
-
-
-typedef double (*te_fun2)(double, double);
-
-enum {
-
-#ifdef TE_WITHOUT_FUNCTION_0
- TE_FUNCTION0 = 8,
-#endif
-#ifdef TE_WITHOUT_CLOSURES
- TE_CLOSURE7 = 23,
-#endif
-
- TOK_NULL = TE_CLOSURE7+1, TOK_ERROR, TOK_END, TOK_SEP,
- TOK_OPEN, TOK_CLOSE, TOK_NUMBER, TOK_VARIABLE, TOK_OFFSET, TOK_INFIX,
-
- TE_CONDITION = 256
-};
-
-typedef struct state {
- const char *start;
- const char *next;
- int type;
- union value v;
- void *context;
-
- const te_variable *lookup;
- int lookup_len;
-} state;
-
-
-#define TYPE_MASK(TYPE) ((TYPE)&0x0000003F)
-
-#define IS_PURE(TYPE) (((TYPE) & TE_FLAG_PURE) != 0)
-#define IS_FUNCTION(TYPE) (((TYPE) & TE_FUNCTION0) != 0)
-#ifdef TE_WITHOUT_CLOSURES
-#define ARITY(TYPE) ( ((TYPE) & TE_FUNCTION0) ? ((TYPE) & 0x00000007) : 0 )
-#else
-#define IS_CLOSURE(TYPE) (((TYPE) & TE_CLOSURE0) != 0)
-#define ARITY(TYPE) ( ((TYPE) & (TE_FUNCTION0 | TE_CLOSURE0)) ? ((TYPE) & 0x00000007) : 0 )
-#endif
-#define IS_CONDITION(TYPE) (((TYPE) & TE_CONDITION) != 0)
-#define NEW_EXPR(type, ...) new_expr((type), (const te_expr*[]){__VA_ARGS__})
-
-static te_expr *new_expr(const int type, const te_expr *parameters[]) {
- const size_t arity = ARITY(type);
- const size_t psize = sizeof(void*) * arity;
- const size_t size = (sizeof(te_expr) - sizeof(void*)) + psize
-#ifndef TE_WITHOUT_CLOSURES
- + (IS_CLOSURE(type) ? sizeof(void*) : 0)
-#endif
- ;
- te_expr *ret = malloc(size);
- memset(ret, 0, size);
- if (arity && parameters) {
- memcpy(ret->parameters, parameters, psize);
- }
- ret->type = type;
- ret->v.bound = 0;
- return ret;
-}
-
-static te_expr *new_expr1(const int type, te_expr *p1) {
- const size_t size = sizeof(te_expr)
-#ifndef TE_WITHOUT_CLOSURES
- + (IS_CLOSURE(type) ? sizeof(void*) : 0)
-#endif
- ;
- assert(p1 && ARITY(type) == 1);
- te_expr *ret = malloc(size);
- ret->type = type;
- ret->v.bound = 0;
- ret->parameters[0] = p1;
- return ret;
-}
-
-te_expr* te_duplicate(te_expr* n) {
- const size_t size = sizeof(te_expr)
-#ifndef TE_WITHOUT_CLOSURES
- + (IS_CLOSURE(n->type) ? sizeof(void*) : 0);
-#endif
- ;
- te_expr* nn;
- assert(n);
- nn = malloc(size);
- if (!nn) return NULL;
- memcpy(nn, n, size);
- return nn;
-}
-
-static te_expr *new_expr2(const int type, te_expr *p1, te_expr *p2) {
- const size_t size = sizeof(te_expr) + sizeof(void*)
-#ifndef TE_WITHOUT_CLOSURES
- + (IS_CLOSURE(type) ? sizeof(void*) : 0)
-#endif
- ;
- assert(p1 && p2 && ARITY(type) == 2);
- te_expr *ret = malloc(size);
- ret->type = type;
- ret->v.bound = 0;
- ret->parameters[0] = p1;
- ret->parameters[1] = p2;
- return ret;
-}
-
-static void te_free_parameters(te_expr *n) {
- int i;
- if (!n) return;
- for (i = 0; i < ARITY(n->type); i++)te_free(n->parameters[i]);
-}
-
-
-void te_free(te_expr *n) {
- if (!n) return;
- te_free_parameters(n);
- free(n);
-}
-
-static double fac(double a) {/* simplest version of fac */
- if (a < 0.0)
- return NAN;
- if (a > UINT_MAX)
- return INFINITY;
- unsigned int ua = (unsigned int)(a);
- unsigned long int result = 1, i;
- for (i = 1; i <= ua; i++) {
- if (i > ULONG_MAX / result)
- return INFINITY;
- result *= i;
- }
- return (double)result;
-}
-static double ncr(double n, double r) {
- if (n < 0.0 || r < 0.0 || n < r) return NAN;
- if (n > UINT_MAX || r > UINT_MAX) return INFINITY;
- unsigned long int un = (unsigned int)(n), ur = (unsigned int)(r), i;
- unsigned long int result = 1;
- if (ur > un / 2) ur = un - ur;
- for (i = 1; i <= ur; i++) {
- if (result > ULONG_MAX / (un - ur + i))
- return INFINITY;
- result *= un - ur + i;
- result /= i;
- }
- return (double)result;
-}
-static double npr(double n, double r) {return ncr(n, r) * fac(r);}
-
-/* Workaround for a VC 2017 problem */
-static double ceil_(double x) { return ceil(x); }
-static double floor_(double x) { return floor(x); }
-
-static const te_variable functions[] = {
- /* must be in alphabetical order */
- {"abs", {.f1=fabs}, TE_FUNCTION1 | TE_FLAG_PURE, 0},
- {"acos", {.f1=acos}, TE_FUNCTION1 | TE_FLAG_PURE, 0},
- {"asin", {.f1=asin}, TE_FUNCTION1 | TE_FLAG_PURE, 0},
- {"atan", {.f1=atan}, TE_FUNCTION1 | TE_FLAG_PURE, 0},
- {"atan2", {.f2=atan2}, TE_FUNCTION2 | TE_FLAG_PURE, 0},
- {"ceil", {.f1=ceil_}, TE_FUNCTION1 | TE_FLAG_PURE, 0},
- {"cos", {.f1=cos}, TE_FUNCTION1 | TE_FLAG_PURE, 0},
- {"cosh", {.f1=cosh}, TE_FUNCTION1 | TE_FLAG_PURE, 0},
- {"e", {.value = M_E}, TE_CONSTANT, 0},
- {"exp", {.f1=exp}, TE_FUNCTION1 | TE_FLAG_PURE, 0},
- {"fac", {.f1=fac}, TE_FUNCTION1 | TE_FLAG_PURE, 0},
- {"floor", {.f1=floor_}, TE_FUNCTION1 | TE_FLAG_PURE, 0},
- {"if", {.f3 = NULL}, /* Specific treatment, no associated C function */
- TE_FUNCTION3 | TE_CONDITION | TE_FLAG_PURE, 0},
- {"ln", {.f1=log}, TE_FUNCTION1 | TE_FLAG_PURE, 0},
-#ifdef TE_NAT_LOG
- {"log", {.f1=log}, TE_FUNCTION1 | TE_FLAG_PURE, 0},
-#else
- {"log", {.f1=log10}, TE_FUNCTION1 | TE_FLAG_PURE, 0},
-#endif
- {"log10", {.f1=log10}, TE_FUNCTION1 | TE_FLAG_PURE, 0},
- {"ncr", {.f2=ncr}, TE_FUNCTION2 | TE_FLAG_PURE, 0},
- {"npr", {.f2=npr}, TE_FUNCTION2 | TE_FLAG_PURE, 0},
- {"pi", {.value=M_PI}, TE_CONSTANT, 0},
- {"pow", {.f2=pow}, TE_FUNCTION2 | TE_FLAG_PURE, 0},
- {"sin", {.f1=sin}, TE_FUNCTION1 | TE_FLAG_PURE, 0},
- {"sinh", {.f1=sinh}, TE_FUNCTION1 | TE_FLAG_PURE, 0},
- {"sqrt", {.f1=sqrt}, TE_FUNCTION1 | TE_FLAG_PURE, 0},
- {"tan", {.f1=tan}, TE_FUNCTION1 | TE_FLAG_PURE, 0},
- {"tanh", {.f1=tanh}, TE_FUNCTION1 | TE_FLAG_PURE, 0},
- {0, {0}, 0, 0}
-};
-
-static const te_variable *find_builtin(const char *name, size_t len) {
- int imin = 0;
- int imax = sizeof(functions) / sizeof(te_variable) - 2;
-
- /*Binary search.*/
- while (imax >= imin) {
- const int i = (imin + ((imax-imin)/2));
- int c = strncmp(name, functions[i].name, len);
- if (!c) c = '\0' - functions[i].name[len];
- if (c == 0) {
- return functions + i;
- } else if (c > 0) {
- imin = i + 1;
- } else {
- imax = i - 1;
- }
- }
-
- return 0;
-}
-
-static const te_variable *find_lookup(const state *s, const char *name, size_t len) {
- int iters;
- const te_variable *var;
- if (!s->lookup) return 0;
-
- for (var = s->lookup, iters = s->lookup_len; iters; ++var, --iters) {
- if (strncmp(name, var->name, len) == 0 && var->name[len] == '\0') {
- return var;
- }
- }
- return 0;
-}
-
-
-
-static double add(double a, double b) {return a + b;}
-static double sub(double a, double b) {return a - b;}
-static double mul(double a, double b) {return a * b;}
-static double divide(double a, double b) {return a / b;}
-static double negate(double a) {return -a;}
-static double comma(double a, double b) {(void)a; return b;}
-static double is_gt(double a, double b) { return a > b ? 1 : 0; }
-static double is_ge(double a, double b) { return a >= b ? 1 : 0; }
-static double is_lt(double a, double b) { return a < b ? 1 : 0; }
-static double is_le(double a, double b) { return a <= b ? 1 : 0; }
-static double is_eq(double a, double b) { return a == b ? 1 : 0; }
-static double is_neq(double a, double b) { return a != b ? 1 : 0; }
-
-static int next_if(state *s, const char c) {
- int r = *s->next && s->next[0] == c;
- if (r) s->next++;
- return r;
-}
-
-static void next_token(state *s) {
- s->type = TOK_NULL;
-
- do {
-
- if (!*s->next){
- s->type = TOK_END;
- return;
- }
-
- /* Try reading a number. */
- if ((s->next[0] >= '0' && s->next[0] <= '9') || s->next[0] == '.') {
- s->v.value = strtod(s->next, (char**)&s->next);
- s->type = TOK_NUMBER;
- } else {
- /* Look for a variable or builtin function call. */
- if (s->next[0] >= 'a' && s->next[0] <= 'z') {
- const char *start;
- start = s->next;
- while ((s->next[0] >= 'a' && s->next[0] <= 'z') || (s->next[0] >= '0' && s->next[0] <= '9') || (s->next[0] == '_')) s->next++;
-
- const te_variable *var = find_lookup(s, start, (size_t)(s->next - start));
- if (!var) var = find_builtin(start, (size_t)(s->next - start));
-
- if (!var) {
- s->type = TOK_ERROR;
- } else {
- switch(TYPE_MASK(var->type))
- {
- case TE_VARIABLE:
- s->type = TOK_VARIABLE;
- s->v.bound = var->v.bound;
- break;
-
- case TE_OFFSET:
- s->type = TOK_OFFSET;
- s->v.offset = var->v.offset;
- break;
-
- case TE_CONSTANT:
- s->type = TE_CONSTANT;
- s->v.value = var->v.value;
- break;
-
-#ifndef TE_WITHOUT_CLOSURES
- case TE_CLOSURE0: case TE_CLOSURE1: case TE_CLOSURE2: case TE_CLOSURE3:
- case TE_CLOSURE4: case TE_CLOSURE5: case TE_CLOSURE6: case TE_CLOSURE7:
- s->context = var->context;
-#endif
-#ifndef TE_WITHOUT_FUNCTION_0
- /* fall through */
- case TE_FUNCTION0:
-#endif
- /* fall through */
- case TE_FUNCTION1: case TE_FUNCTION2: case TE_FUNCTION3:
-#if TE_MAX_FUNCTION_ARITY >= 4
- /* fall through */
- case TE_FUNCTION4:
-#endif
-#if TE_MAX_FUNCTION_ARITY >= 5
- /* fall through */
- case TE_FUNCTION5:
-#endif
-#if TE_MAX_FUNCTION_ARITY >= 6
- /* fall through */
- case TE_FUNCTION6:
-#endif
-#if TE_MAX_FUNCTION_ARITY == 7
- /* fall through */
- case TE_FUNCTION7:
-#endif
- s->type = var->type;
- s->v.any = var->v.any;
- break;
- }
- }
-
- } else {
- /* Look for an operator or special character. */
- switch (s->next++[0]) {
- case '+': s->type = TOK_INFIX; s->v.f2 = add; break;
- case '-': s->type = TOK_INFIX; s->v.f2 = sub; break;
- case '*': s->type = TOK_INFIX; s->v.f2 = mul; break;
- case '/': s->type = TOK_INFIX; s->v.f2 = divide; break;
- case '^': s->type = TOK_INFIX; s->v.f2 = pow; break;
- case '%': s->type = TOK_INFIX; s->v.f2 = fmod; break;
- case '>': s->type = TOK_INFIX;
- s->v.f2 = next_if(s, '=') ? is_ge : is_gt; break;
- case '<': s->type = TOK_INFIX;
- s->v.f2 = next_if(s, '=') ? is_le : is_lt; break;
- case '=': s->type = TOK_INFIX;
- /* The only valid char after = is = */
- if (next_if(s, '=')) s->v.f2 = is_eq; else s->type = TOK_ERROR;
- break;
- case '!': s->type = TOK_INFIX;
- /* The only valid char after ! is = */
- if (next_if(s, '=')) s->v.f2 = is_neq; else s->type = TOK_ERROR;
- break;
- case '(': s->type = TOK_OPEN; break;
- case ')': s->type = TOK_CLOSE; break;
- case ',': s->type = TOK_SEP; break;
- case ' ': case '\t': case '\n': case '\r': break;
- default: s->type = TOK_ERROR; break;
- }
- }
- }
- } while (s->type == TOK_NULL);
-}
-
-
-static te_expr *list(state *s);
-static te_expr *eql(state *s);
-static te_expr *power(state *s);
-
-static te_expr *base(state *s) {
- /* <base> = <constant> | <variable> | <function-0> {"(" ")"} | <function-1> <power> | <function-X> "(" <expr> {"," <expr>} ")" | "(" <list> ")" */
- te_expr *ret;
- int arity;
-
- switch (TYPE_MASK(s->type)) {
- case TOK_NUMBER:
- ret = new_expr(TE_CONSTANT, 0);
- ret->v.value = s->v.value;
- next_token(s);
- break;
-
- case TOK_VARIABLE:
- ret = new_expr(TE_VARIABLE, 0);
- ret->v.bound = s->v.bound;
- next_token(s);
- break;
-
- case TOK_OFFSET:
- ret = new_expr(TE_OFFSET, 0);
- ret->v.offset = s->v.offset;
- next_token(s);
- break;
-
- case TE_CONSTANT:
- ret = new_expr(TE_CONSTANT, 0);
- ret->v.value = s->v.value;
- next_token(s);
- break;
-
-#if ! defined(TE_WITHOUT_FUNCTION_0) || ! defined(TE_WITHOUT_CLOSURES)
-#ifndef TE_WITHOUT_FUNCTION_0
- case TE_FUNCTION0:
-#endif
-#ifndef TE_WITHOUT_CLOSURES
- case TE_CLOSURE0:
-#endif
- ret = new_expr(s->type, 0);
- ret->v.any = s->v.any;
-#ifndef TE_WITHOUT_CLOSURES
- if (IS_CLOSURE(s->type)) ret->parameters[0] = s->context;
-#endif
- next_token(s);
- if (s->type == TOK_OPEN) {
- next_token(s);
- if (s->type != TOK_CLOSE) {
- s->type = TOK_ERROR;
- } else {
- next_token(s);
- }
- }
- break;
-#endif
-
- case TE_FUNCTION1:
-#ifndef TE_WITHOUT_CLOSURES
- case TE_CLOSURE1:
-#endif
- ret = new_expr(s->type, 0);
- ret->v.any = s->v.any;
-#ifndef TE_WITHOUT_CLOSURES
- if (IS_CLOSURE(s->type)) ret->parameters[1] = s->context;
-#endif
- next_token(s);
- ret->parameters[0] = power(s);
- break;
-
- case TE_FUNCTION2: case TE_FUNCTION3:
-#if TE_MAX_FUNCTION_ARITY >= 4
- case TE_FUNCTION4:
-#endif
-#if TE_MAX_FUNCTION_ARITY >= 5
- case TE_FUNCTION5:
-#endif
-#if TE_MAX_FUNCTION_ARITY >= 6
- case TE_FUNCTION6:
-#endif
-#if TE_MAX_FUNCTION_ARITY == 7
- case TE_FUNCTION7:
-#endif
-#ifndef TE_WITHOUT_CLOSURES
- case TE_CLOSURE2: case TE_CLOSURE3: case TE_CLOSURE4:
- case TE_CLOSURE5: case TE_CLOSURE6: case TE_CLOSURE7:
-#endif
- arity = ARITY(s->type);
-
- ret = new_expr(s->type, 0);
- ret->v.any = s->v.any;
-#ifndef TE_WITHOUT_CLOSURES
- if (IS_CLOSURE(s->type)) ret->parameters[arity] = s->context;
-#endif
- next_token(s);
-
- if (s->type != TOK_OPEN) {
- s->type = TOK_ERROR;
- } else {
- int i;
- for(i = 0; i < arity; i++) {
- next_token(s);
- ret->parameters[i] = eql(s);
- if(s->type != TOK_SEP) {
- break;
- }
- }
- if(s->type != TOK_CLOSE || i != arity - 1) {
- s->type = TOK_ERROR;
- } else {
- next_token(s);
- }
- }
-
- break;
-
- case TOK_OPEN:
- next_token(s);
- ret = list(s);
- if (s->type != TOK_CLOSE) {
- s->type = TOK_ERROR;
- } else {
- next_token(s);
- }
- break;
-
- default:
- ret = new_expr(0, 0);
- s->type = TOK_ERROR;
- ret->v.value = NAN;
- break;
- }
-
- return ret;
-}
-
-
-static te_expr *power(state *s) {
- /* <power> = {("-" | "+")} <base> */
- int sign = 1;
- while (s->type == TOK_INFIX && (s->v.f2 == add || s->v.f2 == sub)) {
- if (s->v.f2 == sub) sign = -sign;
- next_token(s);
- }
-
- te_expr *ret;
-
- if (sign == 1) {
- ret = base(s);
- } else {
- ret = new_expr1(TE_FUNCTION1 | TE_FLAG_PURE, base(s));
- ret->v.f1 = negate;
- }
-
- return ret;
-}
-
-#ifdef TE_POW_FROM_RIGHT
-static te_expr *factor(state *s) {
- /* <factor> = <power> {"^" <power>} */
- te_expr *ret = power(s);
-
- int neg = 0;
- te_expr *insertion = 0;
-
- if (ret->type == (TE_FUNCTION1 | TE_FLAG_PURE) && ret->v.f1 == negate) {
- te_expr *se = ret->parameters[0];
- free(ret);
- ret = se;
- neg = 1;
- }
-
- while (s->type == TOK_INFIX && (s->v.f2 == pow)) {
- te_fun2 t = s->v.f2;
- next_token(s);
-
- if (insertion) {
- /* Make exponentiation go right-to-left. */
- te_expr *insert = new_expr2(TE_FUNCTION2 | TE_FLAG_PURE, insertion->parameters[1], power(s));
- insert->v.f2 = t;
- insertion->parameters[1] = insert;
- insertion = insert;
- } else {
- ret = new_expr2(TE_FUNCTION2 | TE_FLAG_PURE, ret, power(s));
- ret->v.f2 = t;
- insertion = ret;
- }
- }
-
- if (neg) {
- ret = new_expr1(TE_FUNCTION1 | TE_FLAG_PURE, ret);
- ret->v.f1 = negate;
- }
-
- return ret;
-}
-#else
-static te_expr *factor(state *s) {
- /* <factor> = <power> {"^" <power>} */
- te_expr *ret = power(s);
-
- while (s->type == TOK_INFIX && (s->v.f2 == pow)) {
- te_fun2 t = s->v.f2;
- next_token(s);
- ret = new_expr2(TE_FUNCTION2 | TE_FLAG_PURE, ret, power(s));
- ret->v.f2 = t;
- }
-
- return ret;
-}
-#endif
-
-
-
-static te_expr *term(state *s) {
- /* <term> = <factor> {("*" | "/" | "%") <factor>} */
- te_expr *ret = factor(s);
-
- while (s->type == TOK_INFIX && (s->v.f2 == mul || s->v.f2 == divide || s->v.f2 == fmod)) {
- te_fun2 t = s->v.f2;
- next_token(s);
- ret = new_expr2(TE_FUNCTION2 | TE_FLAG_PURE, ret, factor(s));
- ret->v.f2 = t;
- }
-
- return ret;
-}
-
-
-static te_expr *expr(state *s) {
- /* <expr> = <term> {("+" | "-") <term>} */
- te_expr *ret = term(s);
-
- while (s->type == TOK_INFIX && (s->v.f2 == add || s->v.f2 == sub)) {
- te_fun2 t = s->v.f2;
- next_token(s);
- ret = new_expr2(TE_FUNCTION2 | TE_FLAG_PURE, ret, term(s));
- ret->v.f2 = t;
- }
-
- return ret;
-}
-
-
-static te_expr *cmp(state *s) {
- /* <cmp> = <expr> {(">" | "<" | ">=" | "<=") <expr>} */
- te_expr *ret = expr(s);
-
- while (s->type == TOK_INFIX
- && (s->v.f2 == is_lt || s->v.f2 == is_le || s->v.f2 == is_gt || s->v.f2 == is_ge)) {
- te_fun2 t = s->v.f2;
- next_token(s);
- ret = new_expr2(TE_FUNCTION2 | TE_FLAG_PURE, ret, expr(s));
- ret->v.f2 = t;
- }
-
- return ret;
-}
-
-
-static te_expr *eql(state *s) {
- /* <eql> = <cmp> {("==" | "!=") <cmp>} */
- te_expr *ret = cmp(s);
-
- while (s->type == TOK_INFIX && (s->v.f2 == is_eq || s->v.f2 == is_neq)) {
- te_fun2 t = s->v.f2;
- next_token(s);
- ret = new_expr2(TE_FUNCTION2 | TE_FLAG_PURE, ret, cmp(s));
- ret->v.f2 = t;
- }
-
- return ret;
-}
-
-
-static te_expr *list(state *s) {
- /* <list> = <eql> {"," <eql>} */
- te_expr *ret = eql(s);
-
- while (s->type == TOK_SEP) {
- next_token(s);
- ret = new_expr2(TE_FUNCTION2 | TE_FLAG_PURE, ret, eql(s));
- ret->v.f2 = comma;
- }
-
- return ret;
-}
-
-
-#define M(e) te_eval(n->parameters[e], base_addr)
-
-
-double te_eval(const te_expr *n, const void* base_addr) {
- if (!n) return NAN;
-
- switch(TYPE_MASK(n->type)) {
- case TE_CONSTANT: return n->v.value;
- case TE_VARIABLE: return *n->v.bound;
- case TE_OFFSET: assert(base_addr);
- return *(double*)(((char*)base_addr)+n->v.offset);
-
-#ifndef TE_WITHOUT_FUNCTION_0
- case TE_FUNCTION0: return n->v.f0();
-#endif
- case TE_FUNCTION1: return n->v.f1(M(0));
- case TE_FUNCTION2: return n->v.f2(M(0), M(1));
- case TE_FUNCTION3:
- if (IS_CONDITION(n->type)) return M(0) ? M(1) : M(2);
- else return n->v.f3(M(0), M(1), M(2));
-#if TE_MAX_FUNCTION_ARITY >= 4
- case TE_FUNCTION4: return n->v.f4(M(0), M(1), M(2), M(3));
-#endif
-#if TE_MAX_FUNCTION_ARITY >= 5
- case TE_FUNCTION5: return n->v.f5(M(0), M(1), M(2), M(3), M(4));
-#endif
-#if TE_MAX_FUNCTION_ARITY >= 6
- case TE_FUNCTION6: return n->v.f6(M(0), M(1), M(2), M(3), M(4), M(5));
-#endif
-#if TE_MAX_FUNCTION_ARITY == 7
- case TE_FUNCTION7: return n->v.f7(M(0), M(1), M(2), M(3), M(4), M(5), M(6));
-#endif
-
-#ifndef TE_WITHOUT_CLOSURES
- case TE_CLOSURE0: return n->v.cl0(n->parameters[0]);
- case TE_CLOSURE1: return n->v.cl1(n->parameters[1], M(0));
- case TE_CLOSURE2: return n->v.cl2(n->parameters[2], M(0), M(1));
- case TE_CLOSURE3: return n->v.cl3(n->parameters[3], M(0), M(1), M(2));
- case TE_CLOSURE4: return n->v.cl4(n->parameters[4], M(0), M(1), M(2), M(3));
- case TE_CLOSURE5: return n->v.cl5(n->parameters[5], M(0), M(1), M(2), M(3), M(4));
- case TE_CLOSURE6: return n->v.cl6(n->parameters[6], M(0), M(1), M(2), M(3), M(4), M(5));
- case TE_CLOSURE7: return n->v.cl7(n->parameters[7], M(0), M(1), M(2), M(3), M(4), M(5), M(6));
-#endif
-
- default: return NAN;
- }
-
-}
-
-#undef M
-
-static int expr_equal(const te_expr* e1, const te_expr* e2) {
- int i;
- if (e1->type != e2->type) return 0;
- if (e1->v.any != e2->v.any) return 0;
- for (i = 0; i < ARITY(e1->type); i++) {
- if(!expr_equal(e1->parameters[i], e2->parameters[i])) return 0;
- }
- return 1;
-}
-
-static void optimize(te_expr *n) {
- /* Only optimize out conditions and functions flagged as pure. */
- if (IS_CONDITION(n->type)) {
- te_expr* cond = n->parameters[0];
- assert(IS_FUNCTION(n->type) && ARITY(n->type) == 3);
- optimize(cond);
- if (cond->type == TE_CONSTANT) {
- te_expr* keep = (cond->v.value) ? n->parameters[1] : n->parameters[2];
- /* Can keep either param[1] or param[2] */
- optimize(keep);
- n->type = keep->type;
- n->v.any = keep->v.any;
- te_free_parameters(n);
- }
- else { /* c ? x : x is x */
- te_expr* if_branch = n->parameters[1];
- te_expr* else_branch = n->parameters[2];
- optimize(if_branch);
- optimize(else_branch);
- if (expr_equal(if_branch, else_branch)) {
- n->type = if_branch->type;
- n->v.any = if_branch->v.any;
- te_free_parameters(n);
- }
- }
- }
- else if (IS_PURE(n->type)) {
- const int arity = ARITY(n->type);
- int known = 1;
- int i;
- assert(IS_FUNCTION(n->type));
- for (i = 0; i < arity; ++i) {
- optimize(n->parameters[i]);
- if (((te_expr*)(n->parameters[i]))->type != TE_CONSTANT) {
- known = 0;
- }
- }
- if (known) {
- const double value = te_eval(n, NULL);
- te_free_parameters(n);
- n->type = TE_CONSTANT;
- n->v.value = value;
- }
- }
-}
-
-
-te_expr *te_compile(const char *expression, const te_variable *variables, int var_count, int *error) {
- state s;
- s.start = s.next = expression;
- s.lookup = variables;
- s.lookup_len = var_count;
-
- next_token(&s);
- te_expr *root = list(&s);
-
- if (s.type != TOK_END) {
- te_free(root);
- if (error) {
- *error = (int)(s.next - s.start);
- if (*error == 0) *error = 1;
- }
- return 0;
- } else {
- optimize(root);
- if (error) *error = 0;
- return root;
- }
-}
-
-
-double te_interp(const char *expression, int *error) {
- te_expr *n = te_compile(expression, 0, 0, error);
- double ret;
- if (n) {
- ret = te_eval(n, NULL);
- te_free(n);
- } else {
- ret = NAN;
- }
- return ret;
-}
-
-static void pn (const te_expr *n, int depth) {
- int i, arity;
- printf("%*s", depth, "");
-
- switch(TYPE_MASK(n->type)) {
- case TE_CONSTANT: printf("%f\n", n->v.value); break;
- case TE_VARIABLE: printf("bound %p\n", (void*) n->v.bound); break;
- case TE_OFFSET: printf("offset %zu\n", n->v.offset); break;
-
-#ifndef TE_WITHOUT_FUNCTION_0
- case TE_FUNCTION0:
-#endif
- case TE_FUNCTION1: case TE_FUNCTION2: case TE_FUNCTION3:
-#if TE_MAX_FUNCTION_ARITY >= 4
- case TE_FUNCTION4:
-#endif
-#if TE_MAX_FUNCTION_ARITY >= 5
- case TE_FUNCTION5:
-#endif
-#if TE_MAX_FUNCTION_ARITY >= 6
- case TE_FUNCTION6:
-#endif
-#if TE_MAX_FUNCTION_ARITY == 7
- case TE_FUNCTION7:
-#endif
-#ifndef TE_WITHOUT_CLOSURES
- case TE_CLOSURE0: case TE_CLOSURE1: case TE_CLOSURE2: case TE_CLOSURE3:
- case TE_CLOSURE4: case TE_CLOSURE5: case TE_CLOSURE6: case TE_CLOSURE7:
-#endif
- arity = ARITY(n->type);
- printf("f%d", arity);
- for(i = 0; i < arity; i++) {
- printf(" %p", n->parameters[i]);
- }
- printf("\n");
- for(i = 0; i < arity; i++) {
- pn(n->parameters[i], depth + 1);
- }
- break;
- }
-}
-
-
-void te_print(const te_expr *n) {
- pn(n, 0);
-}
diff --git a/tinyexpr/tinyexpr.h b/tinyexpr/tinyexpr.h
@@ -1,197 +0,0 @@
-/*
- * TINYEXPR - Tiny recursive descent parser and evaluation engine in C
- *
- * Copyright (c) 2015-2018 Lewis Van Winkle
- *
- * http://CodePlea.com
- *
- * This software is provided 'as-is', without any express or implied
- * warranty. In no event will the authors be held liable for any damages
- * arising from the use of this software.
- *
- * Permission is granted to anyone to use this software for any purpose,
- * including commercial applications, and to alter it and redistribute it
- * freely, subject to the following restrictions:
- *
- * 1. The origin of this software must not be misrepresented; you must not
- * claim that you wrote the original software. If you use this software
- * in a product, an acknowledgement in the product documentation would be
- * appreciated but is not required.
- * 2. Altered source versions must be plainly marked as such, and must not be
- * misrepresented as being the original software.
- * 3. This notice may not be removed or altered from any source distribution.
- */
-
-#ifndef __TINYEXPR_H__
-#define __TINYEXPR_H__
-
-#include <stddef.h>
-
-/* Helper macro to be used when defining a te_variable */
-#define TE_DEF_VARIABLE(Name, Var) {(Name), {.var=&(Var)}, TE_VARIABLE, NULL}
-#define TE_DEF_OFFSET(Name, Offset) {(Name), {.offset=(Offset)}, TE_OFFSET, NULL}
-#define TE_DEF_CONSTANT(Name, Value) {(Name), {.value=(Value)}, TE_CONSTANT, NULL}
-#define TE_DEF_FUNCTION(Name, Fun, Arity) {(Name), {.f##Arity=(Fun)}, TE_FUNCTION##Arity, NULL}
-#ifndef TE_WITHOUT_CLOSURES
-#define TE_DEF_CLOSURE(Name, Closure, Arity, Ctx) {(Name), {.cl##Arity=(Closure)}, TE_CLOSURE##Arity, (Ctx)}
-#endif
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#ifdef TE_MAX_FUNCTION_ARITY
-#if !(TE_MAX_FUNCTION_ARITY >= 3 && TE_MAX_FUNCTION_ARITY <= 7)
-#error Valid range for TE_MAX_FUNCTION_ARITY is [3 7]
-#endif
-#else
-#define TE_MAX_FUNCTION_ARITY 7
-#endif
-
-
-#ifndef TE_WITHOUT_FUNCTION_0
-#define FUN_TYPE_0 \
- double(*f0)(void);
-#else
-#define FUN_TYPE_0
-#endif
-#define FUN_TYPES_1_3 \
- void *any;\
- double(*f1)(double);\
- double(*f2)(double, double);\
- double(*f3)(double, double, double);
-#if TE_MAX_FUNCTION_ARITY >= 4
-#define FUN_TYPE_4 \
- double(*f4)(double, double, double, double);
-#else
-#define FUN_TYPE_4
-#endif
-#if TE_MAX_FUNCTION_ARITY >= 5
-#define FUN_TYPE_5 \
- double(*f5)(double, double, double, double, double);
-#else
-#define FUN_TYPE_5
-#endif
-#if TE_MAX_FUNCTION_ARITY >= 6
-#define FUN_TYPE_6 \
- double(*f6)(double, double, double, double, double, double);
-#else
-#define FUN_TYPE_6
-#endif
-#if TE_MAX_FUNCTION_ARITY == 7
-#define FUN_TYPE_7 \
- double(*f7)(double, double, double, double, double, double, double);
-#else
-#define FUN_TYPE_7
-#endif
-
-#ifndef TE_WITHOUT_CLOSURES
-#define CLOSURE_TYPES \
- double(*cl0)(void*);\
- double(*cl1)(void*, double);\
- double(*cl2)(void*, double, double);\
- double(*cl3)(void*, double, double, double);\
- double(*cl4)(void*, double, double, double, double);\
- double(*cl5)(void*, double, double, double, double, double);\
- double(*cl6)(void*, double, double, double, double, double, double);\
- double(*cl7)(void*, double, double, double, double, double, double, double);
-#else
-#define CLOSURE_TYPES
-#endif
-
-union fun {
- FUN_TYPE_0
- FUN_TYPES_1_3
- FUN_TYPE_4
- FUN_TYPE_5
- FUN_TYPE_6
- FUN_TYPE_7
- CLOSURE_TYPES
-};
-
-union value {
- FUN_TYPE_0
- FUN_TYPES_1_3
- FUN_TYPE_4
- FUN_TYPE_5
- FUN_TYPE_6
- FUN_TYPE_7
- CLOSURE_TYPES
- double value;
- const double *var;
- size_t offset;
- const double *bound;
-};
-
-typedef struct te_expr {
- int type;
- union value v;
- void *parameters[1];
-} te_expr;
-
-
-enum {
- TE_VARIABLE = 0,
- TE_OFFSET = 1,
- TE_CONSTANT = 2,
-
-#ifndef TE_WITHOUT_FUNCTION_0
- TE_FUNCTION0 = 8,
-#endif
- TE_FUNCTION1 = 9, TE_FUNCTION2, TE_FUNCTION3,
-#if TE_MAX_FUNCTION_ARITY >= 4
- TE_FUNCTION4,
-#endif
-#if TE_MAX_FUNCTION_ARITY >= 5
- TE_FUNCTION5,
-#endif
-#if TE_MAX_FUNCTION_ARITY >= 6
- TE_FUNCTION6,
-#endif
-#if TE_MAX_FUNCTION_ARITY == 7
- TE_FUNCTION7,
-#endif
-#ifndef TE_WITHOUT_CLOSURES
- TE_CLOSURE0 = 16, TE_CLOSURE1, TE_CLOSURE2, TE_CLOSURE3,
- TE_CLOSURE4, TE_CLOSURE5, TE_CLOSURE6, TE_CLOSURE7,
-#endif
- TE_FLAG_PURE = 64
-};
-
-typedef struct te_variable {
- const char *name;
- const union value v;
- int type;
- /* context could be member only if TE_WITHOUT_CLOSURES is undefined
- * we don't take the opportunity as it would add too much complexity */
- void *context;
-} te_variable;
-
-
-
-/* Parses the input expression, evaluates it, and frees it. */
-/* Returns NaN on error. */
-double te_interp(const char *expression, int *error);
-
-/* Parses the input expression and binds variables. */
-/* Returns NULL on error. */
-te_expr *te_compile(const char *expression, const te_variable *variables, int var_count, int *error);
-
-/* Evaluates the expression. */
-double te_eval(const te_expr *n, const void* base_addr);
-
-/* Prints debugging information on the syntax tree. */
-void te_print(const te_expr *n);
-
-/* Frees the expression. */
-/* This is safe to call on NULL pointers. */
-void te_free(te_expr *n);
-
-/* Duplicates a te_expr */
-te_expr* te_duplicate(te_expr* n);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /*__TINYEXPR_H__*/