commit 1ba3244d6b9eaf2c4f5d3b065c474ca7af7e4612
parent 592fdcacb4d294c779742ebca5015b83042cdd48
Author: Vincent Forest <vincent.forest@meso-star.com>
Date: Fri, 8 Feb 2019 14:39:51 +0100
Full rewrite of the green function internal API
Diffstat:
| M | src/sdis_green.c | | | 396 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++---------------- |
| M | src/sdis_green.h | | | 167 | +++++++++++-------------------------------------------------------------------- |
2 files changed, 338 insertions(+), 225 deletions(-)
diff --git a/src/sdis_green.c b/src/sdis_green.c
@@ -18,67 +18,197 @@
#include "sdis_medium_c.h"
#include "sdis_interface_c.h"
+#include <rsys/dynamic_array.h>
#include <rsys/mem_allocator.h>
+#include <rsys/ref_count.h>
+
+#include "sdis_scene_c.h" /* struct darray_<medium|interface> */
+
+#include <rsys/dynamic_array.h>
+#include <rsys/ref_count.h>
+
+struct green_vertex {
+ double pos[3]; /* Position */
+ double delta_time; /* Time "spent" into the system */
+ unsigned id; /* Id of the medium/interface onto wich the vertex lies */
+};
+#define GREEN_VERTEX_NULL__ {{INF,INF,INF}, INF, UINT_MAX}
+static const struct green_vertex GREEN_VERTEX_NULL = GREEN_VERTEX_NULL__;
+
+struct green_term {
+ double term; /* Term computed during green estimation */
+ unsigned id; /* Identifier of the medium/interface of the term */
+};
+#define GREEN_TERM_NULL__ {INF, UINT_MAX}
+static const struct green_term GREEN_TERM_NULL = GREEN_TERM_NULL__;
+
+static INLINE void
+green_term_init(struct mem_allocator* allocator, struct green_term* term)
+{
+ ASSERT(term); (void)allocator;
+ *term = GREEN_TERM_NULL;
+}
+
+/* Generate the dynamic array of green vertices */
+#define DARRAY_NAME green_term
+#define DARRAY_DATA struct green_term
+#define DARRAY_FUNCTOR_INIT green_term_init
+#include <rsys/dynamic_array.h>
+
+struct green_path {
+ struct darray_green_term flux_terms; /* List of flux terms */
+ struct darray_green_term power_terms; /* List of volumic power terms */
+ struct green_vertex limit_vertex; /* End vertex of the path */
+ int end_on_interface; /* Define if the limit vertex lies on an interface */
+
+ /* Indices of the last accessed medium/interface. Used to speed up the access
+ * to the medium/interface. */
+ uint16_t ilast_medium;
+ uint16_t ilast_interf;
+};
+
+static INLINE void
+green_path_init(struct mem_allocator* allocator, struct green_path* path)
+{
+ ASSERT(path);
+ darray_green_term_init(allocator, &path->flux_terms);
+ darray_green_term_init(allocator, &path->power_terms);
+ path->limit_vertex = GREEN_VERTEX_NULL;
+ path->end_on_interface = 0;
+ path->ilast_medium = UINT16_MAX;
+ path->ilast_interf = UINT16_MAX;
+}
+
+static INLINE void
+green_path_release(struct green_path* path)
+{
+ ASSERT(path);
+ darray_green_term_release(&path->flux_terms);
+ darray_green_term_release(&path->power_terms);
+}
+
+static INLINE res_T
+green_path_copy(struct green_path* dst, const struct green_path* src)
+{
+ res_T res = RES_OK;
+ ASSERT(dst && src);
+ dst->limit_vertex = src->limit_vertex;
+ dst->end_on_interface = src->end_on_interface;
+ dst->ilast_medium = src->ilast_medium;
+ dst->ilast_interf = src->ilast_interf;
+ res = darray_green_term_copy(&dst->flux_terms, &src->flux_terms);
+ if(res != RES_OK) return res;
+ res = darray_green_term_copy(&dst->power_terms, &src->power_terms);
+ if(res != RES_OK) return res;
+ return RES_OK;
+}
+
+static INLINE res_T
+green_path_copy_and_release(struct green_path* dst, struct green_path* src)
+{
+ res_T res = RES_OK;
+ ASSERT(dst && src);
+ dst->limit_vertex = src->limit_vertex;
+ dst->end_on_interface = src->end_on_interface;
+ dst->ilast_medium = src->ilast_medium;
+ dst->ilast_interf = src->ilast_interf;
+ res = darray_green_term_copy_and_release(&dst->flux_terms, &src->flux_terms);
+ if(res != RES_OK) return res;
+ res = darray_green_term_copy_and_release(&dst->power_terms, &src->power_terms);
+ if(res != RES_OK) return res;
+ return RES_OK;
+}
+
+/* Generate the dynamic array of green paths */
+#define DARRAY_NAME green_path
+#define DARRAY_DATA struct green_path
+#define DARRAY_FUNCTOR_INIT green_path_init
+#define DARRAY_FUNCTOR_RELEASE green_path_release
+#define DARRAY_FUNCTOR_COPY green_path_copy
+#define DARRAY_FUNCTOR_COPY_AND_RELEASE green_path_copy_and_release
+#include <rsys/dynamic_array.h>
+
+struct sdis_green_function {
+ struct darray_medium media; /* List of registered media */
+ struct darray_interf interfaces; /* List of registered interfaces */
+ struct darray_green_path paths; /* List of paths used to estimate the green */
+
+ /* Indices of the last accessed medium/interface used to speed up the access
+ * to the medium/interface. */
+ size_t ilast_medium;
+ size_t ilast_interf;
+
+ ref_T ref;
+ struct sdis_device* dev;
+};
/*******************************************************************************
* Helper functions
******************************************************************************/
-static struct green_medium*
-fetch_green_medium
- (struct sdis_green_function* green, struct sdis_medium* mdm)
+static res_T
+ensure_medium_registration
+ (struct sdis_green_function* green,
+ struct sdis_medium* mdm)
{
- struct green_medium* gmdm = NULL;
size_t i;
res_T res = RES_OK;
ASSERT(green && mdm);
- i = medium_get_id(mdm);
+ /* Early find */
+ if(green->ilast_medium < darray_medium_size_get(&green->media)
+ && darray_medium_cdata_get(&green->media)[green->ilast_medium] == mdm)
+ goto exit;
- /* Ensure that the LUT can store the medium */
- if(i >= darray_green_medium_size_get(&green->media)) {
- res = darray_green_medium_resize(&green->media, i+1);
- if(res != RES_OK) goto error;
+ /* Linear search of the submitted medium */
+ FOR_EACH(i, 0, darray_medium_size_get(&green->media)) {
+ if(darray_medium_cdata_get(&green->media)[i] == mdm) break;
}
- gmdm = darray_green_medium_data_get(&green->media) + i;
- if(!gmdm->mdm) {
- /* Register the medium against the green function */
+ /* Register the medium if it is not already registered */
+ if(i >= darray_medium_size_get(&green->media)) {
SDIS(medium_ref_get(mdm));
- gmdm->mdm = mdm;
+ res = darray_medium_push_back(&green->media, &mdm);
+ if(res != RES_OK) goto error;
}
+ green->ilast_medium = i;
+
exit:
- return res != RES_OK ? NULL : gmdm;
+ return res;
error:
goto exit;
}
-static struct green_interface*
-fetch_green_interface
- (struct sdis_green_function* green, struct sdis_interface* interf)
+static res_T
+ensure_interface_registration
+ (struct sdis_green_function* green,
+ struct sdis_interface* interf)
{
- struct green_interface* ginterf = NULL;
size_t i;
res_T res = RES_OK;
ASSERT(green && interf);
- i = interface_get_id(interf);
+ /* Early find */
+ if(green->ilast_interf < darray_interf_size_get(&green->interfaces)
+ && darray_interf_cdata_get(&green->interfaces)[green->ilast_interf] == interf)
+ goto exit;
- /* Ensure that the LUT can store the interface */
- if(i >= darray_green_interface_size_get(&green->interfaces)) {
- res = darray_green_interface_resize(&green->interfaces, i+1);
- if(res != RES_OK) goto error;
+ /* Linear search of the submitted interface */
+ FOR_EACH(i, 0, darray_interf_size_get(&green->interfaces)) {
+ if(darray_interf_cdata_get(&green->interfaces)[i] == interf) break;
}
- ginterf = darray_green_interface_data_get(&green->interfaces) + i;
- if(!ginterf->interf) {
- /* Register the interface against the green function */
+ /* Register the interface if it is not already registered */
+ if(i >= darray_interf_size_get(&green->interfaces)) {
SDIS(interface_ref_get(interf));
- ginterf->interf = interf;
+ res = darray_interf_push_back(&green->interfaces, &interf);
+ if(res != RES_OK) goto error;
}
+ green->ilast_interf = i;
+
exit:
- return res != RES_OK ? NULL : ginterf;
+ return res;
error:
goto exit;
}
@@ -86,28 +216,20 @@ error:
static void
green_function_clear(struct sdis_green_function* green)
{
- size_t i, n;
- struct green_medium* media;
- struct green_interface* interfaces;
+ size_t i;
ASSERT(green);
- n = darray_green_medium_size_get(&green->media);
- media = darray_green_medium_data_get(&green->media);
- FOR_EACH(i, 0, n) {
- if(media[i].mdm) {
- SDIS(medium_ref_put(media[i].mdm));
- }
+ FOR_EACH(i, 0, darray_medium_size_get(&green->media)) {
+ SDIS(medium_ref_put(darray_medium_data_get(&green->media)[i]));
}
- darray_green_medium_clear(&green->media);
-
- n = darray_green_interface_size_get(&green->interfaces);
- interfaces = darray_green_interface_data_get(&green->interfaces);
- FOR_EACH(i, 0, n) {
- if(interfaces[i].interf) {
- SDIS(interface_ref_put(interfaces[i].interf));
- }
+ darray_medium_clear(&green->media);
+
+ FOR_EACH(i, 0, darray_interf_size_get(&green->interfaces)) {
+ SDIS(interface_ref_put(darray_interf_data_get(&green->interfaces)[i]));
}
- darray_green_interface_clear(&green->interfaces);
+ darray_interf_clear(&green->interfaces);
+
+ darray_green_path_clear(&green->paths);
}
static void
@@ -119,8 +241,9 @@ green_function_release(ref_T* ref)
green = CONTAINER_OF(ref, struct sdis_green_function, ref);
dev = green->dev;
green_function_clear(green);
- darray_green_medium_release(&green->media);
- darray_green_interface_release(&green->interfaces);
+ darray_medium_release(&green->media);
+ darray_interf_release(&green->interfaces);
+ darray_green_path_release(&green->paths);
MEM_RM(dev->allocator, green);
SDIS(device_ref_put(dev));
}
@@ -144,8 +267,11 @@ green_function_create
ref_init(&green->ref);
SDIS(device_ref_get(dev));
green->dev = dev;
- darray_green_medium_init(dev->allocator, &green->media);
- darray_green_interface_init(dev->allocator, &green->interfaces);
+ darray_medium_init(dev->allocator, &green->media);
+ darray_interf_init(dev->allocator, &green->interfaces);
+ darray_green_path_init(dev->allocator, &green->paths);
+ green->ilast_medium = SIZE_MAX;
+ green->ilast_interf = SIZE_MAX;
exit:
*out_green = green;
@@ -173,56 +299,164 @@ green_function_ref_put(struct sdis_green_function* green)
}
res_T
-green_function_add_medium_limit_vertex
+green_function_create_path
(struct sdis_green_function* green,
+ struct green_path_handle* handle)
+{
+ size_t n;
+ res_T res = RES_OK;
+ ASSERT(green && handle);
+
+ n = darray_green_path_size_get(&green->paths);
+ res = darray_green_path_resize(&green->paths, n+1);
+ if(res != RES_OK) return res;
+
+ handle->green = green;
+ handle->path = darray_green_path_data_get(&green->paths) + n;
+ return RES_OK;
+}
+
+res_T
+green_path_add_medium_limit_vertex
+ (struct green_path_handle* handle,
struct sdis_medium* mdm,
- const struct green_vertex* vertex)
+ const double pos[3],
+ const double delta_time)
{
- struct green_medium* gmdm = NULL;
- ASSERT(green && mdm && vertex);
- gmdm = fetch_green_medium(green, mdm);
- if(!gmdm) return RES_MEM_ERR;
- return darray_green_vertex_push_back(&gmdm->limit_vertices, vertex);
+ res_T res = RES_OK;
+ ASSERT(handle && mdm && pos);
+ res = ensure_medium_registration(handle->green, mdm);
+ if(res != RES_OK) return res;
+ handle->path->limit_vertex.pos[0] = pos[0];
+ handle->path->limit_vertex.pos[1] = pos[1];
+ handle->path->limit_vertex.pos[2] = pos[2];
+ handle->path->limit_vertex.delta_time = delta_time;
+ handle->path->limit_vertex.id = medium_get_id(mdm);
+ handle->path->end_on_interface = 0;
+ return RES_OK;
}
res_T
-green_function_add_interface_limit_vertex
- (struct sdis_green_function* green,
+green_path_add_interface_limit_vertex
+ (struct green_path_handle* handle,
struct sdis_interface* interf,
- const struct green_vertex* vertex)
+ const double pos[3],
+ const double delta_time)
{
- struct green_interface* ginterf = NULL;
- ASSERT(green && interf && vertex);
- ginterf = fetch_green_interface(green, interf);
- if(!ginterf) return RES_MEM_ERR;
- return darray_green_vertex_push_back(&ginterf->limit_vertices, vertex);
+ res_T res = RES_OK;
+ ASSERT(handle && interf && pos);
+ res = ensure_interface_registration(handle->green, interf);
+ if(res != RES_OK) return res;
+ handle->path->limit_vertex.pos[0] = pos[0];
+ handle->path->limit_vertex.pos[1] = pos[1];
+ handle->path->limit_vertex.pos[2] = pos[2];
+ handle->path->limit_vertex.delta_time = delta_time;
+ handle->path->limit_vertex.id = interface_get_id(interf);
+ handle->path->end_on_interface = 1;
+ return RES_OK;
}
res_T
-green_function_add_power_term
- (struct sdis_green_function* green,
+green_path_add_power_term
+ (struct green_path_handle* handle,
struct sdis_medium* mdm,
const double term)
{
- struct green_medium* gmdm = NULL;
- ASSERT(green && mdm && term >= 0);
- gmdm = fetch_green_medium(green, mdm);
- if(!gmdm) return RES_MEM_ERR;
- gmdm->power_term += term;
- return RES_OK;
+ struct green_path* path;
+ struct green_term* terms;
+ size_t nterms;
+ size_t iterm;
+ unsigned id;
+ res_T res = RES_OK;
+ ASSERT(handle && mdm && term >= 0);
+
+ res = ensure_medium_registration(handle->green, mdm);
+ if(res != RES_OK) goto error;
+
+ path = handle->path;
+ terms = darray_green_term_data_get(&path->power_terms);
+ nterms = darray_green_term_size_get(&path->power_terms);
+ id = medium_get_id(mdm);
+ iterm = SIZE_MAX;
+
+ /* Early find */
+ if(path->ilast_medium < nterms && terms[path->ilast_medium].id == id) {
+ iterm = path->ilast_medium;
+ } else {
+ /* Linear search of the submitted medium */
+ FOR_EACH(iterm, 0, nterms) if(terms[iterm].id == id) break;
+ }
+
+ /* Add the power term to the path wrt the submitted medium */
+ if(iterm < nterms) {
+ terms[iterm].term += term;
+ } else {
+ struct green_term gterm = GREEN_TERM_NULL;
+ gterm.term = term;
+ gterm.id = id;
+ res = darray_green_term_push_back(&handle->path->power_terms, >erm);
+ if(res != RES_OK) goto error;
+ }
+
+ /* Register the slot into which the last accessed medium lies */
+ CHK(iterm < UINT16_MAX);
+ path->ilast_medium = (uint16_t)iterm;
+
+exit:
+ return res;
+error:
+ goto exit;
}
res_T
-green_function_add_flux_term
- (struct sdis_green_function* green,
+green_path_add_flux_term
+ (struct green_path_handle* handle,
struct sdis_interface* interf,
const double term)
{
- struct green_interface* ginterf = NULL;
- ASSERT(green && interf && term >= 0);
- ginterf = fetch_green_interface(green, interf);
- if(!ginterf) return RES_MEM_ERR;
- ginterf->flux_term += term;
- return RES_OK;
+ struct green_path* path;
+ struct green_term* terms;
+ size_t nterms;
+ size_t iterm;
+ unsigned id;
+ res_T res = RES_OK;
+ ASSERT(handle && interf && term >= 0);
+
+ res = ensure_interface_registration(handle->green, interf);
+ if(res != RES_OK) goto error;
+
+ path = handle->path;
+ terms = darray_green_term_data_get(&path->flux_terms);
+ nterms = darray_green_term_size_get(&path->flux_terms);
+ id = interface_get_id(interf);
+ iterm = SIZE_MAX;
+
+ /* Early find */
+ if(path->ilast_interf < nterms && terms[path->ilast_interf].id == id) {
+ iterm = path->ilast_interf;
+ } else {
+ /* Linear search of the submitted interface */
+ FOR_EACH(iterm, 0, nterms) if(terms[iterm].id == id) break;
+ }
+
+ /* Add the flux term to the path wrt the submitted interface */
+ if(iterm < nterms) {
+ terms[iterm].term += term;
+ } else {
+ struct green_term gterm = GREEN_TERM_NULL;
+ gterm.term = term;
+ gterm.id = id;
+ res = darray_green_term_push_back(&handle->path->flux_terms, >erm);
+ if(res != RES_OK) goto error;
+ }
+
+ /* Register the slot into which the last accessed interface lies */
+ CHK(iterm < UINT16_MAX);
+ path->ilast_interf = (uint16_t)iterm;
+
+exit:
+ return res;
+error:
+ goto exit;
}
diff --git a/src/sdis_green.h b/src/sdis_green.h
@@ -16,143 +16,15 @@
#ifndef SDIS_GREEN_H
#define SDIS_GREEN_H
-#include <rsys/dynamic_array.h>
-#include <rsys/ref_count.h>
+#include <rsys/rsys.h>
-/*******************************************************************************
- * Spatio temporal vertices registered against the green function
- ******************************************************************************/
-struct green_vertex {
- double pos[3];
- double delta_time; /* Time spent into the system */
-};
-
-/* Generate the dynamic array of green vertices */
-#define DARRAY_NAME green_vertex
-#define DARRAY_DATA struct green_vertex
-#include <rsys/dynamic_array.h>
-
-/*******************************************************************************
- * Medium registered against the green function
- ******************************************************************************/
-struct green_medium {
- struct sdis_medium* mdm;
- double power_term;
- struct darray_green_vertex limit_vertices;
-};
-
-static INLINE void
-green_medium_init
- (struct mem_allocator* allocator, struct green_medium* gmdm)
-{
- ASSERT(gmdm);
- gmdm->mdm = NULL;
- gmdm->power_term = 0;
- darray_green_vertex_init(allocator, &gmdm->limit_vertices);
-}
-
-static INLINE void
-green_medium_release(struct green_medium* gmdm)
-{
- ASSERT(gmdm);
- darray_green_vertex_release(&gmdm->limit_vertices);
-}
-
-static INLINE res_T
-green_medium_copy
- (struct green_medium* dst, const struct green_medium* src)
-{
- ASSERT(dst && src);
- dst->mdm = src->mdm;
- dst->power_term = src->power_term;
- return darray_green_vertex_copy(&dst->limit_vertices, &src->limit_vertices);
-}
-
-static INLINE res_T
-green_medium_copy_and_release
- (struct green_medium* dst, struct green_medium* src)
-{
- ASSERT(dst && src);
- dst->mdm = src->mdm;
- dst->power_term = src->power_term;
- return darray_green_vertex_copy_and_release
- (&dst->limit_vertices, &src->limit_vertices);
-}
-
-/* Generate the dynamic array of media registered in the green function */
-#define DARRAY_NAME green_medium
-#define DARRAY_DATA struct green_medium
-#define DARRAY_FUNCTOR_INIT green_medium_init
-#define DARRAY_FUNCTOR_RELEASE green_medium_release
-#define DARRAY_FUNCTOR_COPY green_medium_copy
-#define DARRAY_FUNCTOR_COPY_AND_RELEASE green_medium_copy_and_release
-#include <rsys/dynamic_array.h>
-
-/*******************************************************************************
- * Interface registered against the green function
- ******************************************************************************/
-struct green_interface {
- struct sdis_interface* interf;
- double flux_term;
- struct darray_green_vertex limit_vertices;
-};
+/* Forward declaration */
+struct sdis_green_function;
+struct green_path;
-static INLINE void
-green_interface_init
- (struct mem_allocator* allocator, struct green_interface* ginter)
-{
- ASSERT(ginter);
- ginter->interf = NULL;
- ginter->flux_term = 0;
- darray_green_vertex_init(allocator, &ginter->limit_vertices);
-}
-
-static INLINE void
-green_interface_release(struct green_interface* ginter)
-{
- ASSERT(ginter);
- darray_green_vertex_release(&ginter->limit_vertices);
-}
-
-static INLINE res_T
-green_interface_copy
- (struct green_interface* dst, const struct green_interface* src)
-{
- ASSERT(dst && src);
- dst->interf = src->interf;
- dst->flux_term = src->flux_term;
- return darray_green_vertex_copy(&dst->limit_vertices, &src->limit_vertices);
-}
-
-static INLINE res_T
-green_interface_copy_and_release
- (struct green_interface* dst, struct green_interface* src)
-{
- ASSERT(dst && src);
- dst->interf = src->interf;
- dst->flux_term = src->flux_term;
- return darray_green_vertex_copy_and_release
- (&dst->limit_vertices, &src->limit_vertices);
-}
-
-/* Generate the dynamic array of interfaces registered in the green function */
-#define DARRAY_NAME green_interface
-#define DARRAY_DATA struct green_interface
-#define DARRAY_FUNCTOR_INIT green_interface_init
-#define DARRAY_FUNCTOR_RELEASE green_interface_release
-#define DARRAY_FUNCTOR_COPY green_interface_copy
-#define DARRAY_FUNCTOR_COPY_AND_RELEASE green_interface_copy_and_release
-#include <rsys/dynamic_array.h>
-
-/*******************************************************************************
- * Green function private API
- ******************************************************************************/
-struct sdis_green_function {
- struct darray_green_medium media;
- struct darray_green_interface interfaces;
-
- ref_T ref;
- struct sdis_device* dev;
+struct green_path_handle {
+ struct sdis_green_function* green;
+ struct green_path* path;
};
extern LOCAL_SYM res_T
@@ -169,26 +41,33 @@ green_function_ref_put
(struct sdis_green_function* green);
extern LOCAL_SYM res_T
-green_function_add_medium_limit_vertex
+green_function_create_path
(struct sdis_green_function* green,
+ struct green_path_handle* handle);
+
+extern LOCAL_SYM res_T
+green_path_add_medium_limit_vertex
+ (struct green_path_handle* path,
struct sdis_medium* mdm,
- const struct green_vertex* vertex);
+ const double pos[3],
+ const double delta_time);
extern LOCAL_SYM res_T
-green_function_add_interface_limit_vertex
- (struct sdis_green_function* green,
+green_path_add_interface_limit_vertex
+ (struct green_path_handle* path,
struct sdis_interface* interf,
- const struct green_vertex* vertex);
+ const double pos[3],
+ const double delta_time);
extern LOCAL_SYM res_T
-green_function_add_power_term
- (struct sdis_green_function* green,
+green_path_add_power_term
+ (struct green_path_handle* path,
struct sdis_medium* mdm,
const double term);
extern LOCAL_SYM res_T
-green_function_add_flux_term
- (struct sdis_green_function* green,
+green_path_add_flux_term
+ (struct green_path_handle* path,
struct sdis_interface* interf,
const double term);