gsl-shell.git - gsl-shell

index : gsl-shell.git
gsl-shell
summary refs log tree commit diff
diff options
context:
space:
mode:
Diffstat
-rw-r--r--Makefile 19
-rw-r--r--agg-plot/Makefile 2
-rw-r--r--agg-plot/factor_labels.h 28
-rw-r--r--agg-plot/lua-draw.cpp 20
-rw-r--r--agg-plot/lua-plot-cpp.h 4
-rw-r--r--agg-plot/lua-plot.cpp 54
-rw-r--r--agg-plot/markers.cpp 251
-rw-r--r--agg-plot/markers.h 3
-rw-r--r--agg-plot/plot-auto.cpp 114
-rw-r--r--agg-plot/plot-auto.h 134
-rw-r--r--agg-plot/plot.cpp 725
-rw-r--r--agg-plot/plot.h 645
-rw-r--r--agg-plot/units.h 1
-rw-r--r--agg-plot/utils.h 4
-rw-r--r--benchmarks/results.csv 16
-rw-r--r--c028-cpm-sige.csv 1021
-rw-r--r--cgdt.lua 88
-rw-r--r--demo-init.lua 2
-rw-r--r--demos/gdt-lm.lua 50
-rw-r--r--expr-parser.lua 229
-rw-r--r--expr-print.lua 90
-rw-r--r--fox-gui/Makefile 4
-rw-r--r--fox-gui/lua_plot_window.cpp 2
-rw-r--r--gdt-eval.lua 79
-rw-r--r--gdt-hist.lua 80
-rw-r--r--gdt-lm.lua 440
-rw-r--r--gdt-parse-csv.lua 120
-rw-r--r--gdt-plot.lua 585
-rw-r--r--gdt.lua 315
-rw-r--r--gdt/Makefile 57
-rw-r--r--gdt/char_buffer.c 71
-rw-r--r--gdt/char_buffer.h 14
-rw-r--r--gdt/gdt_index.c 81
-rw-r--r--gdt/gdt_index.h 23
-rw-r--r--gdt/gdt_table.c 372
-rw-r--r--gdt/gdt_table.h 75
-rw-r--r--gdt/xmalloc.h 31
-rw-r--r--graph-init.lua 8
-rw-r--r--gsl.lua 105
-rw-r--r--gslext.lua 5
-rw-r--r--lm-expr.lua 26
-rw-r--r--lm-helpers.lua 65
-rw-r--r--lua-gsl/lua-gsl.c 7
-rw-r--r--makedefs 4
-rw-r--r--matrix-quicksort.lua 31
-rw-r--r--matrix.lua 20
-rw-r--r--monomial.lua 92
-rw-r--r--sigeb-doe-mbir.csv 307
-rw-r--r--sigeb-doe-new.csv 443
49 files changed, 6097 insertions, 865 deletions
diff --git a/Makefile b/Makefile
index bb59d772..4fac1676 100644
--- a/Makefile
+++ b/Makefile
@@ -30,7 +30,19 @@ GSL_SHELL = gsl-shell$(EXE_EXT)
GSL_SHELL_GUI = gsl-shell-gui$(EXE_EXT)
LUA_CFLAGS = -I$(LUADIR)/src
-SUBDIRS = $(LUADIR) lua-gsl
+ifeq ($(HOST_SYS),Windows)
+ INCLUDES += -I/usr/include
+ LIBS += -L/usr/lib -lsupc++
+else
+ ifeq ($(HOST_SYS),Darwin)
+ LDFLAGS += -L/usr/X11/lib -undefined dynamic_lookup -pagezero_size 10000 -image_base 100000000
+ LIBS += -ldl -lreadline -lncurses
+ else
+ LIBS += -ldl -lreadline -lhistory -lncurses -lsupc++
+ endif
+endif
+
+SUBDIRS = $(LUADIR) lua-gsl gdt
C_SRC_FILES =
@@ -43,7 +55,7 @@ endif
LUA_BASE_FILES = bspline.lua fft-init.lua integ-init.lua template.lua check.lua graph-init.lua rng.lua rnd.lua randist.lua iter.lua time.lua gsl-check.lua linfit.lua roots.lua contour.lua gsl.lua matrix.lua csv.lua gslext.lua num.lua demo-init.lua import.lua plot3d.lua sf.lua vegas.lua eigen.lua help.lua
HELP_FILES = graphics matrix iter integ ode nlfit vegas rng fft
-DEMOS_LIST = bspline fft plot wave-particle fractals ode nlinfit integ anim linfit contour svg graphics sf vegas
+DEMOS_LIST = bspline fft plot wave-particle fractals ode nlinfit integ anim linfit contour svg graphics sf vegas gdt-lm
LUA_TEMPLATES = gauss-kronrod-x-wgs qag rk8pd lmfit qng rkf45 ode-defs rk4 sf-defs vegas-defs
LUA_BASE_FILES += $(DEMOS_LIST:%=demos/%.lua)
@@ -64,7 +76,7 @@ SUBDIRS += agg-plot $(GUI_SUBDIR)
LUAGSL_LIBS += agg-plot/libaggplot.a
LIBS += $(AGG_LIBS) $(FREETYPE_LIBS) $(PTHREADS_LIBS)
-LUAGSL_LIBS += lua-gsl/libluagsl.a
+LUAGSL_LIBS += lua-gsl/libluagsl.a gdt/libgdt.a
COMPILE = $(CC) $(CFLAGS) $(LUA_CFLAGS) $(DEFS) $(INCLUDES)
@@ -111,6 +123,7 @@ clean:
$(MAKE) -C agg-plot clean
$(MAKE) -C $(LUADIR) clean
$(MAKE) -C fox-gui clean
+ $(MAKE) -C gdt clean
$(HOST_RM) *.o $(TARGETS)
$(HOST_RM) -r ./.libs/
diff --git a/agg-plot/Makefile b/agg-plot/Makefile
index f68b3cd8..5f2c1a48 100644
--- a/agg-plot/Makefile
+++ b/agg-plot/Makefile
@@ -39,7 +39,7 @@ endif
INCLUDES += $(FREETYPE_INCLUDES) $(AGG_INCLUDES) -I$(GSH_BASE_DIR) -I$(GSH_BASE_DIR)/lua-gsl -I$(LUADIR)/src -I$(GSH_BASE_DIR)/cpp-utils
-AGGPLOT_SRC_FILES = $(PLATSUP_SRC_FILES) printf_check.cpp fonts.cpp gamma.cpp agg_font_freetype.cpp utils.cpp units.cpp colors.cpp markers.cpp draw_svg.cpp canvas_svg.cpp lua-draw.cpp lua-text.cpp text.cpp agg-parse-trans.cpp window_registry.cpp window.cpp lua-plot.cpp canvas-window.cpp bitmap-plot.cpp lua-graph.cpp
+AGGPLOT_SRC_FILES = $(PLATSUP_SRC_FILES) printf_check.cpp fonts.cpp gamma.cpp agg_font_freetype.cpp plot.cpp plot-auto.cpp utils.cpp units.cpp colors.cpp markers.cpp draw_svg.cpp canvas_svg.cpp lua-draw.cpp lua-text.cpp text.cpp agg-parse-trans.cpp window_registry.cpp window.cpp lua-plot.cpp canvas-window.cpp bitmap-plot.cpp lua-graph.cpp
AGGPLOT_OBJ_FILES := $(AGGPLOT_SRC_FILES:%.cpp=%.o)
diff --git a/agg-plot/factor_labels.h b/agg-plot/factor_labels.h
new file mode 100644
index 00000000..27f6ef47
--- /dev/null
+++ b/agg-plot/factor_labels.h
@@ -0,0 +1,28 @@
+#include "agg_array.h"
+#include "utils.h"
+#include "strpp.h"
+
+class factor_labels
+{
+public:
+ factor_labels(double delta): m_mark_delta(delta) {}
+
+ double mark(int k) const { return m_mark_index[k] * m_mark_delta; }
+ const char *label_text(int k) const { return m_label_text[k]->cstr(); }
+ int labels_number() const { return m_label_text.size(); }
+
+ void add_mark(int index, const char *text)
+ {
+ m_mark_index.add(index);
+ if (text)
+ {
+ str* text_str = new str(text);
+ m_label_text.add(text_str);
+ }
+ }
+
+private:
+ double m_mark_delta;
+ agg::pod_bvector<short> m_mark_index;
+ ptr_list<str> m_label_text;
+};
diff --git a/agg-plot/lua-draw.cpp b/agg-plot/lua-draw.cpp
index 7181dfb2..af6f69ad 100644
--- a/agg-plot/lua-draw.cpp
+++ b/agg-plot/lua-draw.cpp
@@ -263,17 +263,23 @@ marker_new (lua_State *L)
{
const double x = luaL_checknumber(L, 1);
const double y = luaL_checknumber(L, 2);
- const char *sym_name = luaL_optstring(L, 3, "");
const double size = luaL_optnumber(L, 4, 5.0);
+ const char *sym_name;
- bool stroke;
- sg_object* sym = new_marker_symbol_raw(sym_name, stroke);
+ if (lua_isnumber(L, 3))
+ {
+ int n = lua_tointeger(L, 3);
+ sym_name = marker_lookup(n);
+ }
+ else
+ {
+ sym_name = luaL_optstring(L, 3, "");
+ }
+
+ sg_object* sym = new_marker_symbol_raw(sym_name);
draw::marker* marker = new draw::marker(x, y, sym, size);
- if (stroke)
- new(L, GS_DRAW_MARKER) trans::stroke(marker);
- else
- new(L, GS_DRAW_MARKER) sg_object_ref<manage_owner>(marker);
+ new(L, GS_DRAW_MARKER) sg_object_ref<manage_owner>(marker);
return 1;
}
diff --git a/agg-plot/lua-plot-cpp.h b/agg-plot/lua-plot-cpp.h
index 5f92e499..0aa7bca4 100644
--- a/agg-plot/lua-plot-cpp.h
+++ b/agg-plot/lua-plot-cpp.h
@@ -10,7 +10,7 @@ extern "C" {
#include "plot-auto.h"
#include "resource-manager.h"
-typedef plot<manage_owner> sg_plot;
-typedef plot_auto<manage_owner> sg_plot_auto;
+typedef plot sg_plot;
+typedef plot_auto sg_plot_auto;
#endif
diff --git a/agg-plot/lua-plot.cpp b/agg-plot/lua-plot.cpp
index 42961d46..5053dbaa 100644
--- a/agg-plot/lua-plot.cpp
+++ b/agg-plot/lua-plot.cpp
@@ -70,6 +70,8 @@ static int plot_ylab_angle_get (lua_State *L);
static int plot_set_categories (lua_State *L);
static int plot_set_legend (lua_State *L);
static int plot_get_legend (lua_State *L);
+static int plot_xaxis_hol_set (lua_State *L);
+static int plot_xaxis_hol_clear(lua_State *L);
static int plot_sync_mode_get (lua_State *L);
static int plot_sync_mode_set (lua_State *L);
@@ -109,6 +111,8 @@ static const struct luaL_Reg plot_methods[] = {
{"set_categories", plot_set_categories},
{"set_legend", plot_set_legend},
{"get_legend", plot_get_legend},
+ {"set_multi_labels", plot_xaxis_hol_set},
+ {"clear_multi_labels", plot_xaxis_hol_clear},
{NULL, NULL}
};
@@ -467,6 +471,56 @@ plot_units_get (lua_State *L)
return plot_bool_property_get(L, &sg_plot::use_units);
}
+int plot_xaxis_hol_set (lua_State *L)
+{
+ sg_plot *p = object_check<sg_plot>(L, 1, GS_PLOT);
+ double delta = lua_tonumber(L, 2);
+
+ if (!lua_istable(L, 3))
+ return luaL_error(L, "expect labels table specification");
+
+ ptr_list<factor_labels>* hol = p->get_xaxis_hol();
+ bool create_hol = (hol == 0);
+ if (create_hol)
+ hol = new ptr_list<factor_labels>();
+
+ factor_labels* fl = new factor_labels(delta);
+ int n = lua_objlen(L, 3);
+ for (int k = 1; k <= n; k += 2)
+ {
+ lua_rawgeti(L, 3, k);
+ int idx = lua_tonumber(L, -1);
+ lua_pop(L, 1);
+
+ lua_rawgeti(L, 3, k + 1);
+ const char* str = lua_tostring(L, -1);
+ fl->add_mark(idx, str);
+ lua_pop(L, 1);
+
+ if (!str)
+ break;
+ }
+
+ AGG_LOCK();
+ hol->add(fl);
+ if (create_hol)
+ p->set_xaxis_hol(hol);
+ AGG_UNLOCK();
+
+ plot_update_raw (L, p, 1);
+ return 0;
+}
+
+int plot_xaxis_hol_clear (lua_State *L)
+{
+ sg_plot *p = object_check<sg_plot>(L, 1, GS_PLOT);
+ AGG_LOCK();
+ p->set_xaxis_hol(0);
+ AGG_UNLOCK();
+ plot_update_raw (L, p, 1);
+ return 0;
+}
+
void
plot_update_raw (lua_State *L, sg_plot *p, int plot_index)
{
diff --git a/agg-plot/markers.cpp b/agg-plot/markers.cpp
index d6e5548c..b355bf12 100644
--- a/agg-plot/markers.cpp
+++ b/agg-plot/markers.cpp
@@ -8,141 +8,197 @@
#include "trans.h"
#include "path.h"
+/* used to encode a simple path */
+struct path_code {
+ enum {closed = 0, open = 1, end = 2};
+ enum {scale = 32767};
+ short x, y;
+};
+
struct symbol_reg {
const char *name;
- sg_object *(*builder)(bool&);
+ sg_object *(*builder)();
+ const path_code* pcode;
+};
+
+static sg_object *build_circle();
+static sg_object *build_path(const path_code* pcode);
+
+/*
+-- lua code to generate the coordinates
+
+use 'math'
+
+b = 2^15 - 1
+
+function rot(alpha, x, y)
+ return x*cos(alpha) - y*sin(alpha), y*cos(alpha) + x*sin(alpha)
+end
+
+function tr(x, y)
+ return floor(x*b+0.5), floor(y*b+0.5)
+end
+
+-- example for asterisk
+tr(rot(0, -0.08, 0.5))
+tr(rot(0, 0.08, 0.5))
+tr(rot(0, 0.08, -0.5))
+tr(rot(0, -0.08, -0.5))
+
+tr(rot(pi/3, -0.08, 0.5))
+tr(rot(pi/3, 0.08, 0.5))
+tr(rot(pi/3, 0.08, -0.5))
+tr(rot(pi/3, -0.08, -0.5))
+...
+*/
+
+static path_code asterisk[] = {
+ {path_code::closed, 4},
+ {-2621, 16384},
+ { 2621, 16384},
+ { 2621, -16384},
+ {-2621, -16384},
+ {path_code::closed, 4},
+ {-15499, 5922},
+ {-12878, 10462},
+ { 15499, -5922},
+ { 12878, -10462},
+ {path_code::closed, 4},
+ { 12878, 10462},
+ { 15499, 5922},
+ {-12878, -10462},
+ {-15499, -5922},
+ {path_code::end},
};
-static sg_object *build_circle(bool& stroke);
-static sg_object *build_square(bool& stroke);
-static sg_object *build_triangle(bool& stroke);
-static sg_object *build_diamond(bool& stroke);
-static sg_object *build_plus(bool& stroke);
-static sg_object *build_cross(bool& stroke);
+static path_code square[] = {
+ {path_code::closed, 4},
+ {-16383, 16384},
+ { 16384, 16384},
+ { 16384, -16383},
+ {-16383, -16383},
+ {path_code::end},
+};
+
+static path_code diamond[] = {
+ {path_code::closed, 4},
+ {-16383, 0},
+ { 0, 16384},
+ { 16384, 0},
+ { 0, -16383},
+ {path_code::end},
+};
+
+static path_code triangle[] = {
+ {path_code::closed, 3},
+ {-18918, -10922},
+ { 18918, -10922},
+ { 0, 21845},
+ {path_code::end},
+};
+
+static path_code plus[] = {
+ {path_code::closed, 4},
+ {-2621, 16384},
+ { 2621, 16384},
+ { 2621, -16384},
+ {-2621, -16384},
+ {path_code::closed, 4},
+ {-16383, 2621},
+ { 16384, 2621},
+ { 16384, -2621},
+ {-16383, -2621},
+ {path_code::end},
+};
+
+static path_code cross[] = {
+ {path_code::closed, 4},
+ {-13438, 9731},
+ {-9731, 13438},
+ {13438, -9731},
+ {9731, -13438},
+ {path_code::closed, 4},
+ {9731, 13438},
+ {13438, 9731},
+ {-9731, -13438},
+ {-13438, -9731},
+ {path_code::end},
+};
-const unsigned NB_SYMBOLS = 6;
+const unsigned NB_SYMBOLS = 7;
static struct symbol_reg builder_table[NB_SYMBOLS+1] = {
{"circle", build_circle},
- {"square", build_square},
- {"triangle", build_triangle},
- {"diamond", build_diamond},
- {"plus", build_plus},
- {"cross", build_cross},
+ {"square", NULL, square},
+ {"triangle", NULL, triangle},
+ {"diamond", NULL, diamond},
+ {"plus", NULL, plus},
+ {"cross", NULL, cross},
+ {"asterisk", NULL, asterisk},
{NULL, NULL}
};
sg_object *
-build_circle(bool& stroke)
+build_circle()
{
draw::ellipse* c = new draw::ellipse();
c->self().init(0.0, 0.0, 0.5, 0.5);
- stroke = false;
return c;
}
-sg_object *
-build_square(bool& stroke)
+static inline void decode_coord(const path_code* p, double x[])
{
- draw::path* p = new draw::path();
-
- agg::path_storage& square = p->self();
- square.move_to(-0.5, -0.5);
- square.line_to( 0.5, -0.5);
- square.line_to( 0.5, 0.5);
- square.line_to(-0.5, 0.5);
- square.close_polygon();
-
- stroke = false;
- return p;
+ x[0] = double(p->x) / path_code::scale;
+ x[1] = double(p->y) / path_code::scale;
}
sg_object *
-build_triangle(bool& stroke)
+build_path(const path_code *pcode)
{
draw::path* p = new draw::path();
+ agg::path_storage& ps = p->self();
- agg::path_storage& triangle = p->self();
-
- double ht = 0.86602540378444;
- triangle.move_to(-0.5, -ht/3);
- triangle.line_to( 0.5, -ht/3);
- triangle.line_to( 0.0, 2*ht/3);
- triangle.close_polygon();
-
- stroke = false;
- return p;
-}
-
-sg_object *
-build_diamond(bool& stroke)
-{
- draw::path* p = new draw::path();
-
- agg::path_storage& square = p->self();
- square.move_to(-0.5, 0.0);
- square.line_to( 0.0, 0.5);
- square.line_to( 0.5, 0.0);
- square.line_to( 0.0, -0.5);
- square.close_polygon();
-
- stroke = false;
- return p;
-}
-
-sg_object *
-build_plus(bool& stroke)
-{
- draw::path* p = new draw::path();
-
- agg::path_storage& plus = p->self();
- plus.move_to(-0.5, 0.0);
- plus.line_to( 0.5, 0.0);
- plus.move_to( 0.0, -0.5);
- plus.line_to( 0.0, 0.5);
-
- stroke = true;
- return p;
-}
-
-sg_object *
-build_cross(bool& stroke)
-{
- draw::path* p = new draw::path();
-
- agg::path_storage& plus = p->self();
- plus.move_to(-0.5, -0.5);
- plus.line_to( 0.5, 0.5);
- plus.move_to(-0.5, 0.5);
- plus.line_to( 0.5, -0.5);
+ for (const path_code* op = pcode; op->x != path_code::end; op = op + op->y + 1)
+ {
+ const path_code* code = op + 1;
+ double x[2];
+ decode_coord(code ++, x);
+ ps.move_to(x[0], x[1]);
+ for (short k = 1; k < op->y; k++)
+ {
+ decode_coord(code ++, x);
+ ps.line_to(x[0], x[1]);
+ }
+
+ if (op->x == path_code::closed)
+ ps.close_polygon();
+ }
- stroke = true;
return p;
}
sg_object*
-new_marker_symbol_raw(const char *req_name, bool& stroke)
+new_marker_symbol_raw(const char *req_name)
{
struct symbol_reg *reg;
for (reg = builder_table; reg->name != NULL; reg++)
{
if (strcmp (reg->name, req_name) == 0)
- return reg->builder(stroke);
+ {
+ if (reg->builder)
+ return reg->builder();
+ else
+ return build_path(reg->pcode);
+ }
}
- return builder_table[0].builder(stroke);
+ return builder_table[0].builder();
}
sg_object*
new_marker_symbol (const char *req_name)
{
- bool stroke;
- sg_object* s = new_marker_symbol_raw(req_name, stroke);
-
- trans::scaling *ss = new trans::scaling(s);
- sg_object* sf = ss;
- if (stroke)
- sf = new trans::stroke(sf);
- return sf;
+ sg_object* s = new_marker_symbol_raw(req_name);
+ return new trans::scaling(s);
}
sg_object*
@@ -151,3 +207,10 @@ new_marker_symbol (int n)
n = (n-1) % NB_SYMBOLS;
return new_marker_symbol(builder_table[n].name);
}
+
+const char*
+marker_lookup(int n)
+{
+ n = (n-1) % NB_SYMBOLS;
+ return builder_table[n].name;
+}
diff --git a/agg-plot/markers.h b/agg-plot/markers.h
index b54b1415..44ffb5b1 100644
--- a/agg-plot/markers.h
+++ b/agg-plot/markers.h
@@ -5,6 +5,7 @@
extern sg_object* new_marker_symbol(const char *name);
extern sg_object* new_marker_symbol(int n);
-extern sg_object* new_marker_symbol_raw(const char *req_name, bool& stroke);
+extern sg_object* new_marker_symbol_raw(const char *req_name);
+extern const char* marker_lookup(int n);
#endif
diff --git a/agg-plot/plot-auto.cpp b/agg-plot/plot-auto.cpp
new file mode 100644
index 00000000..e7ae8869
--- /dev/null
+++ b/agg-plot/plot-auto.cpp
@@ -0,0 +1,114 @@
+#include "plot-auto.h"
+
+void plot_auto::add(sg_object* vs, agg::rgba8& color, bool outline)
+{
+ item d(vs, color, outline);
+
+ if (!this->fit_inside(vs))
+ {
+ this->m_bbox_updated = false;
+ this->m_need_redraw = true;
+ this->m_enlarged_layer = true;
+ }
+
+ list<item> *nn = new list<item>(d);
+ this->m_drawing_queue = list<item>::push_back(this->m_drawing_queue, nn);
+
+ RM::acquire(vs);
+}
+
+void plot_auto::check_bounding_box()
+{
+ this->calc_bounding_box();
+ this->update_units();
+ this->m_bbox_updated = true;
+}
+
+void plot_auto::calc_layer_bounding_box(plot_auto::item_list* layer,
+ opt_rect<double>& rect)
+{
+ for (unsigned j = 0; j < layer->size(); j++)
+ {
+ item& d = (*layer)[j];
+ agg::rect_base<double> r;
+
+ d.vs->bounding_box(&r.x1, &r.y1, &r.x2, &r.y2);
+ rect.add<rect_union>(r);
+ }
+}
+
+void plot_auto::calc_bounding_box()
+{
+ opt_rect<double> box;
+
+ unsigned n = this->nb_layers();
+ for (unsigned j = 0; j < n-1; j++)
+ {
+ box.add<rect_union>(this->get_layer(j)->bounding_box());
+ }
+
+ calc_layer_bounding_box(this->get_layer(n-1), box);
+ for (list<item> *t = this->m_drawing_queue; t; t = t->next())
+ {
+ const item& d = t->content();
+ agg::rect_base<double> r;
+ d.vs->bounding_box(&r.x1, &r.y1, &r.x2, &r.y2);
+ box.add<rect_union>(r);
+ }
+
+ this->m_rect = box;
+}
+
+bool plot_auto::fit_inside(sg_object* obj) const
+{
+ if (!this->m_bbox_updated || !this->m_rect.is_defined())
+ return false;
+
+ agg::rect_base<double> r;
+ obj->bounding_box(&r.x1, &r.y1, &r.x2, &r.y2);
+
+ const agg::rect_base<double>& bb = this->m_rect.rect();
+ return bb.hit_test(r.x1, r.y1) && bb.hit_test(r.x2, r.y2);
+}
+
+void plot_auto::set_opt_limits(const opt_rect<double>& r)
+{
+ if (r.is_defined())
+ this->set_limits(r.rect());
+ else
+ this->unset_limits();
+}
+
+bool plot_auto::push_layer()
+{
+ bool retval = this->plot::push_layer();
+ if (this->m_rect.is_defined())
+ this->parent_layer()->set_bounding_box(this->m_rect.rect());
+ this->m_bbox_updated = true;
+ this->m_enlarged_layer = false;
+ return retval;
+}
+
+bool plot_auto::pop_layer()
+{
+ bool retval = this->plot::pop_layer();
+ if (this->m_enlarged_layer)
+ this->m_bbox_updated = false;
+ this->m_enlarged_layer = true;
+ return retval;
+}
+
+void plot_auto::clear_current_layer()
+{
+ this->plot::clear_current_layer();
+ if (this->m_enlarged_layer)
+ {
+ item_list* parent = this->parent_layer();
+ if (parent)
+ set_opt_limits(parent->bounding_box());
+ else
+ this->unset_limits();
+ }
+ this->m_bbox_updated = true;
+ this->m_enlarged_layer = false;
+}
diff --git a/agg-plot/plot-auto.h b/agg-plot/plot-auto.h
index 52e40de2..a6321840 100644
--- a/agg-plot/plot-auto.h
+++ b/agg-plot/plot-auto.h
@@ -27,15 +27,13 @@
#include "agg_array.h"
#include "agg_basics.h"
-template<class resource_manager>
-class plot_auto : public plot<resource_manager> {
- typedef typename plot<resource_manager>::item item;
- typedef typename plot<resource_manager>::item_list item_list;
+class plot_auto : public plot {
+ typedef typename plot::item item;
+ typedef typename plot::item_list item_list;
public:
plot_auto() :
- plot<resource_manager>(true),
- m_bbox_updated(true), m_enlarged_layer(false)
+ plot(true), m_bbox_updated(true), m_enlarged_layer(false)
{ };
virtual ~plot_auto() { };
@@ -43,7 +41,7 @@ public:
virtual void add(sg_object* vs, agg::rgba8& color, bool outline);
virtual void before_draw()
{
- plot<resource_manager>::before_draw();
+ plot::before_draw();
if (!m_bbox_updated)
check_bounding_box();
};
@@ -65,126 +63,4 @@ private:
bool m_enlarged_layer;
};
-template <class RM>
-void plot_auto<RM>::add(sg_object* vs, agg::rgba8& color, bool outline)
-{
- item d(vs, color, outline);
-
- if (!this->fit_inside(vs))
- {
- this->m_bbox_updated = false;
- this->m_need_redraw = true;
- this->m_enlarged_layer = true;
- }
-
- list<item> *nn = new list<item>(d);
- this->m_drawing_queue = list<item>::push_back(this->m_drawing_queue, nn);
-
- RM::acquire(vs);
-}
-
-template<class RM>
-void plot_auto<RM>::check_bounding_box()
-{
- this->calc_bounding_box();
- this->update_units();
- this->m_bbox_updated = true;
-}
-
-template<class RM>
-void plot_auto<RM>::calc_layer_bounding_box(plot_auto<RM>::item_list* layer,
- opt_rect<double>& rect)
-{
- for (unsigned j = 0; j < layer->size(); j++)
- {
- item& d = (*layer)[j];
- agg::rect_base<double> r;
-
- d.vs->bounding_box(&r.x1, &r.y1, &r.x2, &r.y2);
- rect.add<rect_union>(r);
- }
-}
-
-template<class RM>
-void plot_auto<RM>::calc_bounding_box()
-{
- opt_rect<double> box;
-
- unsigned n = this->nb_layers();
- for (unsigned j = 0; j < n-1; j++)
- {
- box.add<rect_union>(this->get_layer(j)->bounding_box());
- }
-
- calc_layer_bounding_box(this->get_layer(n-1), box);
- for (list<item> *t = this->m_drawing_queue; t; t = t->next())
- {
- const item& d = t->content();
- agg::rect_base<double> r;
- d.vs->bounding_box(&r.x1, &r.y1, &r.x2, &r.y2);
- box.add<rect_union>(r);
- }
-
- this->m_rect = box;
-}
-
-template<class RM>
-bool plot_auto<RM>::fit_inside(sg_object* obj) const
-{
- if (!this->m_bbox_updated || !this->m_rect.is_defined())
- return false;
-
- agg::rect_base<double> r;
- obj->bounding_box(&r.x1, &r.y1, &r.x2, &r.y2);
-
- const agg::rect_base<double>& bb = this->m_rect.rect();
- return bb.hit_test(r.x1, r.y1) && bb.hit_test(r.x2, r.y2);
-}
-
-template<class RM>
-void plot_auto<RM>::set_opt_limits(const opt_rect<double>& r)
-{
- if (r.is_defined())
- this->set_limits(r.rect());
- else
- this->unset_limits();
-}
-
-template<class RM>
-bool plot_auto<RM>::push_layer()
-{
- bool retval = this->plot<RM>::push_layer();
- if (this->m_rect.is_defined())
- this->parent_layer()->set_bounding_box(this->m_rect.rect());
- this->m_bbox_updated = true;
- this->m_enlarged_layer = false;
- return retval;
-}
-
-template<class RM>
-bool plot_auto<RM>::pop_layer()
-{
- bool retval = this->plot<RM>::pop_layer();
- if (this->m_enlarged_layer)
- this->m_bbox_updated = false;
- this->m_enlarged_layer = true;
- return retval;
-}
-
-template<class RM>
-void plot_auto<RM>::clear_current_layer()
-{
- this->plot<RM>::clear_current_layer();
- if (this->m_enlarged_layer)
- {
- item_list* parent = this->parent_layer();
- if (parent)
- set_opt_limits(parent->bounding_box());
- else
- this->unset_limits();
- }
- this->m_bbox_updated = true;
- this->m_enlarged_layer = false;
-}
-
#endif
diff --git a/agg-plot/plot.cpp b/agg-plot/plot.cpp
new file mode 100644
index 00000000..c235c35f
--- /dev/null
+++ b/agg-plot/plot.cpp
@@ -0,0 +1,725 @@
+#include "plot.h"
+
+static double compute_scale(const agg::trans_affine& m)
+{
+ return m.scale() / 480.0;
+}
+
+static double
+std_line_width(double scale, double w = 1.0)
+{
+#if 0
+ const double dsf = M_LN10;
+ double ls = log(scale) / dsf;
+ return exp(round(ls) * dsf) * w * 1.5;
+#else
+ return w * 1.5;
+#endif
+}
+
+void plot::commit_pending_draw()
+{
+ push_drawing_queue();
+ m_need_redraw = false;
+ m_changes_pending.clear();
+}
+
+void plot::add(sg_object* vs, agg::rgba8& color, bool outline)
+{
+ item d(vs, color, outline);
+ list<item> *new_node = new list<item>(d);
+ m_drawing_queue = list<item>::push_back(m_drawing_queue, new_node);
+ RM::acquire(vs);
+}
+
+void plot::push_drawing_queue()
+{
+ item_list* layer = current_layer();
+ for (list<item> *c = m_drawing_queue; c != 0; c = c->next())
+ {
+ layer->add(c->content());
+ }
+
+ while (m_drawing_queue)
+ m_drawing_queue = list<item>::pop(m_drawing_queue);
+}
+
+void plot::clear_drawing_queue()
+{
+ while (m_drawing_queue)
+ {
+ item& d = m_drawing_queue->content();
+ RM::dispose(d.vs);
+ m_drawing_queue = list<item>::pop(m_drawing_queue);
+ }
+}
+
+static bool area_is_valid(const agg::trans_affine& b)
+{
+ const double thresold = 40.0;
+ return (b.sx > thresold && b.sy > thresold);
+}
+
+void plot::draw_virtual_canvas(canvas_type& canvas, plot_layout& layout, const agg::rect_i* clip)
+{
+ before_draw();
+ draw_legends(canvas, layout);
+
+ if (area_is_valid(layout.plot_area))
+ {
+ draw_axis(canvas, layout, clip);
+ draw_elements(canvas, layout);
+ }
+};
+
+void plot::draw_simple(canvas_type& canvas, plot_layout& layout, const agg::rect_i* clip)
+{
+ before_draw();
+ draw_axis(canvas, layout, clip);
+ draw_elements(canvas, layout);
+};
+
+void plot::draw_element(item& c, canvas_type& canvas, const agg::trans_affine& m)
+{
+ sg_object& vs = c.content();
+ vs.apply_transform(m, 1.0);
+
+ if (c.outline)
+ canvas.draw_outline(vs, c.color);
+ else
+ canvas.draw(vs, c.color);
+}
+
+agg::trans_affine plot::get_model_matrix(const plot_layout& layout)
+{
+ agg::trans_affine m = m_trans;
+ trans_affine_compose (m, layout.plot_active_area);
+ return m;
+}
+
+void plot::clip_plot_area(canvas_type& canvas, const agg::trans_affine& area_mtx)
+{
+ if (this->clip_is_active())
+ {
+ agg::rect_base<int> clip = rect_of_slot_matrix<int>(area_mtx);
+ canvas.clip_box(clip);
+ }
+}
+
+void plot::draw_elements(canvas_type& canvas, const plot_layout& layout)
+{
+ const agg::trans_affine m = get_model_matrix(layout);
+
+ this->clip_plot_area(canvas, layout.plot_active_area);
+
+ for (unsigned k = 0; k < m_layers.size(); k++)
+ {
+ item_list& layer = *(m_layers[k]);
+ for (unsigned j = 0; j < layer.size(); j++)
+ {
+ draw_element(layer[j], canvas, m);
+ }
+ }
+
+ canvas.reset_clipping();
+}
+
+void plot::compute_user_trans()
+{
+ agg::rect_base<double> r;
+
+ if (m_use_units && m_pad_units)
+ {
+ int ixi, ixs, iyi, iys;
+ double xd, yd;
+ m_ux.limits(ixi, ixs, xd);
+ r.x1 = ixi * xd;
+ r.x2 = ixs * xd;
+
+ m_uy.limits(iyi, iys, yd);
+ r.y1 = iyi * yd;
+ r.y2 = iys * yd;
+ }
+ else
+ {
+ r = m_rect.is_defined() ? m_rect.rect() : agg::rect_base<double>(0.0, 0.0, 1.0, 1.0);
+ }
+
+ if (m_xaxis_hol)
+ {
+ for (unsigned k = 0; k < m_xaxis_hol->size(); k++)
+ {
+ factor_labels* f = m_xaxis_hol->at(k);
+ double x1 = f->mark(0), x2 = f->mark(f->labels_number());
+ if (k == 0 || x1 < r.x1) r.x1 = x1;
+ if (k == 0 || x2 > r.x2) r.x2 = x2;
+ }
+ }
+
+ double dx = r.x2 - r.x1, dy = r.y2 - r.y1;
+ double fx = (dx == 0 ? 1.0 : 1/dx), fy = (dy == 0 ? 1.0 : 1/dy);
+ this->m_trans = agg::trans_affine(fx, 0.0, 0.0, fy, -r.x1 * fx, -r.y1 * fy);
+}
+
+void plot::draw_grid(const axis_e dir, const units& u,
+ const agg::trans_affine& user_mtx,
+ agg::path_storage& ln)
+{
+ const double eps = 1.0e-3;
+ const bool isx = (dir == x_axis);
+
+ int jinf = u.begin(), jsup = u.end();
+ for (int j = jinf+1; j < jsup; j++)
+ {
+ double uq = u.mark_value(j);
+ double x = (isx ? uq : 0), y = (isx ? 0.0 : uq);
+ user_mtx.transform(&x, &y);
+ const double q = (isx ? x : y);
+
+ if (q >= -eps && q <= 1.0 + eps)
+ {
+ ln.move_to(isx ? q : 0.0, isx ? 0.0 : q);
+ ln.line_to(isx ? q : 1.0, isx ? 1.0 : q);
+ }
+ }
+}
+
+
+double plot::draw_axis_m(axis_e dir, units& u,
+ const agg::trans_affine& user_mtx,
+ ptr_list<draw::text>& labels, double scale,
+ agg::path_storage& mark, agg::path_storage& ln)
+{
+ const double ppad = double(axis_label_prop_space) / 1000.0;
+ const double text_label_size = get_default_font_size(text_axis_labels, scale);
+ const double eps = 1.0e-3;
+
+ // used to store the bounding box of text labels
+ opt_rect<double> bb;
+ agg::rect_base<double> r;
+
+ bool isx = (dir == x_axis);
+
+ const axis& ax = get_axis(dir);
+ double hj = ax.labels_hjustif(), vj = ax.labels_vjustif();
+ double langle = ax.labels_angle();
+
+ category_map::iterator clabels(ax.categories);
+ units_iterator ulabels(u, ax.format_tag, ax.label_format());
+
+ label_iterator* ilabels = (ax.use_categories ? (label_iterator*) &clabels : (label_iterator*) &ulabels);
+
+ double uq;
+ const char* text;
+ while (ilabels->next(uq, text))
+ {
+ double x = (isx ? uq : 0.0), y = (isx ? 0.0 : uq);
+ user_mtx.transform(&x, &y);
+
+ double q = (isx ? x : y);
+
+ if (q < -eps || q > 1.0 + eps)
+ continue;
+
+ draw::text* label = new draw::text(text, text_label_size, hj, vj);
+
+ label->set_point(isx ? q : -ppad, isx ? -ppad : q);
+ label->angle(langle);
+
+ agg::bounding_rect_single(*label, 0, &r.x1, &r.y1, &r.x2, &r.y2);
+ bb.add<rect_union>(r);
+
+ labels.add(label);
+
+ mark.move_to(isx ? q : 0.0 , isx ? 0.0 : q);
+ mark.line_to(isx ? q : -0.01, isx ? -0.01 : q);
+ }
+
+ this->draw_grid(dir, u, user_mtx, ln);
+
+ double label_size;
+ if (bb.is_defined())
+ {
+ const agg::rect_base<double>& br = bb.rect();
+ label_size = (isx ? br.y2 - br.y1 : br.x2 - br.x1);
+ }
+ else
+ {
+ label_size = 0.0;
+ }
+
+ return label_size;
+}
+
+double plot::draw_xaxis_factors(units& u,
+ const agg::trans_affine& user_mtx,
+ ptr_list<draw::text>& labels,
+ ptr_list<factor_labels>* f_labels, double scale,
+ agg::path_storage& mark, agg::path_storage& ln)
+{
+ const double text_label_size = get_default_font_size(text_axis_labels, scale);
+
+ const axis& ax = get_axis(x_axis);
+ const double lab_angle = ax.labels_angle();
+
+ const double y_spac_top = 3, y_spac_bot = 3;
+ const int layers_number = f_labels->size();
+ double p_lab = 0;
+ for (int layer = layers_number - 1; layer >= 0; layer--)
+ {
+ factor_labels* factor = f_labels->at(layer);
+
+ if (factor->labels_number() > 256) continue;
+
+ agg::pod_bvector<draw::text*> tlabels;
+ double hmax = 0.0;
+ bool draw_labels = (factor->labels_number() < 32);
+ if (draw_labels)
+ {
+ for (int k = 0; k < factor->labels_number(); k++)
+ {
+ const char* text = factor->label_text(k);
+ draw::text* label = new draw::text(text, text_label_size, 0.5, 0.5);
+ label->angle(lab_angle);
+
+ double rx1, ry1, rx2, ry2;
+ agg::bounding_rect_single(*label, 0, &rx1, &ry1, &rx2, &ry2);
+ double rh = ry2 - ry1;
+ if (rh > hmax) hmax = rh;
+ tlabels.add(label);
+ }
+ }
+
+ double p_lab_inf = p_lab - (y_spac_top + y_spac_bot + hmax);
+
+ for (int k = 0; k < factor->labels_number(); k++)
+ {
+ double x_lab_a = factor->mark(k);
+ double x_lab_b = factor->mark(k+1);
+
+ double x_a = x_lab_a, y_a = 0.0;
+ user_mtx.transform(&x_a, &y_a);
+ double q_a = x_a;
+
+ double x_lab = (x_lab_a + x_lab_b) / 2, y_lab = 0.0;
+ user_mtx.transform(&x_lab, &y_lab);
+ double q_lab = x_lab;
+
+ mark.move_to(q_a, p_lab);
+ mark.line_to(q_a, p_lab_inf);
+
+ if (draw_labels)
+ {
+ draw::text* label = tlabels[k];
+ label->set_point(q_lab, p_lab_inf + y_spac_bot + hmax/2.0);
+ labels.add(label);
+ }
+ }
+
+ double x_lab = factor->mark(factor->labels_number());
+ double x_a = x_lab, y_a = 0.0;
+ user_mtx.transform(&x_a, &y_a);
+ double q_a = x_a;
+ mark.move_to(q_a, p_lab);
+ mark.line_to(q_a, p_lab_inf);
+
+ p_lab = p_lab_inf;
+ }
+
+ this->draw_grid(x_axis, u, user_mtx, ln);
+
+ return - p_lab;
+}
+
+static inline double approx_text_height(double text_size)
+{
+ return text_size * 1.5;
+}
+
+plot_layout plot::compute_plot_layout(const agg::trans_affine& canvas_mtx, bool do_legends)
+{
+ plot_layout layout;
+
+ const double sx = canvas_mtx.sx, sy = canvas_mtx.sy;
+ const double ppad = double(canvas_margin_prop_space) / 1000.0;
+ const double fpad = double(canvas_margin_fixed_space);
+ const double size_frac_x = 0.125, size_frac_y = 0.05;
+
+ double dxl, dxr, dyb, dyt;
+
+ dxl = dxr = fpad + ppad * sx;
+ dyb = dyt = fpad + ppad * sy;
+
+ if (!str_is_null(&m_title))
+ {
+ const double scale = compute_scale(canvas_mtx);
+ const double ptpad = double(axis_title_prop_space) / 1000.0;
+ const double title_text_size = get_default_font_size(text_plot_title, scale);
+ const double th = approx_text_height(title_text_size);
+
+ double x = 0.5, y = 1.0;
+ canvas_mtx.transform(&x, &y);
+ y -= ptpad + dyt + title_text_size;
+
+ layout.title_pos = plot_layout::point(x, y);
+ layout.title_font_size = title_text_size;
+
+ dyt += 2 * ptpad + th;
+ }
+
+ for (int k = 0; k < 4 && do_legends; k++)
+ {
+ plot* mp = m_legend[k];
+
+ if (mp)
+ {
+ agg::rect_base<double> bb;
+ mp->get_bounding_rect(bb);
+
+ double bb_dx = bb.x2 - bb.x1, bb_dy = bb.y2 - bb.y1;
+ double dx, dy;
+ double px, py;
+ switch (k)
+ {
+ case right:
+ dx = max(sx * size_frac_x, bb_dx);
+ dy = dx * bb_dy / bb_dx;
+ px = sx - dx - ppad * sx - dxr;
+ py = (sy - dy) / 2;
+ dxr += dx + 2 * ppad * sx;
+ break;
+ case left:
+ dx = max(sx * size_frac_x, bb_dx);
+ dy = dx * bb_dy / bb_dx;
+ px = ppad * sx + dxr;
+ py = (sy - dy) / 2;
+ dxl += dx + 2 * ppad * sx;
+ break;
+ case bottom:
+ dy = sy * size_frac_y;
+ dx = dy * bb_dx / bb_dy;
+ py = ppad * sy + dyb;
+ px = (sx - dx) / 2;
+ dyb += dy + 2 * ppad * sy;
+ break;
+ case top:
+ dy = sy * size_frac_y;
+ dx = dy * bb_dx / bb_dy;
+ py = sy - dy - ppad * sy - dyt;
+ px = (sx - dx) / 2;
+ dyt += dy + 2 * ppad * sy;
+ break;
+ default:
+ /* */
+ ;
+ }
+
+ if (px >= 0 && py >= 0 && px + dx < sx && py + dy < sy)
+ {
+ const double x0 = canvas_mtx.tx + px, y0 = canvas_mtx.ty + py;
+ layout.legend_area[k] = agg::trans_affine(dx, 0.0, 0.0, dy, x0, y0);
+ }
+ else
+ {
+ plot_layout::set_area_undefined(layout.legend_area[k]);
+ }
+ }
+ }
+
+ double x0 = canvas_mtx.tx + dxl, y0 = canvas_mtx.ty + dyb;
+ double ssx = sx - (dxl + dxr), ssy = sy - (dyb + dyt);
+ layout.plot_area = agg::trans_affine(ssx, 0.0, 0.0, ssy, x0, y0);
+
+ return layout;
+}
+
+void plot::draw_legends(canvas_type& canvas, const plot_layout& layout)
+{
+ if (!str_is_null(&m_title))
+ {
+ const plot_layout::point& pos = layout.title_pos;
+ draw::text title(m_title.cstr(), layout.title_font_size, 0.5, 0.0);
+ title.set_point(pos.x, pos.y);
+ title.apply_transform(identity_matrix, 1.0);
+ canvas.draw(title, colors::black);
+ }
+
+ for (int k = 0; k < 4; k++)
+ {
+ plot* mp = m_legend[k];
+ const agg::trans_affine& mtx = layout.legend_area[k];
+
+ if (mp && plot_layout::is_area_defined(mtx))
+ {
+ agg::rect_i clip = rect_of_slot_matrix<int>(mtx);
+ plot_layout mp_layout = mp->compute_plot_layout(mtx, false);
+ mp->draw_simple(canvas, mp_layout, &clip);
+ }
+ }
+}
+
+// Draw the axis elements and labels and set layout.plot_active_area
+// to the actual plotting are matrix.
+void plot::draw_axis(canvas_type& canvas, plot_layout& layout, const agg::rect_i* clip)
+{
+ if (!m_use_units)
+ {
+ layout.plot_active_area = layout.plot_area;
+ return;
+ }
+
+ double scale = compute_scale(layout.plot_area);
+
+ if (clip)
+ canvas.clip_box(*clip);
+
+ const agg::trans_affine& m = layout.plot_active_area;
+
+ agg::path_storage box;
+ sg_object_gen<agg::conv_transform<agg::path_storage> > boxtr(box, m);
+ trans::stroke_a boxvs(&boxtr);
+
+ box.move_to(0.0, 0.0);
+ box.line_to(0.0, 1.0);
+ box.line_to(1.0, 1.0);
+ box.line_to(1.0, 0.0);
+ box.close_polygon();
+
+ agg::path_storage x_mark;
+ sg_object_gen<agg::conv_transform<agg::path_storage> > x_mark_tr(x_mark, m);
+ trans::stroke_a x_mark_stroke(&x_mark_tr);
+
+ agg::path_storage y_mark;
+ sg_object_gen<agg::conv_transform<agg::path_storage> > y_mark_tr(y_mark, m);
+ trans::stroke_a y_mark_stroke(&y_mark_tr);
+
+ agg::path_storage ln;
+ sg_object_gen<agg::conv_transform<agg::path_storage> > ln_tr(ln, m);
+ trans::dash_a lndash(&ln_tr);
+ trans::stroke_a lns(&lndash);
+
+ const double label_text_size = get_default_font_size(text_axis_title, scale);
+ const double plpad = double(axis_label_prop_space) / 1000.0;
+ const double ptpad = double(axis_title_prop_space) / 1000.0;
+
+ ptr_list<draw::text> xlabels, ylabels;
+
+ double dy_label = 0;
+ if (this->m_xaxis_hol)
+ dy_label = draw_xaxis_factors(m_ux, m_trans, xlabels, this->m_xaxis_hol, scale, x_mark, ln);
+ else
+ dy_label = draw_axis_m(x_axis, m_ux, m_trans, xlabels, scale, x_mark, ln);
+
+ double dx_label = draw_axis_m(y_axis, m_uy, m_trans, ylabels, scale, y_mark, ln);
+
+ double ppad_left = plpad, ppad_right = plpad;
+ double ppad_bottom = plpad, ppad_top = plpad;
+ double dx_left = dx_label, dx_right = 0.0;
+ double dy_bottom = dy_label, dy_top = 0.0;
+
+ if (!str_is_null(&m_y_axis.title))
+ {
+ dx_left += approx_text_height(label_text_size);
+ ppad_left += ptpad;
+ }
+
+ if (!str_is_null(&m_x_axis.title))
+ {
+ dy_bottom += approx_text_height(label_text_size);
+ ppad_bottom += ptpad;
+ }
+
+ const double sx = layout.plot_area.sx, sy = layout.plot_area.sy;
+ const double x0 = layout.plot_area.tx, y0 = layout.plot_area.ty;
+
+ const double xppad = (ppad_left + ppad_right);
+ const double lsx = (dx_left + dx_right + xppad * sx) / (1 + xppad);
+
+ const double yppad = (ppad_bottom + ppad_top);
+ const double lsy = (dy_bottom + dy_top + yppad * sy) / (1 + yppad);
+
+ const double sxr = sx - lsx;
+ const double syr = sy - lsy;
+
+ const double aax = x0 + dx_left + ppad_left * sxr;
+ const double aay = y0 + dy_bottom + ppad_bottom * syr;
+ layout.set_plot_active_area(sxr, syr, aax, aay);
+
+ agg::trans_affine m_xlabels;
+ if (this->m_xaxis_hol)
+ {
+ m_xlabels.sx = m.sx;
+ m_xlabels.tx = m.tx;
+ m_xlabels.ty = m.ty;
+
+ x_mark_tr.self().transformer(m_xlabels);
+ }
+ else
+ {
+ m_xlabels = m;
+ }
+
+ for (unsigned j = 0; j < xlabels.size(); j++)
+ {
+ draw::text* label = xlabels[j];
+ label->apply_transform(m_xlabels, 1.0);
+ canvas.draw(*label, colors::black);
+ }
+
+ for (unsigned j = 0; j < ylabels.size(); j++)
+ {
+ draw::text* label = ylabels[j];
+ label->apply_transform(m, 1.0);
+ canvas.draw(*label, colors::black);
+ }
+
+ lndash.add_dash(7.0, 3.0);
+
+ lns.width(std_line_width(scale, 0.15));
+ canvas.draw(lns, colors::black);
+
+ x_mark_stroke.width(std_line_width(scale, 0.75));
+ canvas.draw(x_mark_stroke, colors::black);
+
+ y_mark_stroke.width(std_line_width(scale, 0.75));
+ canvas.draw(y_mark_stroke, colors::black);
+
+ boxvs.width(std_line_width(scale, 0.75));
+ canvas.draw(boxvs, colors::black);
+
+ if (!str_is_null(&m_x_axis.title))
+ {
+ double labx = m.sx * 0.5 + m.tx;
+ double laby = y0;
+
+ const char* text = m_x_axis.title.cstr();
+ draw::text xlabel(text, label_text_size, 0.5, 0.0);
+ xlabel.set_point(labx, laby);
+ xlabel.apply_transform(identity_matrix, 1.0);
+
+ canvas.draw(xlabel, colors::black);
+ }
+
+ if (!str_is_null(&m_y_axis.title))
+ {
+ double labx = x0;
+ double laby = m.sy * 0.5 + m.ty;
+
+ const char* text = m_y_axis.title.cstr();
+ draw::text ylabel(text, label_text_size, 0.5, 1.0);
+ ylabel.set_point(labx, laby);
+ ylabel.angle(M_PI/2.0);
+ ylabel.apply_transform(identity_matrix, 1.0);
+
+ canvas.draw(ylabel, colors::black);
+ }
+
+ if (clip)
+ canvas.reset_clipping();
+}
+
+void plot::set_axis_labels_angle(axis_e axis_dir, double angle)
+{
+ get_axis(axis_dir).set_labels_angle(angle);
+ m_need_redraw = true;
+ compute_user_trans();
+}
+
+void plot::set_units(bool use_units)
+{
+ if (m_use_units != use_units)
+ {
+ m_use_units = use_units;
+ m_need_redraw = true;
+ compute_user_trans();
+ }
+}
+
+void plot::update_units()
+{
+ if (m_rect.is_defined())
+ {
+ const rect_base<double>& r = m_rect.rect();
+ m_ux = units(r.x1, r.x2);
+ m_uy = units(r.y1, r.y2);
+ }
+ else
+ {
+ m_ux = units();
+ m_uy = units();
+ }
+
+ compute_user_trans();
+}
+
+void plot::set_limits(const agg::rect_base<double>& r)
+{
+ m_rect.set(r);
+ update_units();
+ m_need_redraw = true;
+}
+
+void plot::unset_limits()
+{
+ m_rect.clear();
+ update_units();
+ m_need_redraw = true;
+}
+
+void plot::layer_dispose_elements(plot::item_list* layer)
+{
+ unsigned n = layer->size();
+ for (unsigned k = 0; k < n; k++)
+ {
+ RM::dispose(layer->at(k).vs);
+ }
+}
+
+bool plot::push_layer()
+{
+ if (m_layers.size() >= max_layers)
+ return false;
+
+ item_list *new_layer = new(std::nothrow) item_list();
+ if (new_layer)
+ {
+ before_draw();
+ push_drawing_queue();
+ m_layers.add(new_layer);
+ return true;
+ }
+
+ return false;
+}
+
+bool plot::pop_layer()
+{
+ if (m_layers.size() <= 1)
+ return false;
+
+ unsigned n = m_layers.size();
+ item_list* layer = m_layers[n-1];
+ m_layers.inc_size(-1);
+ layer_dispose_elements(layer);
+ delete layer;
+
+ clear_drawing_queue();
+ m_need_redraw = true;
+
+ return true;
+}
+
+void plot::clear_current_layer()
+{
+ item_list* current = current_layer();
+ clear_drawing_queue();
+ layer_dispose_elements(current);
+ current->clear();
+ m_changes_pending = m_changes_accu;
+ m_changes_accu.clear();
+}
+
+int plot::current_layer_index()
+{
+ return m_layers.size();
+}
diff --git a/agg-plot/plot.h b/agg-plot/plot.h
index 06d0d35a..25b0ce72 100644
--- a/agg-plot/plot.h
+++ b/agg-plot/plot.h
@@ -36,6 +36,7 @@
#include "text.h"
#include "categories.h"
#include "sg_object.h"
+#include "factor_labels.h"
#include "agg_array.h"
#include "agg_bounding_rect.h"
@@ -123,7 +124,8 @@ struct plot_item {
};
};
-template<class ResourceManager>
+typedef manage_owner RM;
+
class plot {
static const unsigned max_layers = 8;
@@ -239,7 +241,8 @@ public:
m_drawing_queue(0), m_clip_flag(true),
m_need_redraw(true), m_rect(),
m_use_units(use_units), m_pad_units(false), m_title(),
- m_sync_mode(true), m_x_axis(x_axis), m_y_axis(y_axis)
+ m_sync_mode(true), m_x_axis(x_axis), m_y_axis(y_axis),
+ m_xaxis_hol(0)
{
m_layers.add(&m_root_layer);
compute_user_trans();
@@ -256,6 +259,8 @@ public:
if (k > 0)
delete layer;
}
+
+ delete m_xaxis_hol;
};
str& title() {
@@ -301,6 +306,14 @@ public:
void set_limits(const agg::rect_base<double>& r);
void unset_limits();
+ ptr_list<factor_labels>* get_xaxis_hol() { return m_xaxis_hol; }
+
+ void set_xaxis_hol(ptr_list<factor_labels>* hol)
+ {
+ delete m_xaxis_hol;
+ m_xaxis_hol = hol;
+ }
+
virtual void add(sg_object* vs, agg::rgba8& color, bool outline);
virtual void before_draw() { }
@@ -417,10 +430,19 @@ protected:
void draw_virtual_canvas(canvas_type& canvas, plot_layout& layout, const agg::rect_i* r);
void draw_simple(canvas_type& canvas, plot_layout& layout, const agg::rect_i* r);
+ void draw_grid(const axis_e dir, const units& u,
+ const agg::trans_affine& user_mtx,
+ agg::path_storage& ln);
+
double draw_axis_m(axis_e dir, units& u, const agg::trans_affine& user_mtx,
ptr_list<draw::text>& labels, double scale,
agg::path_storage& mark, agg::path_storage& ln);
+ double draw_xaxis_factors(units& u, const agg::trans_affine& user_mtx,
+ ptr_list<draw::text>& labels,
+ ptr_list<factor_labels>* f_labels, double scale,
+ agg::path_storage& mark, agg::path_storage& ln);
+
void draw_elements(canvas_type &canvas, const plot_layout& layout);
void draw_element(item& c, canvas_type &canvas, const agg::trans_affine& m);
void draw_axis(canvas_type& can, plot_layout& layout, const agg::rect_i* clip = 0);
@@ -486,144 +508,12 @@ private:
axis m_x_axis, m_y_axis;
plot* m_legend[4];
-};
-
-static double compute_scale(const agg::trans_affine& m)
-{
- return m.scale() / 480.0;
-}
-
-static double
-std_line_width(double scale, double w = 1.0)
-{
-#if 0
- const double dsf = M_LN10;
- double ls = log(scale) / dsf;
- return exp(round(ls) * dsf) * w * 1.5;
-#else
- return w * 1.5;
-#endif
-}
-
-template <class RM>
-void plot<RM>::commit_pending_draw()
-{
- push_drawing_queue();
- m_need_redraw = false;
- m_changes_pending.clear();
-}
-
-template <class RM>
-void plot<RM>::add(sg_object* vs, agg::rgba8& color, bool outline)
-{
- item d(vs, color, outline);
- list<item> *new_node = new list<item>(d);
- m_drawing_queue = list<item>::push_back(m_drawing_queue, new_node);
- RM::acquire(vs);
-}
-
-template <class RM>
-void plot<RM>::push_drawing_queue()
-{
- item_list* layer = current_layer();
- for (list<item> *c = m_drawing_queue; c != 0; c = c->next())
- {
- layer->add(c->content());
- }
-
- while (m_drawing_queue)
- m_drawing_queue = list<item>::pop(m_drawing_queue);
-}
-
-template <class RM>
-void plot<RM>::clear_drawing_queue()
-{
- while (m_drawing_queue)
- {
- item& d = m_drawing_queue->content();
- RM::dispose(d.vs);
- m_drawing_queue = list<item>::pop(m_drawing_queue);
- }
-}
-
-static bool area_is_valid(const agg::trans_affine& b)
-{
- const double thresold = 40.0;
- return (b.sx > thresold && b.sy > thresold);
-}
-template <class RM>
-void plot<RM>::draw_virtual_canvas(canvas_type& canvas, plot_layout& layout, const agg::rect_i* clip)
-{
- before_draw();
- draw_legends(canvas, layout);
-
- if (area_is_valid(layout.plot_area))
- {
- draw_axis(canvas, layout, clip);
- draw_elements(canvas, layout);
- }
-};
-
-template <class RM>
-void plot<RM>::draw_simple(canvas_type& canvas, plot_layout& layout, const agg::rect_i* clip)
-{
- before_draw();
- draw_axis(canvas, layout, clip);
- draw_elements(canvas, layout);
+ ptr_list<factor_labels>* m_xaxis_hol;
};
-template <class RM>
-void plot<RM>::draw_element(item& c, canvas_type& canvas, const agg::trans_affine& m)
-{
- sg_object& vs = c.content();
- vs.apply_transform(m, 1.0);
-
- if (c.outline)
- canvas.draw_outline(vs, c.color);
- else
- canvas.draw(vs, c.color);
-}
-
-template <class RM>
-agg::trans_affine plot<RM>::get_model_matrix(const plot_layout& layout)
-{
- agg::trans_affine m = m_trans;
- trans_affine_compose (m, layout.plot_active_area);
- return m;
-}
-
-template<class RM>
-void plot<RM>::clip_plot_area(canvas_type& canvas, const agg::trans_affine& area_mtx)
-{
- if (this->clip_is_active())
- {
- agg::rect_base<int> clip = rect_of_slot_matrix<int>(area_mtx);
- canvas.clip_box(clip);
- }
-}
-
-template <class RM>
-void plot<RM>::draw_elements(canvas_type& canvas, const plot_layout& layout)
-{
- const agg::trans_affine m = get_model_matrix(layout);
-
- this->clip_plot_area(canvas, layout.plot_active_area);
-
- for (unsigned k = 0; k < m_layers.size(); k++)
- {
- item_list& layer = *(m_layers[k]);
- for (unsigned j = 0; j < layer.size(); j++)
- {
- draw_element(layer[j], canvas, m);
- }
- }
-
- canvas.reset_clipping();
-}
-
-template <class RM>
-template <class Canvas> void plot<RM>::draw_queue(Canvas& _canvas, const agg::trans_affine& canvas_mtx, const plot_render_info& inf, opt_rect<double>& bb)
+template <class Canvas>
+void plot::draw_queue(Canvas& _canvas, const agg::trans_affine& canvas_mtx, const plot_render_info& inf, opt_rect<double>& bb)
{
canvas_adapter<Canvas> canvas(&_canvas);
before_draw();
@@ -633,7 +523,7 @@ template <class Canvas> void plot<RM>::draw_queue(Canvas& _canvas, const agg::tr
this->clip_plot_area(canvas, layout.plot_active_area);
- typedef typename plot<RM>::iterator iter_type;
+ typedef typename plot::iterator iter_type;
iter_type *c0 = m_drawing_queue;
for (iter_type *c = c0; c != 0; c = c->next())
{
@@ -658,483 +548,4 @@ template <class Canvas> void plot<RM>::draw_queue(Canvas& _canvas, const agg::tr
canvas.reset_clipping();
}
-template <class RM>
-void plot<RM>::compute_user_trans()
-{
- agg::rect_base<double> r;
-
- if (m_use_units && m_pad_units)
- {
- int ixi, ixs, iyi, iys;
- double xd, yd;
- m_ux.limits(ixi, ixs, xd);
- r.x1 = ixi * xd;
- r.x2 = ixs * xd;
-
- m_uy.limits(iyi, iys, yd);
- r.y1 = iyi * yd;
- r.y2 = iys * yd;
- }
- else
- {
- r = m_rect.is_defined() ? m_rect.rect() : agg::rect_base<double>(0.0, 0.0, 1.0, 1.0);
- }
-
- double dx = r.x2 - r.x1, dy = r.y2 - r.y1;
- double fx = (dx == 0 ? 1.0 : 1/dx), fy = (dy == 0 ? 1.0 : 1/dy);
- this->m_trans = agg::trans_affine(fx, 0.0, 0.0, fy, -r.x1 * fx, -r.y1 * fy);
-}
-
-template <class RM>
-double plot<RM>::draw_axis_m(axis_e dir, units& u,
- const agg::trans_affine& user_mtx,
- ptr_list<draw::text>& labels, double scale,
- agg::path_storage& mark, agg::path_storage& ln)
-{
- const double ppad = double(axis_label_prop_space) / 1000.0;
- const double text_label_size = get_default_font_size(text_axis_labels, scale);
- const double eps = 1.0e-3;
-
- opt_rect<double> bb;
- agg::rect_base<double> r;
-
- bool isx = (dir == x_axis);
-
- const axis& ax = get_axis(dir);
- double hj = ax.labels_hjustif(), vj = ax.labels_vjustif();
- double langle = ax.labels_angle();
-
- category_map::iterator clabels(ax.categories);
- units_iterator ulabels(u, ax.format_tag, ax.label_format());
-
- label_iterator* ilabels = (ax.use_categories ? (label_iterator*) &clabels : (label_iterator*) &ulabels);
-
- double uq;
- const char* text;
- while (ilabels->next(uq, text))
- {
- double x = (isx ? uq : 0.0), y = (isx ? 0.0 : uq);
- user_mtx.transform(&x, &y);
-
- double q = (isx ? x : y);
-
- if (q < -eps || q > 1.0 + eps)
- continue;
-
- draw::text* label = new draw::text(text, text_label_size, hj, vj);
-
- label->set_point(isx ? q : -ppad, isx ? -ppad : q);
- label->angle(langle);
-
- agg::bounding_rect_single(*label, 0, &r.x1, &r.y1, &r.x2, &r.y2);
- bb.add<rect_union>(r);
-
- labels.add(label);
-
- mark.move_to(isx ? q : 0.0 , isx ? 0.0 : q);
- mark.line_to(isx ? q : -0.01, isx ? -0.01 : q);
- }
-
- int jinf = u.begin(), jsup = u.end();
- for (int j = jinf+1; j < jsup; j++)
- {
- double uq = u.mark_value(j);
- double x = (isx ? uq : 0), y = (isx ? 0.0 : uq);
- user_mtx.transform(&x, &y);
- double q = (isx ? x : y);
-
- if (q >= -eps && q <= 1.0 + eps)
- {
- ln.move_to(isx ? q : 0.0, isx ? 0.0 : q);
- ln.line_to(isx ? q : 1.0, isx ? 1.0 : q);
- }
- }
-
- double label_size;
- if (bb.is_defined())
- {
- const agg::rect_base<double>& br = bb.rect();
- label_size = (isx ? br.y2 - br.y1 : br.x2 - br.x1);
- }
- else
- {
- label_size = 0.0;
- }
-
- return label_size;
-}
-
-static inline double approx_text_height(double text_size)
-{
- return text_size * 1.5;
-}
-
-template <class RM>
-plot_layout plot<RM>::compute_plot_layout(const agg::trans_affine& canvas_mtx, bool do_legends)
-{
- plot_layout layout;
-
- const double sx = canvas_mtx.sx, sy = canvas_mtx.sy;
- const double ppad = double(canvas_margin_prop_space) / 1000.0;
- const double fpad = double(canvas_margin_fixed_space);
- const double size_frac_x = 0.125, size_frac_y = 0.05;
-
- double dxl, dxr, dyb, dyt;
-
- dxl = dxr = fpad + ppad * sx;
- dyb = dyt = fpad + ppad * sy;
-
- if (!str_is_null(&m_title))
- {
- const double scale = compute_scale(canvas_mtx);
- const double ptpad = double(axis_title_prop_space) / 1000.0;
- const double title_text_size = get_default_font_size(text_plot_title, scale);
- const double th = approx_text_height(title_text_size);
-
- double x = 0.5, y = 1.0;
- canvas_mtx.transform(&x, &y);
- y -= ptpad + dyt + title_text_size;
-
- layout.title_pos = plot_layout::point(x, y);
- layout.title_font_size = title_text_size;
-
- dyt += 2 * ptpad + th;
- }
-
- for (int k = 0; k < 4 && do_legends; k++)
- {
- plot* mp = m_legend[k];
-
- if (mp)
- {
- agg::rect_base<double> bb;
- mp->get_bounding_rect(bb);
-
- double bb_dx = bb.x2 - bb.x1, bb_dy = bb.y2 - bb.y1;
- double dx, dy;
- double px, py;
- switch (k)
- {
- case right:
- dx = max(sx * size_frac_x, bb_dx);
- dy = dx * bb_dy / bb_dx;
- px = sx - dx - ppad * sx - dxr;
- py = (sy - dy) / 2;
- dxr += dx + 2 * ppad * sx;
- break;
- case left:
- dx = max(sx * size_frac_x, bb_dx);
- dy = dx * bb_dy / bb_dx;
- px = ppad * sx + dxr;
- py = (sy - dy) / 2;
- dxl += dx + 2 * ppad * sx;
- break;
- case bottom:
- dy = sy * size_frac_y;
- dx = dy * bb_dx / bb_dy;
- py = ppad * sy + dyb;
- px = (sx - dx) / 2;
- dyb += dy + 2 * ppad * sy;
- break;
- case top:
- dy = sy * size_frac_y;
- dx = dy * bb_dx / bb_dy;
- py = sy - dy - ppad * sy - dyt;
- px = (sx - dx) / 2;
- dyt += dy + 2 * ppad * sy;
- break;
- default:
- /* */
- ;
- }
-
- if (px >= 0 && py >= 0 && px + dx < sx && py + dy < sy)
- {
- const double x0 = canvas_mtx.tx + px, y0 = canvas_mtx.ty + py;
- layout.legend_area[k] = agg::trans_affine(dx, 0.0, 0.0, dy, x0, y0);
- }
- else
- {
- plot_layout::set_area_undefined(layout.legend_area[k]);
- }
- }
- }
-
- double x0 = canvas_mtx.tx + dxl, y0 = canvas_mtx.ty + dyb;
- double ssx = sx - (dxl + dxr), ssy = sy - (dyb + dyt);
- layout.plot_area = agg::trans_affine(ssx, 0.0, 0.0, ssy, x0, y0);
-
- return layout;
-}
-
-template <class RM>
-void plot<RM>::draw_legends(canvas_type& canvas, const plot_layout& layout)
-{
- if (!str_is_null(&m_title))
- {
- const plot_layout::point& pos = layout.title_pos;
- draw::text title(m_title.cstr(), layout.title_font_size, 0.5, 0.0);
- title.set_point(pos.x, pos.y);
- title.apply_transform(identity_matrix, 1.0);
- canvas.draw(title, colors::black);
- }
-
- for (int k = 0; k < 4; k++)
- {
- plot* mp = m_legend[k];
- const agg::trans_affine& mtx = layout.legend_area[k];
-
- if (mp && plot_layout::is_area_defined(mtx))
- {
- agg::rect_i clip = rect_of_slot_matrix<int>(mtx);
- plot_layout mp_layout = mp->compute_plot_layout(mtx, false);
- mp->draw_simple(canvas, mp_layout, &clip);
- }
- }
-}
-
-// Draw the axis elements and labels and set layout.plot_active_area
-// to the actual plotting are matrix.
-template <class RM>
-void plot<RM>::draw_axis(canvas_type& canvas, plot_layout& layout, const agg::rect_i* clip)
-{
- if (!m_use_units)
- {
- layout.plot_active_area = layout.plot_area;
- return;
- }
-
- double scale = compute_scale(layout.plot_area);
-
- if (clip)
- canvas.clip_box(*clip);
-
- const agg::trans_affine& m = layout.plot_active_area;
-
- agg::path_storage box;
- sg_object_gen<agg::conv_transform<agg::path_storage> > boxtr(box, m);
- trans::stroke_a boxvs(&boxtr);
-
- box.move_to(0.0, 0.0);
- box.line_to(0.0, 1.0);
- box.line_to(1.0, 1.0);
- box.line_to(1.0, 0.0);
- box.close_polygon();
-
- agg::path_storage mark;
- sg_object_gen<agg::conv_transform<agg::path_storage> > mark_tr(mark, m);
- trans::stroke_a mark_stroke(&mark_tr);
-
- agg::path_storage ln;
- sg_object_gen<agg::conv_transform<agg::path_storage> > ln_tr(ln, m);
- trans::dash_a lndash(&ln_tr);
- trans::stroke_a lns(&lndash);
-
- const double label_text_size = get_default_font_size(text_axis_title, scale);
- const double plpad = double(axis_label_prop_space) / 1000.0;
- const double ptpad = double(axis_title_prop_space) / 1000.0;
-
- ptr_list<draw::text> labels;
-
- double dy_label = draw_axis_m(x_axis, m_ux, m_trans, labels, scale, mark, ln);
- double dx_label = draw_axis_m(y_axis, m_uy, m_trans, labels, scale, mark, ln);
-
- double ppad_left = plpad, ppad_right = plpad;
- double ppad_bottom = plpad, ppad_top = plpad;
- double dx_left = dx_label, dx_right = 0.0;
- double dy_bottom = dy_label, dy_top = 0.0;
-
- if (!str_is_null(&m_y_axis.title))
- {
- dx_left += approx_text_height(label_text_size);
- ppad_left += ptpad;
- }
-
- if (!str_is_null(&m_x_axis.title))
- {
- dy_bottom += approx_text_height(label_text_size);
- ppad_bottom += ptpad;
- }
-
- const double sx = layout.plot_area.sx, sy = layout.plot_area.sy;
- const double x0 = layout.plot_area.tx, y0 = layout.plot_area.ty;
-
- const double xppad = (ppad_left + ppad_right);
- const double lsx = (dx_left + dx_right + xppad * sx) / (1 + xppad);
-
- const double yppad = (ppad_bottom + ppad_top);
- const double lsy = (dy_bottom + dy_top + yppad * sy) / (1 + yppad);
-
- const double sxr = sx - lsx;
- const double syr = sy - lsy;
-
- const double aax = x0 + dx_left + ppad_left * sxr;
- const double aay = y0 + dy_bottom + ppad_bottom * syr;
- layout.set_plot_active_area(sxr, syr, aax, aay);
-
- for (unsigned j = 0; j < labels.size(); j++)
- {
- draw::text* label = labels[j];
- label->apply_transform(m, 1.0);
- canvas.draw(*label, colors::black);
- }
-
- lndash.add_dash(7.0, 3.0);
-
- lns.width(std_line_width(scale, 0.15));
- canvas.draw(lns, colors::black);
-
- mark_stroke.width(std_line_width(scale, 0.75));
- canvas.draw(mark_stroke, colors::black);
-
- boxvs.width(std_line_width(scale, 0.75));
- canvas.draw(boxvs, colors::black);
-
- if (!str_is_null(&m_x_axis.title))
- {
- double labx = m.sx * 0.5 + m.tx;
- double laby = y0;
-
- const char* text = m_x_axis.title.cstr();
- draw::text xlabel(text, label_text_size, 0.5, 0.0);
- xlabel.set_point(labx, laby);
- xlabel.apply_transform(identity_matrix, 1.0);
-
- canvas.draw(xlabel, colors::black);
- }
-
- if (!str_is_null(&m_y_axis.title))
- {
- double labx = x0;
- double laby = m.sy * 0.5 + m.ty;
-
- const char* text = m_y_axis.title.cstr();
- draw::text ylabel(text, label_text_size, 0.5, 1.0);
- ylabel.set_point(labx, laby);
- ylabel.angle(M_PI/2.0);
- ylabel.apply_transform(identity_matrix, 1.0);
-
- canvas.draw(ylabel, colors::black);
- }
-
- if (clip)
- canvas.reset_clipping();
-}
-
-template<class RM>
-void plot<RM>::set_axis_labels_angle(axis_e axis_dir, double angle)
-{
- get_axis(axis_dir).set_labels_angle(angle);
- m_need_redraw = true;
- compute_user_trans();
-}
-
-template<class RM>
-void plot<RM>::set_units(bool use_units)
-{
- if (m_use_units != use_units)
- {
- m_use_units = use_units;
- m_need_redraw = true;
- compute_user_trans();
- }
-}
-
-template<class RM>
-void plot<RM>::update_units()
-{
- if (m_rect.is_defined())
- {
- const rect_base<double>& r = m_rect.rect();
- m_ux = units(r.x1, r.x2);
- m_uy = units(r.y1, r.y2);
- }
- else
- {
- m_ux = units();
- m_uy = units();
- }
-
- compute_user_trans();
-}
-
-template<class RM>
-void plot<RM>::set_limits(const agg::rect_base<double>& r)
-{
- m_rect.set(r);
- update_units();
- m_need_redraw = true;
-}
-
-template<class RM>
-void plot<RM>::unset_limits()
-{
- m_rect.clear();
- update_units();
- m_need_redraw = true;
-}
-
-template<class RM>
-void plot<RM>::layer_dispose_elements(plot<RM>::item_list* layer)
-{
- unsigned n = layer->size();
- for (unsigned k = 0; k < n; k++)
- {
- RM::dispose(layer->at(k).vs);
- }
-}
-
-template<class RM>
-bool plot<RM>::push_layer()
-{
- if (m_layers.size() >= max_layers)
- return false;
-
- item_list *new_layer = new(std::nothrow) item_list();
- if (new_layer)
- {
- before_draw();
- push_drawing_queue();
- m_layers.add(new_layer);
- return true;
- }
-
- return false;
-}
-
-template<class RM>
-bool plot<RM>::pop_layer()
-{
- if (m_layers.size() <= 1)
- return false;
-
- unsigned n = m_layers.size();
- item_list* layer = m_layers[n-1];
- m_layers.inc_size(-1);
- layer_dispose_elements(layer);
- delete layer;
-
- clear_drawing_queue();
- m_need_redraw = true;
-
- return true;
-}
-
-template <class RM>
-void plot<RM>::clear_current_layer()
-{
- item_list* current = current_layer();
- clear_drawing_queue();
- layer_dispose_elements(current);
- current->clear();
- m_changes_pending = m_changes_accu;
- m_changes_accu.clear();
-}
-
-template <class RM>
-int plot<RM>::current_layer_index()
-{
- return m_layers.size();
-}
-
#endif
diff --git a/agg-plot/units.h b/agg-plot/units.h
index f315d804..b929e38d 100644
--- a/agg-plot/units.h
+++ b/agg-plot/units.h
@@ -90,7 +90,6 @@ public:
val = m_units.mark_value(m_index);
text = m_buffer;
- text = m_buffer;
m_index ++;
return true;
}
diff --git a/agg-plot/utils.h b/agg-plot/utils.h
index d1274d32..1e66be31 100644
--- a/agg-plot/utils.h
+++ b/agg-plot/utils.h
@@ -40,6 +40,10 @@ public:
return m_list[k];
}
+ T* at(unsigned k) const {
+ return m_list[k];
+ }
+
unsigned size() const {
return m_list.size();
}
diff --git a/benchmarks/results.csv b/benchmarks/results.csv
new file mode 100644
index 00000000..a750caf7
--- /dev/null
+++ b/benchmarks/results.csv
@@ -0,0 +1,16 @@
+Test,Source,Time
+ODE rk8pd,LuaJIT2 joff,10.408
+ODE rk8pd,C,1.449
+ODE rk8pd,LuaJIT2,0.732
+ODE rkf45,LuaJIT2 joff,22.27
+ODE rkf45,C,2.192
+ODE rkf45,LuaJIT2,0.95
+SF roots,LuaJIT2 joff,18.765
+SF roots,LuaJIT2 FFI,6.437
+SF roots,LuaJIT2,6.531
+VEGAS,LuaJIT2 joff,134.617
+VEGAS,C,2.509
+VEGAS,LuaJIT2,2.914
+QAG,LuaJIT2 joff,6.889
+QAG,C,1.886
+QAG,LuaJIT2,1.107
diff --git a/c028-cpm-sige.csv b/c028-cpm-sige.csv
new file mode 100644
index 00000000..f67805f6
--- /dev/null
+++ b/c028-cpm-sige.csv
@@ -0,0 +1,1021 @@
+exec_time,reprod,repeat,tool,site,th_oxide,ri_sige,th_sige,GOF
+0,1,1,QFX1001,1,2.8768,27.9672,91.3146,0.8911
+0,1,1,QFX1001,2,2.9174,27.962,88.7189,0.8952
+0,1,1,QFX1001,3,3.0534,27.9883,87.7529,0.8988
+0,1,1,QFX1001,4,3.0699,27.9698,88.1033,0.8952
+0,1,1,QFX1001,5,2.9877,27.9726,87.5407,0.8954
+0,1,1,QFX1001,6,2.9656,27.9725,88.654,0.8947
+0,1,1,QFX1001,7,3.1267,27.9691,90.0054,0.8927
+0,1,1,QFX1001,8,2.8226,28.0335,88.8976,0.8993
+0,1,1,QFX1001,9,3.5913,27.9602,88.2237,0.8939
+0,1,1,QFX1001,10,3.7521,27.9873,87.9821,0.8976
+0,1,1,QFX1001,11,3.9671,27.9711,87.4903,0.8972
+0,1,1,QFX1001,12,4.0065,27.9778,88.3878,0.8972
+0,1,1,QFX1001,13,3.768,27.9675,87.6378,0.8972
+0,1,1,QFX1001,14,2.6454,28.03,89.3415,0.8988
+0,1,1,QFX1001,15,2.9999,27.9852,88.1469,0.8949
+0,1,1,QFX1001,16,3.3563,27.9788,87.1844,0.8972
+0,1,1,QFX1001,17,3.1252,27.9697,87.9573,0.8957
+0,1,2,QFX1001,1,2.955,27.9746,91.2626,0.8915
+0,1,2,QFX1001,2,2.949,27.9771,88.6664,0.896
+0,1,2,QFX1001,3,3.0596,27.9909,87.8157,0.8987
+0,1,2,QFX1001,4,3.1502,27.9802,88.0928,0.8973
+0,1,2,QFX1001,5,3.0944,27.9695,87.5523,0.8972
+0,1,2,QFX1001,6,2.9575,27.9684,88.7325,0.8932
+0,1,2,QFX1001,7,3.1959,27.9633,89.9479,0.8932
+0,1,2,QFX1001,8,2.8787,28.0329,89.0195,0.8984
+0,1,2,QFX1001,9,3.6279,27.9679,88.2854,0.8963
+0,1,2,QFX1001,10,3.8151,27.9858,87.9602,0.8978
+0,1,2,QFX1001,11,3.993,27.9785,87.4471,0.8979
+0,1,2,QFX1001,12,3.9557,27.9851,88.3645,0.8962
+0,1,2,QFX1001,13,3.7671,27.9628,87.6516,0.8966
+0,1,2,QFX1001,14,2.6523,28.0441,89.3495,0.8989
+0,1,2,QFX1001,15,3.0374,27.978,88.2228,0.8951
+0,1,2,QFX1001,16,3.3506,27.9861,87.1881,0.896
+0,1,2,QFX1001,17,3.1066,27.964,87.9809,0.8955
+0,1,3,QFX1001,1,2.9953,27.9603,91.2843,0.8916
+0,1,3,QFX1001,2,2.9117,27.9719,88.7788,0.8946
+0,1,3,QFX1001,3,3.024,27.991,87.8271,0.8982
+0,1,3,QFX1001,4,3.1542,27.978,88.1864,0.8959
+0,1,3,QFX1001,5,3.1174,27.9671,87.5671,0.8958
+0,1,3,QFX1001,6,3.0921,27.9663,88.4532,0.8913
+0,1,3,QFX1001,7,3.2308,27.9621,89.9923,0.8934
+0,1,3,QFX1001,8,2.9012,28.0332,88.8756,0.8973
+0,1,3,QFX1001,9,3.6262,27.9676,88.2522,0.8944
+0,1,3,QFX1001,10,3.824,27.9823,87.9936,0.8985
+0,1,3,QFX1001,11,3.9913,27.9767,87.463,0.8966
+0,1,3,QFX1001,12,4.0578,27.9668,88.4117,0.8961
+0,1,3,QFX1001,13,3.854,27.9617,87.6832,0.8964
+0,1,3,QFX1001,14,2.6532,28.0362,89.4173,0.8991
+0,1,3,QFX1001,15,3.1181,27.9777,88.0958,0.8942
+0,1,3,QFX1001,16,3.4308,27.9891,87.1482,0.8971
+0,1,3,QFX1001,17,3.128,27.9793,87.937,0.8968
+0,1,4,QFX1001,1,3.0215,27.9606,91.3557,0.8909
+0,1,4,QFX1001,2,3.004,27.9715,88.7782,0.8962
+0,1,4,QFX1001,3,3.0416,27.9941,87.8659,0.8987
+0,1,4,QFX1001,4,3.2381,27.9768,88.1452,0.8968
+0,1,4,QFX1001,5,3.1712,27.9697,87.4901,0.8964
+0,1,4,QFX1001,6,3.1154,27.9625,88.659,0.8927
+0,1,4,QFX1001,7,3.2603,27.9761,89.9834,0.894
+0,1,4,QFX1001,8,2.9306,28.0387,88.9388,0.8988
+0,1,4,QFX1001,9,3.6187,27.9691,88.2616,0.895
+0,1,4,QFX1001,10,3.8866,27.9886,87.9686,0.8984
+0,1,4,QFX1001,11,4.0177,27.9766,87.5191,0.8976
+0,1,4,QFX1001,12,4.0878,27.974,88.4209,0.8957
+0,1,4,QFX1001,13,3.9321,27.9595,87.6478,0.8958
+0,1,4,QFX1001,14,2.6994,28.0291,89.3712,0.8985
+0,1,4,QFX1001,15,3.1535,27.9759,88.0372,0.8942
+0,1,4,QFX1001,16,3.4852,27.9873,87.2236,0.8976
+0,1,4,QFX1001,17,3.1766,27.9789,87.884,0.8964
+0,1,5,QFX1001,1,3.0805,27.9639,91.3832,0.8924
+0,1,5,QFX1001,2,3.0537,27.9711,88.7136,0.8952
+0,1,5,QFX1001,3,3.1078,27.993,87.8438,0.8984
+0,1,5,QFX1001,4,3.1981,27.9764,88.2034,0.8946
+0,1,5,QFX1001,5,3.1666,27.9647,87.5171,0.8961
+0,1,5,QFX1001,6,3.152,27.9733,88.5211,0.8927
+0,1,5,QFX1001,7,3.2746,27.9676,90.0312,0.894
+0,1,5,QFX1001,8,2.943,28.0406,88.9989,0.8987
+0,1,5,QFX1001,9,3.6822,27.9794,88.3033,0.895
+0,1,5,QFX1001,10,3.883,27.9903,87.9885,0.8982
+0,1,5,QFX1001,11,4.1017,27.9772,87.5236,0.8981
+0,1,5,QFX1001,12,4.1151,27.9804,88.4124,0.8968
+0,1,5,QFX1001,13,3.9181,27.9569,87.6754,0.8966
+0,1,5,QFX1001,14,2.7444,28.0296,89.3347,0.8985
+0,1,5,QFX1001,15,3.2079,27.9794,88.1296,0.8958
+0,1,5,QFX1001,16,3.497,27.9877,87.1329,0.8962
+0,1,5,QFX1001,17,3.2174,27.9782,87.9624,0.8967
+15668,1,1,QFX1002,1,3.5344,28.3869,89.946,0.913
+15668,1,1,QFX1002,2,3.4285,28.4125,87.8389,0.9165
+15668,1,1,QFX1002,3,3.5632,28.418,86.7361,0.9153
+15668,1,1,QFX1002,4,3.7042,28.4051,87.0678,0.9148
+15668,1,1,QFX1002,5,3.5974,28.4135,86.7576,0.9201
+15668,1,1,QFX1002,6,3.6503,28.4147,87.4717,0.919
+15668,1,1,QFX1002,7,3.7414,28.3964,88.6632,0.9112
+15668,1,1,QFX1002,8,3.3847,28.494,87.9582,0.9195
+15668,1,1,QFX1002,9,4.07,28.4181,87.4459,0.9198
+15668,1,1,QFX1002,10,4.3719,28.4296,86.9052,0.9156
+15668,1,1,QFX1002,11,4.67,28.4145,86.2776,0.9139
+15668,1,1,QFX1002,12,4.5882,28.4231,87.5132,0.9163
+15668,1,1,QFX1002,13,4.4483,28.4166,86.9351,0.92
+15668,1,1,QFX1002,14,3.2902,28.4891,88.541,0.9204
+15668,1,1,QFX1002,15,3.7966,28.4193,86.9925,0.9185
+15668,1,1,QFX1002,16,3.9139,28.4304,86.3021,0.9178
+15668,1,1,QFX1002,17,3.684,28.4266,86.9431,0.9173
+15668,1,2,QFX1002,1,3.6346,28.4031,89.9827,0.9131
+15668,1,2,QFX1002,2,3.5204,28.4332,87.9745,0.9187
+15668,1,2,QFX1002,3,3.6547,28.4229,86.7915,0.9166
+15668,1,2,QFX1002,4,3.8034,28.4044,87.1383,0.9148
+15668,1,2,QFX1002,5,3.7149,28.4159,86.7996,0.9198
+15668,1,2,QFX1002,6,3.7414,28.4187,87.4598,0.919
+15668,1,2,QFX1002,7,3.7858,28.4061,88.771,0.9115
+15668,1,2,QFX1002,8,3.4572,28.4953,87.9905,0.9199
+15668,1,2,QFX1002,9,4.1355,28.4348,87.4807,0.9204
+15668,1,2,QFX1002,10,4.4424,28.4307,86.944,0.9166
+15668,1,2,QFX1002,11,4.758,28.4165,86.2745,0.9142
+15668,1,2,QFX1002,12,4.6733,28.4265,87.5469,0.9168
+15668,1,2,QFX1002,13,4.5609,28.4157,86.9024,0.9199
+15668,1,2,QFX1002,14,3.3631,28.4913,88.5203,0.9198
+15668,1,2,QFX1002,15,3.9076,28.4166,86.9758,0.9188
+15668,1,2,QFX1002,16,3.993,28.4287,86.3137,0.9175
+15668,1,2,QFX1002,17,3.765,28.4279,87.0151,0.9181
+15668,1,3,QFX1002,1,3.7466,28.3957,89.9671,0.9134
+15668,1,3,QFX1002,2,3.6292,28.4264,87.9137,0.9186
+15668,1,3,QFX1002,3,3.7666,28.4223,86.7568,0.917
+15668,1,3,QFX1002,4,3.9184,28.4093,87.1013,0.9159
+15668,1,3,QFX1002,5,3.8258,28.4177,86.7652,0.9197
+15668,1,3,QFX1002,6,3.8881,28.4144,87.4745,0.9187
+15668,1,3,QFX1002,7,3.8816,28.4066,88.7573,0.9113
+15668,1,3,QFX1002,8,3.5213,28.4929,88.0383,0.9204
+15668,1,3,QFX1002,9,4.2215,28.4324,87.5498,0.921
+15668,1,3,QFX1002,10,4.5271,28.4336,86.9991,0.9174
+15668,1,3,QFX1002,11,4.858,28.4228,86.3228,0.9149
+15668,1,3,QFX1002,12,4.7633,28.4308,87.5165,0.9173
+15668,1,3,QFX1002,13,4.6466,28.4158,86.8704,0.9195
+15668,1,3,QFX1002,14,3.46,28.4903,88.516,0.9203
+15668,1,3,QFX1002,15,4.047,28.4236,86.9895,0.9183
+15668,1,3,QFX1002,16,4.0734,28.4369,86.3026,0.9184
+15668,1,3,QFX1002,17,3.8354,28.4259,87.0301,0.9176
+15668,1,4,QFX1002,1,3.8566,28.3992,89.9716,0.9139
+15668,1,4,QFX1002,2,3.7344,28.4226,87.9006,0.9172
+15668,1,4,QFX1002,3,3.8655,28.4273,86.7936,0.918
+15668,1,4,QFX1002,4,4.0318,28.4113,87.0749,0.9159
+15668,1,4,QFX1002,5,3.9383,28.417,86.772,0.92
+15668,1,4,QFX1002,6,3.9938,28.4114,87.4473,0.9188
+15668,1,4,QFX1002,7,3.9786,28.4071,88.7519,0.9124
+15668,1,4,QFX1002,8,3.5741,28.4991,88.0367,0.9205
+15668,1,4,QFX1002,9,4.2802,28.4332,87.5529,0.921
+15668,1,4,QFX1002,10,4.6117,28.4336,86.977,0.9167
+15668,1,4,QFX1002,11,4.9344,28.4216,86.2895,0.9146
+15668,1,4,QFX1002,12,4.8745,28.4323,87.5649,0.9163
+15668,1,4,QFX1002,13,4.7521,28.4219,86.8795,0.9199
+15668,1,4,QFX1002,14,3.5296,28.4936,88.5072,0.9208
+15668,1,4,QFX1002,15,4.1312,28.4157,86.9782,0.9192
+15668,1,4,QFX1002,16,4.1644,28.4325,86.2612,0.9179
+15668,1,4,QFX1002,17,3.9318,28.4334,87.0445,0.9188
+15668,1,5,QFX1002,1,3.9676,28.4014,89.9875,0.9142
+15668,1,5,QFX1002,2,3.8157,28.4338,87.9367,0.919
+15668,1,5,QFX1002,3,3.9638,28.4222,86.7768,0.9169
+15668,1,5,QFX1002,4,4.1403,28.4181,87.092,0.9167
+15668,1,5,QFX1002,5,4.04,28.4161,86.752,0.9192
+15668,1,5,QFX1002,6,4.0887,28.4201,87.4481,0.919
+15668,1,5,QFX1002,7,4.0494,28.4087,88.7256,0.9123
+15668,1,5,QFX1002,8,3.653,28.497,88.0188,0.9205
+15668,1,5,QFX1002,9,4.3706,28.4356,87.5308,0.9204
+15668,1,5,QFX1002,10,4.7131,28.4407,87.0456,0.9196
+15668,1,5,QFX1002,11,5.0237,28.4208,86.3198,0.915
+15668,1,5,QFX1002,12,4.9419,28.4239,87.4936,0.9172
+15668,1,5,QFX1002,13,4.8562,28.4181,86.8931,0.9194
+15668,1,5,QFX1002,14,3.6119,28.4971,88.4901,0.92
+15668,1,5,QFX1002,15,4.2284,28.423,86.9452,0.9185
+15668,1,5,QFX1002,16,4.227,28.4355,86.3044,0.9178
+15668,1,5,QFX1002,17,4.0184,28.4332,87.0216,0.919
+10795,1,1,QFX1003,1,3.4723,28.0508,91.3229,0.9265
+10795,1,1,QFX1003,2,3.3573,28.054,88.8815,0.9291
+10795,1,1,QFX1003,3,3.4757,28.0709,87.8251,0.9304
+10795,1,1,QFX1003,4,3.6554,28.0475,87.7957,0.9274
+10795,1,1,QFX1003,5,3.5493,28.0462,87.464,0.929
+10795,1,1,QFX1003,6,3.5554,28.0352,88.2893,0.9286
+10795,1,1,QFX1003,7,3.6763,28.0389,89.8706,0.9259
+10795,1,1,QFX1003,8,3.2501,28.1166,89.0179,0.9334
+10795,1,1,QFX1003,9,4.0106,28.0519,88.4196,0.9309
+10795,1,1,QFX1003,10,4.2888,28.0614,87.9148,0.9309
+10795,1,1,QFX1003,11,4.5449,28.0263,87.0872,0.9275
+10795,1,1,QFX1003,12,4.4947,28.08,88.4083,0.9299
+10795,1,1,QFX1003,13,4.3564,28.0414,87.5276,0.9297
+10795,1,1,QFX1003,14,3.0736,28.1166,89.5014,0.9313
+10795,1,1,QFX1003,15,3.6501,28.0488,87.9801,0.9298
+10795,1,1,QFX1003,16,3.7799,28.0681,87.5228,0.9304
+10795,1,1,QFX1003,17,3.5549,28.0581,87.9861,0.9311
+10795,1,2,QFX1003,1,3.4832,28.0493,91.3169,0.9262
+10795,1,2,QFX1003,2,3.359,28.0561,88.9536,0.929
+10795,1,2,QFX1003,3,3.4658,28.0656,87.8223,0.9295
+10795,1,2,QFX1003,4,3.6778,28.0423,87.7865,0.927
+10795,1,2,QFX1003,5,3.5807,28.0403,87.4706,0.9289
+10795,1,2,QFX1003,6,3.5927,28.0347,88.2702,0.928
+10795,1,2,QFX1003,7,3.7102,28.0407,89.8536,0.9265
+10795,1,2,QFX1003,8,3.2797,28.1216,89.0255,0.9326
+10795,1,2,QFX1003,9,4.0615,28.0511,88.3612,0.9297
+10795,1,2,QFX1003,10,4.2889,28.0595,87.9323,0.9313
+10795,1,2,QFX1003,11,4.5627,28.0475,87.1074,0.9285
+10795,1,2,QFX1003,12,4.519,28.0608,88.3895,0.9291
+10795,1,2,QFX1003,13,4.3847,28.0459,87.5418,0.9302
+10795,1,2,QFX1003,14,3.1133,28.1193,89.5057,0.9319
+10795,1,2,QFX1003,15,3.6951,28.0514,87.947,0.9296
+10795,1,2,QFX1003,16,3.8165,28.0774,87.5022,0.9299
+10795,1,2,QFX1003,17,3.5904,28.0576,87.956,0.9301
+10795,1,3,QFX1003,1,3.5122,28.0533,91.2874,0.9262
+10795,1,3,QFX1003,2,3.4016,28.0551,88.9233,0.9286
+10795,1,3,QFX1003,3,3.5196,28.0646,87.8187,0.9302
+10795,1,3,QFX1003,4,3.7183,28.0408,87.7283,0.9275
+10795,1,3,QFX1003,5,3.6403,28.0453,87.4574,0.9298
+10795,1,3,QFX1003,6,3.6499,28.042,88.2862,0.9286
+10795,1,3,QFX1003,7,3.7276,28.0539,89.7892,0.9258
+10795,1,3,QFX1003,8,3.3244,28.1139,88.9994,0.9317
+10795,1,3,QFX1003,9,4.0787,28.0508,88.3853,0.929
+10795,1,3,QFX1003,10,4.3261,28.0715,87.8964,0.9309
+10795,1,3,QFX1003,11,4.595,28.0409,87.0578,0.9288
+10795,1,3,QFX1003,12,4.5473,28.0536,88.3543,0.9293
+10795,1,3,QFX1003,13,4.4454,28.0485,87.5195,0.9289
+10795,1,3,QFX1003,14,3.1859,28.1174,89.4144,0.9315
+10795,1,3,QFX1003,15,3.7194,28.0401,87.8987,0.9294
+10795,1,3,QFX1003,16,3.8423,28.0695,87.5171,0.9314
+10795,1,3,QFX1003,17,3.6372,28.0497,87.9623,0.9301
+10795,1,4,QFX1003,1,3.5351,28.0496,91.3043,0.9261
+10795,1,4,QFX1003,2,3.4517,28.0589,88.9228,0.9276
+10795,1,4,QFX1003,3,3.5617,28.0683,87.8745,0.9301
+10795,1,4,QFX1003,4,3.7777,28.0451,87.7938,0.9266
+10795,1,4,QFX1003,5,3.6553,28.0463,87.3951,0.9297
+10795,1,4,QFX1003,6,3.682,28.0386,88.2427,0.9291
+10795,1,4,QFX1003,7,3.7599,28.0436,89.8383,0.9254
+10795,1,4,QFX1003,8,3.3993,28.1164,88.9733,0.9331
+10795,1,4,QFX1003,9,4.1127,28.0558,88.4303,0.93
+10795,1,4,QFX1003,10,4.3716,28.0757,87.9291,0.9313
+10795,1,4,QFX1003,11,4.6412,28.0374,87.0764,0.9281
+10795,1,4,QFX1003,12,4.5935,28.0713,88.3896,0.9292
+10795,1,4,QFX1003,13,4.4729,28.0461,87.5429,0.9299
+10795,1,4,QFX1003,14,3.2787,28.1284,89.4101,0.9321
+10795,1,4,QFX1003,15,3.7718,28.0451,87.8461,0.9292
+10795,1,4,QFX1003,16,3.8822,28.0716,87.5226,0.9301
+10795,1,4,QFX1003,17,3.6463,28.0546,88.0163,0.9295
+10795,1,5,QFX1003,1,3.614,28.0485,91.2679,0.9254
+10795,1,5,QFX1003,2,3.5014,28.054,88.8668,0.9285
+10795,1,5,QFX1003,3,3.6001,28.0638,87.862,0.9301
+10795,1,5,QFX1003,4,3.7947,28.0355,87.6992,0.9261
+10795,1,5,QFX1003,5,3.6965,28.0425,87.4475,0.9291
+10795,1,5,QFX1003,6,3.7019,28.0318,88.2724,0.9292
+10795,1,5,QFX1003,7,3.769,28.0426,89.8728,0.9258
+10795,1,5,QFX1003,8,3.4401,28.1207,88.9686,0.9328
+10795,1,5,QFX1003,9,4.1257,28.051,88.3983,0.9291
+10795,1,5,QFX1003,10,4.3961,28.0607,87.9256,0.9307
+10795,1,5,QFX1003,11,4.6936,28.0598,87.0744,0.9283
+10795,1,5,QFX1003,12,4.5974,28.061,88.3358,0.9297
+10795,1,5,QFX1003,13,4.5206,28.0472,87.4774,0.93
+10795,1,5,QFX1003,14,3.3197,28.1225,89.442,0.9313
+10795,1,5,QFX1003,15,3.8202,28.0548,87.8863,0.9297
+10795,1,5,QFX1003,16,3.9422,28.0676,87.4522,0.9301
+10795,1,5,QFX1003,17,3.6663,28.0492,87.9947,0.9296
+18994,1,1,QFX1006,1,4.1242,28.138,90.7455,0.9225
+18994,1,1,QFX1006,2,4.0108,28.1456,88.2548,0.9246
+18994,1,1,QFX1006,3,4.124,28.119,86.9429,0.9188
+18994,1,1,QFX1006,4,4.2862,28.1507,87.7271,0.9256
+18994,1,1,QFX1006,5,4.2196,28.1636,87.2865,0.9283
+18994,1,1,QFX1006,6,4.3585,28.1398,87.5883,0.9212
+18994,1,1,QFX1006,7,4.1391,28.1481,89.711,0.9239
+18994,1,1,QFX1006,8,3.735,28.2101,88.4601,0.927
+18994,1,1,QFX1006,9,4.5696,28.1183,87.6029,0.9219
+18994,1,1,QFX1006,10,4.828,28.1294,87.2363,0.9207
+18994,1,1,QFX1006,11,5.1295,28.1632,87.2191,0.929
+18994,1,1,QFX1006,12,5.0473,28.1643,88.1587,0.9263
+18994,1,1,QFX1006,13,5.0018,28.1597,87.3464,0.9284
+18994,1,1,QFX1006,14,3.7234,28.2518,89.1957,0.9313
+18994,1,1,QFX1006,15,4.491,28.1328,87.1663,0.923
+18994,1,1,QFX1006,16,4.3996,28.1551,86.7471,0.9253
+18994,1,1,QFX1006,17,4.1692,28.1437,87.3661,0.9244
+18994,1,2,QFX1006,1,4.1733,28.1421,90.852,0.9236
+18994,1,2,QFX1006,2,4.0525,28.1451,88.3643,0.9257
+18994,1,2,QFX1006,3,4.1406,28.1254,87.1886,0.9226
+18994,1,2,QFX1006,4,4.3466,28.1596,87.82,0.9263
+18994,1,2,QFX1006,5,4.2872,28.1644,87.2894,0.9275
+18994,1,2,QFX1006,6,4.4137,28.1321,87.6051,0.9224
+18994,1,2,QFX1006,7,4.1762,28.1487,89.775,0.9235
+18994,1,2,QFX1006,8,3.7781,28.2149,88.4538,0.9286
+18994,1,2,QFX1006,9,4.6168,28.1282,87.7008,0.9234
+18994,1,2,QFX1006,10,4.8559,28.1321,87.3552,0.9216
+18994,1,2,QFX1006,11,5.1881,28.1706,87.2042,0.9282
+18994,1,2,QFX1006,12,5.0883,28.1733,88.2233,0.928
+18994,1,2,QFX1006,13,5.0401,28.1607,87.3647,0.9283
+18994,1,2,QFX1006,14,3.7269,28.25,89.1477,0.9308
+18994,1,2,QFX1006,15,4.5524,28.1381,87.2689,0.9228
+18994,1,2,QFX1006,16,4.4497,28.1544,86.7604,0.9264
+18994,1,2,QFX1006,17,4.2257,28.1403,87.4095,0.925
+18994,1,3,QFX1006,1,4.2642,28.14,90.8266,0.922
+18994,1,3,QFX1006,2,4.0975,28.149,88.3696,0.925
+18994,1,3,QFX1006,3,4.1966,28.1205,87.0586,0.9191
+18994,1,3,QFX1006,4,4.4498,28.1626,87.8551,0.927
+18994,1,3,QFX1006,5,4.3547,28.1656,87.3208,0.9279
+18994,1,3,QFX1006,6,4.4697,28.1303,87.5948,0.9221
+18994,1,3,QFX1006,7,4.2603,28.1492,89.7682,0.9239
+18994,1,3,QFX1006,8,3.8182,28.2197,88.5628,0.9288
+18994,1,3,QFX1006,9,4.6654,28.1356,87.7788,0.9233
+18994,1,3,QFX1006,10,4.9204,28.1406,87.4073,0.924
+18994,1,3,QFX1006,11,5.2422,28.1653,87.2459,0.9303
+18994,1,3,QFX1006,12,5.157,28.1747,88.2213,0.9269
+18994,1,3,QFX1006,13,5.1235,28.1567,87.3416,0.9281
+18994,1,3,QFX1006,14,3.8079,28.2472,89.1665,0.931
+18994,1,3,QFX1006,15,4.6728,28.1384,87.2072,0.9229
+18994,1,3,QFX1006,16,4.5021,28.15,86.7277,0.9258
+18994,1,3,QFX1006,17,4.3266,28.1485,87.4118,0.9252
+18994,1,4,QFX1006,1,4.3668,28.1334,90.8237,0.9219
+18994,1,4,QFX1006,2,4.1952,28.1462,88.3571,0.9243
+18994,1,4,QFX1006,3,4.3118,28.1356,87.2098,0.9233
+18994,1,4,QFX1006,4,4.5439,28.1552,87.855,0.9262
+18994,1,4,QFX1006,5,4.4627,28.1714,87.3551,0.9301
+18994,1,4,QFX1006,6,4.5798,28.13,87.634,0.9219
+18994,1,4,QFX1006,7,4.325,28.1495,89.7917,0.9244
+18994,1,4,QFX1006,8,3.8767,28.2176,88.526,0.9297
+18994,1,4,QFX1006,9,4.7356,28.1365,87.7713,0.9241
+18994,1,4,QFX1006,10,4.9956,28.1475,87.5268,0.9257
+18994,1,4,QFX1006,11,5.3279,28.1749,87.2734,0.9299
+18994,1,4,QFX1006,12,5.2324,28.1698,88.2157,0.9274
+18994,1,4,QFX1006,13,5.2029,28.1552,87.3535,0.9275
+18994,1,4,QFX1006,14,3.8929,28.2456,89.1678,0.9316
+18994,1,4,QFX1006,15,4.7236,28.1378,87.2176,0.9227
+18994,1,4,QFX1006,16,4.5446,28.1547,86.7129,0.9254
+18994,1,4,QFX1006,17,4.3557,28.1429,87.4052,0.9255
+18994,1,5,QFX1006,1,4.4374,28.1367,90.8308,0.9226
+18994,1,5,QFX1006,2,4.2628,28.1511,88.3601,0.9246
+18994,1,5,QFX1006,3,4.3589,28.1318,87.2035,0.9229
+18994,1,5,QFX1006,4,4.6039,28.1582,87.7931,0.927
+18994,1,5,QFX1006,5,4.5203,28.1674,87.3258,0.9284
+18994,1,5,QFX1006,6,4.6707,28.1315,87.556,0.9214
+18994,1,5,QFX1006,7,4.3913,28.1446,89.7514,0.9235
+18994,1,5,QFX1006,8,3.9521,28.2233,88.5833,0.9284
+18994,1,5,QFX1006,9,4.7637,28.1261,87.7943,0.9228
+18994,1,5,QFX1006,10,5.0523,28.1511,87.5287,0.9242
+18994,1,5,QFX1006,11,5.3908,28.175,87.2544,0.9297
+18994,1,5,QFX1006,12,5.3312,28.1746,88.2038,0.9272
+18994,1,5,QFX1006,13,5.2867,28.1632,87.3215,0.9276
+18994,1,5,QFX1006,14,3.9509,28.248,89.1568,0.9308
+18994,1,5,QFX1006,15,4.8434,28.1374,87.1955,0.9235
+18994,1,5,QFX1006,16,4.6106,28.1504,86.7345,0.9246
+18994,1,5,QFX1006,17,4.4527,28.153,87.446,0.9261
+31020,2,1,QFX1001,1,4.8775,27.9332,90.4024,0.888
+31020,2,1,QFX1001,2,4.7037,27.9321,87.8458,0.8912
+31020,2,1,QFX1001,3,4.8318,27.9536,86.973,0.8939
+31020,2,1,QFX1001,4,5.1065,27.9353,87.2663,0.8917
+31020,2,1,QFX1001,5,4.9963,27.9427,86.6666,0.8936
+31020,2,1,QFX1001,6,4.9973,27.9357,87.65,0.8897
+31020,2,1,QFX1001,7,4.7887,27.949,89.1303,0.891
+31020,2,1,QFX1001,8,4.2573,28.028,88.2,0.8965
+31020,2,1,QFX1001,9,5.1465,27.9408,87.5917,0.8923
+31020,2,1,QFX1001,10,5.4625,27.9691,87.3816,0.8952
+31020,2,1,QFX1001,11,5.737,27.9604,86.8929,0.8958
+31020,2,1,QFX1001,12,5.7317,27.9669,87.8337,0.8945
+31020,2,1,QFX1001,13,5.6196,27.9585,86.949,0.8966
+31020,2,1,QFX1001,14,4.2464,28.0236,88.5171,0.8952
+31020,2,1,QFX1001,15,5.1813,27.9435,87.2044,0.8913
+31020,2,1,QFX1001,16,5.0215,27.9674,86.4908,0.896
+31020,2,1,QFX1001,17,4.8672,27.9447,87.1922,0.893
+31020,2,2,QFX1001,1,4.8606,27.9315,90.5315,0.887
+31020,2,2,QFX1001,2,4.7499,27.9449,87.9474,0.8923
+31020,2,2,QFX1001,3,4.8548,27.965,86.9852,0.8953
+31020,2,2,QFX1001,4,5.1255,27.941,87.2348,0.8927
+31020,2,2,QFX1001,5,5.0218,27.9362,86.6698,0.892
+31020,2,2,QFX1001,6,4.9502,27.9367,87.8506,0.8908
+31020,2,2,QFX1001,7,4.8271,27.9443,89.2232,0.8907
+31020,2,2,QFX1001,8,4.2972,28.0136,88.1984,0.8966
+31020,2,2,QFX1001,9,5.2089,27.9558,87.5123,0.894
+31020,2,2,QFX1001,10,5.4613,27.9629,87.4263,0.8955
+31020,2,2,QFX1001,11,5.6937,27.9658,87.0205,0.8953
+31020,2,2,QFX1001,12,5.7042,27.9685,87.7337,0.8948
+31020,2,2,QFX1001,13,5.6167,27.9565,87.0788,0.8953
+31020,2,2,QFX1001,14,4.2888,28.0089,88.5498,0.8947
+31020,2,2,QFX1001,15,5.158,27.9517,87.3143,0.8925
+31020,2,2,QFX1001,16,5.0269,27.9692,86.5345,0.8955
+31020,2,2,QFX1001,17,4.812,27.9565,87.213,0.893
+31020,2,3,QFX1001,1,4.9524,27.9302,90.4331,0.8883
+31020,2,3,QFX1001,2,4.7564,27.9431,87.976,0.8922
+31020,2,3,QFX1001,3,4.8808,27.9652,87.053,0.8955
+31020,2,3,QFX1001,4,5.033,27.9358,87.5369,0.8916
+31020,2,3,QFX1001,5,4.9731,27.9405,86.7878,0.8925
+31020,2,3,QFX1001,6,4.993,27.9426,87.7899,0.8901
+31020,2,3,QFX1001,7,4.8889,27.9386,89.3319,0.8894
+31020,2,3,QFX1001,8,4.3101,28.0132,88.2764,0.896
+31020,2,3,QFX1001,9,5.2127,27.9491,87.6182,0.8934
+31020,2,3,QFX1001,10,5.4532,27.9712,87.4685,0.8951
+31020,2,3,QFX1001,11,5.6923,27.9677,87.1112,0.8961
+31020,2,3,QFX1001,12,5.7047,27.9545,87.8215,0.8927
+31020,2,3,QFX1001,13,5.6566,27.9516,87.0655,0.8945
+31020,2,3,QFX1001,14,4.3812,28.0139,88.4982,0.8957
+31020,2,3,QFX1001,15,5.172,27.949,87.2606,0.8918
+31020,2,3,QFX1001,16,4.9956,27.9682,86.4981,0.8946
+31020,2,3,QFX1001,17,4.8654,27.9521,87.2064,0.8927
+31020,2,4,QFX1001,1,4.9328,27.9321,90.4738,0.8883
+31020,2,4,QFX1001,2,4.7609,27.9464,87.98,0.8916
+31020,2,4,QFX1001,3,4.8327,27.9658,87.0863,0.8954
+31020,2,4,QFX1001,4,5.1202,27.9349,87.411,0.8922
+31020,2,4,QFX1001,5,5.0045,27.9452,86.8106,0.8917
+31020,2,4,QFX1001,6,5.0284,27.9454,87.723,0.8902
+31020,2,4,QFX1001,7,4.9156,27.9454,89.2425,0.8906
+31020,2,4,QFX1001,8,4.3431,28.0213,88.2731,0.8971
+31020,2,4,QFX1001,9,5.1925,27.9544,87.7247,0.8926
+31020,2,4,QFX1001,10,5.514,27.9724,87.5006,0.8955
+31020,2,4,QFX1001,11,5.7199,27.9677,87.0548,0.8952
+31020,2,4,QFX1001,12,5.741,27.9638,87.916,0.8939
+31020,2,4,QFX1001,13,5.6802,27.9538,87.0237,0.8954
+31020,2,4,QFX1001,14,4.3639,28.0134,88.4549,0.8956
+31020,2,4,QFX1001,15,5.2249,27.9477,87.196,0.8925
+31020,2,4,QFX1001,16,5.0276,27.963,86.4799,0.8944
+31020,2,4,QFX1001,17,4.8905,27.9502,87.2895,0.8936
+31020,2,5,QFX1001,1,4.9085,27.9411,90.5834,0.888
+31020,2,5,QFX1001,2,4.7716,27.9501,88.0331,0.8918
+31020,2,5,QFX1001,3,4.8963,27.9575,87.0613,0.8938
+31020,2,5,QFX1001,4,5.1354,27.9293,87.4289,0.8909
+31020,2,5,QFX1001,5,5.0353,27.95,86.8058,0.8934
+31020,2,5,QFX1001,6,5.0482,27.9443,87.7894,0.8908
+31020,2,5,QFX1001,7,4.8967,27.9457,89.3531,0.8909
+31020,2,5,QFX1001,8,4.3331,28.0346,88.2524,0.8963
+31020,2,5,QFX1001,9,5.2473,27.9556,87.6989,0.893
+31020,2,5,QFX1001,10,5.4932,27.9756,87.4766,0.8958
+31020,2,5,QFX1001,11,5.773,27.9658,87.0189,0.8942
+31020,2,5,QFX1001,12,5.7628,27.9639,87.8788,0.8936
+31020,2,5,QFX1001,13,5.7285,27.949,87.0677,0.8952
+31020,2,5,QFX1001,14,4.3713,28.0168,88.4218,0.8956
+31020,2,5,QFX1001,15,5.1863,27.9565,87.2974,0.8919
+31020,2,5,QFX1001,16,5.065,27.9678,86.5154,0.8936
+31020,2,5,QFX1001,17,4.9287,27.9453,87.17,0.8933
+37175,2,1,QFX1002,1,5.1819,28.3732,89.4643,0.9126
+37175,2,1,QFX1002,2,4.9743,28.411,87.3517,0.9178
+37175,2,1,QFX1002,3,5.0935,28.3983,86.2565,0.9153
+37175,2,1,QFX1002,4,5.3273,28.4015,86.6372,0.9146
+37175,2,1,QFX1002,5,5.1785,28.4015,86.2846,0.9189
+37175,2,1,QFX1002,6,5.2722,28.3987,86.9863,0.9183
+37175,2,1,QFX1002,7,5.0701,28.391,88.3,0.9114
+37175,2,1,QFX1002,8,4.4875,28.4905,87.5594,0.9198
+37175,2,1,QFX1002,9,5.3319,28.4157,87.0721,0.9192
+37175,2,1,QFX1002,10,5.6881,28.4215,86.5686,0.917
+37175,2,1,QFX1002,11,6.0075,28.4181,85.9592,0.9145
+37175,2,1,QFX1002,12,5.8822,28.423,87.259,0.9173
+37175,2,1,QFX1002,13,5.879,28.4133,86.5581,0.9193
+37175,2,1,QFX1002,14,4.5517,28.4854,88.0568,0.92
+37175,2,1,QFX1002,15,5.4933,28.4122,86.4663,0.9182
+37175,2,1,QFX1002,16,5.2136,28.4182,85.8969,0.9173
+37175,2,1,QFX1002,17,5.089,28.4147,86.5207,0.9159
+37175,2,2,QFX1002,1,5.2475,28.3835,89.51,0.9136
+37175,2,2,QFX1002,2,5.0486,28.4106,87.415,0.9182
+37175,2,2,QFX1002,3,5.1646,28.4072,86.3205,0.9166
+37175,2,2,QFX1002,4,5.3852,28.4035,86.6383,0.9152
+37175,2,2,QFX1002,5,5.2745,28.3996,86.3648,0.9193
+37175,2,2,QFX1002,6,5.3131,28.3989,87.0361,0.9192
+37175,2,2,QFX1002,7,5.1537,28.3882,88.3825,0.9118
+37175,2,2,QFX1002,8,4.5267,28.4856,87.5985,0.9192
+37175,2,2,QFX1002,9,5.4116,28.4138,87.1026,0.92
+37175,2,2,QFX1002,10,5.7596,28.418,86.6585,0.9166
+37175,2,2,QFX1002,11,6.0906,28.422,85.9772,0.9147
+37175,2,2,QFX1002,12,5.9543,28.4281,87.249,0.9169
+37175,2,2,QFX1002,13,5.9629,28.4147,86.4866,0.9193
+37175,2,2,QFX1002,14,4.6144,28.4793,88.0689,0.9199
+37175,2,2,QFX1002,15,5.5814,28.4069,86.4638,0.9179
+37175,2,2,QFX1002,16,5.273,28.4245,85.9266,0.918
+37175,2,2,QFX1002,17,5.1519,28.4193,86.609,0.9176
+37175,2,3,QFX1002,1,5.3463,28.3819,89.5002,0.9133
+37175,2,3,QFX1002,2,5.096,28.4102,87.4542,0.9185
+37175,2,3,QFX1002,3,5.2178,28.4095,86.3476,0.916
+37175,2,3,QFX1002,4,5.4931,28.3974,86.6423,0.9151
+37175,2,3,QFX1002,5,5.331,28.4018,86.3441,0.9191
+37175,2,3,QFX1002,6,5.4061,28.4031,86.9929,0.9189
+37175,2,3,QFX1002,7,5.2018,28.3968,88.3638,0.9118
+37175,2,3,QFX1002,8,4.5582,28.4949,87.6108,0.9209
+37175,2,3,QFX1002,9,5.4582,28.4108,87.1475,0.9194
+37175,2,3,QFX1002,10,5.8016,28.4323,86.6742,0.9166
+37175,2,3,QFX1002,11,6.0922,28.4197,85.9724,0.9141
+37175,2,3,QFX1002,12,6.0102,28.4286,87.2222,0.9163
+37175,2,3,QFX1002,13,6.0104,28.4043,86.4432,0.9188
+37175,2,3,QFX1002,14,4.6535,28.4807,88.0199,0.9193
+37175,2,3,QFX1002,15,5.625,28.4002,86.4998,0.9187
+37175,2,3,QFX1002,16,5.3297,28.4221,85.9603,0.918
+37175,2,3,QFX1002,17,5.2212,28.4163,86.5862,0.9187
+37175,2,4,QFX1002,1,5.4044,28.3861,89.4974,0.9134
+37175,2,4,QFX1002,2,5.1655,28.4127,87.4441,0.9179
+37175,2,4,QFX1002,3,5.2751,28.4044,86.3238,0.9158
+37175,2,4,QFX1002,4,5.5263,28.4037,86.6831,0.9156
+37175,2,4,QFX1002,5,5.3847,28.4044,86.3104,0.9195
+37175,2,4,QFX1002,6,5.4692,28.4058,87.0175,0.9192
+37175,2,4,QFX1002,7,5.2585,28.3947,88.3388,0.9118
+37175,2,4,QFX1002,8,4.6355,28.4895,87.6177,0.9212
+37175,2,4,QFX1002,9,5.5063,28.4185,87.1723,0.9196
+37175,2,4,QFX1002,10,5.8584,28.4253,86.6554,0.9173
+37175,2,4,QFX1002,11,6.2104,28.4263,85.965,0.9142
+37175,2,4,QFX1002,12,6.0458,28.4254,87.2637,0.9173
+37175,2,4,QFX1002,13,6.0661,28.4143,86.5012,0.9197
+37175,2,4,QFX1002,14,4.7303,28.4833,88.047,0.9195
+37175,2,4,QFX1002,15,5.7018,28.4125,86.4992,0.9183
+37175,2,4,QFX1002,16,5.3926,28.4232,85.9321,0.9167
+37175,2,4,QFX1002,17,5.2551,28.4201,86.561,0.918
+37175,2,5,QFX1002,1,5.5034,28.3873,89.5209,0.9131
+37175,2,5,QFX1002,2,5.219,28.4131,87.4683,0.918
+37175,2,5,QFX1002,3,5.3583,28.4144,86.3712,0.9162
+37175,2,5,QFX1002,4,5.5881,28.4006,86.6743,0.9148
+37175,2,5,QFX1002,5,5.4693,28.4006,86.3226,0.9196
+37175,2,5,QFX1002,6,5.5327,28.4071,87.0415,0.9196
+37175,2,5,QFX1002,7,5.3308,28.3914,88.3386,0.9123
+37175,2,5,QFX1002,8,4.6634,28.487,87.6183,0.9203
+37175,2,5,QFX1002,9,5.5473,28.4223,87.1603,0.9203
+37175,2,5,QFX1002,10,5.8937,28.4251,86.6911,0.9174
+37175,2,5,QFX1002,11,6.2548,28.4246,86.0145,0.9145
+37175,2,5,QFX1002,12,6.1091,28.4334,87.2882,0.9169
+37175,2,5,QFX1002,13,6.1024,28.4166,86.5607,0.9188
+37175,2,5,QFX1002,14,4.7657,28.4918,88.0892,0.9192
+37175,2,5,QFX1002,15,5.7516,28.4098,86.5425,0.9185
+37175,2,5,QFX1002,16,5.454,28.4268,85.9507,0.9181
+37175,2,5,QFX1002,17,5.347,28.4147,86.5607,0.9176
+34318,2,1,QFX1003,1,5.1042,28.0328,90.5455,0.9239
+34318,2,1,QFX1003,2,4.8874,28.0237,88.2311,0.9265
+34318,2,1,QFX1003,3,5.0175,28.0531,87.1499,0.9264
+34318,2,1,QFX1003,4,5.2908,28.016,87.0952,0.9236
+34318,2,1,QFX1003,5,5.172,28.0195,86.7924,0.927
+34318,2,1,QFX1003,6,5.2216,28.0243,87.6795,0.927
+34318,2,1,QFX1003,7,5.0578,28.0219,89.2142,0.9229
+34318,2,1,QFX1003,8,4.4249,28.097,88.3406,0.93
+34318,2,1,QFX1003,9,5.318,28.0265,87.857,0.9281
+34318,2,1,QFX1003,10,5.6535,28.0536,87.4034,0.9295
+34318,2,1,QFX1003,11,5.9811,28.0257,86.589,0.9246
+34318,2,1,QFX1003,12,5.8421,28.0487,87.8544,0.9273
+34318,2,1,QFX1003,13,5.8494,28.0249,87.0027,0.9276
+34318,2,1,QFX1003,14,4.4411,28.1083,88.7908,0.9294
+34318,2,1,QFX1003,15,5.4067,28.0213,87.3073,0.9275
+34318,2,1,QFX1003,16,5.1391,28.0489,86.9717,0.9308
+34318,2,1,QFX1003,17,4.9951,28.0338,87.3927,0.9281
+34318,2,2,QFX1003,1,5.1164,28.0239,90.6335,0.9237
+34318,2,2,QFX1003,2,4.8915,28.0253,88.2426,0.9258
+34318,2,2,QFX1003,3,5.0358,28.0689,87.1699,0.927
+34318,2,2,QFX1003,4,5.2847,28.0193,87.1079,0.9239
+34318,2,2,QFX1003,5,5.1864,28.0307,86.7913,0.928
+34318,2,2,QFX1003,6,5.2382,28.0092,87.6452,0.9261
+34318,2,2,QFX1003,7,5.0485,28.0253,89.2716,0.9237
+34318,2,2,QFX1003,8,4.4437,28.1044,88.38,0.9307
+34318,2,2,QFX1003,9,5.3208,28.0432,87.8492,0.9283
+34318,2,2,QFX1003,10,5.6631,28.0564,87.3567,0.9295
+34318,2,2,QFX1003,11,5.9783,28.0225,86.5435,0.9261
+34318,2,2,QFX1003,12,5.8642,28.0476,87.8673,0.9267
+34318,2,2,QFX1003,13,5.8469,28.0214,86.992,0.9269
+34318,2,2,QFX1003,14,4.4795,28.1067,88.7762,0.9299
+34318,2,2,QFX1003,15,5.4167,28.0276,87.2391,0.9271
+34318,2,2,QFX1003,16,5.1585,28.0584,86.916,0.9301
+34318,2,2,QFX1003,17,4.9978,28.0312,87.3455,0.9274
+34318,2,3,QFX1003,1,5.1526,28.0232,90.5632,0.9233
+34318,2,3,QFX1003,2,4.9377,28.0243,88.1725,0.9254
+34318,2,3,QFX1003,3,5.0463,28.0427,87.1809,0.9285
+34318,2,3,QFX1003,4,5.332,28.0139,87.0982,0.9242
+34318,2,3,QFX1003,5,5.2076,28.018,86.7429,0.9253
+34318,2,3,QFX1003,6,5.2322,28.0123,87.6399,0.9258
+34318,2,3,QFX1003,7,5.056,28.0187,89.2389,0.924
+34318,2,3,QFX1003,8,4.4819,28.1188,88.3598,0.931
+34318,2,3,QFX1003,9,5.366,28.038,87.8905,0.9283
+34318,2,3,QFX1003,10,5.7063,28.0676,87.3679,0.929
+34318,2,3,QFX1003,11,6.0235,28.0305,86.6061,0.9262
+34318,2,3,QFX1003,12,5.922,28.0446,87.8742,0.9278
+34318,2,3,QFX1003,13,5.9074,28.0318,87.0203,0.9283
+34318,2,3,QFX1003,14,4.5001,28.1045,88.7731,0.9299
+34318,2,3,QFX1003,15,5.446,28.024,87.2528,0.9269
+34318,2,3,QFX1003,16,5.1971,28.0671,86.9277,0.9282
+34318,2,3,QFX1003,17,5.0306,28.0332,87.3703,0.9276
+34318,2,4,QFX1003,1,5.1602,28.0275,90.614,0.9235
+34318,2,4,QFX1003,2,4.9766,28.0316,88.3003,0.9263
+34318,2,4,QFX1003,3,5.0588,28.0646,87.2017,0.9271
+34318,2,4,QFX1003,4,5.3729,28.0204,87.1157,0.9244
+34318,2,4,QFX1003,5,5.2415,28.0204,86.7958,0.9263
+34318,2,4,QFX1003,6,5.282,28.0125,87.6437,0.9262
+34318,2,4,QFX1003,7,5.07,28.0175,89.2552,0.9231
+34318,2,4,QFX1003,8,4.511,28.1046,88.4346,0.9307
+34318,2,4,QFX1003,9,5.3793,28.0426,87.8915,0.9281
+34318,2,4,QFX1003,10,5.7108,28.0611,87.4177,0.9299
+34318,2,4,QFX1003,11,6.0261,28.0316,86.6004,0.9266
+34318,2,4,QFX1003,12,5.9285,28.041,87.8389,0.9278
+34318,2,4,QFX1003,13,5.9092,28.0179,86.9097,0.9271
+34318,2,4,QFX1003,14,4.5398,28.1041,88.7972,0.9302
+34318,2,4,QFX1003,15,5.4743,28.0365,87.2771,0.9282
+34318,2,4,QFX1003,16,5.2046,28.0586,86.9251,0.9287
+34318,2,4,QFX1003,17,5.0456,28.0352,87.4223,0.9269
+34318,2,5,QFX1003,1,5.2111,28.0296,90.6095,0.9239
+34318,2,5,QFX1003,2,4.9694,28.0279,88.2709,0.9255
+34318,2,5,QFX1003,3,5.0863,28.0388,87.1657,0.9276
+34318,2,5,QFX1003,4,5.3924,28.0244,87.1139,0.9256
+34318,2,5,QFX1003,5,5.2682,28.0341,86.7642,0.9257
+34318,2,5,QFX1003,6,5.3205,28.0134,87.6504,0.9257
+34318,2,5,QFX1003,7,5.1266,28.0331,89.2443,0.9237
+34318,2,5,QFX1003,8,4.5462,28.1187,88.3811,0.931
+34318,2,5,QFX1003,9,5.4078,28.0392,87.9412,0.9284
+34318,2,5,QFX1003,10,5.7272,28.0575,87.4595,0.9305
+34318,2,5,QFX1003,11,6.0711,28.0354,86.5565,0.9261
+34318,2,5,QFX1003,12,5.9536,28.0448,87.8436,0.9273
+34318,2,5,QFX1003,13,5.9807,28.0329,87.0178,0.9288
+34318,2,5,QFX1003,14,4.5956,28.1053,88.7135,0.9305
+34318,2,5,QFX1003,15,5.5147,28.0239,87.2745,0.9269
+34318,2,5,QFX1003,16,5.2343,28.0545,86.9921,0.9294
+34318,2,5,QFX1003,17,5.1026,28.0379,87.3977,0.9278
+39858,2,1,QFX1006,1,5.5416,28.133,90.5185,0.9227
+39858,2,1,QFX1006,2,5.3573,28.1523,88.1074,0.9263
+39858,2,1,QFX1006,3,5.4345,28.1334,87.0008,0.9237
+39858,2,1,QFX1006,4,5.7036,28.1519,87.501,0.9272
+39858,2,1,QFX1006,5,5.5989,28.1644,87.0924,0.9292
+39858,2,1,QFX1006,6,5.7025,28.1218,87.236,0.9217
+39858,2,1,QFX1006,7,5.3489,28.1533,89.5226,0.9249
+39858,2,1,QFX1006,8,4.7576,28.2137,88.1637,0.928
+39858,2,1,QFX1006,9,5.6956,28.1364,87.5157,0.9249
+39858,2,1,QFX1006,10,5.9639,28.1478,87.382,0.9266
+39858,2,1,QFX1006,11,6.2668,28.1603,87.0287,0.9281
+39858,2,1,QFX1006,12,6.187,28.1898,88.123,0.9299
+39858,2,1,QFX1006,13,6.1905,28.1796,87.3441,0.9304
+39858,2,1,QFX1006,14,4.8292,28.2546,88.9652,0.932
+39858,2,1,QFX1006,15,5.9355,28.1277,86.9463,0.9234
+39858,2,1,QFX1006,16,5.555,28.1553,86.7096,0.9277
+39858,2,1,QFX1006,17,5.4178,28.1286,87.2167,0.9241
+39858,2,2,QFX1006,1,5.5801,28.1341,90.5619,0.9218
+39858,2,2,QFX1006,2,5.3899,28.1412,88.089,0.925
+39858,2,2,QFX1006,3,5.4675,28.1317,87.0086,0.9246
+39858,2,2,QFX1006,4,5.7158,28.1541,87.5135,0.9257
+39858,2,2,QFX1006,5,5.6617,28.17,87.0177,0.9288
+39858,2,2,QFX1006,6,5.7634,28.1275,87.3317,0.9213
+39858,2,2,QFX1006,7,5.4001,28.1519,89.583,0.9243
+39858,2,2,QFX1006,8,4.7889,28.214,88.2031,0.928
+39858,2,2,QFX1006,9,5.7268,28.1496,87.6168,0.925
+39858,2,2,QFX1006,10,5.9893,28.1558,87.3941,0.9271
+39858,2,2,QFX1006,11,6.286,28.1658,87.0375,0.9297
+39858,2,2,QFX1006,12,6.2249,28.1931,88.1188,0.9289
+39858,2,2,QFX1006,13,6.2207,28.1849,87.3801,0.931
+39858,2,2,QFX1006,14,4.8542,28.256,88.9563,0.9323
+39858,2,2,QFX1006,15,5.9648,28.1279,86.9099,0.9228
+39858,2,2,QFX1006,16,5.5515,28.1562,86.6955,0.9271
+39858,2,2,QFX1006,17,5.476,28.1485,87.2712,0.9262
+39858,2,3,QFX1006,1,5.6187,28.1236,90.5162,0.922
+39858,2,3,QFX1006,2,5.4391,28.1473,88.1262,0.9247
+39858,2,3,QFX1006,3,5.5233,28.1245,86.9595,0.9226
+39858,2,3,QFX1006,4,5.7585,28.1314,87.3965,0.9235
+39858,2,3,QFX1006,5,5.6814,28.1577,86.9557,0.9286
+39858,2,3,QFX1006,6,5.7938,28.1113,87.2198,0.9197
+39858,2,3,QFX1006,7,5.3992,28.142,89.5355,0.9234
+39858,2,3,QFX1006,8,4.793,28.2089,88.1949,0.9276
+39858,2,3,QFX1006,9,5.7634,28.1314,87.5819,0.9242
+39858,2,3,QFX1006,10,6.0371,28.1444,87.3516,0.9264
+39858,2,3,QFX1006,11,6.3102,28.1525,86.9858,0.9285
+39858,2,3,QFX1006,12,6.2395,28.1711,88.0474,0.9273
+39858,2,3,QFX1006,13,6.2833,28.1761,87.2855,0.93
+39858,2,3,QFX1006,14,4.9309,28.2505,88.8825,0.931
+39858,2,3,QFX1006,15,6.0046,28.1193,86.8373,0.9211
+39858,2,3,QFX1006,16,5.5748,28.1515,86.6764,0.9271
+39858,2,3,QFX1006,17,5.5076,28.1424,87.1939,0.9245
+39858,2,4,QFX1006,1,5.6562,28.1261,90.4943,0.921
+39858,2,4,QFX1006,2,5.4906,28.1382,88.1441,0.9252
+39858,2,4,QFX1006,3,5.6055,28.1328,87.0138,0.9241
+39858,2,4,QFX1006,4,5.8192,28.1365,87.4317,0.9246
+39858,2,4,QFX1006,5,5.7315,28.1483,86.9541,0.9281
+39858,2,4,QFX1006,6,5.8454,28.1122,87.2509,0.9204
+39858,2,4,QFX1006,7,5.443,28.1518,89.5789,0.9253
+39858,2,4,QFX1006,8,4.8241,28.2086,88.1974,0.9287
+39858,2,4,QFX1006,9,5.7803,28.132,87.5413,0.9244
+39858,2,4,QFX1006,10,6.0774,28.1472,87.3799,0.926
+39858,2,4,QFX1006,11,6.3902,28.1502,86.9442,0.9286
+39858,2,4,QFX1006,12,6.2886,28.1731,88.0655,0.9275
+39858,2,4,QFX1006,13,6.337,28.1733,87.2658,0.9304
+39858,2,4,QFX1006,14,4.9602,28.247,88.8608,0.9315
+39858,2,4,QFX1006,15,6.057,28.128,86.8591,0.9216
+39858,2,4,QFX1006,16,5.6446,28.1546,86.6829,0.9263
+39858,2,4,QFX1006,17,5.5501,28.1377,87.1797,0.9254
+39858,2,5,QFX1006,1,5.733,28.1347,90.5715,0.9231
+39858,2,5,QFX1006,2,5.5239,28.1545,88.176,0.9269
+39858,2,5,QFX1006,3,5.6231,28.1396,87.0783,0.925
+39858,2,5,QFX1006,4,5.8869,28.1567,87.5331,0.9258
+39858,2,5,QFX1006,5,5.8069,28.1601,87.0841,0.9296
+39858,2,5,QFX1006,6,5.8873,28.1261,87.3123,0.9211
+39858,2,5,QFX1006,7,5.526,28.163,89.6227,0.9254
+39858,2,5,QFX1006,8,4.8619,28.2256,88.3671,0.931
+39858,2,5,QFX1006,9,5.8497,28.1435,87.6408,0.9254
+39858,2,5,QFX1006,10,6.1228,28.1533,87.4439,0.9275
+39858,2,5,QFX1006,11,6.4223,28.1578,87.0388,0.9283
+39858,2,5,QFX1006,12,6.3361,28.1848,88.1106,0.9285
+39858,2,5,QFX1006,13,6.3672,28.1753,87.2823,0.9298
+39858,2,5,QFX1006,14,4.9993,28.2536,88.904,0.9328
+39858,2,5,QFX1006,15,6.1288,28.1365,86.8746,0.9232
+39858,2,5,QFX1006,16,5.6888,28.1644,86.7059,0.928
+39858,2,5,QFX1006,17,5.5963,28.1469,87.227,0.9262
+53998,3,1,QFX1001,1,6.063,27.9308,90.1249,0.8863
+53998,3,1,QFX1001,2,5.921,27.9304,87.5722,0.89
+53998,3,1,QFX1001,3,6.0127,27.9589,86.583,0.8929
+53998,3,1,QFX1001,4,6.2308,27.9363,87.0652,0.8905
+53998,3,1,QFX1001,5,6.1301,27.9264,86.5211,0.8911
+53998,3,1,QFX1001,6,6.0797,27.9298,87.3542,0.8875
+53998,3,1,QFX1001,7,5.8431,27.9403,88.8927,0.8884
+53998,3,1,QFX1001,8,5.1698,28.017,87.9569,0.8942
+53998,3,1,QFX1001,9,6.0919,27.9543,87.3788,0.8924
+53998,3,1,QFX1001,10,6.442,27.9744,87.1144,0.8945
+53998,3,1,QFX1001,11,6.6555,27.9696,86.7074,0.8946
+53998,3,1,QFX1001,12,6.596,27.9621,87.6543,0.8922
+53998,3,1,QFX1001,13,6.6512,27.9438,86.6527,0.8945
+53998,3,1,QFX1001,14,5.3617,28.0079,88.1159,0.8933
+53998,3,1,QFX1001,15,6.3454,27.9434,86.9638,0.8908
+53998,3,1,QFX1001,16,6.0104,27.9531,86.2276,0.8924
+53998,3,1,QFX1001,17,5.9715,27.9331,86.8963,0.8902
+53998,3,2,QFX1001,1,6.1519,27.9263,90.0644,0.8858
+53998,3,2,QFX1001,2,5.9259,27.944,87.6335,0.8905
+53998,3,2,QFX1001,3,6.0453,27.9585,86.7362,0.8937
+53998,3,2,QFX1001,4,6.2836,27.9266,87.0894,0.8891
+53998,3,2,QFX1001,5,6.1519,27.9236,86.5601,0.89
+53998,3,2,QFX1001,6,6.112,27.9235,87.5551,0.8858
+53998,3,2,QFX1001,7,5.8472,27.9372,88.9502,0.8876
+53998,3,2,QFX1001,8,5.2518,28.0094,88.0161,0.8955
+53998,3,2,QFX1001,9,6.1442,27.9538,87.433,0.8907
+53998,3,2,QFX1001,10,6.4702,27.9773,87.1728,0.8947
+53998,3,2,QFX1001,11,6.7255,27.9707,86.6602,0.8955
+53998,3,2,QFX1001,12,6.6497,27.9574,87.6781,0.8908
+53998,3,2,QFX1001,13,6.6907,27.9423,86.6928,0.8932
+53998,3,2,QFX1001,14,5.3663,28.0038,88.2686,0.8943
+53998,3,2,QFX1001,15,6.327,27.9351,86.942,0.8882
+53998,3,2,QFX1001,16,6.0265,27.9588,86.2049,0.8919
+53998,3,2,QFX1001,17,5.9293,27.9339,86.7973,0.8896
+53998,3,3,QFX1001,1,6.1237,27.9417,90.2269,0.888
+53998,3,3,QFX1001,2,5.9534,27.9311,87.6477,0.8902
+53998,3,3,QFX1001,3,6.0353,27.9575,86.8107,0.8933
+53998,3,3,QFX1001,4,6.3007,27.9386,87.123,0.8898
+53998,3,3,QFX1001,5,6.2386,27.9335,86.4954,0.891
+53998,3,3,QFX1001,6,6.1424,27.9371,87.4937,0.8879
+53998,3,3,QFX1001,7,5.8965,27.9369,89,0.888
+53998,3,3,QFX1001,8,5.1868,28.0126,87.9242,0.8935
+53998,3,3,QFX1001,9,6.1461,27.948,87.4508,0.8906
+53998,3,3,QFX1001,10,6.4711,27.9779,87.1779,0.8943
+53998,3,3,QFX1001,11,6.675,27.9662,86.673,0.8941
+53998,3,3,QFX1001,12,6.6107,27.9639,87.643,0.8936
+53998,3,3,QFX1001,13,6.6618,27.9384,86.7621,0.892
+53998,3,3,QFX1001,14,5.3553,28.0051,88.2805,0.8928
+53998,3,3,QFX1001,15,6.4265,27.937,86.9783,0.8894
+53998,3,3,QFX1001,16,6.0903,27.9563,86.2278,0.8933
+53998,3,3,QFX1001,17,5.9504,27.9417,86.8879,0.8907
+53998,3,4,QFX1001,1,6.1556,27.9206,90.1895,0.886
+53998,3,4,QFX1001,2,5.9652,27.9362,87.6528,0.8901
+53998,3,4,QFX1001,3,6.0649,27.9562,86.7421,0.8933
+53998,3,4,QFX1001,4,6.3379,27.9378,87.1656,0.891
+53998,3,4,QFX1001,5,6.1716,27.9296,86.5173,0.8895
+53998,3,4,QFX1001,6,6.1704,27.9268,87.502,0.887
+53998,3,4,QFX1001,7,5.9078,27.9371,89.0605,0.8895
+53998,3,4,QFX1001,8,5.2436,28.0064,87.9402,0.8928
+53998,3,4,QFX1001,9,6.2042,27.9482,87.5182,0.8921
+53998,3,4,QFX1001,10,6.4618,27.9749,87.1804,0.8938
+53998,3,4,QFX1001,11,6.7023,27.9674,86.7386,0.8937
+53998,3,4,QFX1001,12,6.6321,27.9567,87.7552,0.8914
+53998,3,4,QFX1001,13,6.6893,27.9472,86.8433,0.8929
+53998,3,4,QFX1001,14,5.3767,27.9946,88.3507,0.8917
+53998,3,4,QFX1001,15,6.423,27.9384,86.9731,0.8892
+53998,3,4,QFX1001,16,6.0631,27.951,86.2724,0.8923
+53998,3,4,QFX1001,17,6.0059,27.9494,86.8792,0.8914
+53998,3,5,QFX1001,1,6.1936,27.9324,90.315,0.8872
+53998,3,5,QFX1001,2,5.9996,27.9368,87.6721,0.8888
+53998,3,5,QFX1001,3,6.1517,27.9618,86.7941,0.8941
+53998,3,5,QFX1001,4,6.3122,27.9186,87.0949,0.888
+53998,3,5,QFX1001,5,6.171,27.9282,86.5885,0.8894
+53998,3,5,QFX1001,6,6.2083,27.9439,87.4519,0.8888
+53998,3,5,QFX1001,7,5.9427,27.9373,89.0112,0.8884
+53998,3,5,QFX1001,8,5.2796,28.0221,87.978,0.8944
+53998,3,5,QFX1001,9,6.1644,27.9559,87.5291,0.8924
+53998,3,5,QFX1001,10,6.5456,27.9808,87.1714,0.8949
+53998,3,5,QFX1001,11,6.7407,27.9598,86.7664,0.8938
+53998,3,5,QFX1001,12,6.7041,27.9574,87.7793,0.8922
+53998,3,5,QFX1001,13,6.7285,27.9397,86.793,0.8939
+53998,3,5,QFX1001,14,5.3918,28.0038,88.322,0.8915
+53998,3,5,QFX1001,15,6.3933,27.9411,87.0027,0.8892
+53998,3,5,QFX1001,16,6.087,27.9614,86.261,0.8933
+53998,3,5,QFX1001,17,6.0123,27.9504,86.9431,0.8922
+57172,3,1,QFX1002,1,6.2852,28.3813,89.14,0.9128
+57172,3,1,QFX1002,2,6.0709,28.4086,87.1078,0.9171
+57172,3,1,QFX1002,3,6.1884,28.4045,85.922,0.9144
+57172,3,1,QFX1002,4,6.4083,28.3959,86.335,0.914
+57172,3,1,QFX1002,5,6.2236,28.3892,85.9164,0.9174
+57172,3,1,QFX1002,6,6.2766,28.3977,86.661,0.9185
+57172,3,1,QFX1002,7,6.0445,28.391,88.0136,0.9108
+57172,3,1,QFX1002,8,5.3079,28.4837,87.3015,0.9188
+57172,3,1,QFX1002,9,6.2246,28.4156,86.8532,0.9194
+57172,3,1,QFX1002,10,6.5786,28.4319,86.3434,0.9159
+57172,3,1,QFX1002,11,6.8809,28.4124,85.6334,0.9129
+57172,3,1,QFX1002,12,6.7189,28.4253,86.9426,0.9156
+57172,3,1,QFX1002,13,6.7824,28.414,86.303,0.919
+57172,3,1,QFX1002,14,5.4998,28.4765,87.6832,0.9195
+57172,3,1,QFX1002,15,6.5448,28.4073,86.1777,0.9169
+57172,3,1,QFX1002,16,6.1174,28.4146,85.6236,0.9162
+57172,3,1,QFX1002,17,6.087,28.4204,86.2617,0.917
+57172,3,2,QFX1002,1,6.3281,28.3776,89.169,0.9122
+57172,3,2,QFX1002,2,6.1163,28.4069,87.1372,0.917
+57172,3,2,QFX1002,3,6.2115,28.408,85.947,0.9146
+57172,3,2,QFX1002,4,6.4676,28.3981,86.2692,0.9139
+57172,3,2,QFX1002,5,6.2953,28.3941,85.9886,0.9177
+57172,3,2,QFX1002,6,6.3403,28.3945,86.6967,0.9177
+57172,3,2,QFX1002,7,6.0893,28.39,88.0289,0.91
+57172,3,2,QFX1002,8,5.3466,28.4896,87.3104,0.9193
+57172,3,2,QFX1002,9,6.2692,28.4181,86.9184,0.9194
+57172,3,2,QFX1002,10,6.6445,28.4282,86.3217,0.9157
+57172,3,2,QFX1002,11,6.9187,28.4202,85.6898,0.9125
+57172,3,2,QFX1002,12,6.8136,28.4248,86.9505,0.9161
+57172,3,2,QFX1002,13,6.8284,28.4154,86.2447,0.9195
+57172,3,2,QFX1002,14,5.5346,28.4775,87.6939,0.9191
+57172,3,2,QFX1002,15,6.6091,28.4047,86.1832,0.9162
+57172,3,2,QFX1002,16,6.1622,28.4173,85.6517,0.9169
+57172,3,2,QFX1002,17,6.1309,28.4078,86.2488,0.9177
+57172,3,3,QFX1002,1,6.375,28.3828,89.2125,0.9128
+57172,3,3,QFX1002,2,6.1447,28.4098,87.1534,0.9174
+57172,3,3,QFX1002,3,6.2566,28.4081,86.0481,0.9149
+57172,3,3,QFX1002,4,6.4929,28.3985,86.3542,0.9141
+57172,3,3,QFX1002,5,6.354,28.3985,85.9886,0.9185
+57172,3,3,QFX1002,6,6.3885,28.4008,86.7271,0.918
+57172,3,3,QFX1002,7,6.1207,28.3905,88.0729,0.9117
+57172,3,3,QFX1002,8,5.377,28.4936,87.3578,0.9204
+57172,3,3,QFX1002,9,6.3282,28.4152,86.8983,0.9191
+57172,3,3,QFX1002,10,6.6616,28.4262,86.4234,0.9167
+57172,3,3,QFX1002,11,6.9687,28.4193,85.7293,0.9135
+57172,3,3,QFX1002,12,6.8502,28.4296,86.9874,0.9158
+57172,3,3,QFX1002,13,6.8651,28.41,86.2589,0.9185
+57172,3,3,QFX1002,14,5.5706,28.4794,87.7318,0.9198
+57172,3,3,QFX1002,15,6.6497,28.4079,86.139,0.917
+57172,3,3,QFX1002,16,6.1969,28.4236,85.6751,0.9171
+57172,3,3,QFX1002,17,6.1573,28.4167,86.3186,0.918
+57172,3,4,QFX1002,1,6.4329,28.3823,89.2043,0.9122
+57172,3,4,QFX1002,2,6.2011,28.4099,87.168,0.9173
+57172,3,4,QFX1002,3,6.3037,28.4051,86.0609,0.9159
+57172,3,4,QFX1002,4,6.556,28.4072,86.3939,0.9147
+57172,3,4,QFX1002,5,6.4006,28.3961,86.0121,0.9184
+57172,3,4,QFX1002,6,6.4182,28.395,86.7243,0.9181
+57172,3,4,QFX1002,7,6.1483,28.3966,88.0828,0.9119
+57172,3,4,QFX1002,8,5.4078,28.4888,87.3584,0.9208
+57172,3,4,QFX1002,9,6.3213,28.4175,86.8847,0.9205
+57172,3,4,QFX1002,10,6.7181,28.4297,86.4172,0.9162
+57172,3,4,QFX1002,11,7.0155,28.4228,85.7559,0.9149
+57172,3,4,QFX1002,12,6.8811,28.4296,86.9994,0.916
+57172,3,4,QFX1002,13,6.8966,28.4093,86.2526,0.9182
+57172,3,4,QFX1002,14,5.6048,28.4772,87.6818,0.9196
+57172,3,4,QFX1002,15,6.6777,28.4072,86.1796,0.9175
+57172,3,4,QFX1002,16,6.231,28.4197,85.6705,0.9171
+57172,3,4,QFX1002,17,6.202,28.4197,86.3125,0.9182
+57172,3,5,QFX1002,1,6.487,28.3822,89.2332,0.9139
+57172,3,5,QFX1002,2,6.2352,28.4066,87.1942,0.918
+57172,3,5,QFX1002,3,6.3535,28.4172,86.0816,0.9165
+57172,3,5,QFX1002,4,6.575,28.4079,86.4061,0.9149
+57172,3,5,QFX1002,5,6.4487,28.398,85.9882,0.9182
+57172,3,5,QFX1002,6,6.4623,28.4,86.7216,0.9183
+57172,3,5,QFX1002,7,6.2012,28.3978,88.134,0.9122
+57172,3,5,QFX1002,8,5.4406,28.5008,87.4464,0.9214
+57172,3,5,QFX1002,9,6.3835,28.4216,86.9577,0.9196
+57172,3,5,QFX1002,10,6.7267,28.4342,86.439,0.9168
+57172,3,5,QFX1002,11,7.0416,28.4243,85.782,0.9142
+57172,3,5,QFX1002,12,6.9134,28.4316,87.0385,0.9167
+57172,3,5,QFX1002,13,6.9408,28.4175,86.3092,0.9182
+57172,3,5,QFX1002,14,5.6225,28.4817,87.7127,0.9202
+57172,3,5,QFX1002,15,6.7195,28.4018,86.2258,0.917
+57172,3,5,QFX1002,16,6.2605,28.4242,85.7488,0.9178
+57172,3,5,QFX1002,17,6.2254,28.4212,86.3068,0.9186
+51362,3,1,QFX1003,1,6.1306,28.0204,90.3197,0.9231
+51362,3,1,QFX1003,2,5.9243,28.0321,87.9327,0.9252
+51362,3,1,QFX1003,3,6.0437,28.0392,86.9109,0.9274
+51362,3,1,QFX1003,4,6.3242,28.0161,86.8626,0.9241
+51362,3,1,QFX1003,5,6.1613,28.0256,86.5276,0.9263
+51362,3,1,QFX1003,6,6.1917,28.0174,87.416,0.9264
+51362,3,1,QFX1003,7,5.8974,28.0146,88.966,0.9227
+51362,3,1,QFX1003,8,5.2241,28.1049,88.1464,0.9311
+51362,3,1,QFX1003,9,6.1518,28.0392,87.6721,0.9266
+51362,3,1,QFX1003,10,6.5317,28.0567,87.166,0.9285
+51362,3,1,QFX1003,11,6.8399,28.0364,86.3877,0.9266
+51362,3,1,QFX1003,12,6.6944,28.0548,87.718,0.9272
+51362,3,1,QFX1003,13,6.7277,28.0311,86.8226,0.9271
+51362,3,1,QFX1003,14,5.3608,28.1064,88.5243,0.93
+51362,3,1,QFX1003,15,6.4489,28.0294,86.9928,0.927
+51362,3,1,QFX1003,16,5.9954,28.0525,86.7073,0.9283
+51362,3,1,QFX1003,17,5.9331,28.0472,87.1316,0.9266
+51362,3,2,QFX1003,1,6.1443,28.0259,90.341,0.922
+51362,3,2,QFX1003,2,5.9032,28.0289,87.9456,0.9251
+51362,3,2,QFX1003,3,6.0175,28.0435,86.9122,0.9272
+51362,3,2,QFX1003,4,6.3352,28.0111,86.8486,0.9236
+51362,3,2,QFX1003,5,6.1837,28.0221,86.5385,0.9271
+51362,3,2,QFX1003,6,6.1999,28.011,87.3673,0.9263
+51362,3,2,QFX1003,7,5.9244,28.0215,89.0182,0.9226
+51362,3,2,QFX1003,8,5.2397,28.1024,88.1043,0.9297
+51362,3,2,QFX1003,9,6.1811,28.0475,87.6957,0.9277
+51362,3,2,QFX1003,10,6.5184,28.0553,87.2303,0.9291
+51362,3,2,QFX1003,11,6.8285,28.0249,86.4233,0.9262
+51362,3,2,QFX1003,12,6.6902,28.0556,87.7259,0.9271
+51362,3,2,QFX1003,13,6.7341,28.0269,86.8272,0.928
+51362,3,2,QFX1003,14,5.3648,28.1067,88.5281,0.9298
+51362,3,2,QFX1003,15,6.4391,28.028,87.0332,0.9256
+51362,3,2,QFX1003,16,6.0279,28.0465,86.7336,0.9274
+51362,3,2,QFX1003,17,5.9566,28.0389,87.1333,0.9272
+51362,3,3,QFX1003,1,6.1744,28.0327,90.3375,0.9226
+51362,3,3,QFX1003,2,5.9412,28.0267,88.0121,0.926
+51362,3,3,QFX1003,3,6.0711,28.0434,86.9111,0.9266
+51362,3,3,QFX1003,4,6.354,28.0265,86.8646,0.9243
+51362,3,3,QFX1003,5,6.197,28.0199,86.6037,0.9259
+51362,3,3,QFX1003,6,6.2208,28.0123,87.3944,0.9248
+51362,3,3,QFX1003,7,5.9415,28.021,89.0377,0.9224
+51362,3,3,QFX1003,8,5.244,28.1099,88.1534,0.9312
+51362,3,3,QFX1003,9,6.1646,28.0454,87.6883,0.9273
+51362,3,3,QFX1003,10,6.519,28.053,87.2068,0.929
+51362,3,3,QFX1003,11,6.8529,28.0331,86.4113,0.9259
+51362,3,3,QFX1003,12,6.7169,28.0556,87.682,0.9273
+51362,3,3,QFX1003,13,6.7355,28.0286,86.7942,0.9273
+51362,3,3,QFX1003,14,5.4141,28.1115,88.5414,0.9301
+51362,3,3,QFX1003,15,6.4567,28.0259,87.0226,0.9268
+51362,3,3,QFX1003,16,6.0101,28.0489,86.7619,0.9282
+51362,3,3,QFX1003,17,5.9484,28.0352,87.1088,0.9275
+51362,3,4,QFX1003,1,6.1756,28.0189,90.4056,0.923
+51362,3,4,QFX1003,2,5.9591,28.0375,88.0084,0.9253
+51362,3,4,QFX1003,3,6.0894,28.0369,86.97,0.9266
+51362,3,4,QFX1003,4,6.3383,28.0214,86.9037,0.9245
+51362,3,4,QFX1003,5,6.2336,28.0191,86.527,0.9263
+51362,3,4,QFX1003,6,6.229,28.013,87.3764,0.9254
+51362,3,4,QFX1003,7,5.9501,28.0163,89.0627,0.923
+51362,3,4,QFX1003,8,5.2678,28.1024,88.1489,0.9301
+51362,3,4,QFX1003,9,6.1921,28.0433,87.6793,0.9281
+51362,3,4,QFX1003,10,6.5453,28.0559,87.2235,0.9286
+51362,3,4,QFX1003,11,6.8991,28.0397,86.4454,0.9281
+51362,3,4,QFX1003,12,6.7577,28.0496,87.6881,0.9272
+51362,3,4,QFX1003,13,6.7761,28.0312,86.7819,0.9277
+51362,3,4,QFX1003,14,5.4354,28.1093,88.537,0.9311
+51362,3,4,QFX1003,15,6.4656,28.0286,87.0867,0.9271
+51362,3,4,QFX1003,16,6.0527,28.0649,86.7618,0.9286
+51362,3,4,QFX1003,17,5.9802,28.03,87.1555,0.9266
+51362,3,5,QFX1003,1,6.216,28.0286,90.3768,0.9225
+51362,3,5,QFX1003,2,5.9629,28.0246,88.0389,0.9256
+51362,3,5,QFX1003,3,6.1209,28.0553,86.9655,0.9275
+51362,3,5,QFX1003,4,6.3851,28.0201,86.9382,0.9241
+51362,3,5,QFX1003,5,6.239,28.0215,86.54,0.9254
+51362,3,5,QFX1003,6,6.2516,28.0107,87.401,0.9254
+51362,3,5,QFX1003,7,5.9611,28.022,89.0102,0.9224
+51362,3,5,QFX1003,8,5.2665,28.1226,88.1926,0.931
+51362,3,5,QFX1003,9,6.2035,28.0435,87.7066,0.9276
+51362,3,5,QFX1003,10,6.5771,28.0695,87.2242,0.9293
+51362,3,5,QFX1003,11,6.8974,28.0405,86.4042,0.9267
+51362,3,5,QFX1003,12,6.7407,28.0584,87.6899,0.9283
+51362,3,5,QFX1003,13,6.781,28.0369,86.7997,0.928
+51362,3,5,QFX1003,14,5.444,28.103,88.5257,0.9296
+51362,3,5,QFX1003,15,6.4951,28.0246,87.0243,0.9257
+51362,3,5,QFX1003,16,6.0465,28.0601,86.7494,0.9292
+51362,3,5,QFX1003,17,5.9825,28.0394,87.1802,0.927
+59933,3,1,QFX1006,1,6.5118,28.1258,90.1079,0.9213
+59933,3,1,QFX1006,2,6.3084,28.1381,87.7426,0.9248
+59933,3,1,QFX1006,3,6.3966,28.1179,86.561,0.9226
+59933,3,1,QFX1006,4,6.6072,28.1448,87.1286,0.9259
+59933,3,1,QFX1006,5,6.5303,28.1467,86.6339,0.9263
+59933,3,1,QFX1006,6,6.6019,28.1019,86.842,0.918
+59933,3,1,QFX1006,7,6.1835,28.143,89.1663,0.9237
+59933,3,1,QFX1006,8,5.5167,28.2089,87.8463,0.9272
+59933,3,1,QFX1006,9,6.4759,28.1279,87.2773,0.9234
+59933,3,1,QFX1006,10,6.7705,28.1416,87.0215,0.9259
+59933,3,1,QFX1006,11,7.0393,28.145,86.6124,0.9267
+59933,3,1,QFX1006,12,6.9404,28.1722,87.7492,0.9275
+59933,3,1,QFX1006,13,7.0008,28.1694,86.9778,0.9294
+59933,3,1,QFX1006,14,5.6815,28.2427,88.4919,0.9305
+59933,3,1,QFX1006,15,6.8554,28.1282,86.5031,0.9217
+59933,3,1,QFX1006,16,6.3634,28.153,86.2951,0.9262
+59933,3,1,QFX1006,17,6.3428,28.1293,86.8017,0.9243
+59933,3,2,QFX1006,1,6.5093,28.1271,90.1336,0.9215
+59933,3,2,QFX1006,2,6.3365,28.1398,87.8078,0.925
+59933,3,2,QFX1006,3,6.4222,28.13,86.7097,0.9242
+59933,3,2,QFX1006,4,6.6375,28.139,87.1242,0.9242
+59933,3,2,QFX1006,5,6.558,28.1486,86.6385,0.9263
+59933,3,2,QFX1006,6,6.6577,28.1061,86.9045,0.9184
+59933,3,2,QFX1006,7,6.1949,28.149,89.2504,0.9241
+59933,3,2,QFX1006,8,5.4934,28.2166,87.8879,0.9295
+59933,3,2,QFX1006,9,6.5135,28.139,87.3468,0.9248
+59933,3,2,QFX1006,10,6.7842,28.1571,87.1622,0.9259
+59933,3,2,QFX1006,11,7.0609,28.1548,86.6967,0.9266
+59933,3,2,QFX1006,12,6.9509,28.1846,87.8033,0.9281
+59933,3,2,QFX1006,13,7.0376,28.1722,86.9021,0.9301
+59933,3,2,QFX1006,14,5.7016,28.2362,88.4806,0.93
+59933,3,2,QFX1006,15,6.8634,28.1154,86.4893,0.9207
+59933,3,2,QFX1006,16,6.3707,28.1524,86.3869,0.926
+59933,3,2,QFX1006,17,6.3607,28.1388,86.9301,0.9256
+59933,3,3,QFX1006,1,6.5419,28.1272,90.2437,0.9218
+59933,3,3,QFX1006,2,6.3475,28.1456,87.817,0.925
+59933,3,3,QFX1006,3,6.4368,28.1388,86.7566,0.9246
+59933,3,3,QFX1006,4,6.6685,28.1352,87.1234,0.924
+59933,3,3,QFX1006,5,6.5957,28.1514,86.6178,0.9266
+59933,3,3,QFX1006,6,6.6543,28.113,86.9286,0.9188
+59933,3,3,QFX1006,7,6.2133,28.139,89.2522,0.9237
+59933,3,3,QFX1006,8,5.5249,28.2014,87.8694,0.9274
+59933,3,3,QFX1006,9,6.5054,28.1333,87.3752,0.9247
+59933,3,3,QFX1006,10,6.8129,28.1506,87.159,0.9268
+59933,3,3,QFX1006,11,7.0898,28.1537,86.7068,0.9275
+59933,3,3,QFX1006,12,7.0209,28.1746,87.7585,0.927
+59933,3,3,QFX1006,13,7.0477,28.1633,86.903,0.9287
+59933,3,3,QFX1006,14,5.718,28.2365,88.4159,0.9296
+59933,3,3,QFX1006,15,6.8728,28.1155,86.5217,0.9201
+59933,3,3,QFX1006,16,6.3673,28.1444,86.3785,0.9255
+59933,3,3,QFX1006,17,6.3535,28.1333,86.9326,0.9242
+59933,3,4,QFX1006,1,6.5915,28.1431,90.244,0.9225
+59933,3,4,QFX1006,2,6.3765,28.1516,87.9259,0.9256
+59933,3,4,QFX1006,3,6.4767,28.1452,86.8024,0.9254
+59933,3,4,QFX1006,4,6.7079,28.1373,87.1779,0.9241
+59933,3,4,QFX1006,5,6.6175,28.1435,86.5769,0.9265
+59933,3,4,QFX1006,6,6.7041,28.1136,86.9516,0.9189
+59933,3,4,QFX1006,7,6.2433,28.1488,89.3373,0.9246
+59933,3,4,QFX1006,8,5.5563,28.2162,88.0048,0.93
+59933,3,4,QFX1006,9,6.5513,28.1373,87.352,0.9248
+59933,3,4,QFX1006,10,6.8275,28.1624,87.1891,0.927
+59933,3,4,QFX1006,11,7.1067,28.1557,86.7443,0.9277
+59933,3,4,QFX1006,12,7.0275,28.1842,87.8124,0.9288
+59933,3,4,QFX1006,13,7.0777,28.1626,86.8159,0.9271
+59933,3,4,QFX1006,14,5.7437,28.2312,88.4971,0.9302
+59933,3,4,QFX1006,15,6.9101,28.1219,86.5248,0.9204
+59933,3,4,QFX1006,16,6.4051,28.155,86.3809,0.927
+59933,3,4,QFX1006,17,6.407,28.1457,86.9448,0.9257
+59933,3,5,QFX1006,1,6.614,28.1308,90.2775,0.9229
+59933,3,5,QFX1006,2,6.3949,28.1468,87.9244,0.9252
+59933,3,5,QFX1006,3,6.4942,28.1449,86.8603,0.925
+59933,3,5,QFX1006,4,6.7219,28.1446,87.1839,0.9247
+59933,3,5,QFX1006,5,6.6411,28.1477,86.6367,0.9253
+59933,3,5,QFX1006,6,6.7131,28.1108,86.9418,0.9183
+59933,3,5,QFX1006,7,6.293,28.1522,89.3425,0.9241
+59933,3,5,QFX1006,8,5.5788,28.2124,88.0038,0.9289
+59933,3,5,QFX1006,9,6.5493,28.1508,87.4244,0.9254
+59933,3,5,QFX1006,10,6.8354,28.1622,87.2303,0.9275
+59933,3,5,QFX1006,11,7.1293,28.1591,86.7217,0.9277
+59933,3,5,QFX1006,12,7.0297,28.1813,87.7996,0.9272
+59933,3,5,QFX1006,13,7.1088,28.1652,86.8698,0.9274
+59933,3,5,QFX1006,14,5.7861,28.2282,88.4165,0.9304
+59933,3,5,QFX1006,15,6.9299,28.1126,86.5176,0.92
+59933,3,5,QFX1006,16,6.4173,28.1512,86.4596,0.9263
+59933,3,5,QFX1006,17,6.4158,28.1422,86.9479,0.9252
diff --git a/cgdt.lua b/cgdt.lua
new file mode 100644
index 00000000..1c3e6293
--- /dev/null
+++ b/cgdt.lua
@@ -0,0 +1,88 @@
+ffi = require 'ffi'
+
+ffi.cdef [[
+struct char_buffer {
+ char *data;
+ size_t length;
+ size_t size;
+};
+
+typedef struct {
+ struct char_buffer names[1];
+ int length;
+ int size;
+ int index[4];
+} gdt_index;
+
+extern gdt_index * gdt_index_new (int alloc_size);
+extern void gdt_index_free (gdt_index *g);
+extern gdt_index * gdt_index_resize (gdt_index *g);
+extern int gdt_index_add (gdt_index *g, const char *str);
+extern const char * gdt_index_get (gdt_index *g, int index);
+extern int gdt_index_lookup (gdt_index *g, const char *req);
+
+enum {
+ TAG_STRING = 0xffff0000,
+ TAG_UNDEF = 0xfffe0000,
+ TAG_NUMBER = 0xfff80000,
+};
+
+typedef union {
+ double number;
+ struct {
+ unsigned int lo;
+ unsigned int hi;
+ } word;
+} gdt_element;
+
+typedef struct {
+ int size;
+ gdt_element *data;
+ int ref_count;
+} gdt_block;
+
+struct string_array {
+ struct char_buffer buffer[1];
+ int *offset_data;
+ int offset_len;
+};
+
+struct __gdt_table;
+
+typedef struct {
+ int __index;
+ struct __gdt_table *__table;
+} gdt_table_cursor;
+
+struct __gdt_table {
+ int size1;
+ int size2;
+ int tda;
+ gdt_element *data;
+ gdt_block *block;
+ gdt_index *strings;
+ struct string_array __headers[1];
+ gdt_table_cursor __cursor[1];
+};
+
+typedef struct __gdt_table gdt_table;
+
+extern gdt_table * gdt_table_new (int nb_rows, int nb_columns, int nb_rows_alloc);
+extern void gdt_table_free (gdt_table *t);
+extern const gdt_element * gdt_table_get (gdt_table *t, int i, int j);
+extern const gdt_element * gdt_table_get_by_name (gdt_table *t, int i, const char* col_name);
+extern const char * gdt_table_element_get_string (gdt_table *t, const gdt_element *e);
+extern void gdt_table_set_number (gdt_table *t, int i, int j, double num);
+extern void gdt_table_set_string (gdt_table *t, int i, int j, const char *s);
+extern void gdt_table_set_undef (gdt_table *t, int i, int j);
+extern const char * gdt_table_get_header (gdt_table *t, int j);
+extern void gdt_table_set_header (gdt_table *t, int j, const char *str);
+extern int gdt_table_header_index (gdt_table *t, const char* col_name);
+extern int gdt_table_insert_columns (gdt_table *t, int j_in, int n);
+extern int gdt_table_insert_rows (gdt_table *t, int i_in, int n);
+extern const gdt_element * gdt_table_cursor_get (gdt_table_cursor *c, const char *key);
+extern gdt_table_cursor * gdt_table_get_cursor (gdt_table *t);
+
+]]
+
+return ffi.C
diff --git a/demo-init.lua b/demo-init.lua
index a435c531..57ce6a22 100644
--- a/demo-init.lua
+++ b/demo-init.lua
@@ -16,7 +16,7 @@ local function load_demo(name)
end
local demo_files = {
- 'fft', 'bspline', 'wave-particle', 'plot', 'fractals', 'ode', 'nlinfit', 'integ', 'anim', 'linfit', 'contour', 'svg', 'graphics', 'sf', 'vegas'}
+ 'fft', 'bspline', 'wave-particle', 'plot', 'fractals', 'ode', 'nlinfit', 'integ', 'anim', 'linfit', 'contour', 'svg', 'graphics', 'sf', 'vegas', 'gdt-lm'}
for i, name in ipairs(demo_files) do
load_demo(name)
diff --git a/demos/gdt-lm.lua b/demos/gdt-lm.lua
new file mode 100644
index 00000000..01416f54
--- /dev/null
+++ b/demos/gdt-lm.lua
@@ -0,0 +1,50 @@
+
+local function lm_demo()
+ local r = rng.new()
+
+ local a, b = 2.3, 1.2
+ local sigma = 0.3
+
+ local tool_effect = {0.4, 0.7, -1.3}
+ local tools = {"tool A", "tool B", "tool C"}
+
+ local N, P = 30, #tool_effect
+ local dx = 3.0
+
+ local t = gdt.alloc(N * P, {"tool", "x", "y"})
+
+ for k, tool in ipairs(tools) do
+ for i = 1, N do
+ local x = dx * (i - 1) / N
+ local y = a + b * x + rnd.gaussian(r, sigma) + tool_effect[k]
+ local ip = (k-1)*N + i
+ t:set(ip, 1, tool)
+ t:set(ip, 2, x)
+ t:set(ip, 3, y)
+ end
+ end
+
+ local p = gdt.plot(t, "y ~ x | tool", {show= false})
+
+ p.title = "Linear Fit example"
+ p.xtitle = "time, s"
+ p.ytitle = "thickness, mm"
+
+ local fit = gdt.lm(t, "y ~ x, tool", {predict= true})
+ fit:summary()
+
+ for k = 1, P do
+ local ln = graph.fxline(|x| fit:eval {tool= tools[k], x= x}, 0, dx)
+ p:addline(ln, graph.webcolor(k), {{'dash', 7, 3}})
+ end
+
+ p:show()
+end
+
+return {'Linear Regression', {
+ {
+ name= 'linreg1',
+ f = lm_demo,
+ description = 'Mixed model regression example'
+ },
+}}
diff --git a/expr-parser.lua b/expr-parser.lua
new file mode 100644
index 00000000..936e48a1
--- /dev/null
+++ b/expr-parser.lua
@@ -0,0 +1,229 @@
+
+local len, match = string.len, string.match
+
+local mini_lexer = {}
+
+local mini_lexer_mt = {
+ __index = mini_lexer,
+}
+
+local literal_chars = {['('] = 1, [')'] = 1, ['~'] = 1, [','] = 1, ['|'] = 1}
+local oper_table = {['+'] = 0, ['-'] = 0, ['*'] = 1, ['/'] = 1, ['^'] = 2, ['%'] = -1}
+
+local function new_lexer(src)
+ local lexer = {n = 1, src= src}
+ setmetatable(lexer, mini_lexer_mt)
+ lexer:next()
+ return lexer
+end
+
+function mini_lexer.char(lexer)
+ local n = lexer.n
+ return lexer.src:sub(n, n)
+end
+
+function mini_lexer.incr(lexer, n)
+ lexer.n_current = lexer.n
+ lexer.n = lexer.n + (n or 1)
+end
+
+function mini_lexer.match(lexer, pattern)
+ return match(lexer.src, '^' .. pattern, lexer.n)
+end
+
+function mini_lexer.consume(lexer, pattern)
+ local m = match(lexer.src, '^' .. pattern, lexer.n)
+ if m then
+ lexer.n_current = lexer.n
+ lexer.n = lexer.n + len(m)
+ return m
+ end
+end
+
+function mini_lexer.skip(lexer, pattern)
+ local m = match(lexer.src, '^' .. pattern, lexer.n)
+ if m then lexer.n = lexer.n + len(m) end
+end
+
+function mini_lexer.next_token(lexer)
+ lexer:skip('%s*')
+ if lexer.n > len(lexer.src) then return {type= 'EOF'} end
+ local c = lexer:char()
+ if c == '[' then
+ local str = lexer:consume('%b[]')
+ return {type= 'ident', value= str:sub(2,-2)}
+ end
+ if oper_table[c] then
+ local prio = oper_table[c]
+ lexer:incr()
+ return {type= 'operator', symbol= c, priority = prio}
+ end
+ if literal_chars[c] then
+ lexer:incr()
+ return {type= c}
+ end
+ if lexer:match('[%l%u_]') then
+ local str = lexer:consume('[%l%u_][%l%u%d_.$]*')
+ return {type= 'ident', value= str}
+ end
+ if lexer:match('%d') then
+ local str = lexer:consume('%d+%.%d*[Ee]%+?%d+')
+ str = str or lexer:consume('%d+%.%d*[Ee]%-?%d+')
+ str = str or lexer:consume('%d+%.%d*')
+ str = str or lexer:consume('%d+')
+ return {type= 'number', value= tonumber(str)}
+ end
+ lexer:local_error("syntax error in expression:", lexer.n)
+end
+
+function mini_lexer.next(lexer)
+ lexer.token = lexer:next_token()
+end
+
+function mini_lexer.local_error(lexer, msg, n_pos)
+ n_pos = n_pos or lexer.n_current
+ local line = string.format(' %s', lexer.src)
+ local pos = string.format(' %s^', string.rep(' ', n_pos - 1))
+ error(string.format("%s\n%s\n%s", msg, line, pos))
+end
+
+local function accept(lexer, token_type)
+ if lexer.token.type == token_type then
+ lexer:next()
+ return true
+ end
+ return false
+end
+
+local function expect(lexer, token_type)
+ if not accept(lexer, token_type) then
+ lexer:local_error("expecting " .. token_type)
+ end
+end
+
+local expr
+
+local function factor(lexer, actions)
+ local token = lexer.token
+ if token.type == 'ident' then
+ local id = token.value
+ lexer:next()
+ if accept(lexer, '(') then
+ local arg = expr(lexer, actions, 0)
+ expect(lexer, ')')
+ return actions.func_eval(id, arg)
+ else
+ return actions.ident(id)
+ end
+ elseif token.type == 'number' then
+ local x = token.value
+ lexer:next()
+ return actions.number(x)
+ elseif token.type == '(' then
+ lexer:next()
+ local a = expr(lexer, actions, 0)
+ expect(lexer, ')')
+ return a
+ elseif token.type == 'operator' and token.symbol == '%' then
+ lexer:next()
+ if lexer.token.type ~= 'ident' then
+ lexer:local_error("expecting identifier:")
+ end
+ local id = lexer.token.value
+ lexer:next()
+ return actions.enum(id)
+ end
+ lexer:local_error('unexpected symbol:')
+end
+
+local function ident_singleton(lexer, actions)
+ local token = lexer.token
+ if token.type == 'ident' then
+ local id = token.value
+ lexer:next()
+ if accept(lexer, '(') then
+ lexer:local_error('expecting simple identifier')
+ end
+ return actions.ident(id)
+ else
+ lexer:local_error('expecting simple identifier')
+ end
+end
+
+expr = function(lexer, actions, prio)
+ if prio > 2 then
+ return factor(lexer, actions)
+ end
+
+ local a
+ local token = lexer.token
+ if prio == 0 and token.type == 'operator' and token.symbol == '-' then
+ local symbol = token.symbol
+ lexer:next()
+ local b = expr(lexer, actions, prio + 1)
+ a = actions.prefix(symbol, b)
+ else
+ a = expr(lexer, actions, prio + 1)
+ end
+
+ token = lexer.token
+ while token.type == 'operator' and token.priority >= prio do
+ local symbol = token.symbol
+ accept(lexer, 'operator')
+ local b = expr(lexer, actions, prio + 1)
+ a, token = actions.infix(symbol, a, b), lexer.token
+ end
+ return a
+end
+
+local function expr_list(lexer, actions)
+ local a = expr(lexer, actions, 0)
+ local els = actions.exprlist(a)
+ while accept(lexer, ',') do
+ local b = expr(lexer, actions, 0)
+ els = actions.exprlist(b, els)
+ end
+ return els
+end
+
+local function ident_list(lexer, actions)
+ local a = ident_singleton(lexer, actions)
+ local els = actions.exprlist(a)
+ while accept(lexer, ',') do
+ local b = ident_singleton(lexer, actions)
+ els = actions.exprlist(b, els)
+ end
+ return els
+end
+
+local function schema(lexer, actions)
+ local y = expr(lexer, actions, 0)
+ expect(lexer, '~')
+ local x = expr_list(lexer, actions)
+ if lexer.token.type ~= 'EOF' then
+ lexer:local_error('unexpected symbol:')
+ end
+ return actions.schema(x, y)
+end
+
+local function gschema(lexer, actions)
+ local y = expr_list(lexer, actions)
+ expect(lexer, '~')
+ local x = expr_list(lexer, actions)
+ local enums
+ if accept(lexer, '|') then
+ enums = ident_list(lexer, actions)
+ else
+ enums = {}
+ end
+ if lexer.token.type ~= 'EOF' then
+ lexer:local_error('unexpected symbol:')
+ end
+ return actions.schema(x, y, enums)
+end
+
+local function parse_expr(lexer, actions)
+ return expr(lexer, actions, 0)
+end
+
+return {lexer = new_lexer, schema= schema, gschema= gschema, parse = parse_expr}
diff --git a/expr-print.lua b/expr-print.lua
new file mode 100644
index 00000000..17f0f6f6
--- /dev/null
+++ b/expr-print.lua
@@ -0,0 +1,90 @@
+local format, concat = string.format, table.concat
+
+local oper_table = {['+'] = 0, ['-'] = 0, ['*'] = 1, ['/'] = 1, ['^'] = 2, ['%'] = -1}
+
+local ex_print
+
+local function is_ident_simple(s)
+ return s:match('^[%l%u_][%w_]*$')
+end
+
+local function op_print(e, prio)
+ if #e == 1 then
+ local c, c_prio = ex_print(e[1])
+ if c_prio < prio then c = format('(%s)', c) end
+ return format("%s%s", e.operator, c)
+ else
+ local a, a_prio = ex_print(e[1])
+ local b, b_prio = ex_print(e[2])
+ if a_prio < prio then a = format('(%s)', a) end
+ if b_prio < prio then b = format('(%s)', b) end
+ local temp = (prio < 2 and "%s %s %s" or "%s%s%s")
+ return format(temp, a, e.operator, b)
+ end
+end
+
+local function exlist_print(e)
+ local t = {}
+ for k = 1, #e do t[k] = ex_print(e[k]) end
+ return concat(t, ', ')
+end
+
+ex_print = function(e)
+ if type(e) == 'number' then
+ return e, 3
+ elseif e.name then
+ local s = e.name
+ if not is_ident_simple(s) then s = format('[%s]', s) end
+ return s, 3
+ elseif e.func then
+ local arg_str = ex_print(e.arg)
+ return format('%s(%s)', e.func, arg_str), 3
+ else
+ local prio = oper_table[e.operator]
+ local s = op_print(e, prio)
+ return s, prio
+ end
+end
+
+local function schema_print(e)
+ local ys = exlist_print(e.y)
+ local xs = exlist_print(e.x)
+ return format("%s ~ %s", ys, xs)
+end
+
+local function eval_operator(op, a, b)
+ if op == '+' then return a + b
+ elseif op == '-' then return a - b
+ elseif op == '*' then return a * b
+ elseif op == '/' then return a / b
+ elseif op == '^' then return a ^ b
+ else error('unkown operation: ' .. op) end
+end
+
+local function eval(expr, scope)
+ if type(expr) == 'number' then
+ return expr
+ elseif expr.name then
+ return scope.ident(expr)
+ elseif expr.func then
+ local arg_value = eval(expr.arg, scope)
+ if arg_value then
+ local f = scope.func(expr)
+ if not f then error('unknown function: '..expr.func) end
+ return f(arg_value)
+ end
+ else
+ if #expr == 1 then
+ local v = eval(expr[1], scope)
+ if v then return -v end
+ else
+ local a = eval(expr[1], scope)
+ local b = eval(expr[2], scope)
+ if a and b then
+ return eval_operator(expr.operator, a, b)
+ end
+ end
+ end
+end
+
+return {schema = schema_print, expr = ex_print, expr_list = exlist_print, eval = eval}
diff --git a/fox-gui/Makefile b/fox-gui/Makefile
index c4738519..af622c2c 100644
--- a/fox-gui/Makefile
+++ b/fox-gui/Makefile
@@ -29,7 +29,7 @@ GSL_SHELL_GUI = gsl-shell-gui$(EXE_EXT)
LUADIR = $(GSH_BASE_DIR)/luajit2
-GSL_SHELL_LIBS = $(LUADIR)/src/libluajit.a $(GSH_BASE_DIR)/agg-plot/libaggplot.a $(GSH_BASE_DIR)/lua-gsl/libluagsl.a
+GSL_SHELL_LIBS = $(LUADIR)/src/libluajit.a $(GSH_BASE_DIR)/agg-plot/libaggplot.a $(GSH_BASE_DIR)/lua-gsl/libluagsl.a $(GSH_BASE_DIR)/gdt/libgdt.a
INCLUDES += -I$(GSH_BASE_DIR) -I$(GSH_BASE_DIR)/lua-gsl -I$(GSH_BASE_DIR)/agg-plot -I$(LUADIR)/src -I$(GSH_BASE_DIR)/cpp-utils
@@ -55,7 +55,7 @@ all: $(TARGETS)
$(GSL_SHELL_GUI): $(FOXGUI_OBJ_FILES) $(GSL_SHELL_LIBS)
@echo Linking $@
- @$(LINK_EXE) -o $@ $(FOXGUI_OBJ_FILES) $(LIBS) $(LDFLAGS)
+ @$(LINK_EXE) -o $@ $(FOXGUI_OBJ_FILES) $(LIBS)
include $(GSH_BASE_DIR)/makerules
diff --git a/fox-gui/lua_plot_window.cpp b/fox-gui/lua_plot_window.cpp
index 15a3107e..f327aef7 100644
--- a/fox-gui/lua_plot_window.cpp
+++ b/fox-gui/lua_plot_window.cpp
@@ -40,7 +40,7 @@ static const struct luaL_Reg fox_window_methods[] =
__END_DECLS
-typedef plot<manage_owner> sg_plot;
+typedef plot sg_plot;
class window_mutex {
public:
diff --git a/gdt-eval.lua b/gdt-eval.lua
new file mode 100644
index 00000000..f42bdafb
--- /dev/null
+++ b/gdt-eval.lua
@@ -0,0 +1,79 @@
+
+local ipairs = ipairs
+
+local function mult(a, b)
+ if a == 1 then return b end
+ if b == 1 then return a end
+ return {operator= '*', a, b}
+end
+
+local function scalar_infix(sym, a, b)
+ if sym == '*' then
+ return mult(a, b)
+ else
+ return {operator= sym, a, b}
+ end
+end
+
+local function factor_infix(sym, a, b)
+ if not (a or b) then return nil end
+ if sym ~= '*' then
+ error('non multiplicative opeation on factors')
+ end
+ local c = {}
+ if a then for i, f in ipairs(a) do c[#c+1] = f end end
+ if b then for i, f in ipairs(b) do c[#c+1] = f end end
+ return c
+end
+
+local function infix_action(sym, a, b)
+ local c = {}
+ c.scalar = scalar_infix(sym, a.scalar, b.scalar)
+ c.factor = factor_infix(sym, a.factor, b.factor)
+ return c
+end
+
+local function prefix_action(sym, a)
+ if a.factor then error('non multiplicative opeation on factors') end
+ return {scalar= {operator= sym, a}}
+end
+
+local function enum_action(id)
+ return {scalar= 1, factor= {id}}
+end
+
+local function func_eval_action(func_name, arg_expr)
+ if arg_expr.factor then
+ error('applying function ' .. func_name .. ' to an enumerated factor')
+ end
+ return {scalar= {func = func_name, arg = arg_expr.scalar}}
+end
+
+local function gdt_eval_actions(t)
+ local n, m = t:dim()
+
+ local column_class = {}
+ for j = 1, m do column_class[j] = t:col_type(j) end
+
+ local function ident_action(id)
+ local index = t:col_index(id)
+ if column_class[index] == 'factor' then
+ return {scalar= 1, factor= {id}}
+ else
+ return {scalar= {name= id, index= t:col_index(id)}}
+ end
+ end
+
+ return {
+ infix = infix_action,
+ ident = ident_action,
+ prefix = prefix_action,
+ enum = enum_action,
+ func_eval = func_eval_action,
+ number = function(x) return {scalar= x} end,
+ exprlist = function(a, ls) if ls then ls[#ls+1] = a else ls = {a} end; return ls end,
+ schema = function(x, y) return {x= x, y= y} end,
+ }
+end
+
+return gdt_eval_actions
diff --git a/gdt-hist.lua b/gdt-hist.lua
new file mode 100644
index 00000000..d5e9c53a
--- /dev/null
+++ b/gdt-hist.lua
@@ -0,0 +1,80 @@
+
+local ffi = require 'ffi'
+local gsl = require 'gsl'
+
+local rect = graph.rect
+
+local function compare_float(a, b)
+ return a < b
+end
+
+local function gdt_table_hist(t, col_name, opt)
+ local j
+ if type(col_name) == 'string' then
+ j = t:col_index(col_name)
+ if not j then error(string.format("invalid column name: %s", col_name)) end
+ else
+ if type(col_name) ~= 'number' then error("invalid column index") end
+ j = col_name
+ end
+
+ local n = #t
+
+ local dv = matrix.alloc(n, 1)
+ for i = 1, n do dv.data[i - 1] = t:get(i, j) end
+
+ dv:sort(compare_float)
+
+ local Q1 = gsl.gsl_stats_quantile_from_sorted_data(dv.data, dv.tda, n, 0.25)
+ local Q3 = gsl.gsl_stats_quantile_from_sorted_data(dv.data, dv.tda, n, 0.75)
+ local IQR = Q3 - Q1
+
+ local a, b
+ if opt and opt.a and opt.b then
+ a, b = opt.a, opt.b
+ else
+ a, b = dv.data[0], dv.data[n - 1]
+ end
+
+ -- Freedman-Diaconis rule from http://stats.stackexchange.com/questions/798/calculating-optimal-number-of-bins-in-a-histogram-for-n-where-n-ranges-from-30
+ -- corresponds to GNU R with breaks='FD'
+ local h_FD = 2 * IQR * n^(-1/3)
+ local nbins = (b - a) / h_FD
+
+ if nbins < 2 then error("not enough data to produce an histogram") end
+
+ local h = ffi.gc(gsl.gsl_histogram_alloc(nbins), gsl.gsl_histogram_free)
+ assert(h, "error creating histogram")
+
+ local eps = (b - a) * 1e-5
+ gsl.gsl_histogram_set_ranges_uniform(h, a - eps, b + eps)
+
+ for i, x in t:column(j) do
+ if x then
+ gsl.gsl_histogram_increment(h, x)
+ end
+ end
+
+ local name = t:header(j)
+ local title = (opt and opt.title) and opt.title or (name .. ' histogram')
+ local color = (opt and opt.color) and opt.color or 'green'
+ local p = graph.plot(title)
+ p.xtitle = name
+ p.ytitle = 'count'
+ p.pad = true
+
+ local lim = ffi.new('double[2]')
+ for k = 0, nbins - 1 do
+ gsl.gsl_histogram_get_range(h, k, lim, lim + 1)
+ local y = gsl.gsl_histogram_get(h, k)
+ local r = rect(lim[0], 0, lim[1], y)
+ p:add(r, color)
+ p:addline(r, 'darkgray')
+ end
+
+ p:show()
+
+ return p
+end
+
+gdt.hist = gdt_table_hist
diff --git a/gdt-lm.lua b/gdt-lm.lua
new file mode 100644
index 00000000..26d76909
--- /dev/null
+++ b/gdt-lm.lua
@@ -0,0 +1,440 @@
+
+local mini = require 'expr-parser'
+local expr_print = require 'expr-print'
+
+local sqrt, abs = math.sqrt, math.abs
+local type, pairs, ipairs = type, pairs, ipairs
+
+local function add_unique(t, val)
+ for k, x in ipairs(t) do
+ if x == val then return k end
+ end
+ local n = #t + 1
+ t[n] = val
+ return n
+end
+
+local function level_number(factors, levels)
+ if not factors then return 0 end
+ local nb = 1
+ for _, factor_name in ipairs(factors) do
+ nb = nb * #levels[factor_name]
+ end
+ return nb
+end
+
+local function enum_levels(factors, levels)
+ local ls, ks, ms = {}, {}, {}
+ local n = #factors
+ for i, name in ipairs(factors) do
+ ks[i], ms[i] = 0, #levels[name]
+ end
+
+ local first = true
+ while true do
+ local lev = {}
+ for i, name in ipairs(factors) do
+ lev[i] = levels[name][ks[i] + 1]
+ end
+ if not (factors.omit_ref_level and first) then ls[#ls + 1] = lev end
+ first = false
+
+ for i = n, 0, -1 do
+ if i == 0 then return ls end
+ ks[i] = (ks[i] + 1) % ms[i]
+ if ks[i] > 0 then break end
+ end
+ end
+end
+
+local function factors_defined(t, i, factors)
+ for k, factor_name in ipairs(factors) do
+ local y = t:get(i, t:col_index(factor_name))
+ if not y then return false end
+ end
+ return true
+end
+
+local function level_does_match(t, i, factors, req_levels)
+ for k, factor_name in ipairs(factors) do
+ local y = t:get(i, t:col_index(factor_name))
+ if y ~= req_levels[k] then return 0 end
+ end
+ return 1
+end
+
+local function expr_are_equal(a, b)
+ if a == b then
+ return true
+ elseif type(a) == 'table' and type(b) == 'table' then
+ if a.operator == b.operator then
+ return expr_are_equal(a[1], b[1]) and expr_are_equal(a[2], b[2])
+ end
+ end
+ return false
+end
+
+local function scalar_term_exists(expr_list, s)
+ for i, expr in ipairs(expr_list) do
+ if not expr.factor and expr_are_equal(expr.scalar, s) then
+ return true
+ end
+ end
+ return false
+end
+
+local function print_expr_level(factors, levels)
+ local t = {}
+ for i, f in ipairs(factors) do
+ t[i] = string.format("%s%s", f, levels[i])
+ end
+ return table.concat(t, ':')
+end
+
+local function expr_is_unit(e)
+ return type(e) == 'number' and e == 1
+end
+
+local function eval_scalar_gen(t)
+ local i
+ local id_res = function(expr) return t:get(i, expr.index) end
+ local func_res = function(expr) return math[expr.func] end
+ local set = function(ix) i = ix end
+ return set, {ident= id_res, func= func_res}
+end
+
+local function eval_lm_matrix(t, expr_list, y_expr)
+ local eval_set, eval_scope = eval_scalar_gen(t)
+ local eval_scalar = expr_print.eval
+
+ local N = #t
+ local NE = #expr_list
+ local XM = 0
+ for k, e in ipairs(expr_list) do XM = XM + e.mult end
+
+ local X = matrix.alloc(N, XM)
+ local Y = y_expr and matrix.alloc(N, 1)
+ local index_map, index_map_start, index_map_len = {}, 1, 0
+ local row_index = 1
+ for i = 1, N do
+ eval_set(i)
+ local row_undef = false
+ local col_index = 1
+ for k = 1, NE do
+ local expr = expr_list[k]
+ local xs = eval_scalar(expr.scalar, eval_scope)
+ local is_undef = (not xs) or (expr.factor and not factors_defined(t, i, expr.factor))
+ row_undef = row_undef or is_undef
+ if not is_undef then
+ if not expr.factor then
+ X:set(row_index, col_index, xs)
+ else
+ local j0 = col_index
+ for j, req_lev in ipairs(expr.levels) do
+ local match = level_does_match(t, i, expr.factor, req_lev)
+ X:set(row_index, j0 + (j - 1), match * xs)
+ end
+ end
+ end
+ col_index = col_index + expr.mult
+ end
+
+ if y_expr and not row_undef then
+ local y_val = eval_scalar(y_expr, eval_scope)
+ row_undef = (not y_val)
+ if y_val then Y:set(row_index, 1, y_val) end
+ end
+
+ if row_undef then
+ local kk = #index_map
+ index_map[kk+1] = index_map_start
+ index_map[kk+2] = index_map_len
+ index_map_start = i + 1
+ index_map_len = 0
+ else
+ row_index = row_index + 1
+ index_map_len = index_map_len + 1
+ end
+ end
+
+ if index_map_len > 0 then
+ local kk = #index_map
+ index_map[kk+1] = index_map_start
+ index_map[kk+2] = index_map_len
+ end
+
+ local nb_rows = row_index - 1
+ assert(nb_rows > 0, "undefined model")
+
+ -- resize X to take into account the rows really defined
+ X.size1 = nb_rows
+ if y_expr then
+ Y.size1 = nb_rows
+ return X, Y, index_map
+ end
+
+ return X
+end
+
+local check = require 'check'
+local mon = require 'monomial'
+
+local function monomial_to_expr(m, context)
+ local coeff = m[1]
+ local prod
+ for k, sym, pow in mon.terms(m) do
+ local base = context[sym]
+ local t = (pow == 1 and base or {operator='^', base, pow})
+ prod = (prod and {operator='*', t, prod} or t)
+ end
+ return coeff == 1 and (prod or 1) or (prod and {operator='*', coeff, prod} or coeff)
+end
+
+local function expr_to_monomial(expr, context)
+ if type(expr) == 'number' then
+ return {expr}
+ elseif expr.operator == '*' then
+ local a = expr_to_monomial(expr[1], context)
+ local b = expr_to_monomial(expr[2], context)
+ mon.mult(a, b)
+ return a
+ elseif expr.operator == '^' and check.is_integer(expr[2]) then
+ local base = expr_to_monomial(expr[1], context)
+ mon.power(base, expr[2])
+ return base
+ else
+ local s = expr_print.expr(expr)
+ context[s] = expr
+ return mon.symbol(s)
+ end
+end
+
+local function build_lm_model(t, expr_list, y_expr)
+ local N, M = t:dim()
+
+ -- list of unique factors referenced in expr_list
+ local used_factors = {}
+ for k, expr in ipairs(expr_list) do
+ if expr.factor then
+ for _, f_name in ipairs(expr.factor) do
+ add_unique(used_factors, f_name)
+ end
+ end
+ end
+
+ -- flag the factors whose scalar part is already used
+ -- in the model. In these cases the first level of the
+ -- factor will be omitted from the model matrix.
+ for k, expr in ipairs(expr_list) do
+ if expr.factor then
+ local s = expr.scalar
+ if scalar_term_exists(expr_list, s) then
+ expr.factor.omit_ref_level = true
+ end
+ end
+ end
+
+ -- for each unique used factor prepare the levels list and
+ -- set the column index
+ local levels, factor_index = {}, {}
+ for k, name in ipairs(used_factors) do
+ levels[name] = {}
+ factor_index[name] = t:col_index(name)
+ end
+
+ -- find the levels for each of the used factors
+ local get = t.get
+ for i = 1, N do
+ for _, name in ipairs(used_factors) do
+ local v = get(t, i, factor_index[name])
+ add_unique(levels[name], v)
+ end
+ end
+
+ for k, expr in ipairs(expr_list) do
+ if expr.factor then
+ local lnb = level_number(expr.factor, levels)
+ local inn = expr.factor.omit_ref_level and lnb - 1 or lnb
+ expr.mult = inn
+ else
+ expr.mult = 1
+ end
+ end
+
+ -- first pass to find coefficient names and levels by expression
+ local names = {}
+ local col_index = 1
+ for k, expr in ipairs(expr_list) do
+ local j0 = col_index
+ local scalar_repr = expr_print.expr(expr.scalar)
+ if not expr.factor then
+ names[j0] = scalar_repr
+ else
+ local flevels = enum_levels(expr.factor, levels)
+ for j, req_lev in ipairs(flevels) do
+ local level_repr = print_expr_level(expr.factor, req_lev)
+ local nm
+ if expr_is_unit(expr.scalar) then
+ nm = level_repr
+ else
+ nm = scalar_repr .. ' * ' .. level_repr
+ end
+ names[j0 + (j - 1)] = nm
+ end
+ expr.levels = flevels
+ end
+ col_index = col_index + expr.mult
+ end
+
+ return names
+end
+
+local function t_test(xm, s, n, df)
+ local t = xm / s
+ local at = abs(t)
+ local p_value = 2 * (1 - randist.tdist_P(at, df))
+ return t, (p_value >= 2e-16 and p_value or '< 2e-16')
+end
+
+local function compute_fit(X, y, names)
+ local n = #y
+ local c, chisq, cov = num.linfit(X, y)
+ local coeff = gdt.alloc(#c, {"term", "estimate", "std error", "t value" ,"Pr(>|t|)"})
+ for i = 1, #c do
+ coeff:set(i, 1, names[i])
+ local xm, s = c[i], cov:get(i,i)
+ coeff:set(i, 2, xm)
+ coeff:set(i, 3, sqrt(s))
+ local t, p_value = t_test(xm, sqrt(s), n, n - #c)
+ coeff:set(i, 4, t)
+ coeff:set(i, 5, p_value)
+ end
+ return {coeff = coeff, c = c, chisq = chisq, cov = cov, n = n, p = #c}
+end
+
+local function fit_compute_Rsquare(fit, X, y)
+ local n, p = fit.n, fit.p
+ local y_pred = X * fit.c
+
+ local y_mean = 0
+ for k = 1, #y do y_mean = y_mean + y:get(k, 1) end
+ y_mean = y_mean / #y
+
+ local SS_tot, SS_reg = 0, 0
+ for k = 1, #y do
+ SS_reg = SS_reg + (y:get(k, 1) - y_pred:get(k, 1))^2
+ SS_tot = SS_tot + (y:get(k, 1) - y_mean)^2
+ end
+
+ local R2 = 1 - SS_reg/SS_tot
+ local R2_adj = R2 - (1 - R2) * p / (n - p - 1)
+ local SE = sqrt(SS_reg / (n - p))
+
+ return SE, R2, R2_adj
+end
+
+local function fit_add_predicted(t, param_name, X, fit, index_map)
+ local cname = string.format("%s (PREDICTED)", param_name)
+ if not t:col_index(cname) then t:append(cname) end
+ local cindex = t:col_index(cname)
+
+ local y_pred = X * fit.c
+ local jy = 1
+ for k = 1, #index_map - 1, 2 do
+ local idx, len = index_map[k], index_map[k+1]
+ for j = 0, len - 1 do
+ t:set(idx + j, cindex, y_pred[jy + j])
+ end
+ jy = jy + len
+ end
+end
+
+local function monomial_exists(ls, e)
+ local n = #ls
+ for k = 1, n do
+ if mon.equal(ls[k], e) then return true end
+ end
+ return false
+end
+
+local function expand_exprs(expr_list)
+ local lsm, lsexp, j = {}, {}, 1
+ for k, e in ipairs(expr_list) do
+ local context = {}
+ local m = expr_to_monomial(e.scalar, context)
+ local ls = mon.combine(m)
+ for _, mexp in ipairs(ls) do
+ if not monomial_exists(lsm, mexp) then
+ lsm[j], j = mexp, j+1
+ local eexp = monomial_to_expr(mexp, context)
+ lsexp[#lsexp+1] = {scalar= eexp}
+ end
+ end
+ if e.factor then lsexp[#lsexp+1] = e end
+ end
+
+ return lsexp
+end
+
+local FIT = {}
+
+function FIT.model(fit, t_alt)
+ return eval_lm_matrix(t_alt, fit.x_exprs)
+end
+
+function FIT.predict(fit, t_alt)
+ local X = eval_lm_matrix(t_alt, fit.x_exprs)
+ return X * fit.c
+end
+
+function FIT.summary(fit)
+ print(fit.coeff)
+ print()
+ print(string.format("Standard Error: %g, R2: %g, Adjusted R2: %g", fit.SE, fit.R2, fit.R2_adj))
+end
+
+local FIT_MT = {__index = FIT}
+
+-- used to eval a model for a single entry
+function FIT.eval(fit, tn)
+ local eval_table = fit.eval_table
+ for k, name in ipairs(fit.headers) do
+ eval_table:set(1, k, tn[name])
+ end
+ local coeff = fit.c
+ local sX = eval_lm_matrix(eval_table, fit.x_exprs)
+ local sy = 0
+ for k = 0, #coeff - 1 do
+ sy = sy + sX.data[k] * coeff.data[k]
+ end
+ return sy
+end
+
+local function lm(t, model_formula, options)
+ local gdt_eval_actions = require('gdt-eval')
+ local actions = gdt_eval_actions(t)
+ local l = mini.lexer(model_formula)
+ local schema = mini.schema(l, actions)
+
+ local expand = not options or (options.expand == nil or options.expand)
+ local x_exprs = expand and expand_exprs(schema.x) or schema.x
+
+ local names = build_lm_model(t, x_exprs, schema.y.scalar)
+ local X, y, index_map = eval_lm_matrix(t, x_exprs, schema.y.scalar)
+ local fit = compute_fit(X, y, names)
+
+ if options and options.predict then
+ local y_name = expr_print.expr(schema.y.scalar)
+ fit_add_predicted(t, y_name, X, fit, index_map)
+ end
+
+ fit.schema = schema
+ fit.x_exprs = x_exprs
+ fit.SE, fit.R2, fit.R2_adj = fit_compute_Rsquare(fit, X, y)
+ fit.eval_table = gdt.alloc(1, t:headers())
+ fit.headers = t:headers()
+
+ return setmetatable(fit, FIT_MT)
+end
+
+gdt.lm = lm
diff --git a/gdt-parse-csv.lua b/gdt-parse-csv.lua
new file mode 100644
index 00000000..9781fde5
--- /dev/null
+++ b/gdt-parse-csv.lua
@@ -0,0 +1,120 @@
+local ffi = require 'ffi'
+local gdt = require 'gdt'
+local csv = require 'csv'
+
+local max = math.max
+local match, gsub = string.match, string.gsub
+
+local function is_string_only(ls)
+ for _, s in ipairs(ls) do
+ if tonumber(s) then return false end
+ end
+ return true
+end
+
+local function pre_parse_csv(source)
+ local head_vs = source()
+ local nrows, ncols = 1, #head_vs
+ local all_strings = true
+ local header_dup = {}
+ for vs in source do
+ if #vs == 0 then break end
+ if all_strings then all_strings = is_string_only(vs) end
+ for k= 1, #vs do
+ if head_vs[k] == vs[k] then header_dup[k] = true end
+ end
+ ncols = max(ncols, #vs)
+ nrows = nrows + 1
+ end
+
+ local header_dup_count = 0
+ for k= 1, ncols do
+ if header_dup[k] then header_dup_count = header_dup_count + 1 end
+ end
+ local header_stand = (header_dup_count < ncols/2)
+
+ local head_all_string = is_string_only(head_vs)
+ local has_header = head_all_string and (header_stand or (not all_strings))
+
+ if has_header then nrows = nrows - 1 end
+
+ return nrows, ncols, has_header
+end
+
+local function is_not_empty(s)
+ return (match(s, '^%s*$') == nil)
+end
+
+local function gdt_parse(source_init)
+ local source = source_init()
+ local nrows, ncols, has_header = pre_parse_csv(source)
+
+ local t = gdt.alloc(nrows, ncols)
+ source = source_init()
+
+ if has_header then
+ local vs = source()
+ for k, s in ipairs(vs) do
+ t:set_header(k, s)
+ end
+ end
+
+ local i = 1
+ for vs in source do
+ if #vs == 0 then break end
+ for j = 1, ncols do
+ local v = (is_not_empty(vs[j]) and vs[j] or nil)
+ gdt.set(t, i, j, v)
+ end
+ i = i + 1
+ end
+
+ return t
+end
+
+local function trim_spaces(line)
+ for j = 1, #line do
+ if type(line[j]) == 'string' then
+ local a = gsub(line[j], "^%s+", "")
+ line[j] = gsub(a, "%s+$", "")
+ end
+ end
+end
+
+local function source_csv(filename, options)
+ local strip_spaces = true
+ if options and (options.strip_spaces ~= nil) then
+ strip_spaces = options.strip_spaces
+ end
+ local f
+ local it, s, i
+ local source = function()
+ local line = it(s, i)
+ if line then
+ local ls = csv.line(line)
+ if strip_spaces then trim_spaces(ls) end
+ return ls
+ else
+ f:close()
+ end
+ end
+ return function()
+ f = assert(io.open(filename, 'r'), 'cannot open file: ' .. filename)
+ it, s, i = f:lines()
+ return source
+ end
+end
+
+local function source_def(def)
+ local n, i = #def, 0
+ local source = function()
+ if i + 1 <= n then
+ i = i + 1
+ return def[i]
+ end
+ end
+ return function() i = 0; return source end
+end
+
+gdt.read_csv = function(filename, options) return gdt_parse(source_csv(filename, options)) end
+gdt.def = function(def) return gdt_parse(source_def(def)) end
diff --git a/gdt-plot.lua b/gdt-plot.lua
new file mode 100644
index 00000000..09761f0d
--- /dev/null
+++ b/gdt-plot.lua
@@ -0,0 +1,585 @@
+local mini = require 'expr-parser'
+local expr_print = require 'expr-print'
+
+local concat = table.concat
+local select, unpack = select, unpack
+local sqrt = math.sqrt
+
+local line_width = 2.5
+
+local function collate(ls, sep)
+ return concat(ls, sep or ' ')
+end
+
+-- recursive algorithm to computer the standard deviation from
+-- wikipedia: http://en.wikipedia.org/wiki/Standard_deviation.
+-- Welford, BP. "Note on a Method for Calculating Corrected Sums of
+-- Squares and Products". Technometrics 4 (3): 419–420
+local function f_stddev(accu, x, n)
+ local A, Q, km = unpack(accu)
+ accu[1] = A + (x - A) / (km + 1)
+ accu[2] = Q + km / (km + 1) * (x - A)^2
+ accu[3] = km + 1
+ return accu
+end
+
+local function f_stddevp_fini(accu)
+ local A, Q, n = unpack(accu)
+ if n > 0 then return sqrt(Q / n) end
+end
+
+local function f_stddev_fini(accu)
+ local A, Q, n = unpack(accu)
+ if n > 1 then return sqrt(Q / (n - 1)) end
+end
+
+local function f_var_fini(accu)
+ local A, Q, n = unpack(accu)
+ if n > 0 then return Q / n end
+end
+
+local stat_lookup = {
+ mean = {f = function(accu, x, n) return (accu * (n-1) + x) / n end},
+ stddev = {f = f_stddev, f0 = || {0, 0, 0}, fini = f_stddev_fini},
+ stddevp = {f = f_stddev, f0 = || {0, 0, 0}, fini = f_stddevp_fini},
+ var = {f = f_stddev, f0 = || {0, 0, 0}, fini = f_var_fini},
+ sum = {f = function(accu, x, n) return accu + x end},
+ count = {f = function(accu, x, n) return n end},
+}
+
+local function quicksort_mirror(t, f, mirror)
+
+ local function quicksort(start, endi)
+ if start >= endi then return end
+ local pivot = start
+ for i = start + 1, endi do
+ if f(t[i], t[pivot]) then
+ local temp = t[pivot + 1]
+ local temp_m = mirror[pivot + 1]
+ t[pivot + 1] = t[pivot]
+ mirror[pivot + 1] = mirror[pivot]
+ if(i == pivot + 1) then
+ t[pivot] = temp
+ mirror[pivot] = temp_m
+ else
+ t[pivot] = t[i]
+ t[i] = temp
+ mirror[pivot] = mirror[i]
+ mirror[i] = temp_m
+ end
+ pivot = pivot + 1
+ end
+ end
+
+ quicksort(start, pivot - 1)
+ quicksort(pivot + 1, endi)
+ end
+
+ quicksort(1, #t)
+end
+
+local function sort_labels_func(lab_a, lab_b)
+ local n = #lab_a
+ for k = 1, n do
+ local a, b = lab_a[k], lab_b[k]
+ if a ~= b then return a < b end
+ end
+ return false
+end
+
+local function compare_list(a, b)
+ local n = #a
+ for k = 1, n do
+ if a[k] ~= b[k] then return false end
+ end
+ return true
+end
+
+local function has_undef_values(ls)
+ local n = #ls
+ for k = 1, n do
+ if not ls[k] then return true end
+ end
+ return false
+end
+
+local function add_unique(ls, e)
+ if has_undef_values(e) then return 0 end
+
+ local n = #ls
+ for i = 1, n do
+ if compare_list(ls[i], e) then return i end
+ end
+ ls[n + 1] = e
+ return n + 1
+end
+
+local function collate_factors(t, i, js)
+ local c = {}
+ local n = #js
+ for k = 1, n do
+ c[k] = t:get(i, js[k])
+ end
+ return c
+end
+
+local function vec2d_get(r, i, j)
+ if r[i] and r[i][j] then
+ return r[i][j]
+ end
+end
+
+local function vec2d_set(r, i, j, v)
+ if not r[i] then r[i] = {} end
+ r[i][j] = v
+end
+
+local function vec2d_incr(r, i, j)
+ if not r[i] then r[i] = {} end
+ local v = r[i][j] or 0
+ r[i][j] = v + 1
+ return v + 1
+end
+
+local function eval_scalar_gen(t)
+ local i
+ local id_res = function(expr) return t:get(i, expr.index) end
+ local func_res = function(expr) return math[expr.func] end
+ local set = function(ix) i = ix end
+ return set, {ident= id_res, func= func_res}
+end
+
+local function rect_funcbin(t, jxs, jys, jes)
+ local eval_set, eval_scope = eval_scalar_gen(t)
+ local eval = expr_print.eval
+
+ local n = #t
+ local val, count = {}, {}
+ local enums, labels = {}, {}
+ local fini_table = {}
+ for i = 1, n do
+ eval_set(i)
+ local c = collate_factors(t, i, jxs)
+ for p = 1, #jys do
+ local jp = jys[p]
+ local fy, fini = jp.f, jp.fini
+ local f0 = jp.f0 and jp.f0() or 0
+ local e = collate_factors(t, i, jes)
+ e[#e+1] = jp.name
+
+ local v = eval(jp.expr, eval_scope)
+ if v then
+ local ie = add_unique(enums, e)
+ local ix = ie > 0 and add_unique(labels, c) or 0
+ if ix > 0 then
+ local cc = vec2d_incr(count, ix, ie)
+ local v_accu = vec2d_get(val, ix, ie) or f0
+ vec2d_set(val, ix, ie, fy(v_accu, v, cc))
+ fini_table[ie] = fini
+ end
+ end
+ end
+ end
+
+ for ie, enum in ipairs(enums) do
+ local fini = fini_table[ie]
+ if fini then
+ for ix = 1, #labels do
+ local v = vec2d_get(val, ix, ie)
+ local v_fin = fini(v)
+ vec2d_set(val, ix, ie, v_fin)
+ end
+ end
+ end
+
+ quicksort_mirror(labels, sort_labels_func, val)
+
+ return labels, enums, val
+end
+
+local function infix_ast(sym, a, b)
+ return {operator= sym, a, b}
+end
+
+local function prefix_ast(sym, a)
+ return {operator= sym, a}
+end
+
+local function func_eval_ast(func_name, arg_expr)
+ return {func= func_name, arg= arg_expr}
+end
+
+local function itself(x) return x end
+
+local function plot_actions_gen(t)
+
+ local function ident_ast(id)
+ local i = t:col_index(id)
+ if not i then error('unknown column name: '..id) end
+ return {name= id, index= i}
+ end
+
+ return {
+ infix = infix_ast,
+ prefix = prefix_ast,
+ ident = ident_ast,
+ enum = ident_ast,
+ func_eval = func_eval_ast,
+ number = itself,
+ exprlist = function(a, ls) if ls then ls[#ls+1] = a else ls = {a} end; return ls end,
+ schema = function(x, y, enums) return {x= x, y= y, enums= enums} end,
+ }
+end
+
+local stat_lookup = {
+ mean = {f = function(accu, x, n) return (accu * (n-1) + x) / n end},
+ stddev = {f = f_stddev, f0 = || {0, 0, 0}, fini = f_stddev_fini},
+ stddevp = {f = f_stddev, f0 = || {0, 0, 0}, fini = f_stddevp_fini},
+ var = {f = f_stddev, f0 = || {0, 0, 0}, fini = f_var_fini},
+ sum = {f = function(accu, x, n) return accu + x end},
+ count = {f = function(accu, x, n) return n end},
+}
+
+local function get_stat(expr)
+ if expr.func and stat_lookup[expr.func]then
+ return expr.func, expr.arg
+ else
+ return 'mean', expr
+ end
+end
+
+local rect, webcolor, path = graph.rect, graph.webcolor, graph.path
+
+function gen_xlabels(plt, labels)
+ local lab0 = labels[1]
+ local n = #lab0
+ local lspecs, accu = {}, {}
+ for k = 1, n do lspecs[k], accu[k] = {}, {1, lab0[k]} end
+ for j = 2, #labels do
+ local lab = labels[j]
+ for k = 1, n do
+ local f = lab[k]
+ local accu_k = accu[k]
+ if f ~= accu_k[2] then
+ local ls = lspecs[k]
+ ls[#ls+1] = accu_k[1] - 1
+ ls[#ls+1] = accu_k[2]
+ accu_k[1] = j
+ accu_k[2] = f
+ end
+ end
+ end
+
+ for k = 1, n do
+ local ls = lspecs[k]
+ local accu_k = accu[k]
+ ls[#ls+1] = accu_k[1] - 1
+ ls[#ls+1] = accu_k[2]
+ ls[#ls+1] = #labels
+
+ plt:set_multi_labels(1, ls)
+ end
+end
+
+local barplot = {xlabels = gen_xlabels}
+
+function barplot.create(labels, enums, val)
+ local plt = graph.plot()
+ local pad = 0.1
+ local dx = (1 - 2*pad) / #enums
+ for p, lab in ipairs(labels) do
+ for q, _ in ipairs(enums) do
+ local v = val[p][q]
+ if v then
+ local x = (p - 1) + pad + dx * (q - 1)
+ local r = rect(x, 0, x + dx, val[p][q])
+ plt:add(r, webcolor(q))
+ end
+ end
+ end
+ return plt
+end
+
+function barplot.legend(plt, labels, enums)
+ if #enums > 1 then
+ for k = 1, #enums do
+ plt:legend(collate(enums[k], '/'), webcolor(k), 'square')
+ end
+ end
+end
+
+local lineplot = {xlabels = gen_xlabels}
+
+local function legend_symbol(sym, dx, dy)
+ if sym == 'square' then
+ return graph.rect(5+dx, 5+dy, 15+dx, 15+dy)
+ elseif sym == 'line' then
+ return graph.segment(dx, 10+dy, 20+dx, 10+dy), {{'stroke', width=line_width}}
+ else
+ return graph.marker(10+dx, 10+dy, sym, 8)
+ end
+end
+
+local function add_legend(lg, k, symspec, color, text)
+ local y = -k * 20
+ local sym, tr = legend_symbol(symspec, 0, y)
+ lg:add(sym, color, tr)
+ if text then
+ lg:add(graph.textshape(25, y + 6, text, 14), 'black')
+ end
+end
+
+function lineplot.create(labels, enums, val)
+ local plt = graph.plot()
+ plt.pad, plt.clip = true, false
+
+ for q, en in ipairs(enums) do
+ local ln = path()
+ local path_method = ln.move_to
+ for p, lab in ipairs(labels) do
+ local y = val[p][q]
+ if y then
+ path_method(ln, p - 0.5, y)
+ path_method = ln.line_to
+ else
+ path_method = ln.move_to
+ end
+ end
+ plt:add(ln, webcolor(q), {{'stroke', width=line_width}})
+ plt:add(ln, webcolor(q), {{'marker', size=8, mark=q}})
+ end
+
+ return plt
+end
+
+function lineplot.legend(plt, labels, enums)
+ if #enums > 1 then
+ local lg = graph.plot()
+ lg.units, lg.clip = false, false
+ for q, en in ipairs(enums) do
+ local label = collate(en)
+ add_legend(lg, q, 'line', webcolor(q), label)
+ add_legend(lg, q, q, webcolor(q))
+ end
+ plt:set_legend(lg)
+ end
+end
+
+local function idents_get_column_indexes(t, exprs)
+ local jxs = {}
+ for i, expr in ipairs(exprs) do
+ if not expr.name then error('invalid enumeration factor') end
+ jxs[i] = t:col_index(expr.name)
+ end
+ return jxs
+end
+
+local function stat_expr_get_functions(exprs)
+ local jys = {}
+ for i, expr in ipairs(exprs) do
+ local stat_name, yexpr = get_stat(expr)
+ local s = stat_lookup[stat_name]
+ jys[i] = {
+ f = s.f,
+ f0 = s.f0,
+ fini = s.fini,
+ name = expr_print.expr(expr),
+ expr = yexpr,
+ }
+ end
+ return jys
+end
+
+local function expr_get_functions(exprs)
+ local jys = {}
+ for i, expr in ipairs(exprs) do
+ jys[i] = {
+ name = expr_print.expr(expr),
+ expr = expr,
+ }
+ end
+ return jys
+end
+
+local function schema_from_plot_descr(plot_descr, t)
+ local l = mini.lexer(plot_descr)
+ local actions = plot_actions_gen(t)
+ return mini.gschema(l, actions)
+end
+
+local function gdt_table_category_plot(plotter, t, plot_descr, opt)
+ local show_plot = true
+ if opt then show_plot = (opt.show ~= false) end
+
+ local schema = schema_from_plot_descr(plot_descr, t)
+ local jxs = idents_get_column_indexes(t, schema.x)
+ local jys = stat_expr_get_functions(schema.y)
+ local jes = idents_get_column_indexes(t, schema.enums)
+
+ local labels, enums, val = rect_funcbin(t, jxs, jys, jes)
+
+ local plt = plotter.create(labels, enums, val)
+ plotter.xlabels(plt, labels)
+ plotter.legend(plt, labels, enums)
+
+ if show_plot then plt:show() end
+ return plt
+end
+
+function gdt.xyline(t, plot_descr)
+ local schema = schema_from_plot_descr(plot_descr, t)
+ local jxs = expr_get_functions(schema.x)
+ local jys = expr_get_functions(schema.y)
+
+ assert(#jys == 1, "single y expression required")
+
+ local jx, jy = jxs[1], jys[1]
+ local n = #t
+
+ local eval_set, eval_scope = eval_scalar_gen(t)
+ local eval = expr_print.eval
+
+ local ln = path()
+ local path_method = ln.move_to
+ for i = 1, n do
+ eval_set(i)
+ local x, y = eval(jx.expr, eval_scope), eval(jy.expr, eval_scope)
+ if x and y then
+ path_method(ln, x, y)
+ path_method = ln.line_to
+ else
+ path_method = ln.move_to
+ end
+ end
+
+ return ln
+end
+
+local function gdt_table_xyplot(t, plot_descr, opt)
+ local show_plot = true
+ if opt then show_plot = (opt.show ~= false) end
+
+ local use_lines = opt and opt.lines
+ local use_markers = opt and (opt.markers ~= false) or true
+
+ local schema = schema_from_plot_descr(plot_descr, t)
+ local jxs = expr_get_functions(schema.x)
+ local jys = expr_get_functions(schema.y)
+ local jes = idents_get_column_indexes(t, schema.enums)
+ local jx = jxs[1]
+
+ local eval_set, eval_scope = eval_scalar_gen(t)
+ local eval = expr_print.eval
+
+ local enums = {}
+ local n = #t
+ for i = 1, n do
+ local e = collate_factors(t, i, jes)
+ add_unique(enums, e)
+ end
+
+ local plt, lg = graph.plot(), graph.plot()
+ plt.pad, plt.clip = true, false
+ lg.units, lg.clip = false, false
+ local mult = #enums * #jys
+ for p = 1, #jys do
+ local name = jys[p].name
+ for q, enum in ipairs(enums) do
+ local ln = path()
+ local path_method = ln.move_to
+ for i = 1, n do
+ eval_set(i)
+ local e = collate_factors(t, i, jes)
+ if compare_list(enum, e) then
+ local x, y = eval(jx.expr, eval_scope), eval(jys[p].expr, eval_scope)
+ if x and y then
+ path_method(ln, x, y)
+ path_method = ln.line_to
+ else
+ path_method = ln.move_to
+ end
+ end
+ end
+
+ local iqs = {}
+ if #enums > 1 then iqs[#iqs+1] = collate(enum) end
+ if #jys > 1 then iqs[#iqs+1] = name end
+ local ienum = concat(iqs, " ")
+ local iq = (q - 1) * #jys + p
+ if mult > 1 then
+ add_legend(lg, iq, iq, webcolor(iq), ienum)
+ end
+
+ if use_lines then
+ plt:add(ln, webcolor(iq), {{'stroke', width=3}})
+ end
+ if use_markers then
+ plt:add(ln, webcolor(iq), {{'marker', size=6, mark=iq}})
+ end
+ end
+ end
+
+ if mult > 1 then plt:set_legend(lg) end
+
+ if show_plot then plt:show() end
+ return plt
+end
+
+function gdt.reduce(t_src, schema_descr)
+ local schema = schema_from_plot_descr(schema_descr, t_src)
+ local jxs = idents_get_column_indexes(t_src, schema.x)
+ local jys = stat_expr_get_functions(schema.y)
+ local jes = idents_get_column_indexes(t_src, schema.enums)
+
+ local labels, enums, val = rect_funcbin(t_src, jxs, jys, jes)
+
+ local n, p, q = #labels, #enums, #labels[1]
+ local t = gdt.alloc(n, q + p)
+
+ for k = 1, q do
+ t:set_header(k, t_src:header(jxs[k]))
+ end
+ for k, en in ipairs(enums) do
+ t:set_header(q + k, collate(en, "/"))
+ end
+
+ local set = t.set
+ for i = 1, n do
+ for k = 1, q do
+ set(t, i, k, labels[i][k])
+ end
+ for k = 1, p do
+ set(t, i, q + k, val[i][k])
+ end
+ end
+
+ return t
+end
+
+local function is_simple_numeric(t, plot_descr)
+ local gdt_eval_actions = require('gdt-eval')
+ local actions = gdt_eval_actions(t)
+ local l = mini.lexer(plot_descr)
+ local schema = mini.gschema(l, actions)
+ if #schema.x == 1 then
+ local expr = schema.x[1]
+ return (expr.factor == nil)
+ end
+ return false
+end
+
+function gdt.plot(t, plot_descr, opts)
+ if is_simple_numeric(t, plot_descr) then
+ return gdt_table_xyplot(t, plot_descr, opts)
+ else
+ return gdt_table_category_plot(lineplot, t, plot_descr, opts)
+ end
+end
+
+function gdt.lineplot(t, plot_descr, opts)
+ return gdt_table_category_plot(lineplot, t, plot_descr, opts)
+end
+
+function gdt.barplot(t, plot_descr, opts)
+ return gdt_table_category_plot(barplot, t, plot_descr, opts)
+end
diff --git a/gdt.lua b/gdt.lua
new file mode 100644
index 00000000..1a1add67
--- /dev/null
+++ b/gdt.lua
@@ -0,0 +1,315 @@
+local cgdt = require 'cgdt'
+
+local format = string.format
+local concat = table.concat
+local max = math.max
+local assert = assert
+
+local gdt_table = ffi.typeof("gdt_table")
+local gdt_table_cursor = ffi.typeof("gdt_table_cursor")
+
+local TAG_STRING = tonumber(cgdt.TAG_STRING)
+local TAG_NUMBER = tonumber(cgdt.TAG_NUMBER)
+
+local function element_is_number(e)
+ return (e.word.hi <= TAG_NUMBER)
+end
+
+local function gdt_element(t, e)
+ local val
+ if e.word.hi <= TAG_NUMBER then
+ val = e.number
+ elseif e.word.hi == TAG_STRING then
+ local s = cgdt.gdt_table_element_get_string(t, e)
+ assert(s ~= nil, "invalid gdt element string refernce")
+ return ffi.string(s)
+ end
+ return val
+end
+
+local function gdt_table_get(t, i, j)
+ assert(i > 0 and i <= t.size1, 'invalid row index')
+ local e
+ if type(j) == 'string' then
+ e = cgdt.gdt_table_get_by_name(t, i - 1, j)
+ assert(e ~= nil, "invalid column name")
+ else
+ assert(j > 0 and j <= t.size2, 'invalid column index')
+ e = cgdt.gdt_table_get(t, i - 1, j - 1)
+ end
+ return gdt_element(t, e)
+end
+
+local function gdt_table_get_number_unsafe(t, i, j)
+ local e = cgdt.gdt_table_get(t, i - 1, j - 1)
+ if e.word.hi <= TAG_NUMBER then return e.number end
+end
+
+local function gdt_table_set_unsafe(t, i, j, val)
+ local tp = type(val)
+ if tp == 'number' then
+ cgdt.gdt_table_set_number(t, i - 1, j - 1, val)
+ elseif tp == 'string' then
+ cgdt.gdt_table_set_string(t, i - 1, j - 1, val)
+ else
+ assert(tp ~= nil, 'expect a number, string or nil value')
+ cgdt.gdt_table_set_undef(t, i - 1, j - 1)
+ end
+end
+
+local function gdt_table_set(t, i, j_name, val)
+ assert(i > 0 and i <= t.size1, 'invalid row index')
+ local j
+ if type(j_name) == 'string' then
+ local index = cgdt.gdt_table_header_index(t, j_name)
+ assert(index >= 0, 'invalid column index')
+ j = index + 1
+ else
+ assert(type(j_name) == 'number', 'invalid column index')
+ j = j_name
+ assert(j > 0 and j <= t.size2, 'invalid column index')
+ end
+ gdt_table_set_unsafe(t, i, j, val)
+end
+
+local function gdt_table_alloc(nrows, ncols, nalloc_rows)
+ nalloc_rows = nalloc_rows or nrows
+ local headers
+ if type(ncols) == 'table' then
+ headers = ncols
+ ncols = #headers
+ end
+ local t = cgdt.gdt_table_new(nrows, ncols, nalloc_rows)
+ if headers then
+ for k, str in ipairs(headers) do
+ cgdt.gdt_table_set_header(t, k - 1, str)
+ end
+ end
+ if t == nil then error('cannot allocate table: not enough memory') end
+ return ffi.gc(t, cgdt.gdt_table_free)
+end
+
+local function gdt_table_new(nrows, cols_spec)
+ local t = gdt_table_alloc(nrows, cols_spec)
+ local ncols = t.size2
+ for i = 1, nrows do
+ for j = 1, ncols do
+ cgdt.gdt_table_set_undef(t, i - 1, j - 1)
+ end
+ end
+ return t
+end
+
+local function gdt_table_dim(t) return t.size1, t.size2 end
+
+local function gdt_table_get_header(t, k)
+ assert(k > 0 and k <= t.size2, 'invalid column index')
+ local s = cgdt.gdt_table_get_header(t, k - 1)
+ return (s == nil and 'V' .. k or ffi.string(s))
+end
+
+local function gdt_table_set_header(t, k, str)
+ assert(k > 0 and k <= t.size2, 'invalid column index')
+ cgdt.gdt_table_set_header(t, k - 1, str)
+end
+
+local function gdt_table_header_index(t, name)
+ local j = cgdt.gdt_table_header_index(t, name)
+ return (j >= 0 and j + 1 or nil)
+end
+
+local function gdt_table_len(t)
+ return t.size1
+end
+
+local function gdt_table_column_iter(t, j)
+ local n = #t
+ local f = function(_t, i)
+ if i + 1 > n then return nil else return i + 1, _t:get(i + 1, j) end
+ end
+ return f, t, 0
+end
+
+local function gdt_table_insert_column(t, col_name, j, f)
+ cgdt.gdt_table_insert_columns(t, j - 1, 1)
+
+ local n = #t
+ if not f then
+ for i = 1, n do
+ cgdt.gdt_table_set_undef(t, i - 1, j - 1)
+ end
+ else
+ for i, row in t:rows() do
+ local status, x = pcall(f, row, i)
+ t:set(i, j, status and x or nil)
+ end
+ end
+
+ t:set_header(j, col_name)
+end
+
+local function gdt_table_append_column(t, col_name, f)
+ gdt_table_insert_column(t, col_name, t.size2 + 1, f)
+end
+
+local function val_tostr(e)
+ if type(e) == "number" then
+ return format("%g", e)
+ else
+ return e or 'NA'
+ end
+end
+
+local function gdt_table_show(dt)
+ local field_lens = {}
+ local r, c = gdt_table_dim(dt)
+ for k = 1, c do
+ field_lens[k] = # gdt_table_get_header(dt, k)
+ end
+ for i = 1, r do
+ for j = 1, c do
+ local len = #val_tostr(gdt_table_get(dt, i, j))
+ field_lens[j] = max(field_lens[j], len)
+ end
+ end
+
+ local field_fmts = {}
+ for j = 1, c do
+ field_fmts[j] = format('%%%ds', field_lens[j])
+ end
+
+ local lines = {}
+
+ local row_ndig = #tostring(#dt)
+ local t = {string.rep(" ", row_ndig)}
+ for j = 1, c do
+ t[#t+1] = format(field_fmts[j], gdt_table_get_header(dt, j))
+ end
+ lines[1] = concat(t, ' ')
+
+ for i = 1, r do
+ local t = {format("%-" .. row_ndig .. "d", i)}
+ for j = 1, c do
+ local x = gdt_table_get(dt, i, j)
+ t[#t+1] = format(field_fmts[j], val_tostr(x))
+ end
+ lines[#lines + 1] = concat(t, ' ')
+ end
+ return concat(lines, '\n')
+end
+
+local function gdt_table_get_cursor(t)
+ local c = cgdt.gdt_table_get_cursor(t)
+ c.__index = 0
+ return c
+end
+
+local function gdt_table_headers(t)
+ local m = t.size2
+ local name = {}
+ for k = 1, m do name[k] = gdt_table_get_header(t, k) end
+ return name
+end
+
+local function gdt_table_rows(t)
+ local n = #t
+ local cursor = cgdt.gdt_table_get_cursor(t)
+ local function f(t, i)
+ i = i + 1
+ if i <= n then
+ cursor.__index = i - 1
+ return i, cursor
+ end
+ end
+ return f, t, 0
+end
+
+local function gdt_table_filter(t, f)
+ local n, m = t:dim()
+ local n_curr = 0
+ local new = gdt.alloc(n_curr, m, 16)
+ for i, row in t:rows() do
+ if f(row, i) then
+ n_curr = n_curr + 1
+ cgdt.gdt_table_insert_rows(new, n_curr - 1, 1)
+ for j = 1, m do
+ local e = cgdt.gdt_table_get(t, i - 1, j - 1)
+ local v = gdt_element(t, e)
+ gdt.set(new, n_curr, j, v)
+ end
+ end
+ end
+ for j = 1, m do
+ new:set_header(j, t:header(j))
+ end
+ return new
+end
+
+local function find_column_type(t, j)
+ local n = #t
+ for i = 1, n do
+ local x = t:get(i, j)
+ if type(x) == 'string' then return 'factor' end
+ end
+ return 'scalar'
+end
+
+local function gdt_table_column_type(t, col)
+ local j = (type(col) == 'string') and gdt_table_header_index(t, col) or col
+ assert(type(j) == 'number', 'invalid column')
+ return find_column_type(t, j)
+end
+
+local gdt_methods = {
+ dim = gdt_table_dim,
+ get = gdt_table_get,
+ set = gdt_table_set,
+ header = gdt_table_get_header,
+ set_header = gdt_table_set_header,
+ headers = gdt_table_headers,
+ show = gdt_table_show,
+ column = gdt_table_column_iter,
+ col_index = gdt_table_header_index,
+ col_type = gdt_table_column_type,
+ insert = gdt_table_insert_column,
+ append = gdt_table_append_column,
+ cursor = gdt_table_get_cursor,
+ rows = gdt_table_rows,
+}
+
+local gdt_mt = {
+ __index = gdt_methods,
+ __len = gdt_table_len,
+}
+
+ffi.metatype(gdt_table, gdt_mt)
+
+local function gdt_table_cursor_get(c, k)
+ local e = cgdt.gdt_table_cursor_get(c, k)
+ if e ~= nil then
+ local t = c.__table
+ return gdt_element(t, e)
+ end
+ return nil
+end
+
+local cursor_mt = {
+ __index = gdt_table_cursor_get,
+}
+
+ffi.metatype(gdt_table_cursor, cursor_mt)
+
+local register_ffi_type = debug.getregistry().__gsl_reg_ffi_type
+register_ffi_type(gdt_table, "data table")
+
+gdt = {
+ new = gdt_table_new,
+ alloc = gdt_table_alloc,
+ get = gdt_table_get,
+ set = gdt_table_set,
+ filter = gdt_table_filter,
+
+ get_number_unsafe = gdt_table_get_number_unsafe,
+}
+
+return gdt
diff --git a/gdt/Makefile b/gdt/Makefile
new file mode 100644
index 00000000..c0c3b630
--- /dev/null
+++ b/gdt/Makefile
@@ -0,0 +1,57 @@
+
+# Makefile
+#
+# Copyright (C) 2009 Francesco Abbate
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or (at
+# your option) any later version.
+#
+# This program is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+
+GSH_BASE_DIR = ..
+
+include $(GSH_BASE_DIR)/makeconfig
+include $(GSH_BASE_DIR)/make-system-detect
+include $(GSH_BASE_DIR)/makepackages
+include $(GSH_BASE_DIR)/makedefs
+
+INCLUDES += -I$(GSH_BASE_DIR)
+
+CFLAGS += -std=c99
+
+GDT_SRC_FILES = char_buffer.c gdt_index.c gdt_table.c
+GDT_OBJ_FILES := $(GDT_SRC_FILES:%.c=%.o)
+
+DEP_FILES := $(GDT_SRC_FILES:%.c=.deps/%.P)
+
+DEPS_MAGIC := $(shell mkdir .deps > /dev/null 2>&1 || :)
+
+COMPILE = $(CC) $(CFLAGS) $(LUA_CFLAGS) $(DEFS) $(INCLUDES)
+
+TARGETS = libgdt.a
+
+all: $(TARGETS)
+
+libgdt.a: $(GDT_OBJ_FILES)
+ @echo Archive $@
+ @$(AR) $@ $?
+ @$(RANLIB) $@
+
+include $(GSH_BASE_DIR)/makerules
+
+.PHONY: clean all
+
+clean:
+ $(HOST_RM) *.o *.a *$(DLL_EXT) $(TARGETS)
+
+-include $(DEP_FILES)
diff --git a/gdt/char_buffer.c b/gdt/char_buffer.c
new file mode 100644
index 00000000..8e434cde
--- /dev/null
+++ b/gdt/char_buffer.c
@@ -0,0 +1,71 @@
+#include <string.h>
+#include "char_buffer.h"
+#include "xmalloc.h"
+
+#define CHAR_BUFFER_ALIGN_SHIFT 2
+#define CHAR_BUFFER_ALIGN (1 << CHAR_BUFFER_ALIGN_SHIFT)
+#define CHAR_BUFFER_ALIGN_MASK (CHAR_BUFFER_ALIGN - 1)
+
+static inline size_t roundup_size(size_t s)
+{
+ return (s + CHAR_BUFFER_ALIGN_MASK) & ~CHAR_BUFFER_ALIGN_MASK;
+}
+
+/* copy data like memcpy but assume that data are aligned with
+ CHAR_BUFFER_ALIGN and padded with zeros at the end of buffer. */
+static inline void bufcopy(char* _dst, const char* _src, size_t _sz)
+{
+ int* dst = (int *) _dst;
+ const int* src = (const int*) _src;
+ int const * const end_ptr = dst + (_sz >> CHAR_BUFFER_ALIGN_SHIFT);
+ while (dst < end_ptr) {
+ *(dst++) = *(src++);
+ }
+}
+
+void
+char_buffer_init(struct char_buffer *b, size_t sz)
+{
+ b->size = roundup_size(sz);
+ b->data = xmalloc(b->size);
+ b->data[0] = 0;
+ b->length = 0;
+}
+
+void
+char_buffer_free(struct char_buffer *b)
+{
+ free(b->data);
+}
+
+static void
+char_buffer_resize(struct char_buffer *b, size_t req_size)
+{
+ req_size = round_two_power(req_size);
+ char *new_data = xmalloc(req_size);
+ bufcopy(new_data, b->data, b->length);
+ free(b->data);
+ b->data = new_data;
+ b->size = req_size;
+}
+
+int
+char_buffer_append(struct char_buffer *b, const char *str)
+{
+ const size_t len = strlen(str);
+ const int string_offset = b->length;
+ const size_t new_len = string_offset + roundup_size(len+1);
+ if (new_len > b->size)
+ char_buffer_resize(b, new_len);
+
+ /* zero the final word of the destination buffer */
+ int* const end_ptr = ((int *) (b->data + new_len)) - 1;
+ *end_ptr = 0;
+
+ /* copy the string data into destination buffer. The final
+ zero is not needed since the last word of dest buffer was
+ padded with zeros. */
+ memcpy(b->data + string_offset, str, len);
+ b->length = new_len;
+ return string_offset;
+}
diff --git a/gdt/char_buffer.h b/gdt/char_buffer.h
new file mode 100644
index 00000000..fe44695a
--- /dev/null
+++ b/gdt/char_buffer.h
@@ -0,0 +1,14 @@
+#ifndef GDT_CHAR_BUFFER_H
+#define GDT_CHAR_BUFFER_H
+
+struct char_buffer {
+ char *data;
+ size_t length;
+ size_t size;
+};
+
+extern void char_buffer_init(struct char_buffer *b, size_t sz);
+extern void char_buffer_free(struct char_buffer *b);
+extern int char_buffer_append(struct char_buffer *b, const char *str);
+
+#endif
diff --git a/gdt/gdt_index.c b/gdt/gdt_index.c
new file mode 100644
index 00000000..7b94be59
--- /dev/null
+++ b/gdt/gdt_index.c
@@ -0,0 +1,81 @@
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <assert.h>
+
+#include "gdt_index.h"
+#include "xmalloc.h"
+
+#define STRING_SECTION_INIT_SIZE 256
+
+gdt_index *
+gdt_index_new(int alloc_size)
+{
+ size_t extra_size = sizeof(int) * (alloc_size - INDEX_AUTO);
+ gdt_index *g = xmalloc(sizeof(gdt_index) + extra_size);
+ char_buffer_init(g->names, STRING_SECTION_INIT_SIZE);
+ g->length = 0;
+ g->size = alloc_size;
+ return g;
+}
+
+void
+gdt_index_free(gdt_index *g)
+{
+ char_buffer_free(g->names);
+ free(g);
+}
+
+gdt_index *
+gdt_index_resize(gdt_index *g)
+{
+ size_t alloc_size = g->size * 2;
+ size_t extra_size = sizeof(int) * (alloc_size - INDEX_AUTO);
+ gdt_index *new_g = xmalloc(sizeof(gdt_index) + extra_size);
+
+ new_g->names[0] = g->names[0];
+ new_g->length = g->length;
+ new_g->size = alloc_size;
+ memcpy(new_g->index, g->index, sizeof(int) * g->length);
+
+ free(g);
+ return new_g;
+}
+
+int
+gdt_index_add(gdt_index *g, const char *str)
+{
+ /* if the index table is not big enough return error code */
+ if (g->length + 1 > g->size)
+ return (-1);
+
+ /* add the given string in the key string buffer */
+ int str_offset = char_buffer_append(g->names, str);
+
+ /* add the new string offset index into the index table */
+ int idx = g->length;
+ g->index[idx] = str_offset;
+ g->length ++;
+ return idx;
+}
+
+const char *
+gdt_index_get(gdt_index *g, int index)
+{
+ if (index < 0 || index >= g->length)
+ return NULL;
+ return g->names->data + g->index[index];
+}
+
+int
+gdt_index_lookup(gdt_index *g, const char *req)
+{
+ const char *base = g->names->data;
+ for (int k = 0; k < g->length; k++)
+ {
+ const char *str = base + g->index[k];
+ if (strcmp(str, req) == 0)
+ return k;
+ }
+ return (-1);
+}
diff --git a/gdt/gdt_index.h b/gdt/gdt_index.h
new file mode 100644
index 00000000..714b06a1
--- /dev/null
+++ b/gdt/gdt_index.h
@@ -0,0 +1,23 @@
+#ifndef GDT_INDEX_H
+#define GDT_INDEX_H
+
+#include "defs.h"
+#include "char_buffer.h"
+
+#define INDEX_AUTO 4
+
+typedef struct {
+ struct char_buffer names[1];
+ int length;
+ int size;
+ int index[INDEX_AUTO];
+} gdt_index;
+
+extern gdt_index * gdt_index_new (int alloc_size);
+extern void gdt_index_free (gdt_index *g);
+extern gdt_index * gdt_index_resize (gdt_index *g);
+extern int gdt_index_add (gdt_index *g, const char *str);
+extern const char * gdt_index_get (gdt_index *g, int index);
+extern int gdt_index_lookup (gdt_index *g, const char *req);
+
+#endif
diff --git a/gdt/gdt_table.c b/gdt/gdt_table.c
new file mode 100644
index 00000000..7f68a443
--- /dev/null
+++ b/gdt/gdt_table.c
@@ -0,0 +1,372 @@
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "gdt_table.h"
+#include "xmalloc.h"
+
+static inline int
+elem_is_string(const gdt_element* e)
+{
+ return e->word.hi == TAG_STRING;
+}
+
+static inline int
+elem_is_undef(const gdt_element* e)
+{
+ return e->word.hi == TAG_UNDEF;
+}
+
+static void
+string_array_init(struct string_array *v, int length)
+{
+ char_buffer_init(v->buffer, 256);
+ v->offset_data = xmalloc(sizeof(int) * length);
+ v->offset_len = length;
+ for (int k = 0; k < length; k++)
+ {
+ v->offset_data[k] = -1;
+ }
+}
+
+static void
+string_array_free(struct string_array *v)
+{
+ char_buffer_free(v->buffer);
+ free(v->offset_data);
+}
+
+static const char *
+string_array_get(struct string_array *v, int k)
+{
+ int offset = v->offset_data[k];
+ return (offset >= 0 ? v->buffer->data + offset : NULL);
+}
+
+static void
+string_array_set(struct string_array *v, int k, const char *str)
+{
+ int offset = char_buffer_append(v->buffer, str);
+ v->offset_data[k] = offset;
+}
+
+static int
+string_array_lookup(struct string_array *v, const char *key)
+{
+ int k, len = v->offset_len;
+ const char * base_data = v->buffer->data;
+ for (k = 0; k < len; k++)
+ {
+ int offset = v->offset_data[k];
+ if (offset >= 0 && strcmp(base_data + offset, key) == 0)
+ return k;
+ }
+ return (-1);
+}
+
+static void
+string_array_insert(struct string_array *v, int j_in, int n)
+{
+ int new_len = v->offset_len + n;
+ int old_len = v->offset_len;
+ int *new_data = xmalloc(sizeof(int) * new_len);
+ int *old_data = v->offset_data;
+ int j, k;
+
+ for (j = 0; j < j_in; j++)
+ new_data[j] = old_data[j];
+ for (k = 0; k < n; k++)
+ new_data[j_in + k] = -1;
+ for (/* */; j < old_len; j++)
+ new_data[j + n] = old_data[j];
+
+ free(v->offset_data);
+
+ v->offset_data = new_data;
+ v->offset_len = new_len;
+}
+
+/* match string in the form "V[1-9]\d*". strtol is not used because
+ it does match other forms like for example "V +015". */
+static int
+match_anonymous_header(const char* s)
+{
+ if (*s == 'V') {
+ const int int0 = (int) '0', int9 = (int) '9';
+ const int s0 = *(++s);
+ if (s0 > int0 && s0 <= int9) {
+ int accu = s0 - int0;
+ for (s++; (int) s[0] >= int0 && (int) s[0] <= int9; s++) {
+ accu = accu * 10 + ((int)s[0] - int0);
+ }
+ if (*s == 0) {
+ return (accu - 1);
+ }
+ }
+ }
+ return (-1);
+}
+
+static gdt_block *
+gdt_block_new(int size)
+{
+ gdt_element *data = malloc(size * sizeof(gdt_element));
+ if (unlikely(data == 0))
+ return NULL;
+ gdt_block *b = xmalloc(sizeof(gdt_block));
+ b->data = data;
+ b->size = size;
+ b->ref_count = 0;
+ return b;
+}
+
+static void
+gdt_block_ref(gdt_block *b)
+{
+ b->ref_count ++;
+}
+
+static void
+gdt_block_unref(gdt_block *b)
+{
+ b->ref_count --;
+ if (b->ref_count <= 0)
+ {
+ free(b->data);
+ free(b);
+ }
+}
+
+gdt_table *
+gdt_table_new(int nb_rows, int nb_columns, int nb_rows_alloc)
+{
+ int sz = nb_columns * nb_rows_alloc;
+ if (unlikely(sz <= 0)) return NULL;
+ gdt_block *b = gdt_block_new(sz);
+ if (unlikely(b == NULL)) return NULL;
+ gdt_block_ref(b);
+
+ gdt_table *dt = xmalloc(sizeof(gdt_table));
+
+ dt->size1 = nb_rows;
+ dt->size2 = nb_columns;
+ dt->tda = nb_columns;
+ dt->data = b->data;
+ dt->block = b;
+
+ dt->strings = gdt_index_new(16);
+
+ string_array_init(dt->headers, nb_columns);
+
+ dt->cursor->table = dt;
+
+ return dt;
+}
+
+void
+gdt_table_free(gdt_table *t)
+{
+ gdt_block_unref(t->block);
+ gdt_index_free(t->strings);
+ string_array_free(t->headers);
+ t->cursor->table = NULL;
+}
+
+const gdt_element *
+gdt_table_get(gdt_table *t, int i, int j)
+{
+ return &t->data[i * t->tda + j];
+}
+
+const gdt_element *
+gdt_table_get_by_name(gdt_table *t, int i, const char* col_name)
+{
+ int j = gdt_table_header_index(t, col_name);
+ if (j >= 0) {
+ return gdt_table_get(t, i, j);
+ }
+ return NULL;
+}
+
+int
+gdt_table_header_index(gdt_table *t, const char* col_name)
+{
+ int j = string_array_lookup(t->headers, col_name);
+ if (likely(j >= 0)) {
+ return j;
+ } else {
+ int jan = match_anonymous_header(col_name);
+ if (jan >= 0 && jan < t->size2) {
+ const char* name = string_array_get(t->headers, jan);
+ if (!name) {
+ return jan;
+ }
+ }
+ }
+ return (-1);
+}
+
+const char *
+gdt_table_element_get_string(gdt_table *t, const gdt_element *e)
+{
+ if (elem_is_string(e))
+ return gdt_index_get(t->strings, e->word.lo);
+ return NULL;
+}
+
+void
+gdt_table_set_undef(gdt_table *t, int i, int j)
+{
+ gdt_element *e = &t->data[i * t->tda + j];
+ e->word.hi = TAG_UNDEF;
+}
+
+void
+gdt_table_set_number(gdt_table *t, int i, int j, double num)
+{
+ gdt_element *e = &t->data[i * t->tda + j];
+ e->number = num;
+}
+
+void
+gdt_table_set_string(gdt_table *t, int i, int j, const char *s)
+{
+ gdt_element *e = &t->data[i * t->tda + j];
+
+ int str_index = gdt_index_lookup(t->strings, s);
+ if (str_index < 0)
+ {
+ str_index = gdt_index_add(t->strings, s);
+ if (str_index < 0)
+ {
+ t->strings = gdt_index_resize(t->strings);
+ str_index = gdt_index_add(t->strings, s);
+ }
+ }
+
+ e->word.hi = TAG_STRING;
+ e->word.lo = str_index;
+}
+
+const char *
+gdt_table_get_header(gdt_table *t, int j)
+{
+ return string_array_get(t->headers, j);
+}
+
+void
+gdt_table_set_header(gdt_table *t, int j, const char *str)
+{
+ string_array_set(t->headers, j, str);
+}
+
+int
+gdt_table_insert_columns(gdt_table *t, int j_in, int n)
+{
+ int os2 = t->size2, ns2 = t->size2 + n;
+ int sz = ns2 * t->size1;
+ int *src, *dst;
+ int i;
+
+ if (unlikely(sz <= 0)) return (-1);
+ gdt_block *new_block = gdt_block_new(sz);
+ if (unlikely(new_block == NULL)) return (-1);
+ gdt_block_ref(new_block);
+
+ src = (int *) t->data;
+ dst = (int *) new_block->data;
+
+ for (i = 0; i < t->size1; i++)
+ {
+ int j;
+
+ for (j = 0; j < 2 * j_in; j++)
+ {
+ dst[j] = src[j];
+ }
+ for (/* */; j < 2 * os2; j++)
+ {
+ dst[j + 2 * n] = src[j];
+ }
+
+ dst += 2 * ns2;
+ src += 2 * os2;
+ }
+
+ gdt_block_unref(t->block);
+
+ t->size2 = ns2;
+ t->tda = ns2;
+ t->block = new_block;
+ t->data = new_block->data;
+
+ string_array_insert(t->headers, j_in, n);
+
+ return 0;
+}
+
+int
+gdt_table_insert_rows(gdt_table *t, int i_in, int n)
+{
+ int n1 = t->size1, n2 = t->size2;
+ int i;
+
+ if (t->block->size < (n1 + n) * n2)
+ {
+ int size_req = (n1 + n) * n2;
+ if (unlikely(size_req <= 0)) return (-1);
+ int new_size = round_two_power(size_req);
+ gdt_block *new_block = gdt_block_new(new_size);
+
+ if (unlikely(new_block == NULL)) return (-1);
+ gdt_block_ref(new_block);
+
+ int * const src = (int *) t->data;
+ int * const dst = (int *) new_block->data;
+
+ for (i = 0; i < 2 * i_in * n2; i++)
+ {
+ dst[i] = src[i];
+ }
+
+ for (/* */; i < 2 * n1 * n2; i++)
+ {
+ dst[i + 2 * n * n2] = src[i];
+ }
+
+ gdt_block_unref(t->block);
+ t->block = new_block;
+ t->data = new_block->data;
+ }
+ else
+ {
+ int * const data = (int *) t->data;
+ for (i = 2 * n1 * n2 - 1; i >= 2 * i_in * n2; i--)
+ {
+ data[i + 2 * n * n2] = data[i];
+ }
+ }
+
+ t->size1 = n1 + n;
+
+ return 0;
+}
+
+gdt_table_cursor *
+gdt_table_get_cursor(gdt_table *t)
+{
+ return t->cursor;
+}
+
+const gdt_element *
+gdt_table_cursor_get(gdt_table_cursor *c, const char *key)
+{
+ gdt_table *t = c->table;
+ int k;
+ if (!t)
+ return NULL;
+ k = string_array_lookup(t->headers, key);
+ if (k < 0)
+ return NULL;
+ return gdt_table_get(t, c->index, k);
+}
diff --git a/gdt/gdt_table.h b/gdt/gdt_table.h
new file mode 100644
index 00000000..55a4880c
--- /dev/null
+++ b/gdt/gdt_table.h
@@ -0,0 +1,75 @@
+#ifndef GDT_TABLE_H
+#define GDT_TABLE_H
+
+#include "defs.h"
+#include "gdt_index.h"
+
+enum {
+ TAG_STRING = 0xffff0000,
+ TAG_UNDEF = 0xfffe0000,
+ TAG_NUMBER = 0xfff80000,
+};
+
+/* NaN encoding is used to discriminate between (double) numbers
+ and strings or undef values.
+ For NaN values "hi" is equal to 0xfff80000 and "lo" is 0.
+ We use values of "hi" higher then 0xfff80000 to tag non-number
+ values. In the case of strings "lo" is used to store the string
+ index. */
+typedef union {
+ double number;
+ struct {
+ unsigned int lo;
+ unsigned int hi;
+ } word;
+} gdt_element;
+
+typedef struct {
+ int size;
+ gdt_element *data;
+ int ref_count;
+} gdt_block;
+
+struct string_array {
+ struct char_buffer buffer[1];
+ int *offset_data;
+ int offset_len;
+};
+
+struct __gdt_table;
+
+typedef struct {
+ int index;
+ struct __gdt_table *table;
+} gdt_table_cursor;
+
+struct __gdt_table {
+ int size1;
+ int size2;
+ int tda;
+ gdt_element *data;
+ gdt_block *block;
+ gdt_index *strings;
+ struct string_array headers[1];
+ gdt_table_cursor cursor[1];
+};
+
+typedef struct __gdt_table gdt_table;
+
+extern gdt_table * gdt_table_new (int nb_rows, int nb_columns, int nb_rows_alloc);
+extern void gdt_table_free (gdt_table *t);
+extern const gdt_element * gdt_table_get (gdt_table *t, int i, int j);
+extern const gdt_element * gdt_table_get_by_name (gdt_table *t, int i, const char* col_name);
+extern const char * gdt_table_element_get_string (gdt_table *t, const gdt_element *e);
+extern void gdt_table_set_number (gdt_table *t, int i, int j, double num);
+extern void gdt_table_set_string (gdt_table *t, int i, int j, const char *s);
+extern void gdt_table_set_undef (gdt_table *t, int i, int j);
+extern const char * gdt_table_get_header (gdt_table *t, int j);
+extern void gdt_table_set_header (gdt_table *t, int j, const char *str);
+extern int gdt_table_header_index (gdt_table *t, const char* col_name);
+extern int gdt_table_insert_columns (gdt_table *t, int j_in, int n);
+extern int gdt_table_insert_rows (gdt_table *t, int i_in, int n);
+extern const gdt_element * gdt_table_cursor_get (gdt_table_cursor *c, const char *key);
+extern gdt_table_cursor * gdt_table_get_cursor (gdt_table *t);
+
+#endif
diff --git a/gdt/xmalloc.h b/gdt/xmalloc.h
new file mode 100644
index 00000000..646473c9
--- /dev/null
+++ b/gdt/xmalloc.h
@@ -0,0 +1,31 @@
+#ifndef GDT_XMALLOC_H
+#define GDT_XMALLOC_H
+
+#include <stdlib.h>
+#include <stdio.h>
+#include "defs.h"
+
+static inline void *xmalloc(size_t sz)
+{
+ void *p = malloc(sz);
+ if (unlikely(p == NULL))
+ {
+ fputs("not enough virtual memory!\n", stderr);
+ abort();
+ }
+ return p;
+}
+
+static inline unsigned int round_two_power(unsigned int n)
+{
+ n = n - 1;
+ n = n | (n >> 1);
+ n = n | (n >> 2);
+ n = n | (n >> 4);
+ n = n | (n >> 8);
+ n = n | (n >> 16);
+ n = n + 1;
+ return n;
+}
+
+#endif
diff --git a/graph-init.lua b/graph-init.lua
index 8c75f4ef..7cc04fcf 100644
--- a/graph-init.lua
+++ b/graph-init.lua
@@ -225,8 +225,12 @@ graph.color = {
}
local bcolors = {'red', 'blue', 'green', 'magenta', 'cyan', 'yellow'}
--- colors from a popular spreadsheet application
-local wcolors = {0x4f81bd, 0xc0504d, 0x9bbb59, 0x695185, 0x3c8da3, 0xcc7b38}
+-- colors from a popular spreadsheet application + random colors from
+-- the web
+local wcolors = {0x4f81bd, 0xc0504d, 0x9bbb59, 0x695185, 0x3c8da3, 0xcc7b38,
+ 0x58c3bb, 0xf29a86, 0xbd87bb, 0xc3a492, 0xf0d845,
+ 0x2d7ac0, 0xfce4ca, 0x8b9068, 0xc0b99d,
+ 0xD9CCB9, 0xDF7782, 0xE95D22, 0x017890, 0x613D2D}
local hue_map = {
{231, 0, 0 },
diff --git a/gsl.lua b/gsl.lua
index a75923ad..b87ae5a8 100644
--- a/gsl.lua
+++ b/gsl.lua
@@ -2395,6 +2395,111 @@ int gsl_sf_eta_int_e(int n, gsl_sf_result * result);
double gsl_sf_eta_int(const int n);
int gsl_sf_eta_e(const double s, gsl_sf_result * result);
double gsl_sf_eta(const double s);
+
+typedef struct {
+ size_t n ;
+ double * range ;
+ double * bin ;
+} gsl_histogram ;
+
+typedef struct {
+ size_t n ;
+ double * range ;
+ double * sum ;
+} gsl_histogram_pdf ;
+
+gsl_histogram * gsl_histogram_alloc (size_t n);
+
+gsl_histogram * gsl_histogram_calloc (size_t n);
+gsl_histogram * gsl_histogram_calloc_uniform (const size_t n, const double xmin, const double xmax);
+void gsl_histogram_free (gsl_histogram * h);
+int gsl_histogram_increment (gsl_histogram * h, double x);
+int gsl_histogram_accumulate (gsl_histogram * h, double x, double weight);
+int gsl_histogram_find (const gsl_histogram * h,
+ const double x, size_t * i);
+
+double gsl_histogram_get (const gsl_histogram * h, size_t i);
+int gsl_histogram_get_range (const gsl_histogram * h, size_t i,
+ double * lower, double * upper);
+
+double gsl_histogram_max (const gsl_histogram * h);
+double gsl_histogram_min (const gsl_histogram * h);
+size_t gsl_histogram_bins (const gsl_histogram * h);
+
+void gsl_histogram_reset (gsl_histogram * h);
+
+gsl_histogram * gsl_histogram_calloc_range(size_t n, double * range);
+
+int
+gsl_histogram_set_ranges (gsl_histogram * h, const double range[], size_t size);
+int
+gsl_histogram_set_ranges_uniform (gsl_histogram * h, double xmin, double xmax);
+
+
+
+int
+gsl_histogram_memcpy(gsl_histogram * dest, const gsl_histogram * source);
+
+gsl_histogram *
+gsl_histogram_clone(const gsl_histogram * source);
+
+double gsl_histogram_max_val (const gsl_histogram * h);
+
+size_t gsl_histogram_max_bin (const gsl_histogram * h);
+
+double gsl_histogram_min_val (const gsl_histogram * h);
+
+size_t gsl_histogram_min_bin (const gsl_histogram * h);
+
+int
+gsl_histogram_equal_bins_p(const gsl_histogram *h1, const gsl_histogram *h2);
+
+int
+gsl_histogram_add(gsl_histogram *h1, const gsl_histogram *h2);
+
+int
+gsl_histogram_sub(gsl_histogram *h1, const gsl_histogram *h2);
+
+int
+gsl_histogram_mul(gsl_histogram *h1, const gsl_histogram *h2);
+
+int
+gsl_histogram_div(gsl_histogram *h1, const gsl_histogram *h2);
+
+int
+gsl_histogram_scale(gsl_histogram *h, double scale);
+
+int
+gsl_histogram_shift (gsl_histogram * h, double shift);
+
+
+double gsl_histogram_sigma (const gsl_histogram * h);
+
+double gsl_histogram_mean (const gsl_histogram * h);
+
+double gsl_histogram_sum (const gsl_histogram * h);
+
+int gsl_histogram_fwrite (FILE * stream, const gsl_histogram * h) ;
+int gsl_histogram_fread (FILE * stream, gsl_histogram * h);
+int gsl_histogram_fprintf (FILE * stream, const gsl_histogram * h,
+ const char * range_format, const char * bin_format);
+int gsl_histogram_fscanf (FILE * stream, gsl_histogram * h);
+
+gsl_histogram_pdf * gsl_histogram_pdf_alloc (const size_t n);
+int gsl_histogram_pdf_init (gsl_histogram_pdf * p, const gsl_histogram * h);
+void gsl_histogram_pdf_free (gsl_histogram_pdf * p);
+double gsl_histogram_pdf_sample (const gsl_histogram_pdf * p, double r);
+
+double gsl_stats_mean (const double data[], const size_t stride, const size_t n);
+double gsl_stats_variance (const double data[], const size_t stride, const size_t n);
+double gsl_stats_sd (const double data[], const size_t stride, const size_t n);
+double gsl_stats_variance_with_fixed_mean (const double data[], const size_t stride, const size_t n, const double mean);
+double gsl_stats_sd_with_fixed_mean (const double data[], const size_t stride, const size_t n, const double mean);
+double gsl_stats_tss (const double data[], const size_t stride, const size_t n);
+double gsl_stats_tss_m (const double data[], const size_t stride, const size_t n, const double mean);
+
+double gsl_stats_median_from_sorted_data (const double sorted_data[], const size_t stride, const size_t n) ;
+double gsl_stats_quantile_from_sorted_data (const double sorted_data[], const size_t stride, const size_t n, const double f) ;
]]
diff --git a/gslext.lua b/gslext.lua
index 48fe2c94..1f883390 100644
--- a/gslext.lua
+++ b/gslext.lua
@@ -15,6 +15,11 @@ require('contour')
require('sf')
require('help')
require('vegas')
+require('gdt')
+require('gdt-parse-csv')
+require('gdt-hist')
+require('gdt-plot')
+require('gdt-lm')
num.linfit = require 'linfit'
num.bspline = require 'bspline'
diff --git a/lm-expr.lua b/lm-expr.lua
new file mode 100644
index 00000000..3c59d7c3
--- /dev/null
+++ b/lm-expr.lua
@@ -0,0 +1,26 @@
+local format = string.format
+
+local function as_char(v, prio)
+ if type(v) == 'table' and v.name then
+ return (v.prio < prio and format("(%s)", v.name) or v.name)
+ end
+ return tostring(v)
+end
+
+local var_name
+
+local var_name_mt = {
+ __add = function(a, b) return var_name(format("%s + %s", as_char(a, 0), as_char(b, 0)), 0) end,
+ __mul = function(a, b) return var_name(format("%s * %s", as_char(a, 2), as_char(b, 2)), 2) end,
+ __sub = function(a, b) return var_name(format("%s - %s", as_char(a, 0), as_char(b, 0)), 0) end,
+ __div = function(a, b) return var_name(format("%s / %s", as_char(a, 2), as_char(b, 2)), 2) end,
+ __pow = function(a, b) return var_name(format("%s^%s", as_char(a, 10), as_char(b, 10)), 10) end,
+ __unm = function(a) return var_name(format("-%s", as_char(a, 1)), 1) end,
+}
+
+var_name = function (name, prio)
+ local t = {prio= prio or 10, name= name}
+ return setmetatable(t, var_name_mt)
+end
+
+return var_name
diff --git a/lm-helpers.lua b/lm-helpers.lua
new file mode 100644
index 00000000..098971fa
--- /dev/null
+++ b/lm-helpers.lua
@@ -0,0 +1,65 @@
+local LM = {}
+
+local var_name = require 'lm-expr'
+
+local factor_mt
+
+local function mul_factor(a, b)
+ local c = {value= a.value .. ":" .. b.value}
+ return setmetatable(c, factor_mt)
+end
+
+factor_mt = {
+ __mul = mul_factor,
+}
+
+function LM.factor(name)
+ local t = {name= name, value = ""}
+ return setmetatable(t, factor_mt)
+end
+
+function LM.eval_test(...)
+ local inf = {np = select('#', ...)}
+ inf.class = {}
+ for k= 1, inf.np do
+ local v = select(k, ...)
+ inf.class[k] = (type(v) == 'number' and 1 or 0)
+ end
+ return inf
+end
+
+function LM.eval_func(inf, pt, i, ...)
+ for k = 1, inf.np do
+ local x = select(k, ...)
+ local value = (inf.class[k] == 1 and x or x.value)
+ gdt.set(pt, i, k, value)
+ end
+end
+
+LM.var_name = var_name
+
+local function expr_to_name(expr)
+ if type(expr) == 'table' then
+ return expr.name
+ else
+ local base = '(average)'
+ local minus = expr < 0 and '- ' or ''
+ if expr == 1 or expr == -1 then
+ return string.format("%s%s", minus, base)
+ else
+ return string.format("%s%s / %g", minus, base, math.abs(expr))
+ end
+ end
+end
+
+function LM.find_names(...)
+ local n = select("#", ...)
+ local names = {}
+ for k = 1, n do
+ local expr = select(k, ...)
+ names[k] = expr_to_name(expr)
+ end
+ return names
+end
+
+return LM
diff --git a/lua-gsl/lua-gsl.c b/lua-gsl/lua-gsl.c
index 004dba16..7243295e 100644
--- a/lua-gsl/lua-gsl.c
+++ b/lua-gsl/lua-gsl.c
@@ -29,6 +29,13 @@
#include "lua-utils.h"
#include "fatal.h"
+#include "gdt/gdt_table.h"
+
+/* used to force the linker to link the gdt library. Otherwise it
+ * would be discarded as there are no other references to its functions. */
+extern gdt_table *(*_gdt_ref)(int nb_rows, int nb_columns, int nb_rows_alloc);
+gdt_table *(*_gdt_ref)(int nb_rows, int nb_columns, int nb_rows_alloc) = gdt_table_new;
+
struct gsl_shell_state* global_state;
void
diff --git a/makedefs b/makedefs
index d50461c7..d27a5dbf 100644
--- a/makedefs
+++ b/makedefs
@@ -57,10 +57,14 @@ LIBS += -lsupc++
ifeq ($(HOST_SYS),Windows)
DEFS += -DWIN32
EXE_EXT = .exe
+ DLL_EXT = .dll
+ LDFLAGS += -Wl,--export-all-symbols
else
EXE_EXT =
+ DLL_EXT = .so
DEFS += -pthread
LIBS += -pthread
+ LDFLAGS += -Wl,-E
endif
ifeq ($(strip $(DEBUG)), yes)
diff --git a/matrix-quicksort.lua b/matrix-quicksort.lua
new file mode 100644
index 00000000..111973ad
--- /dev/null
+++ b/matrix-quicksort.lua
@@ -0,0 +1,31 @@
+
+local function quicksort_array(m, f)
+ local t = m.data
+
+ local function quicksort(start, endi)
+ if start >= endi then return end
+ local pivot = start
+ for i = start + 1, endi do
+ if f(t[i], t[pivot]) then
+ local temp = t[pivot + 1]
+ t[pivot + 1] = t[pivot]
+ if(i == pivot + 1) then
+ t[pivot] = temp
+ else
+ t[pivot] = t[i]
+ t[i] = temp
+ end
+ pivot = pivot + 1
+ end
+ end
+
+ quicksort(start, pivot - 1)
+ quicksort(pivot + 1, endi)
+ end
+
+ local n, ncols = m:dim()
+ assert(ncols == 1, "expecting column matrix")
+ quicksort(0, n - 1)
+end
+
+return quicksort_array
diff --git a/matrix.lua b/matrix.lua
index b911812b..5e5e3c8f 100644
--- a/matrix.lua
+++ b/matrix.lua
@@ -522,7 +522,7 @@ local function matrix_complex_unm(a)
return m
end
-local function matrix_norm(m)
+local function matrix_norm2(m)
local r, c = matrix_dim(m)
local tda = m.tda
local ssq, idx = 0, 0
@@ -533,10 +533,14 @@ local function matrix_norm(m)
end
idx = idx + tda
end
- return sqrt(ssq)
+ return ssq
end
-local function matrix_complex_norm(m)
+local function matrix_norm(m)
+ return sqrt(matrix_norm2(m))
+end
+
+local function matrix_complex_norm2(m)
local r, c = matrix_dim(m)
local tda = m.tda
local ssq, idx = 0, 0
@@ -547,7 +551,11 @@ local function matrix_complex_norm(m)
end
idx = idx + 2*tda
end
- return sqrt(ssq)
+ return ssq
+end
+
+local function matrix_complex_norm(m)
+ return sqrt(matrix_complex_norm2(m))
end
complex = {
@@ -556,6 +564,7 @@ complex = {
real = complex_real,
imag = complex_imag,
abs = complex_abs,
+ norm = complex_abs,
norm2 = complex_norm2,
rect = cartesian,
i = 1i,
@@ -675,7 +684,9 @@ local matrix_methods = {
set = matrix_set,
copy = matrix_copy,
norm = matrix_norm,
+ norm2 = matrix_norm2,
slice = matrix_slice,
+ sort = require("matrix-quicksort"),
show = matrix_display_gen(mat_real_get),
}
@@ -740,6 +751,7 @@ local matrix_complex_methods = {
set = matrix_complex_set,
copy = matrix_complex_copy,
norm = matrix_complex_norm,
+ norm2 = matrix_complex_norm2,
slice = matrix_complex_slice,
show = matrix_display_gen(mat_complex_get),
}
diff --git a/monomial.lua b/monomial.lua
new file mode 100644
index 00000000..d6ef769d
--- /dev/null
+++ b/monomial.lua
@@ -0,0 +1,92 @@
+local function monomial_len(a)
+ return (#a - 1) / 2
+end
+
+local function mon_terms_iter(a, k)
+ k = k + 1
+ if 2*k + 1 <= #a then
+ return k, a[2*k], a[2*k+1]
+ end
+end
+
+local function mon_terms(a)
+ return mon_terms_iter, a, 0
+end
+
+local function mon_symbol(sym)
+ return {1, sym, 1}
+end
+
+local function monomial_set_term_pow(a, k, new_pow)
+ a[2*k+1] = new_pow
+end
+
+local function monomial_insert_term(a, k, sym, pow)
+ local n = monomial_len(a)
+ for k= n, k, -1 do
+ a[2*k+2] = a[2*k ]
+ a[2*k+3] = a[2*k+1]
+ end
+ a[2*k ] = sym
+ a[2*k + 1] = pow
+end
+
+local function monomial_mult_factor(a, sym, pow)
+ for k, a_sym, a_pow in mon_terms(a) do
+ if a_sym == sym then
+ monomial_set_term_pow(a, k, a_pow + pow)
+ return
+ end
+ if a_sym > sym then
+ monomial_insert_term(a, k, sym, pow)
+ return
+ end
+ end
+ local n = monomial_len(a)
+ monomial_insert_term(a, n + 1, sym, pow)
+end
+
+local function monomial_mult(a, b)
+ a[1] = a[1] * b[1]
+ for k, sym, pow in mon_terms(b) do
+ monomial_mult_factor(a, sym, pow)
+ end
+end
+
+local function monomial_power(m, n)
+ m[1] = m[1]^n
+ for k, sym, pow in mon_terms(m) do
+ monomial_set_term_pow(m, k, pow * n)
+ end
+end
+
+local function monomial_equal(a, b)
+ if a[1] ~= b[1] or #a ~= #b then return false end
+ for k, asym, apow in mon_terms(a) do
+ bsym, bpow = b[2*k], b[2*k+1]
+ if bsym ~= asym or bpow ~= apow then return false end
+ end
+ return true
+end
+
+local function combine_rec(a, k)
+ local n = monomial_len(a)
+ if k > n then return {{1}} end
+ local sym, pow = a[2*k], a[2*k+1]
+ local rls = combine_rec(a, k + 1)
+ local ls = {}
+ for p = 0, pow do
+ for _, mon in ipairs(rls) do
+ local xt = p > 0 and {1, sym, p} or {1}
+ monomial_mult(xt, mon)
+ ls[#ls+1] = xt
+ end
+ end
+ return ls
+end
+
+local function monomial_combine(a)
+ return combine_rec(a, 1)
+end
+
+return {symbol=mon_symbol, mult= monomial_mult, power=monomial_power, combine= monomial_combine, terms= mon_terms, equal=monomial_equal}
diff --git a/sigeb-doe-mbir.csv b/sigeb-doe-mbir.csv
new file mode 100644
index 00000000..94195d29
--- /dev/null
+++ b/sigeb-doe-mbir.csv
@@ -0,0 +1,307 @@
+site,wafer,time_dep,geh4,b2h6,XCoord,YCoord,GAMMA,THICK_SIGE,CONC_BORE,DOSE_BORE,sigeb_th,sigeb_conc,dose,SiGe25p free carriers gamma,SiGe25p free carriers doping,model_quality
+1,1,350,690,125,0,-0.001,1160.9441,101.6132,116.0944,11.7967,101.6132,116.0944,11.7967,1160.9441,257.0574,0.0123
+2,1,350,690,125,73.999,-14.8,1139.2299,128.2958,113.923,14.6158,128.2958,113.923,14.6158,1139.2299,198.4226,0.0129
+3,1,350,690,125,29.6,-74.001,1132.6603,110.6792,113.266,12.5362,110.6792,113.266,12.5362,1132.6603,227.417,0.0124
+4,1,350,690,125,-44.401,-59.199,1167.0649,114.8651,116.7065,13.4055,114.8651,116.7065,13.4055,1167.0649,225.321,0.0159
+5,1,350,690,125,-74.001,14.801,1154.0609,81.1815,115.4061,9.3688,81.1815,115.4061,9.3688,1154.0609,316.6042,0.012
+6,1,350,690,125,-29.599,74,1170.0858,116.0159,117.0086,13.5749,116.0159,117.0086,13.5749,1170.0858,223.2926,0.0151
+7,1,350,690,125,44.399,59.2,1195.4558,190.9536,119.5456,22.8277,190.9536,119.5456,22.8277,1195.4558,136.2262,0.0202
+8,1,350,690,125,118.4,-0.001,1213.585,132.6457,121.3585,16.0977,132.6457,121.3585,16.0977,1213.585,193.294,0.0186
+9,1,350,690,125,103.599,-74.001,1209.037,148.0181,120.9037,17.8959,148.0181,120.9037,17.8959,1209.037,168.344,0.0174
+10,1,350,690,125,44.398,-118.4,1203.9659,121.269,120.3966,14.6004,121.269,120.3966,14.6004,1203.9659,205.7172,0.0172
+11,1,350,690,125,-44.4,-118.4,1196.0825,148.2113,119.6083,17.7273,148.2113,119.6083,17.7273,1196.0825,166.7153,0.0159
+12,1,350,690,125,-103.6,-74,1228.8953,116.6782,122.8895,14.3385,116.6782,122.8895,14.3385,1228.8953,215.4175,0.0179
+13,1,350,690,125,-118.4,0,1225.613,132.3679,122.5613,16.2232,132.3679,122.5613,16.2232,1225.613,191.7461,0.0191
+14,1,350,690,125,-103.599,74,1191.651,134.1236,119.1651,15.9828,134.1236,119.1651,15.9828,1191.651,188.5197,0.0178
+15,1,350,690,125,-44.4,118.4,1182.6534,100.4732,118.2654,11.8825,100.4732,118.2654,11.8825,1182.6534,250.8498,0.0122
+16,1,350,690,125,44.399,118.4,1158.233,100.0726,115.8233,11.5907,100.0726,115.8233,11.5907,1158.233,254.0417,0.0136
+17,1,350,690,125,103.601,74,1191.0448,108.2786,119.1045,12.8965,108.2786,119.1045,12.8965,1191.0448,235.8914,0.0176
+1,2,425,560,125,0,-0.001,1340.9701,110.7836,134.097,14.8558,110.7836,134.097,14.8558,1340.9701,218.9478,0.0103
+2,2,425,560,125,74,-14.8,1352.7814,147.5634,135.2781,19.9621,147.5634,135.2781,19.9621,1352.7814,159.3164,0.0146
+3,2,425,560,125,29.6,-74.001,1398.4663,142.6645,139.8466,19.9512,142.6645,139.8466,19.9512,1398.4663,166.1914,0.0146
+4,2,425,560,125,-44.4,-59.198,1395.6664,129.766,139.5666,18.111,129.766,139.5666,18.111,1395.6664,182.9004,0.0153
+5,2,425,560,125,-74.001,14.801,1427.3025,113.0309,142.7303,16.1329,113.0309,142.7303,16.1329,1427.3025,215.4577,0.0135
+6,2,425,560,125,-29.599,74,1404.3782,125.8235,140.4378,17.6704,125.8235,140.4378,17.6704,1404.3782,191.9325,0.0128
+7,2,425,560,125,44.4,59.2,1320.8767,116.027,132.0877,15.3257,116.027,132.0877,15.3257,1320.8767,203.3011,0.0104
+8,2,425,560,125,118.401,-0.001,1442.5963,129.9383,144.2596,18.7449,129.9383,144.2596,18.7449,1442.5963,183.4069,0.0162
+9,2,425,560,125,103.601,-74.002,1403.6919,137.4036,140.3692,19.2872,137.4036,140.3692,19.2872,1403.6919,166.8992,0.0159
+10,2,425,560,125,44.399,-118.4,1419.2523,131.4971,141.9252,18.6628,131.4971,141.9252,18.6628,1419.2523,174.9044,0.0167
+11,2,425,560,125,-44.402,-118.4,1351.7634,126.853,135.1763,17.1475,126.853,135.1763,17.1475,1351.7634,175.2173,0.0131
+12,2,425,560,125,-103.6,-74,1420.8838,124.3073,142.0884,17.6626,124.3073,142.0884,17.6626,1420.8838,188.0764,0.0165
+13,2,425,560,125,-118.4,0.001,1392.4772,135.8725,139.2477,18.9199,135.8725,139.2477,18.9199,1392.4772,171.6227,0.0169
+14,2,425,560,125,-103.6,73.999,1360.2761,124.28,136.0276,16.9055,124.28,136.0276,16.9055,1360.2761,187.439,0.0162
+15,2,425,560,125,-44.4,118.4,1401.3322,139.4659,140.1332,19.5438,139.4659,140.1332,19.5438,1401.3322,169.9649,0.0164
+16,2,425,560,125,44.4,118.4,1391.1602,126.1553,139.116,17.5502,126.1553,139.116,17.5502,1391.1602,186.5518,0.015
+17,2,425,560,125,103.601,74,1410.959,120.8274,141.0959,17.0483,120.8274,141.0959,17.0483,1410.959,193.4996,0.0111
+1,3,500,690,125,-0.001,-0.001,1098.6635,148.778,109.8663,16.3457,148.778,109.8663,16.3457,1098.6635,257.4893,0.0095
+2,3,500,690,125,73.999,-14.8,1050.8905,134.9192,105.0891,14.1785,134.9192,105.0891,14.1785,1050.8905,273.244,0.007
+3,3,500,690,125,29.601,-74.002,1095.5502,139.4366,109.555,15.276,139.4366,109.555,15.276,1095.5502,265.6098,0.0086
+4,3,500,690,125,-44.4,-59.198,1078.2655,132.1626,107.8265,14.2506,132.1626,107.8265,14.2506,1078.2655,281.2629,0.0087
+5,3,500,690,125,-74.002,14.801,1125.2391,147.1914,112.5239,16.5626,147.1914,112.5239,16.5626,1125.2391,259.057,0.0101
+6,3,500,690,125,-29.599,74,1111.0837,158.5089,111.1084,17.6117,158.5089,111.1084,17.6117,1111.0837,239.5477,0.01
+7,3,500,690,125,44.401,59.2,1118.9916,151.8772,111.8992,16.9949,151.8772,111.8992,16.9949,1118.9916,250.988,0.0093
+8,3,500,690,125,118.401,-0.001,1126.8556,147.3221,112.6856,16.6011,147.3221,112.6856,16.6011,1126.8556,249.9522,0.0113
+9,3,500,690,125,103.6,-74.001,1100.6057,131.7269,110.0606,14.4979,131.7269,110.0606,14.4979,1100.6057,270.5363,0.0082
+10,3,500,690,125,44.398,-118.401,1138.3494,167.6986,113.8349,19.09,167.6986,113.8349,19.09,1138.3494,215.0619,0.0123
+11,3,500,690,125,-44.401,-118.4,1075.0031,144.5505,107.5003,15.5392,144.5505,107.5003,15.5392,1075.0031,248.1641,0.0097
+12,3,500,690,125,-103.601,-73.999,1123.7715,137.0708,112.3772,15.4036,137.0708,112.3772,15.4036,1123.7715,266.8614,0.0104
+13,3,500,690,125,-118.401,0,1102.6298,133.2532,110.263,14.6929,133.2532,110.263,14.6929,1102.6298,276.3846,0.0094
+14,3,500,690,125,-103.601,73.999,1103.1072,195.6354,110.3107,21.5807,195.6354,110.3107,21.5807,1103.1072,189.041,0.0117
+15,3,500,690,125,-44.4,118.4,1091.3899,128.5676,109.139,14.0317,128.5676,109.139,14.0317,1091.3899,288.2108,0.0078
+16,3,500,690,125,44.4,118.4,1104.0432,154.7197,110.4043,17.0817,154.7197,110.4043,17.0817,1104.0432,238.2348,0.0104
+17,3,500,690,125,103.601,74,1133.6483,147.5149,113.3648,16.723,147.5149,113.3648,16.723,1133.6483,248.7319,0.0118
+1,4,425,820,125,-0.001,0,959.3732,147.3553,95.9373,14.1369,147.3553,95.9373,14.1369,959.3732,288.3061,0.0076
+2,4,425,820,125,74,-14.8,930.3077,151.7954,93.0308,14.1216,151.7954,93.0308,14.1216,930.3077,272.4224,0.0064
+3,4,425,820,125,29.599,-74.001,945.3029,140.1995,94.5303,13.2531,140.1995,94.5303,13.2531,945.3029,294.1247,0.0058
+4,4,425,820,125,-44.402,-59.199,946.8767,134.2821,94.6877,12.7149,134.2821,94.6877,12.7149,946.8767,307.701,0.0059
+5,4,425,820,125,-74.002,14.801,982.3398,153.8791,98.234,15.1162,153.8791,98.234,15.1162,982.3398,274.8448,0.0086
+6,4,425,820,125,-29.598,74,954.0851,152.0713,95.4085,14.5089,152.0713,95.4085,14.5089,954.0851,276.77,0.0078
+7,4,425,820,125,44.401,59.2,953.4825,146.4125,95.3483,13.9602,146.4125,95.3483,13.9602,953.4825,288.373,0.0074
+8,4,425,820,125,118.4,-0.001,957.3687,126.3103,95.7369,12.0925,126.3103,95.7369,12.0925,957.3687,320.8157,0.0074
+9,4,425,820,125,103.599,-74.002,974.9827,150.7522,97.4983,14.6981,150.7522,97.4983,14.6981,974.9827,263.0969,0.0081
+10,4,425,820,125,44.398,-118.399,945.7808,119.4648,94.5781,11.2988,119.4648,94.5781,11.2988,945.7808,330.1664,0.0059
+11,4,425,820,125,-44.401,-118.4,956.6352,160.8106,95.6635,15.3837,160.8106,95.6635,15.3837,956.6352,246.8589,0.0086
+12,4,425,820,125,-103.601,-74.001,984.6396,170.9414,98.464,16.8316,170.9414,98.464,16.8316,984.6396,237.2368,0.0095
+13,4,425,820,125,-118.401,0,978.1149,166.0597,97.8115,16.2425,166.0597,97.8115,16.2425,978.1149,246.8126,0.009
+14,4,425,820,125,-103.601,74,939.1465,131.7551,93.9146,12.3737,131.7551,93.9146,12.3737,939.1465,307.3555,0.0067
+15,4,425,820,125,-44.401,118.4,966.8745,159.8504,96.6875,15.4555,159.8504,96.6875,15.4555,966.8745,256.696,0.0087
+16,4,425,820,125,44.4,118.4,952.5738,137.4299,95.2574,13.0912,137.4299,95.2574,13.0912,952.5738,295.1786,0.0074
+17,4,425,820,125,103.602,73.999,963.6486,131.8012,96.3649,12.701,131.8012,96.3649,12.701,963.6486,306.505,0.008
+1,5,350,560,150,0,-0.001,1522.4639,121.9129,152.2464,18.5608,121.9129,152.2464,18.5608,1522.4639,226.2355,0.0094
+2,5,350,560,150,74,-14.8,1441.3958,119.4457,144.1396,17.2169,119.4457,144.1396,17.2169,1441.3958,219.6275,0.0098
+3,5,350,560,150,29.6,-74.001,1432.8378,97.5556,143.2838,13.9781,97.5556,143.2838,13.9781,1432.8378,265.9988,0.0087
+4,5,350,560,150,-44.402,-59.199,1440.3071,95.9859,144.0307,13.8249,95.9859,144.0307,13.8249,1440.3071,269.2918,0.0084
+5,5,350,560,150,-74.002,14.801,1533.3241,99.9684,153.3324,15.3284,99.9684,153.3324,15.3284,1533.3241,270.5641,0.0094
+6,5,350,560,150,-29.599,74,1489.0645,106.0987,148.9064,15.7988,106.0987,148.9064,15.7988,1489.0645,251.6372,0.0083
+7,5,350,560,150,44.4,59.2,1529.0575,117.6483,152.9057,17.9891,117.6483,152.9057,17.9891,1529.0575,233.5129,0.0127
+8,5,350,560,150,118.4,-0.001,1546.8643,126.3409,154.6864,19.5432,126.3409,154.6864,19.5432,1546.8643,210.2897,0.0133
+9,5,350,560,150,103.599,-74.001,1424.3513,99.3836,142.4351,14.1557,99.3836,142.4351,14.1557,1424.3513,250.6941,0.01
+10,5,350,560,150,44.399,-118.4,1508.7517,120.5587,150.8752,18.1893,120.5587,150.8752,18.1893,1508.7517,213.4964,0.0132
+11,5,350,560,150,-44.4,-118.4,1420.1658,110.0666,142.0166,15.6313,110.0666,142.0166,15.6313,1420.1658,224.7218,0.0097
+12,5,350,560,150,-103.6,-74.001,1469.0427,92.9494,146.9043,13.6547,92.9494,146.9043,13.6547,1469.0427,274.7619,0.0115
+13,5,350,560,150,-118.4,0,1537.1573,116.595,153.7157,17.9225,116.595,153.7157,17.9225,1537.1573,224.078,0.0108
+14,5,350,560,150,-103.6,74,1425.4626,101.3291,142.5463,14.4441,101.3291,142.5463,14.4441,1425.4626,252.0004,0.0094
+15,5,350,560,150,-44.4,118.4,1481.8595,115.075,148.1859,17.0525,115.075,148.1859,17.0525,1481.8595,228.1937,0.0111
+16,5,350,560,150,44.4,118.4,1496.2394,127.9479,149.6239,19.1441,127.9479,149.6239,19.1441,1496.2394,203.3417,0.0118
+17,5,350,560,150,103.602,73.998,1455.1559,86.3596,145.5156,12.5667,86.3596,145.5156,12.5667,1455.1559,298.9005,0.0096
+1,6,350,820,150,0,0,1040.9357,134.3012,104.0936,13.9799,134.3012,104.0936,13.9799,1040.9357,316.8077,0.0084
+2,6,350,820,150,74,-14.801,1011.8945,134.42,101.1894,13.6019,134.42,101.1894,13.6019,1011.8945,307.2251,0.0064
+3,6,350,820,150,29.601,-74,1037.3596,132.181,103.736,13.7119,132.181,103.736,13.7119,1037.3596,314.3874,0.0072
+4,6,350,820,150,-44.401,-59.199,1056.7278,148.2117,105.6728,15.6619,148.2117,105.6728,15.6619,1056.7278,282.0483,0.0087
+5,6,350,820,150,-74.002,14.801,1074.7209,163.7163,107.4721,17.5949,163.7163,107.4721,17.5949,1074.7209,259.131,0.0105
+6,6,350,820,150,-29.599,74,1027.4191,131.5946,102.7419,13.5203,131.5946,102.7419,13.5203,1027.4191,319.5789,0.0078
+7,6,350,820,150,44.401,59.2,1048.8521,141.1099,104.8852,14.8003,141.1099,104.8852,14.8003,1048.8521,299.573,0.0084
+8,6,350,820,150,118.4,0,1029.912,117.5913,102.9912,12.1109,117.5913,102.9912,12.1109,1029.912,345.8013,0.0082
+9,6,350,820,150,103.599,-74.001,1023.3384,123.7673,102.3338,12.6656,123.7673,102.3338,12.6656,1023.3384,322.0461,0.008
+10,6,350,820,150,44.399,-118.401,1036.6729,127.8704,103.6673,13.256,127.8704,103.6673,13.256,1036.6729,311.967,0.0089
+11,6,350,820,150,-44.4,-118.4,1026.6694,135.5508,102.6669,13.9166,135.5508,102.6669,13.9166,1026.6694,293.6286,0.008
+12,6,350,820,150,-103.601,-74,1044.5675,135.6537,104.4567,14.1699,135.6537,104.4567,14.1699,1044.5675,299.7883,0.0096
+13,6,350,820,150,-118.4,0.001,1016.7437,116.7579,101.6744,11.8713,116.7579,101.6744,11.8713,1016.7437,347.7873,0.0073
+14,6,350,820,150,-103.598,74.001,1043.826,139.3021,104.3826,14.5407,139.3021,104.3826,14.5407,1043.826,292.2158,0.0077
+15,6,350,820,150,-44.4,118.4,1042.925,141.859,104.2925,14.7948,141.859,104.2925,14.7948,1042.925,290.3291,0.0095
+16,6,350,820,150,44.401,118.4,1032.2683,132.91,103.2268,13.7199,132.91,103.2268,13.7199,1032.2683,306.5731,0.0081
+17,6,350,820,150,103.601,74,1072.3485,156.039,107.2349,16.7328,156.039,107.2349,16.7328,1072.3485,261.7688,0.0106
+1,7,425,690,150,0,-0.001,1139.9686,123.1208,113.9969,14.0354,123.1208,113.9969,14.0354,1139.9686,333.6,0.0064
+2,7,425,690,150,74,-14.8,1134.7286,143.0049,113.4729,16.2272,143.0049,113.4729,16.2272,1134.7286,279.5648,0.0071
+3,7,425,690,150,29.6,-74.001,1118.854,124.5106,111.8854,13.9309,124.5106,111.8854,13.9309,1118.854,317.8181,0.0059
+4,7,425,690,150,-44.402,-59.199,1177.7003,172.041,117.77,20.2613,172.041,117.77,20.2613,1177.7003,234.195,0.009
+5,7,425,690,150,-74.001,14.802,1148.4651,119.9049,114.8465,13.7707,119.9049,114.8465,13.7707,1148.4651,340.2529,0.0068
+6,7,425,690,150,-29.6,73.999,1167.1372,144.0397,116.7137,16.8114,144.0397,116.7137,16.8114,1167.1372,284.5324,0.0073
+7,7,425,690,150,44.4,59.2,1156.9921,128.1438,115.6992,14.8261,128.1438,115.6992,14.8261,1156.9921,319.0108,0.0073
+8,7,425,690,150,118.4,-0.002,1176.5168,147.7013,117.6517,17.3773,147.7013,117.6517,17.3773,1176.5168,267.9968,0.0094
+9,7,425,690,150,103.599,-74.001,1155.1473,136.2332,115.5147,15.7369,136.2332,115.5147,15.7369,1155.1473,282.0941,0.0085
+10,7,425,690,150,44.398,-118.402,1161.446,135.3569,116.1446,15.721,135.3569,116.1446,15.721,1161.446,285.5377,0.0095
+11,7,425,690,150,-44.401,-118.4,1150.6721,151.5359,115.0672,17.4368,151.5359,115.0672,17.4368,1150.6721,252.7599,0.0089
+12,7,425,690,150,-103.601,-74,1134.3208,115.6318,113.4321,13.1164,115.6318,113.4321,13.1164,1134.3208,336.1958,0.0074
+13,7,425,690,150,-118.4,0.001,1146.0645,126.7663,114.6064,14.5282,126.7663,114.6064,14.5282,1146.0645,312.782,0.0081
+14,7,425,690,150,-103.599,74,1161.9893,173.0368,116.1989,20.1067,173.0368,116.1989,20.1067,1161.9893,230.2462,0.0094
+15,7,425,690,150,-44.4,118.4,1123.3571,117.7319,112.3357,13.2255,117.7319,112.3357,13.2255,1123.3571,338.3218,0.0064
+16,7,425,690,150,44.401,118.4,1160.8114,148.623,116.0811,17.2523,148.623,116.0811,17.2523,1160.8114,268.2859,0.0086
+17,7,425,690,150,103.601,74,1118.2275,108.3438,111.8227,12.1153,108.3438,111.8227,12.1153,1118.2275,359.3965,0.006
+1,8,425,690,150,0,-0.001,1157.6516,131.3165,115.7652,15.2019,131.3165,115.7652,15.2019,1157.6516,314.8207,0.006
+2,8,425,690,150,74,-14.801,1107.1106,134.9486,110.7111,14.9403,134.9486,110.7111,14.9403,1107.1106,294.2646,0.006
+3,8,425,690,150,29.599,-74.001,1135.3351,128.832,113.5335,14.6267,128.832,113.5335,14.6267,1135.3351,309.9772,0.0067
+4,8,425,690,150,-44.4,-59.199,1120.0377,118.227,112.0038,13.2419,118.227,112.0038,13.2419,1120.0377,338.45,0.0058
+5,8,425,690,150,-74.002,14.801,1179.2781,149.6723,117.9278,17.6505,149.6723,117.9278,17.6505,1179.2781,275.618,0.0092
+6,8,425,690,150,-29.598,74,1119.655,125.3812,111.9655,14.0384,125.3812,111.9655,14.0384,1119.655,323.7866,0.0063
+7,8,425,690,150,44.4,59.2,1155.7062,133.2421,115.5706,15.3989,133.2421,115.5706,15.3989,1155.7062,308.0564,0.0072
+8,8,425,690,150,118.4,-0.002,1154.4113,121.1354,115.4411,13.984,121.1354,115.4411,13.984,1154.4113,325.6235,0.0076
+9,8,425,690,150,103.601,-74.002,1151.8226,139.1282,115.1823,16.0251,139.1282,115.1823,16.0251,1151.8226,276.7519,0.0083
+10,8,425,690,150,44.399,-118.4,1117.2654,118.6821,111.7265,13.2599,118.6821,111.7265,13.2599,1117.2654,323.0569,0.0071
+11,8,425,690,150,-44.4,-118.4,1087.4218,128.832,108.7422,14.0095,128.832,108.7422,14.0095,1087.4218,295.9807,0.0056
+12,8,425,690,150,-103.6,-74,1162.0498,131.9962,116.205,15.3386,131.9962,116.205,15.3386,1162.0498,297.6368,0.0079
+13,8,425,690,150,-118.4,0,1150.3326,138.4217,115.0333,15.9231,138.4217,115.0333,15.9231,1150.3326,287.6591,0.0073
+14,8,425,690,150,-103.599,74,1129.1129,133.5416,112.9113,15.0784,133.5416,112.9113,15.0784,1129.1129,297.6233,0.007
+15,8,425,690,150,-44.4,118.4,1133.5565,131.5212,113.3557,14.9087,131.5212,113.3557,14.9087,1133.5565,303.6555,0.0073
+16,8,425,690,150,44.401,118.4,1126.9139,128.71,112.6914,14.5045,128.71,112.6914,14.5045,1126.9139,305.3612,0.0066
+17,8,425,690,150,103.6,74,1148.5432,135.9828,114.8543,15.6182,135.9828,114.8543,15.6182,1148.5432,289.6769,0.0071
+1,9,500,560,150,0,-0.002,1398.2841,119.2919,139.8284,16.6804,119.2919,139.8284,16.6804,1398.2841,333.7281,0.0049
+2,9,500,560,150,74.001,-14.8,1381.7664,132.0324,138.1766,18.2438,132.0324,138.1766,18.2438,1381.7664,291.6813,0.0054
+3,9,500,560,150,29.599,-74.001,1372.9491,121.8222,137.2949,16.7256,121.8222,137.2949,16.7256,1372.9491,312.6319,0.0045
+4,9,500,560,150,-44.4,-59.198,1412.8303,126.2842,141.283,17.8418,126.2842,141.283,17.8418,1412.8303,307.8591,0.0057
+5,9,500,560,150,-74.002,14.801,1440.0875,129.6621,144.0088,18.6725,129.6621,144.0088,18.6725,1440.0875,307.3572,0.0067
+6,9,500,560,150,-29.599,74.001,1381.9885,122.263,138.1989,16.8966,122.263,138.1989,16.8966,1381.9885,320.9442,0.0056
+7,9,500,560,150,44.4,59.201,1415.1222,127.5906,141.5122,18.0556,127.5906,141.5122,18.0556,1415.1222,310.9431,0.0047
+8,9,500,560,150,118.4,-0.001,1437.807,136.5523,143.7807,19.6336,136.5523,143.7807,19.6336,1437.807,283.1598,0.0072
+9,9,500,560,150,103.6,-74.001,1402.5479,131.1021,140.2548,18.3877,131.1021,140.2548,18.3877,1402.5479,285.1945,0.006
+10,9,500,560,150,44.399,-118.402,1421.7739,126.5238,142.1774,17.9888,126.5238,142.1774,17.9888,1421.7739,296.0705,0.0057
+11,9,500,560,150,-44.402,-118.4,1390.0883,139.7046,139.0088,19.4202,139.7046,139.0088,19.4202,1390.0883,264.9912,0.0065
+12,9,500,560,150,-103.601,-74,1420.3638,126.3209,142.0364,17.9422,126.3209,142.0364,17.9422,1420.3638,299.4482,0.0067
+13,9,500,560,150,-118.401,0,1412.4456,123.5645,141.2446,17.4528,123.5645,141.2446,17.4528,1412.4456,310.8511,0.0061
+14,9,500,560,150,-103.601,73.999,1348.3495,119.8113,134.8349,16.1547,119.8113,134.8349,16.1547,1348.3495,317.4254,0.0045
+15,9,500,560,150,-44.4,118.4,1373.5247,117.95,137.3525,16.2007,117.95,137.3525,16.2007,1373.5247,326.0612,0.0057
+16,9,500,560,150,44.4,118.4,1365.3591,111.5789,136.5359,15.2345,111.5789,136.5359,15.2345,1365.3591,341.6983,0.0054
+17,9,500,560,150,103.601,74,1409.9067,124.4067,140.9907,17.5402,124.4067,140.9907,17.5402,1409.9067,310.086,0.0071
+1,10,500,820,150,0,0,934.3936,203.8473,93.4394,19.0474,203.8473,93.4394,19.0474,934.3936,302.392,0.0043
+2,10,500,820,150,74,-14.801,911.2024,197.9812,91.1202,18.0401,197.9812,91.1202,18.0401,911.2024,303.6357,0.0036
+3,10,500,820,150,29.6,-74.001,905.6408,188.4489,90.5641,17.0667,188.4489,90.5641,17.0667,905.6408,316.9743,0.0027
+4,10,500,820,150,-44.401,-59.199,924.2469,191.4788,92.4247,17.6974,191.4788,92.4247,17.6974,924.2469,314.4996,0.0038
+5,10,500,820,150,-74.002,14.801,937.0928,188.0172,93.7093,17.619,188.0172,93.7093,17.619,937.0928,324.6773,0.004
+6,10,500,820,150,-29.599,73.998,926.4006,194.7829,92.6401,18.0447,194.7829,92.6401,18.0447,926.4006,313.6027,0.0036
+7,10,500,820,150,44.401,59.2,915.2459,186.4029,91.5246,17.0604,186.4029,91.5246,17.0604,915.2459,327.4021,0.0032
+8,10,500,820,150,118.4,0,935.3946,198.4357,93.5395,18.5616,198.4357,93.5395,18.5616,935.3946,299.1221,0.0046
+9,10,500,820,150,103.599,-74.001,922.5721,188.9889,92.2572,17.4356,188.9889,92.2572,17.4356,922.5721,307.8723,0.004
+10,10,500,820,150,44.399,-118.4,922.1081,179.5398,92.2108,16.5555,179.5398,92.2108,16.5555,922.1081,322.9603,0.0037
+11,10,500,820,150,-44.401,-118.401,915.8755,192.1954,91.5875,17.6027,192.1954,91.5875,17.6027,915.8755,299.7164,0.0039
+12,10,500,820,150,-103.6,-74.002,924.4468,175.3309,92.4447,16.2084,175.3309,92.4447,16.2084,924.4468,330.6322,0.0038
+13,10,500,820,150,-118.402,0,921.4701,183.2796,92.147,16.8887,183.2796,92.147,16.8887,921.4701,321.3475,0.0037
+14,10,500,820,150,-103.598,73.999,922.6891,191.2822,92.2689,17.6494,191.2822,92.2689,17.6494,922.6891,307.1461,0.0041
+15,10,500,820,150,-44.4,118.4,913.4069,173.6426,91.3407,15.8606,173.6426,91.3407,15.8606,913.4069,341.7005,0.0036
+16,10,500,820,150,44.4,118.4,905.8611,175.2945,90.5861,15.8793,175.2945,90.5861,15.8793,905.8611,338.8118,0.0031
+17,10,500,820,150,103.601,74,913.1182,167.2369,91.3118,15.2707,167.2369,91.3118,15.2707,913.1182,352.3076,0.0033
+1,11,425,560,175,0,-0.001,1577.2516,115.5139,157.7252,18.2194,115.5139,157.7252,18.2194,1577.2516,376.1414,0.005
+2,11,425,560,175,74,-14.802,1576.9465,141.4918,157.6946,22.3125,141.4918,157.6946,22.3125,1576.9465,298.2518,0.0058
+3,11,425,560,175,29.6,-74,1576.5328,119.8478,157.6533,18.8944,119.8478,157.6533,18.8944,1576.5328,352.0585,0.0057
+4,11,425,560,175,-44.4,-59.2,1590.7429,121.8368,159.0743,19.3811,121.8368,159.0743,19.3811,1590.7429,347.3639,0.0058
+5,11,425,560,175,-74.002,14.801,1539.521,91.7546,153.9521,14.1258,91.7546,153.9521,14.1258,1539.521,459.3864,0.005
+6,11,425,560,175,-29.599,74,1551.4679,104.2055,155.1468,16.1672,104.2055,155.1468,16.1672,1551.4679,409.2702,0.0046
+7,11,425,560,175,44.4,59.198,1559.7476,96.9797,155.9748,15.1264,96.9797,155.9748,15.1264,1559.7476,442.5668,0.0052
+8,11,425,560,175,118.4,-0.002,1559.1539,107.5377,155.9154,16.7668,107.5377,155.9154,16.7668,1559.1539,391.7175,0.0057
+9,11,425,560,175,103.599,-74.001,1532.7208,110.2128,153.2721,16.8925,110.2128,153.2721,16.8925,1532.7208,370.8411,0.0059
+10,11,425,560,175,44.399,-118.4,1543.5431,110.0292,154.3543,16.9835,110.0292,154.3543,16.9835,1543.5431,371.5874,0.0067
+11,11,425,560,175,-44.401,-118.401,1496.551,107.9053,149.6551,16.1486,107.9053,149.6551,16.1486,1496.551,371.9031,0.0062
+12,11,425,560,175,-103.601,-74,1528.3134,89.6321,152.8313,13.6986,89.6321,152.8313,13.6986,1528.3134,454.0893,0.0056
+13,11,425,560,175,-118.4,0,1594.9004,142.0633,159.49,22.6577,142.0633,159.49,22.6577,1594.9004,294.3279,0.0077
+14,11,425,560,175,-103.6,74,1506.0541,99.4095,150.6054,14.9716,99.4095,150.6054,14.9716,1506.0541,413.524,0.005
+15,11,425,560,175,-44.4,118.401,1533.2604,95.1805,153.326,14.5936,95.1805,153.326,14.5936,1533.2604,440.0305,0.0052
+16,11,425,560,175,44.4,118.4,1587.3641,136.5686,158.7364,21.6784,136.5686,158.7364,21.6784,1587.3641,309.0923,0.0068
+17,11,425,560,175,103.602,73.999,1529.3723,96.8544,152.9372,14.8126,96.8544,152.9372,14.8126,1529.3723,427.8804,0.0039
+1,12,350,690,175,0,0,1262.6829,128.6814,126.2683,16.2484,128.6814,126.2683,16.2484,1262.6829,327.4826,0.0075
+2,12,350,690,175,74,-14.801,1225.7365,124.1813,122.5736,15.2214,124.1813,122.5736,15.2214,1225.7365,327.6692,0.0064
+3,12,350,690,175,29.6,-74.001,1255.9065,124.8767,125.5906,15.6834,124.8767,125.5906,15.6834,1255.9065,327.159,0.0077
+4,12,350,690,175,-44.401,-59.199,1243.5211,110.5973,124.3521,13.753,110.5973,124.3521,13.753,1243.5211,367.7591,0.0073
+5,12,350,690,175,-74.001,14.801,1280.6741,115.9303,128.0674,14.8469,115.9303,128.0674,14.8469,1280.6741,360.5648,0.0079
+6,12,350,690,175,-29.599,74,1254.269,125.2864,125.4269,15.7143,125.2864,125.4269,15.7143,1254.269,332.1158,0.0084
+7,12,350,690,175,44.4,59.2,1250.984,115.3199,125.0984,14.4263,115.3199,125.0984,14.4263,1250.984,360.2453,0.0067
+8,12,350,690,175,118.4,-0.001,1276.1816,141.6809,127.6182,18.0811,141.6809,127.6182,18.0811,1276.1816,288.0168,0.0098
+9,12,350,690,175,103.601,-74.001,1249.4902,129.925,124.949,16.234,129.925,124.949,16.234,1249.4902,304.6896,0.0086
+10,12,350,690,175,44.399,-118.4,1235.246,105.5023,123.5246,13.0321,105.5023,123.5246,13.0321,1235.246,371.9051,0.0075
+11,12,350,690,175,-44.401,-118.399,1231.3326,122.8381,123.1333,15.1255,122.8381,123.1333,15.1255,1231.3326,316.9024,0.0082
+12,12,350,690,175,-103.6,-74,1265.4224,130.389,126.5422,16.4997,130.389,126.5422,16.4997,1265.4224,306.6324,0.01
+13,12,350,690,175,-118.4,-0.001,1247.0762,115.9334,124.7076,14.4578,115.9334,124.7076,14.4578,1247.0762,348.2094,0.0087
+14,12,350,690,175,-103.601,74.001,1223.8086,114.607,122.3809,14.0257,114.607,122.3809,14.0257,1223.8086,351.5815,0.0069
+15,12,350,690,175,-44.401,118.4,1211.6361,103.4511,121.1636,12.5345,103.4511,121.1636,12.5345,1211.6361,392.5425,0.0075
+16,12,350,690,175,44.4,118.4,1203.1277,103.4183,120.3128,12.4425,103.4183,120.3128,12.4425,1203.1277,388.8979,0.0066
+17,12,350,690,175,103.603,74,1275.9834,124.0386,127.5983,15.8271,124.0386,127.5983,15.8271,1275.9834,328.2786,0.008
+1,13,425,820,175,0,-0.001,1026.9851,187.2942,102.6985,19.2348,187.2942,102.6985,19.2348,1026.9851,328.9004,0.0048
+2,13,425,820,175,74.001,-14.8,995.9362,178.6365,99.5936,17.7911,178.6365,99.5936,17.7911,995.9362,334.2852,0.0034
+3,13,425,820,175,29.599,-74.002,1009.9288,176.3346,100.9929,17.8085,176.3346,100.9929,17.8085,1009.9288,340.7504,0.004
+4,13,425,820,175,-44.402,-59.198,1010.898,172.2551,101.0898,17.4132,172.2551,101.0898,17.4132,1010.898,348.0244,0.0037
+5,13,425,820,175,-74.002,14.801,1025.9451,170.7877,102.5945,17.5219,170.7877,102.5945,17.5219,1025.9451,357.3063,0.0046
+6,13,425,820,175,-29.599,74,1017.6483,177.3801,101.7648,18.0511,177.3801,101.7648,18.0511,1017.6483,343.2542,0.0046
+7,13,425,820,175,44.401,59.2,1027.6479,184.5124,102.7648,18.9614,184.5124,102.7648,18.9614,1027.6479,331.1529,0.0049
+8,13,425,820,175,118.4,-0.001,1033.7094,187.612,103.3709,19.3936,187.612,103.3709,19.3936,1033.7094,316.7488,0.0056
+9,13,425,820,175,103.599,-74.002,1023.3242,189.8949,102.3324,19.4324,189.8949,102.3324,19.4324,1023.3242,309.2833,0.0053
+10,13,425,820,175,44.398,-118.4,1006.0446,167.8854,100.6045,16.89,167.8854,100.6045,16.89,1006.0446,346.5529,0.004
+11,13,425,820,175,-44.401,-118.399,983.3046,170.634,98.3305,16.7785,170.634,98.3305,16.7785,983.3046,337.0011,0.0036
+12,13,425,820,175,-103.601,-74.001,1004.5849,164.7505,100.4585,16.5506,164.7505,100.4585,16.5506,1004.5849,353.922,0.0044
+13,13,425,820,175,-118.4,0,1001.4636,175.1772,100.1464,17.5434,175.1772,100.1464,17.5434,1001.4636,333.5986,0.0037
+14,13,425,820,175,-103.601,74,995.1066,173.1695,99.5107,17.2322,173.1695,99.5107,17.2322,995.1066,338.2366,0.0042
+15,13,425,820,175,-44.4,118.4,1011.2062,169.9928,101.1206,17.1898,169.9928,101.1206,17.1898,1011.2062,345.9093,0.0038
+16,13,425,820,175,44.4,118.4,1012.6649,167.8883,101.2665,17.0015,167.8883,101.2665,17.0015,1012.6649,349.3786,0.0036
+17,13,425,820,175,103.602,74,1006.1393,163.6858,100.6139,16.4691,163.6858,100.6139,16.4691,1006.1393,358.2688,0.0042
+1,14,500,690,175,0,-0.001,1200.2115,181.4321,120.0212,21.7757,181.4321,120.0212,21.7757,1200.2115,335.1192,0.0046
+2,14,500,690,175,74.001,-14.8,1175.4667,185.3515,117.5467,21.7875,185.3515,117.5467,21.7875,1175.4667,319.2879,0.0046
+3,14,500,690,175,29.6,-74.001,1187.8223,178.9529,118.7822,21.2564,178.9529,118.7822,21.2564,1187.8223,330.7546,0.0051
+4,14,500,690,175,-44.4,-59.199,1163.1127,166.805,116.3113,19.4013,166.805,116.3113,19.4013,1163.1127,351.8608,0.0039
+5,14,500,690,175,-74.002,14.801,1185.476,161.8775,118.5476,19.1902,161.8775,118.5476,19.1902,1185.476,370.9543,0.0048
+6,14,500,690,175,-29.599,74.001,1157.6405,166.9275,115.764,19.3242,166.9275,115.764,19.3242,1157.6405,356.915,0.0038
+7,14,500,690,175,44.401,59.2,1195.1595,174.6315,119.516,20.8713,174.6315,119.516,20.8713,1195.1595,346.3336,0.0049
+8,14,500,690,175,118.4,0,1178.6151,158.5145,117.8615,18.6828,158.5145,117.8615,18.6828,1178.6151,367.7084,0.0047
+9,14,500,690,175,103.599,-74.001,1151.3474,158.624,115.1348,18.2631,158.624,115.1348,18.2631,1151.3474,359.2731,0.0041
+10,14,500,690,175,44.399,-118.4,1181.156,178.9433,118.1156,21.136,178.9433,118.1156,21.136,1181.156,321.738,0.0056
+11,14,500,690,175,-44.401,-118.399,1173.3024,184.8949,117.3302,21.6938,184.8949,117.3302,21.6938,1173.3024,307.3172,0.0053
+12,14,500,690,175,-103.599,-74,1189.1587,175.8474,118.9159,20.911,175.8474,118.9159,20.911,1189.1587,327.4549,0.0057
+13,14,500,690,175,-118.402,0,1167.9316,165.323,116.7932,19.3086,165.323,116.7932,19.3086,1167.9316,350.5558,0.0041
+14,14,500,690,175,-103.598,74,1157.9685,170.4319,115.7969,19.7355,170.4319,115.7969,19.7355,1157.9685,340.5424,0.0044
+15,14,500,690,175,-44.4,118.4,1181.1707,171.7384,118.1171,20.2852,171.7384,118.1171,20.2852,1181.1707,341.8434,0.0048
+16,14,500,690,175,44.4,118.4,1154.916,158.8994,115.4916,18.3515,158.8994,115.4916,18.3515,1154.916,364.8066,0.0045
+17,14,500,690,175,103.601,74,1185.6005,165.8131,118.56,19.6588,165.8131,118.56,19.6588,1185.6005,352.3506,0.0048
+1,15,425,690,150,0,-0.001,1180.0281,118.5564,118.0028,13.99,118.5564,118.0028,13.99,1180.0281,344.8683,0.0071
+2,15,425,690,150,74,-14.801,1213.5027,179.9232,121.3503,21.8337,179.9232,121.3503,21.8337,1213.5027,222.1038,0.0106
+3,15,425,690,150,29.601,-74.001,1204.845,128.9742,120.4845,15.5394,128.9742,120.4845,15.5394,1204.845,310.7895,0.0095
+4,15,425,690,150,-44.402,-59.199,1205.4177,120.5808,120.5418,14.535,120.5808,120.5418,14.535,1205.4177,332.9639,0.0089
+5,15,425,690,150,-74.001,14.801,1223.9078,114.6912,122.3908,14.0371,114.6912,122.3908,14.0371,1223.9078,358.4737,0.0101
+6,15,425,690,150,-29.599,74,1209.4362,134.9985,120.9436,16.3272,134.9985,120.9436,16.3272,1209.4362,303.9903,0.0107
+7,15,425,690,150,44.4,59.201,1228.4595,129.7705,122.846,15.9418,129.7705,122.846,15.9418,1228.4595,318.1927,0.0105
+8,15,425,690,150,118.4,-0.001,1208.3083,106.9388,120.8308,12.9215,106.9388,120.8308,12.9215,1208.3083,368.3277,0.0098
+9,15,425,690,150,103.599,-74.001,1162.2089,105.6266,116.2209,12.276,105.6266,116.2209,12.276,1162.2089,361.7582,0.0087
+10,15,425,690,150,44.399,-118.401,1244.9277,140.2387,124.4928,17.4587,140.2387,124.4928,17.4587,1244.9277,276.8294,0.0116
+11,15,425,690,150,-44.402,-118.4,1153.3521,108.5453,115.3352,12.5191,108.5453,115.3352,12.5191,1153.3521,350.1047,0.0084
+12,15,425,690,150,-103.601,-74.001,1246.7141,130.2036,124.6714,16.2327,130.2036,124.6714,16.2327,1246.7141,305.1168,0.0119
+13,15,425,690,150,-118.402,0,1196.9844,108.6696,119.6984,13.0076,108.6696,119.6984,13.0076,1196.9844,367.3816,0.0102
+14,15,425,690,150,-103.601,73.998,1210.6956,128.4285,121.0696,15.5488,128.4285,121.0696,15.5488,1210.6956,310.8858,0.0112
+15,15,425,690,150,-44.399,118.401,1171.0328,98.4096,117.1033,11.5241,98.4096,117.1033,11.5241,1171.0328,404.1108,0.0087
+16,15,425,690,150,44.4,118.4,1169.9117,100.7126,116.9912,11.7825,100.7126,116.9912,11.7825,1169.9117,392.2843,0.0088
+17,15,425,690,150,103.603,73.999,1199.7618,108.1952,119.9762,12.9808,108.1952,119.9762,12.9808,1199.7618,364.4402,0.0107
+1,16,350,820,150,0,0,1029.9489,157.9004,102.9949,16.2629,157.9004,102.9949,16.2629,1029.9489,270.9289,0.0109
+2,16,350,820,150,74,-14.801,989.5313,130.8999,98.9531,12.953,130.8999,98.9531,12.953,989.5313,316.7947,0.0069
+3,16,350,820,150,29.602,-74,968.9048,121.7231,96.8905,11.7938,121.7231,96.8905,11.7938,968.9048,337.616,0.0069
+4,16,350,820,150,-44.401,-59.199,1008.6535,134.1505,100.8653,13.5311,134.1505,100.8653,13.5311,1008.6535,309.924,0.0098
+5,16,350,820,150,-74.001,14.802,991.4529,109.1183,99.1453,10.8186,109.1183,99.1453,10.8186,991.4529,383.7622,0.0073
+6,16,350,820,150,-29.599,74,997.0968,123.7614,99.7097,12.3402,123.7614,99.7097,12.3402,997.0968,339.8541,0.0086
+7,16,350,820,150,44.401,59.198,991.1741,111.3156,99.1174,11.0333,111.3156,99.1174,11.0333,991.1741,379.4342,0.0077
+8,16,350,820,150,118.4,-0.001,1002.0113,108.9231,100.2011,10.9142,108.9231,100.2011,10.9142,1002.0113,374.8463,0.0083
+9,16,350,820,150,103.599,-74.001,1000.4697,123.3659,100.047,12.3424,123.3659,100.047,12.3424,1000.4697,325.5202,0.0092
+10,16,350,820,150,44.398,-118.4,1013.8029,121.1421,101.3803,12.2814,121.1421,101.3803,12.2814,1013.8029,330.2841,0.0094
+11,16,350,820,150,-44.401,-118.4,987.4907,115.4388,98.7491,11.3995,115.4388,98.7491,11.3995,987.4907,342.9402,0.0075
+12,16,350,820,150,-103.601,-73.999,1020.0015,129.1119,102.0001,13.1694,129.1119,102.0001,13.1694,1020.0015,313.6122,0.0122
+13,16,350,820,150,-118.402,0,1012.4409,122.6144,101.2441,12.414,122.6144,101.2441,12.414,1012.4409,333.1339,0.0102
+14,16,350,820,150,-103.598,74,1014.5298,124.9659,101.453,12.6782,124.9659,101.453,12.6782,1014.5298,323.0759,0.0089
+15,16,350,820,150,-44.4,118.401,997.7552,112.2317,99.7755,11.198,112.2317,99.7755,11.198,997.7552,362.5231,0.0088
+16,16,350,820,150,44.401,118.4,977.0716,97.4107,97.7072,9.5177,97.4107,97.7072,9.5177,977.0716,414.4219,0.0079
+17,16,350,820,150,103.601,74,995.0288,102.6314,99.5029,10.2121,102.6314,99.5029,10.2121,995.0288,392.5791,0.0078
+1,17,350,820,150,0,-0.001,967.4733,216.1438,96.7473,20.9113,216.1438,96.7473,20.9113,967.4733,204.7814,0.0042
+2,17,350,820,150,74.001,-14.8,926.9498,216.5282,92.695,20.0711,216.5282,92.695,20.0711,926.9498,199.3709,0.0037
+3,17,350,820,150,29.601,-74.001,943.6208,215.1827,94.3621,20.3051,215.1827,94.3621,20.3051,943.6208,201.5136,0.004
+4,17,350,820,150,-44.401,-59.198,959.7181,214.6907,95.9718,20.6043,214.6907,95.9718,20.6043,959.7181,202.6169,0.0048
+5,17,350,820,150,-74,14.801,995.183,232.9227,99.5183,23.1801,232.9227,99.5183,23.1801,995.183,190.24,0.0055
+6,17,350,820,150,-29.599,74,937.8175,208.7773,93.7818,19.5795,208.7773,93.7818,19.5795,937.8175,209.9875,0.0034
+7,17,350,820,150,44.4,59.199,977.2335,231.4196,97.7234,22.6151,231.4196,97.7234,22.6151,977.2335,191.7707,0.0055
+8,17,350,820,150,118.4,-0.001,973.6445,209.9531,97.3645,20.442,209.9531,97.3645,20.442,973.6445,207.1429,0.0044
+9,17,350,820,150,103.601,-74.001,962.7674,211.3637,96.2767,20.3494,211.3637,96.2767,20.3494,962.7674,202.8725,0.0042
+10,17,350,820,150,44.399,-118.401,971.0012,216.5083,97.1001,21.023,216.5083,97.1001,21.023,971.0012,198.3957,0.0054
+11,17,350,820,150,-44.402,-118.4,942.0002,204.0039,94.2,19.2172,204.0039,94.2,19.2172,942.0002,207.056,0.0037
+12,17,350,820,150,-103.6,-74,973.6995,200.8508,97.3699,19.5568,200.8508,97.3699,19.5568,973.6995,215.2973,0.0054
+13,17,350,820,150,-118.4,0,961.8871,201.8273,96.1887,19.4135,201.8273,96.1887,19.4135,961.8871,216.2349,0.0049
+14,17,350,820,150,-103.601,74.001,977.9094,222.0011,97.7909,21.7097,222.0011,97.7909,21.7097,977.9094,197.6788,0.0051
+15,17,350,820,150,-44.4,118.4,963.5474,223.0385,96.3547,21.4908,223.0385,96.3547,21.4908,963.5474,198.4774,0.0056
+16,17,350,820,150,44.4,118.4,958.5841,212.906,95.8584,20.4088,212.906,95.8584,20.4088,958.5841,205.7514,0.005
+17,17,350,820,150,103.602,73.999,969.0357,214.0431,96.9036,20.7415,214.0431,96.9036,20.7415,969.0357,203.7684,0.0053
+1,18,350,820,150,0,0,1016.0071,133.132,101.6007,13.5263,133.132,101.6007,13.5263,1016.0071,321.2368,0.007
+2,18,350,820,150,74,-14.801,987.7178,136.1069,98.7718,13.4435,136.1069,98.7718,13.4435,987.7178,305.331,0.0056
+3,18,350,820,150,29.599,-74.001,1019.0529,141.7201,101.9053,14.442,141.7201,101.9053,14.442,1019.0529,295.4286,0.0074
+4,18,350,820,150,-44.401,-59.199,1021.54,143.0793,102.154,14.6161,143.0793,102.154,14.6161,1021.54,293.4315,0.0077
+5,18,350,820,150,-74.002,14.801,1029.3126,140.8482,102.9313,14.4977,140.8482,102.9313,14.4977,1029.3126,303.9875,0.0093
+6,18,350,820,150,-29.599,74,1007.5427,129.7302,100.7543,13.0709,129.7302,100.7543,13.0709,1007.5427,327.5743,0.0072
+7,18,350,820,150,44.4,59.2,1053.8663,156.7547,105.3866,16.5199,156.7547,105.3866,16.5199,1053.8663,273.9025,0.0087
+8,18,350,820,150,118.401,-0.001,1045.0486,147.8745,104.5049,15.4536,147.8745,104.5049,15.4536,1045.0486,283.0747,0.0092
+9,18,350,820,150,103.599,-74.001,1028.8269,149.3593,102.8827,15.3665,149.3593,102.8827,15.3665,1028.8269,273.9069,0.0088
+10,18,350,820,150,44.398,-118.401,1046.8239,143.8671,104.6824,15.0604,143.8671,104.6824,15.0604,1046.8239,284.7881,0.0096
+11,18,350,820,150,-44.402,-118.4,1019.8665,141.967,101.9866,14.4787,141.967,101.9866,14.4787,1019.8665,286.7693,0.0082
+12,18,350,820,150,-103.601,-74,1022.0805,117.0597,102.2081,11.9644,117.0597,102.2081,11.9644,1022.0805,352.8903,0.0077
+13,18,350,820,150,-118.4,0,1019.1177,126.9935,101.9118,12.9421,126.9935,101.9118,12.9421,1019.1177,328.637,0.0088
+14,18,350,820,150,-103.599,74.001,993.0048,115.8635,99.3005,11.5053,115.8635,99.3005,11.5053,993.0048,355.9823,0.0059
+15,18,350,820,150,-44.4,118.4,1007.6011,114.3499,100.7601,11.5219,114.3499,100.7601,11.5219,1007.6011,366.751,0.0076
+16,18,350,820,150,44.4,118.4,1015.3873,129.8054,101.5387,13.1803,129.8054,101.5387,13.1803,1015.3873,321.9023,0.0084
+17,18,350,820,150,103.601,74,1015.5718,115.81,101.5572,11.7613,115.81,101.5572,11.7613,1015.5718,357.6244,0.007
diff --git a/sigeb-doe-new.csv b/sigeb-doe-new.csv
new file mode 100644
index 00000000..57692d02
--- /dev/null
+++ b/sigeb-doe-new.csv
@@ -0,0 +1,443 @@
+wafer,site,time_dep,geh4,b2h6,th_sigeb,oxide, GOF
+1,1,350,690,125,145.514,10.0168,0.91157
+1,2,350,690,125,145.055,10.1523,0.91233
+1,3,350,690,125,144.982,10.2892,0.91194
+1,4,350,690,125,144.464,10.0638,0.91097
+1,5,350,690,125,145.525,10.0484,0.91154
+1,6,350,690,125,146.326,10.1825,0.91064
+1,7,350,690,125,145.991,10.0093,0.91145
+1,8,350,690,125,144.453,10.2859,0.9111
+1,9,350,690,125,144.038,10.4623,0.91101
+1,10,350,690,125,143.361,10.5098,0.91163
+1,11,350,690,125,143.028,10.4588,0.91136
+1,12,350,690,125,142.481,10.4081,0.91182
+1,13,350,690,125,143.147,10.3145,0.91243
+1,14,350,690,125,144.31,10.3705,0.91096
+1,15,350,690,125,145.766,10.4885,0.91092
+1,16,350,690,125,145.902,10.3611,0.90982
+1,17,350,690,125,144.253,10.1681,0.91174
+1,18,350,690,125,145.505,10.0081,0.91165
+1,19,350,690,125,145.566,10.1,0.911
+1,20,350,690,125,145.572,10.0218,0.91202
+1,21,350,690,125,145.687,10.0665,0.91044
+1,22,350,690,125,145.68,10.0761,0.91055
+1,23,350,690,125,145.361,10.0334,0.91162
+1,24,350,690,125,143.082,10.3668,0.91189
+1,25,350,690,125,143.199,10.3587,0.91228
+1,26,350,690,125,143.347,10.3197,0.91262
+2,1,425,560,125,116.785,8.6946,0.89922
+2,2,425,560,125,115.419,8.7367,0.90145
+2,3,425,560,125,115.032,8.9338,0.90063
+2,4,425,560,125,115.188,8.8582,0.90065
+2,5,425,560,125,116.295,8.8693,0.90087
+2,6,425,560,125,117.133,8.9213,0.90176
+2,7,425,560,125,116.604,8.6695,0.90046
+2,8,425,560,125,114.236,8.9176,0.90152
+2,9,425,560,125,113.302,9.1138,0.90279
+2,10,425,560,125,112.919,9.2271,0.90462
+2,11,425,560,125,113.507,9.2392,0.90302
+2,12,425,560,125,114.24,9.2459,0.90451
+2,13,425,560,125,114.676,9.2358,0.90337
+2,14,425,560,125,116.384,9.2687,0.90447
+2,15,425,560,125,117.148,9.2305,0.90459
+2,16,425,560,125,116.449,9.1342,0.90446
+2,17,425,560,125,114.922,8.8886,0.90343
+2,18,425,560,125,116.741,8.6945,0.90052
+2,19,425,560,125,116.764,8.7589,0.89989
+2,20,425,560,125,116.799,8.715,0.90048
+2,21,425,560,125,116.312,8.9032,0.90211
+2,22,425,560,125,116.362,8.9025,0.90126
+2,23,425,560,125,116.203,8.864,0.90065
+2,24,425,560,125,114.656,9.2897,0.9046
+2,25,425,560,125,114.751,9.252,0.90342
+2,26,425,560,125,114.783,9.2136,0.90333
+3,1,500,690,125,207.834,9.2361,0.88955
+3,2,500,690,125,207.203,9.333,0.88948
+3,3,500,690,125,207.132,9.4713,0.88968
+3,4,500,690,125,206.786,9.3504,0.88861
+3,5,500,690,125,208.169,9.4038,0.88855
+3,6,500,690,125,209.411,9.409,0.88771
+3,7,500,690,125,208.479,9.2213,0.88892
+3,8,500,690,125,203.66,9.4801,0.88863
+3,9,500,690,125,202.748,9.6177,0.88806
+3,10,500,690,125,202.804,9.6772,0.88777
+3,11,500,690,125,204.744,9.5466,0.88807
+3,12,500,690,125,205.242,9.5361,0.88791
+3,13,500,690,125,206.366,9.6722,0.88801
+3,14,500,690,125,207.426,9.5462,0.88706
+3,15,500,690,125,208.343,9.5627,0.88631
+3,16,500,690,125,206.172,9.5173,0.88745
+3,17,500,690,125,203.489,9.349,0.88846
+3,18,500,690,125,207.751,9.2326,0.88838
+3,19,500,690,125,207.755,9.3003,0.88952
+3,20,500,690,125,207.684,9.2133,0.88822
+3,21,500,690,125,208.455,9.3974,0.88861
+3,22,500,690,125,208.321,9.398,0.88907
+3,23,500,690,125,207.863,9.3973,0.88882
+3,24,500,690,125,206.001,9.6793,0.88688
+3,25,500,690,125,206.426,9.6652,0.88752
+3,26,500,690,125,206.664,9.5924,0.88802
+4,1,425,820,125,254.491,9.044,0.88419
+4,2,425,820,125,254.842,9.1095,0.88408
+4,3,425,820,125,254.954,9.2301,0.88504
+4,4,425,820,125,253.842,9.112,0.8843
+4,5,425,820,125,255.473,9.2031,0.88458
+4,6,425,820,125,257.257,9.2664,0.88306
+4,7,425,820,125,256.196,9.0418,0.88476
+4,8,425,820,125,249.808,9.1655,0.88366
+4,9,425,820,125,247.836,9.2871,0.88226
+4,10,425,820,125,248.207,9.3255,0.88193
+4,11,425,820,125,249.76,9.2167,0.88276
+4,12,425,820,125,251.016,9.2033,0.88206
+4,13,425,820,125,252.896,9.3954,0.88333
+4,14,425,820,125,252.717,9.341,0.88157
+4,15,425,820,125,254.407,9.3804,0.8817
+4,16,425,820,125,252.007,9.2789,0.88194
+4,17,425,820,125,248.825,9.0224,0.88281
+4,18,425,820,125,254.399,9.0179,0.88321
+4,19,425,820,125,254.418,9.1339,0.88475
+4,20,425,820,125,254.372,9.0182,0.88326
+4,21,425,820,125,255.933,9.2065,0.88511
+4,22,425,820,125,255.701,9.2107,0.88465
+4,23,425,820,125,254.971,9.1803,0.88508
+4,24,425,820,125,252.279,9.4159,0.88319
+4,25,425,820,125,252.935,9.3853,0.88298
+4,26,425,820,125,253.494,9.3655,0.88401
+5,1,350,560,150,113.375,9.1907,0.87433
+5,2,350,560,150,112.017,9.1516,0.87784
+5,3,350,560,150,111.629,9.2904,0.88099
+5,4,350,560,150,111.626,9.25,0.87976
+5,5,350,560,150,112.632,9.2946,0.8796
+5,6,350,560,150,113.51,9.3519,0.87999
+5,7,350,560,150,113.139,9.1506,0.87649
+5,8,350,560,150,110.971,9.2219,0.88351
+5,9,350,560,150,110.434,9.3196,0.88919
+5,10,350,560,150,110.561,9.3276,0.89137
+5,11,350,560,150,110.531,9.2665,0.89273
+5,12,350,560,150,110.446,9.2775,0.89143
+5,13,350,560,150,111.274,9.4339,0.88699
+5,14,350,560,150,112.944,9.4018,0.89135
+5,15,350,560,150,113.335,9.3575,0.8881
+5,16,350,560,150,112.582,9.2881,0.88735
+5,17,350,560,150,111.458,9.0891,0.8854
+5,18,350,560,150,113.333,9.1931,0.87364
+5,19,350,560,150,113.429,9.2488,0.87435
+5,20,350,560,150,113.391,9.1973,0.87337
+5,21,350,560,150,112.698,9.3398,0.88015
+5,22,350,560,150,112.809,9.321,0.88021
+5,23,350,560,150,112.669,9.3225,0.87959
+5,24,350,560,150,111.273,9.4797,0.88861
+5,25,350,560,150,111.29,9.4566,0.88787
+5,26,350,560,150,111.289,9.422,0.8875
+6,1,350,820,150,223.754,9.1031,0.88108
+6,2,350,820,150,223.832,9.1178,0.88268
+6,3,350,820,150,223.807,9.2311,0.88197
+6,4,350,820,150,223.385,9.1473,0.88135
+6,5,350,820,150,225.163,9.2337,0.88146
+6,6,350,820,150,226.335,9.2297,0.88146
+6,7,350,820,150,225.131,9.0664,0.88166
+6,8,350,820,150,221.776,9.2743,0.88145
+6,9,350,820,150,220.265,9.4186,0.88189
+6,10,350,820,150,219.815,9.4368,0.88182
+6,11,350,820,150,221.186,9.3154,0.88088
+6,12,350,820,150,222.457,9.3061,0.8804
+6,13,350,820,150,223.131,9.422,0.88128
+6,14,350,820,150,223.808,9.3943,0.87952
+6,15,350,820,150,224.756,9.3546,0.88001
+6,16,350,820,150,223.123,9.3159,0.88008
+6,17,350,820,150,220.961,9.1681,0.88052
+6,18,350,820,150,223.741,9.0918,0.88249
+6,19,350,820,150,223.587,9.1561,0.88265
+6,20,350,820,150,223.677,9.0742,0.88096
+6,21,350,820,150,225.554,9.2554,0.88148
+6,22,350,820,150,225.356,9.2422,0.88079
+6,23,350,820,150,224.815,9.2516,0.88188
+6,24,350,820,150,222.884,9.4817,0.88046
+6,25,350,820,150,223.201,9.4438,0.88075
+6,26,350,820,150,223.543,9.4049,0.88136
+7,1,425,690,150,197.907,9.511,0.89173
+7,2,425,690,150,197.101,9.5863,0.89099
+7,3,425,690,150,196.633,9.6784,0.89146
+7,4,425,690,150,196.486,9.6373,0.89126
+7,5,425,690,150,198.183,9.6796,0.89097
+7,6,425,690,150,199.421,9.6729,0.89093
+7,7,425,690,150,198.539,9.5264,0.89151
+7,8,425,690,150,194.219,9.7533,0.89195
+7,9,425,690,150,192.92,9.8558,0.89242
+7,10,425,690,150,192.86,9.8802,0.89216
+7,11,425,690,150,193.839,9.7845,0.89108
+7,12,425,690,150,195.018,9.8333,0.89182
+7,13,425,690,150,196.848,9.8554,0.89053
+7,14,425,690,150,197.903,9.7841,0.88875
+7,15,425,690,150,198.965,9.7663,0.88786
+7,16,425,690,150,197.443,9.7202,0.88975
+7,17,425,690,150,194.822,9.6183,0.89235
+7,18,425,690,150,197.898,9.5314,0.89193
+7,19,425,690,150,197.869,9.5898,0.89211
+7,20,425,690,150,197.885,9.5324,0.89198
+7,21,425,690,150,198.337,9.6761,0.8916
+7,22,425,690,150,198.303,9.6993,0.89077
+7,23,425,690,150,197.873,9.6802,0.89129
+7,24,425,690,150,196.604,9.8809,0.89007
+7,25,425,690,150,196.913,9.8868,0.89181
+7,26,425,690,150,197.056,9.8507,0.89084
+8,1,425,690,150,199.214,9.5196,0.8916
+8,2,425,690,150,198.348,9.583,0.89186
+8,3,425,690,150,198.118,9.6587,0.89157
+8,4,425,690,150,197.957,9.6154,0.8913
+8,5,425,690,150,199.407,9.7073,0.89133
+8,6,425,690,150,200.58,9.6753,0.8898
+8,7,425,690,150,199.637,9.5283,0.89128
+8,8,425,690,150,195.201,9.7685,0.89245
+8,9,425,690,150,194.143,9.8567,0.89125
+8,10,425,690,150,194.54,9.8543,0.89218
+8,11,425,690,150,196.496,9.7172,0.89029
+8,12,425,690,150,196.225,9.79,0.891
+8,13,425,690,150,197.959,9.8747,0.89134
+8,14,425,690,150,199.377,9.7811,0.88865
+8,15,425,690,150,199.721,9.809,0.88812
+8,16,425,690,150,197.523,9.7538,0.89096
+8,17,425,690,150,195.19,9.6418,0.89161
+8,18,425,690,150,199.125,9.5184,0.89131
+8,19,425,690,150,199.106,9.5729,0.8917
+8,20,425,690,150,199.05,9.497,0.89095
+8,21,425,690,150,199.709,9.7215,0.89173
+8,22,425,690,150,199.645,9.7217,0.89103
+8,23,425,690,150,199.215,9.694,0.89134
+8,24,425,690,150,197.616,9.8937,0.89009
+8,25,425,690,150,197.979,9.859,0.89103
+8,26,425,690,150,198.149,9.8424,0.88996
+9,1,500,560,150,171.219,9.3213,0.88059
+9,2,500,560,150,168.824,9.2898,0.88235
+9,3,500,560,150,167.992,9.3826,0.88479
+9,4,500,560,150,168.385,9.3533,0.883
+9,5,500,560,150,170.089,9.4412,0.88419
+9,6,500,560,150,171.125,9.4637,0.88526
+9,7,500,560,150,170.528,9.2816,0.8829
+9,8,500,560,150,165.942,9.3819,0.885
+9,9,500,560,150,164.681,9.4762,0.88767
+9,10,500,560,150,163.792,9.4819,0.88893
+9,11,500,560,150,164.59,9.4292,0.88888
+9,12,500,560,150,165.074,9.5164,0.88871
+9,13,500,560,150,167.494,9.5837,0.88775
+9,14,500,560,150,169.998,9.6664,0.89077
+9,15,500,560,150,169.999,9.616,0.89055
+9,16,500,560,150,169.034,9.4979,0.88918
+9,17,500,560,150,167.333,9.3395,0.88773
+9,18,500,560,150,171.255,9.3297,0.87966
+9,19,500,560,150,171.207,9.3688,0.88086
+9,20,500,560,150,171.27,9.3797,0.88162
+9,21,500,560,150,170.124,9.4378,0.88383
+9,22,500,560,150,170.211,9.4321,0.88402
+9,23,500,560,150,170.043,9.4412,0.88348
+9,24,500,560,150,167.26,9.6049,0.88892
+9,25,500,560,150,167.57,9.5893,0.8876
+9,26,500,560,150,167.687,9.5774,0.88719
+10,1,500,820,150,324.651,9.5177,0.90332
+10,2,500,820,150,324.836,9.5548,0.90257
+10,3,500,820,150,324.289,9.6089,0.90188
+10,4,500,820,150,323.051,9.5188,0.90149
+10,5,500,820,150,325.471,9.6739,0.90238
+10,6,500,820,150,327.638,9.7456,0.90323
+10,7,500,820,150,326.633,9.55,0.9035
+10,8,500,820,150,321.363,9.5655,0.89838
+10,9,500,820,150,319.899,9.6231,0.89695
+10,10,500,820,150,318.39,9.5666,0.8963
+10,11,500,820,150,318.159,9.4704,0.89611
+10,12,500,820,150,317.739,9.5313,0.89541
+10,13,500,820,150,320.951,9.7599,0.89801
+10,14,500,820,150,320.942,9.7003,0.89516
+10,15,500,820,150,323.289,9.7635,0.89812
+10,16,500,820,150,323.646,9.6401,0.89888
+10,17,500,820,150,320.027,9.3668,0.89791
+10,18,500,820,150,324.6,9.4834,0.90238
+10,19,500,820,150,324.577,9.5883,0.90405
+10,20,500,820,150,324.611,9.5069,0.90314
+10,21,500,820,150,325.907,9.7,0.90266
+10,22,500,820,150,325.739,9.6772,0.90292
+10,23,500,820,150,325.046,9.6503,0.90233
+10,24,500,820,150,320.312,9.6848,0.89677
+10,25,500,820,150,321.101,9.7492,0.89832
+10,26,500,820,150,321.679,9.7177,0.89767
+11,1,425,560,175,170.221,10.052,0.84759
+11,2,425,560,175,168.204,10.0193,0.85147
+11,3,425,560,175,167.091,10.057,0.8538
+11,4,425,560,175,167.122,10.0629,0.85169
+11,5,425,560,175,168.461,10.1213,0.85242
+11,6,425,560,175,169.599,10.1577,0.85463
+11,7,425,560,175,169.464,10.0226,0.85173
+11,8,425,560,175,165.893,10.004,0.85991
+11,9,425,560,175,163.678,9.9432,0.86659
+11,10,425,560,175,162.668,9.9428,0.86667
+11,11,425,560,175,162.821,9.8704,0.86822
+11,12,425,560,175,162.719,9.9728,0.86604
+11,13,425,560,175,164.397,10.1248,0.86049
+11,14,425,560,175,165.637,10.0314,0.86758
+11,15,425,560,175,166.875,10.0366,0.86722
+11,16,425,560,175,166.549,9.9406,0.8633
+11,17,425,560,175,165.627,9.8118,0.86289
+11,18,425,560,175,170.104,10.0742,0.84733
+11,19,425,560,175,170.216,10.1402,0.84855
+11,20,425,560,175,170.227,10.1031,0.84801
+11,21,425,560,175,168.38,10.1203,0.85316
+11,22,425,560,175,168.552,10.0993,0.85089
+11,23,425,560,175,168.427,10.114,0.85198
+11,24,425,560,175,164.131,10.1201,0.8625
+11,25,425,560,175,164.463,10.1348,0.86103
+11,26,425,560,175,164.785,10.1361,0.86069
+12,1,350,690,175,184.429,9.8748,0.90254
+12,2,350,690,175,183.219,9.915,0.90278
+12,3,350,690,175,182.672,9.9855,0.90266
+12,4,350,690,175,182.645,9.9603,0.90207
+12,5,350,690,175,184.361,10.019,0.90167
+12,6,350,690,175,185.253,10.0237,0.90088
+12,7,350,690,175,184.55,9.8467,0.9024
+12,8,350,690,175,181.271,10.104,0.90493
+12,9,350,690,175,179.494,10.1351,0.90436
+12,10,350,690,175,179.019,10.1481,0.9044
+12,11,350,690,175,179.53,10.0902,0.90294
+12,12,350,690,175,180.727,10.1145,0.90304
+12,13,350,690,175,182.023,10.1747,0.90213
+12,14,350,690,175,183.276,10.1591,0.90063
+12,15,350,690,175,184.149,10.1035,0.89983
+12,16,350,690,175,183.348,10.0513,0.90159
+12,17,350,690,175,181.831,9.967,0.9032
+12,18,350,690,175,184.406,9.8525,0.90248
+12,19,350,690,175,184.334,9.9174,0.9022
+12,20,350,690,175,184.32,9.8413,0.90157
+12,21,350,690,175,184.44,10.0577,0.90235
+12,22,350,690,175,184.433,10.0124,0.90117
+12,23,350,690,175,184.166,10.0251,0.9027
+12,24,350,690,175,181.871,10.1833,0.90248
+12,25,350,690,175,182.136,10.2115,0.90262
+12,26,350,690,175,182.23,10.1702,0.90197
+13,1,425,820,175,292.202,9.1663,0.89238
+13,2,425,820,175,291.759,9.1725,0.89074
+13,3,425,820,175,291.668,9.2152,0.89002
+13,4,425,820,175,290.778,9.231,0.88994
+13,5,425,820,175,292.582,9.2785,0.89094
+13,6,425,820,175,293.808,9.2801,0.89174
+13,7,425,820,175,292.837,9.1161,0.89297
+13,8,425,820,175,288.549,9.251,0.89001
+13,9,425,820,175,288.634,9.2536,0.88851
+13,10,425,820,175,287.597,9.2449,0.88866
+13,11,425,820,175,287.6,9.2276,0.88637
+13,12,425,820,175,287.92,9.2618,0.8869
+13,13,425,820,175,288.812,9.3774,0.88877
+13,14,425,820,175,288.758,9.3416,0.88703
+13,15,425,820,175,288.931,9.3116,0.88823
+13,16,425,820,175,287.662,9.1981,0.88802
+13,17,425,820,175,286.416,9.1196,0.88831
+13,18,425,820,175,292.218,9.1371,0.89118
+13,19,425,820,175,292.142,9.2263,0.89213
+13,20,425,820,175,292.18,9.1386,0.88973
+13,21,425,820,175,292.972,9.284,0.89174
+13,22,425,820,175,292.808,9.2962,0.89146
+13,23,425,820,175,292.27,9.2772,0.89133
+13,24,425,820,175,288.434,9.4141,0.88619
+13,25,425,820,175,288.852,9.376,0.8879
+13,26,425,820,175,289.257,9.3542,0.88889
+14,1,500,690,175,259.519,8.7268,0.88819
+14,2,500,690,175,257.807,8.751,0.88782
+14,3,500,690,175,257.436,8.827,0.88721
+14,4,500,690,175,257.183,8.8243,0.88664
+14,5,500,690,175,259.134,8.8602,0.88711
+14,6,500,690,175,260.255,8.8925,0.8876
+14,7,500,690,175,259.461,8.7201,0.88832
+14,8,500,690,175,254.12,8.9055,0.88725
+14,9,500,690,175,252.424,8.9223,0.8861
+14,10,500,690,175,253.313,8.9736,0.88644
+14,11,500,690,175,252.893,8.8805,0.88523
+14,12,500,690,175,252.887,8.9266,0.88527
+14,13,500,690,175,255.043,9.0161,0.88717
+14,14,500,690,175,256.317,8.9341,0.88518
+14,15,500,690,175,256.622,8.9268,0.88607
+14,16,500,690,175,255.149,8.8486,0.88598
+14,17,500,690,175,253.716,8.7923,0.88616
+14,18,500,690,175,259.429,8.7133,0.88707
+14,19,500,690,175,259.453,8.7927,0.88733
+14,20,500,690,175,259.439,8.7181,0.8874
+14,21,500,690,175,259.362,8.8878,0.88721
+14,22,500,690,175,259.297,8.8704,0.88772
+14,23,500,690,175,259.027,8.8843,0.88752
+14,24,500,690,175,254.832,9.0135,0.88624
+14,25,500,690,175,255.162,8.9976,0.88596
+14,26,500,690,175,255.484,8.9819,0.88635
+15,1,425,690,150,197.956,9.6905,0.89394
+15,2,425,690,150,196.561,9.7232,0.89484
+15,3,425,690,150,196.079,9.831,0.89479
+15,4,425,690,150,196.071,9.8243,0.89438
+15,5,425,690,150,197.571,9.8277,0.89357
+15,6,425,690,150,198.766,9.8569,0.89183
+15,7,425,690,150,197.931,9.6956,0.89415
+15,8,425,690,150,192.895,9.9616,0.89498
+15,9,425,690,150,191.459,9.9804,0.89418
+15,10,425,690,150,191.551,10.0448,0.89544
+15,11,425,690,150,192.413,10.0173,0.89455
+15,12,425,690,150,193.65,9.9505,0.89367
+15,13,425,690,150,195.344,9.9868,0.89404
+15,14,425,690,150,196.033,9.9571,0.89208
+15,15,425,690,150,197.121,9.8914,0.89087
+15,16,425,690,150,195.54,9.8878,0.89315
+15,17,425,690,150,193.203,9.8615,0.89481
+15,18,425,690,150,197.89,9.6823,0.89428
+15,19,425,690,150,197.879,9.7376,0.89374
+15,20,425,690,150,197.853,9.6945,0.89335
+15,21,425,690,150,197.768,9.8552,0.89448
+15,22,425,690,150,197.727,9.8432,0.89426
+15,23,425,690,150,197.401,9.857,0.89437
+15,24,425,690,150,195.044,9.993,0.89301
+15,25,425,690,150,195.413,10.0025,0.89309
+15,26,425,690,150,195.662,9.9647,0.8939
+16,1,350,820,150,234.612,9.018,0.88232
+16,2,350,820,150,234.112,9.0162,0.88186
+16,3,350,820,150,233.763,9.1845,0.88161
+16,4,350,820,150,233.233,9.1616,0.88229
+16,5,350,820,150,234.866,9.1689,0.88264
+16,6,350,820,150,235.813,9.1467,0.88175
+16,7,350,820,150,235.146,8.979,0.88298
+16,8,350,820,150,230.611,9.2715,0.88184
+16,9,350,820,150,229.191,9.3451,0.87982
+16,10,350,820,150,227.962,9.4103,0.88064
+16,11,350,820,150,228.802,9.3852,0.88068
+16,12,350,820,150,228.494,9.3225,0.87873
+16,13,350,820,150,229.894,9.3715,0.8808
+16,14,350,820,150,228.896,9.3628,0.87839
+16,15,350,820,150,229.631,9.3221,0.87892
+16,16,350,820,150,228.926,9.2514,0.88077
+16,17,350,820,150,227.714,9.1847,0.88118
+16,18,350,820,150,234.655,9.0425,0.88229
+16,19,350,820,150,234.541,9.0911,0.88328
+16,20,350,820,150,234.614,9.0232,0.88137
+16,21,350,820,150,235.135,9.1964,0.8827
+16,22,350,820,150,235.056,9.1589,0.88196
+16,23,350,820,150,234.56,9.1559,0.88187
+16,24,350,820,150,229.297,9.3606,0.88012
+16,25,350,820,150,229.912,9.3629,0.8806
+16,26,350,820,150,230.509,9.3365,0.88078
+18,1,350,820,150,228.446,9.1394,0.882
+18,2,350,820,150,228.228,9.2263,0.88109
+18,3,350,820,150,228.157,9.3743,0.88159
+18,4,350,820,150,227.709,9.2978,0.88255
+18,5,350,820,150,229.461,9.2777,0.88145
+18,6,350,820,150,230.567,9.3037,0.88103
+18,7,350,820,150,229.535,9.142,0.88119
+18,8,350,820,150,226.277,9.3444,0.88184
+18,9,350,820,150,225.378,9.6416,0.88213
+18,10,350,820,150,224.996,9.682,0.88166
+18,11,350,820,150,225.889,9.5442,0.88183
+18,12,350,820,150,226.963,9.5057,0.8794
+18,13,350,820,150,227.654,9.4551,0.88029
+18,14,350,820,150,227.983,9.5043,0.87875
+18,15,350,820,150,229.177,9.4398,0.87903
+18,16,350,820,150,228.004,9.48,0.88038
+18,17,350,820,150,225.563,9.4523,0.88227
+18,18,350,820,150,228.399,9.127,0.88081
+18,19,350,820,150,228.305,9.2,0.88204
+18,20,350,820,150,228.358,9.0938,0.87994
+18,21,350,820,150,229.816,9.3323,0.88149
+18,22,350,820,150,229.664,9.2771,0.88134
+18,23,350,820,150,229.116,9.279,0.88255
+18,24,350,820,150,227.467,9.4927,0.88179
+18,25,350,820,150,227.671,9.5128,0.88031
+18,26,350,820,150,227.944,9.4633,0.88128
generated by cgit v1.2.3 (git 2.46.0) at 2025年10月03日 18:41:05 +0000

AltStyle によって変換されたページ (->オリジナル) /