tioga 1.11 → 1.13
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/Tioga_README +58 -35
- data/{split/scripts → bin}/tioga +1 -1
- data/{split → ext/Dobjects}/Dtable/dtable.c +81 -15
- data/{split → ext/Dobjects}/Dtable/dtable_intern.h +0 -0
- data/ext/Dobjects/Dtable/extconf.rb +7 -0
- data/{split → ext/Dobjects}/Dtable/include/dtable.h +0 -0
- data/{split → ext/Dobjects}/Dvector/dvector.c +361 -51
- data/{split → ext/Dobjects}/Dvector/dvector_intern.h +0 -0
- data/ext/Dobjects/Dvector/extconf.rb +22 -0
- data/{split/Dtable → ext/Dobjects/Dvector/include}/dvector.h +0 -0
- data/ext/Dobjects/Function/extconf.rb +7 -0
- data/{split → ext/Dobjects}/Function/function.c +636 -11
- data/{split → ext/Dobjects}/Function/joint_qsort.c +0 -0
- data/ext/Flate/extconf.rb +26 -0
- data/{split → ext}/Flate/flate.c +7 -3
- data/{split → ext}/Flate/flate_intern.h +0 -0
- data/{split → ext}/Flate/include/flate.h +0 -0
- data/ext/Flate/zlib/adler32.c +149 -0
- data/ext/Flate/zlib/compress.c +79 -0
- data/ext/Flate/zlib/crc32.c +423 -0
- data/ext/Flate/zlib/crc32.h +441 -0
- data/ext/Flate/zlib/deflate.c +1736 -0
- data/ext/Flate/zlib/deflate.h +331 -0
- data/ext/Flate/zlib/gzio.c +1026 -0
- data/ext/Flate/zlib/infback.c +623 -0
- data/ext/Flate/zlib/inffast.c +318 -0
- data/ext/Flate/zlib/inffast.h +11 -0
- data/ext/Flate/zlib/inffixed.h +94 -0
- data/ext/Flate/zlib/inflate.c +1368 -0
- data/ext/Flate/zlib/inflate.h +115 -0
- data/ext/Flate/zlib/inftrees.c +329 -0
- data/ext/Flate/zlib/inftrees.h +55 -0
- data/ext/Flate/zlib/trees.c +1219 -0
- data/ext/Flate/zlib/trees.h +128 -0
- data/ext/Flate/zlib/uncompr.c +61 -0
- data/ext/Flate/zlib/zlib.h +1357 -0
- data/ext/Flate/zlib/zutil.c +318 -0
- data/ext/Flate/zlib/zutil.h +269 -0
- data/ext/Tioga/FigureMaker/__shared_axes.c +1373 -0
- data/ext/Tioga/FigureMaker/__shared_makers.c +1303 -0
- data/{split/Tioga/pdf_font_dicts.c → ext/Tioga/FigureMaker/__shared_pdf_font_dicts.c} +0 -0
- data/{split/Tioga/pdfcolor.c → ext/Tioga/FigureMaker/__shared_pdfcolor.c} +0 -0
- data/{split/Tioga/pdfcoords.c → ext/Tioga/FigureMaker/__shared_pdfcoords.c} +0 -0
- data/{split/Tioga/pdffile.c → ext/Tioga/FigureMaker/__shared_pdffile.c} +0 -0
- data/{split/Tioga/pdfimage.c → ext/Tioga/FigureMaker/__shared_pdfimage.c} +0 -0
- data/{split/Tioga/pdfpath.c → ext/Tioga/FigureMaker/__shared_pdfpath.c} +0 -0
- data/{split/Tioga/pdftext.c → ext/Tioga/FigureMaker/__shared_pdftext.c} +0 -0
- data/{split/Tioga/texout.c → ext/Tioga/FigureMaker/__shared_texout.c} +0 -0
- data/ext/Tioga/FigureMaker/extconf.rb +7 -0
- data/{split/Tioga → ext/Tioga/FigureMaker}/figures.c +14 -2
- data/{split/Tioga → ext/Tioga/FigureMaker}/figures.h +0 -0
- data/{split/Tioga → ext/Tioga/FigureMaker}/generic.c +1 -2
- data/{split/Tioga → ext/Tioga/FigureMaker}/generic.h +0 -1
- data/{split/Tioga → ext/Tioga/FigureMaker}/init.c +0 -0
- data/{split/Tioga → ext/Tioga/FigureMaker}/pdfs.h +0 -0
- data/{split/Tioga → ext/Tioga/FigureMaker/shared}/axes.c +32 -7
- data/{split/Tioga → ext/Tioga/FigureMaker/shared}/makers.c +2 -2
- data/ext/Tioga/FigureMaker/shared/pdf_font_dicts.c +18253 -0
- data/ext/Tioga/FigureMaker/shared/pdfcolor.c +904 -0
- data/ext/Tioga/FigureMaker/shared/pdfcoords.c +518 -0
- data/ext/Tioga/FigureMaker/shared/pdffile.c +451 -0
- data/ext/Tioga/FigureMaker/shared/pdfimage.c +539 -0
- data/ext/Tioga/FigureMaker/shared/pdfpath.c +766 -0
- data/ext/Tioga/FigureMaker/shared/pdftext.c +710 -0
- data/ext/Tioga/FigureMaker/shared/texout.c +533 -0
- data/{split/Tioga → ext/Tioga/FigureMaker}/wrappers.c +5 -5
- data/{split/Tioga → ext/Tioga/FigureMaker}/wrappers.h +0 -0
- data/{split/Dtable → ext/includes}/defs.h +0 -0
- data/{split/Dtable → ext/includes}/namespace.h +0 -0
- data/{split/Dtable → ext/includes}/safe_double.h +0 -0
- data/{split → ext/includes}/symbols.c +0 -1
- data/{split/Dtable → ext/includes}/symbols.h +0 -0
- data/{split/Dtable/lib → lib/Dobjects}/Dtable_extras.rb +0 -0
- data/{split/Dvector/lib → lib/Dobjects}/Dvector_extras.rb +1 -0
- data/{split/Function/lib → lib/Dobjects}/Function_extras.rb +0 -0
- data/{split/Dvector/lib → lib/Dobjects}/Numeric_extras.rb +0 -0
- data/{split/Tioga/lib → lib/Tioga}/Arcs_and_Circles.rb +0 -0
- data/{split/Tioga/lib → lib/Tioga}/ColorConstants.rb +0 -0
- data/{split/Tioga/lib → lib/Tioga}/Colorbars.rb +0 -0
- data/{split/Tioga/lib → lib/Tioga}/Colormaps.rb +0 -0
- data/{split/Tioga/lib → lib/Tioga}/Coordinate_Conversions.rb +0 -0
- data/{split/Tioga/lib → lib/Tioga}/Creating_Paths.rb +0 -0
- data/{split/Tioga/lib → lib/Tioga}/Doc.rb +0 -0
- data/{split/Tioga/lib → lib/Tioga}/Executive.rb +0 -0
- data/{split/Tioga/lib → lib/Tioga}/FigMkr.rb +13 -70
- data/{split/Tioga/lib → lib/Tioga}/FigureConstants.rb +0 -0
- data/{split/Tioga/lib → lib/Tioga}/Figures_and_Plots.rb +0 -0
- data/{split/Tioga/lib → lib/Tioga}/Images.rb +0 -0
- data/{split/Tioga/lib → lib/Tioga}/Legends.rb +0 -0
- data/{split/Tioga/lib → lib/Tioga}/MarkerConstants.rb +0 -0
- data/{split/Tioga/lib → lib/Tioga}/Markers.rb +0 -0
- data/{split/Tioga/lib → lib/Tioga}/Page_Frame_Bounds.rb +0 -0
- data/{split/Tioga/lib → lib/Tioga}/Rectangles.rb +0 -0
- data/{split/Tioga/lib → lib/Tioga}/Shading.rb +0 -0
- data/{split/Tioga/lib → lib/Tioga}/Special_Paths.rb +0 -0
- data/{split/Tioga/lib → lib/Tioga}/Strokes.rb +0 -0
- data/{split/Tioga/lib → lib/Tioga}/TeX_Text.rb +0 -0
- data/{split/Tioga/lib → lib/Tioga}/TexPreamble.rb +0 -0
- data/{split/Tioga/lib → lib/Tioga}/Titles_and_Labels.rb +0 -0
- data/{split/Tioga/lib → lib/Tioga}/Transparency.rb +0 -0
- data/{split/Tioga/lib → lib/Tioga}/Using_Paths.rb +0 -0
- data/{split/Tioga/lib → lib/Tioga}/Utils.rb +74 -0
- data/{split/Tioga/lib → lib/Tioga}/X_and_Y_Axes.rb +0 -0
- data/{split/Tioga/lib → lib/Tioga}/irb_tioga.rb +0 -0
- data/{split/Tioga/lib → lib/Tioga}/maker.rb +0 -0
- data/{split/Tioga/lib → lib/Tioga}/tioga.rb +0 -0
- data/{split/Tioga/lib → lib/Tioga}/tioga_ui.rb +0 -0
- data/{split/Tioga/lib → lib/Tioga}/tioga_ui_cmds.rb +0 -0
- data/tests/Icon_Test.pdf +0 -0
- data/tests/benchmark_dvector_reads.rb +20 -42
- data/tests/tc_Dvector.rb +45 -4
- data/tests/tc_Flate.rb +4 -5
- data/tests/tc_Function.rb +79 -0
- data/tests/vg.log +1453 -0
- metadata +141 -122
- data/split/Dtable/extconf.rb +0 -4
- data/split/Dvector/defs.h +0 -39
- data/split/Dvector/extconf.rb +0 -4
- data/split/Dvector/include/dvector.h +0 -77
- data/split/Dvector/namespace.h +0 -59
- data/split/Dvector/safe_double.h +0 -104
- data/split/Dvector/symbols.h +0 -52
- data/split/Flate/defs.h +0 -39
- data/split/Flate/extconf.rb +0 -19
- data/split/Flate/namespace.h +0 -59
- data/split/Flate/safe_double.h +0 -104
- data/split/Flate/symbols.h +0 -52
- data/split/Function/defs.h +0 -39
- data/split/Function/dvector.h +0 -77
- data/split/Function/extconf.rb +0 -4
- data/split/Function/namespace.h +0 -59
- data/split/Function/safe_double.h +0 -104
- data/split/Function/symbols.h +0 -52
- data/split/Tioga/defs.h +0 -39
- data/split/Tioga/dtable.h +0 -35
- data/split/Tioga/dvector.h +0 -77
- data/split/Tioga/extconf.rb +0 -4
- data/split/Tioga/flate.h +0 -98
- data/split/Tioga/mk_tioga_sty.rb +0 -53
- data/split/Tioga/namespace.h +0 -59
- data/split/Tioga/safe_double.h +0 -104
- data/split/Tioga/symbols.h +0 -52
- data/split/defs.h +0 -39
- data/split/extconf.rb +0 -125
- data/split/mkmf2.rb +0 -1623
- data/split/namespace.h +0 -59
- data/split/safe_double.h +0 -104
- data/split/symbols.h +0 -52
|
File without changes
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
# Dtable installation file
|
|
2
|
+
require 'mkmf'
|
|
3
|
+
|
|
4
|
+
# Conditional use of fftw3
|
|
5
|
+
if have_header("fftw3.h") and have_library("fftw3", "fftw_execute", "fftw3.h")
|
|
6
|
+
puts "fftw3 was found on this system: Fourier transforms will be available"
|
|
7
|
+
else
|
|
8
|
+
puts "fftw3 was not found on this system: no Fourier transforms"
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
# "Safe" way to store doubles (ie in a platform-independant way)
|
|
12
|
+
unless have_header("ieee754.h")
|
|
13
|
+
puts "You lack the ieee754.h header file, which might mean lower " +
|
|
14
|
+
"reliability when Marshalling Dvectors and Dtables"
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
# We add include directories
|
|
19
|
+
$INCFLAGS += " -I../../includes"
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
create_makefile 'Dobjects/Dvector'
|
|
File without changes
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
An object embedding two Dvectors for the ease of manipulation as
|
|
6
6
|
a function.
|
|
7
7
|
|
|
8
|
-
Copyright (C) 2006 Vincent Fourmond
|
|
8
|
+
Copyright (C) 2006,2010 Vincent Fourmond
|
|
9
9
|
|
|
10
10
|
This program is free software; you can redistribute it and/or modify
|
|
11
11
|
it under the terms of the GNU General Library Public License as published
|
|
@@ -26,12 +26,16 @@
|
|
|
26
26
|
#include <namespace.h>
|
|
27
27
|
#include <ruby.h>
|
|
28
28
|
|
|
29
|
-
#include "dvector.h"
|
|
30
|
-
#include "../symbols.c"
|
|
31
29
|
|
|
32
30
|
#include <math.h>
|
|
33
|
-
|
|
31
|
+
|
|
32
|
+
/* Private include files */
|
|
33
|
+
#include "dvector.h"
|
|
34
|
+
#include "symbols.c"
|
|
35
|
+
|
|
36
|
+
/* compiler-dependent defintions, such as is_okay_number */
|
|
34
37
|
#include <defs.h>
|
|
38
|
+
/* End of private files */
|
|
35
39
|
|
|
36
40
|
/* the class we're defining */
|
|
37
41
|
static VALUE cFunction;
|
|
@@ -609,6 +613,8 @@ static VALUE function_interpolate(VALUE self, VALUE x_values)
|
|
|
609
613
|
return Qnil;
|
|
610
614
|
}
|
|
611
615
|
|
|
616
|
+
|
|
617
|
+
|
|
612
618
|
/*
|
|
613
619
|
Strips all the points containing NaN values from the function, and
|
|
614
620
|
returns the number of points stripped.
|
|
@@ -644,7 +650,6 @@ static VALUE function_strip_nan(VALUE self)
|
|
|
644
650
|
Returns the array of the subfunctions. The returned values are
|
|
645
651
|
necessarily new values.
|
|
646
652
|
*/
|
|
647
|
-
|
|
648
653
|
static VALUE function_split_monotonic(VALUE self)
|
|
649
654
|
{
|
|
650
655
|
VALUE ret = rb_ary_new();
|
|
@@ -707,6 +712,60 @@ static VALUE function_split_monotonic(VALUE self)
|
|
|
707
712
|
}
|
|
708
713
|
|
|
709
714
|
|
|
715
|
+
/*
|
|
716
|
+
Splits the function on NaN values for x, y or xy, depending on
|
|
717
|
+
whether _sym_ is +:x+, +:y+ or +:xy+ (or, as a matter of fact,
|
|
718
|
+
anything else than +:x+ or +:y+).
|
|
719
|
+
|
|
720
|
+
This returns an array of new Function objects.
|
|
721
|
+
|
|
722
|
+
This function will return empty Function objects between consecutive
|
|
723
|
+
NaN values.
|
|
724
|
+
*/
|
|
725
|
+
static VALUE function_split_on_nan(VALUE self, VALUE sym)
|
|
726
|
+
{
|
|
727
|
+
VALUE ret = rb_ary_new();
|
|
728
|
+
VALUE cur_x = Dvector_Create();
|
|
729
|
+
VALUE cur_y = Dvector_Create();
|
|
730
|
+
int on_x = 1;
|
|
731
|
+
int on_y = 1;
|
|
732
|
+
long size = function_sanity_check(self);
|
|
733
|
+
long cur_size = 0;
|
|
734
|
+
long i;
|
|
735
|
+
if(size < 2)
|
|
736
|
+
rb_raise(rb_eRuntimeError, "Function needs to have at least 2 points");
|
|
737
|
+
|
|
738
|
+
double *x = Dvector_Data_for_Read(get_x_vector(self),NULL);
|
|
739
|
+
double *y = Dvector_Data_for_Read(get_y_vector(self),NULL);
|
|
740
|
+
|
|
741
|
+
VALUE f;
|
|
742
|
+
|
|
743
|
+
if(sym == ID2SYM(rb_intern("x")))
|
|
744
|
+
on_y = 0;
|
|
745
|
+
else if(sym == ID2SYM(rb_intern("y")))
|
|
746
|
+
on_x = 0;
|
|
747
|
+
|
|
748
|
+
|
|
749
|
+
for(i = 0; i < size; i++) {
|
|
750
|
+
if((on_x && isnan(x[i])) ||
|
|
751
|
+
(on_y && isnan(y[i]))) {
|
|
752
|
+
/* We split */
|
|
753
|
+
f = Function_Create(cur_x, cur_y);
|
|
754
|
+
rb_ary_push(ret, f);
|
|
755
|
+
cur_x = Dvector_Create();
|
|
756
|
+
cur_y = Dvector_Create();
|
|
757
|
+
}
|
|
758
|
+
else {
|
|
759
|
+
Dvector_Push_Double(cur_x, x[i]);
|
|
760
|
+
Dvector_Push_Double(cur_y, y[i]);
|
|
761
|
+
}
|
|
762
|
+
}
|
|
763
|
+
f = Function_Create(cur_x, cur_y);
|
|
764
|
+
rb_ary_push(ret, f);
|
|
765
|
+
return ret;
|
|
766
|
+
}
|
|
767
|
+
|
|
768
|
+
|
|
710
769
|
/*
|
|
711
770
|
Sorts the X values while keeping the matching Y values.
|
|
712
771
|
*/
|
|
@@ -899,7 +958,8 @@ static VALUE function_primitive(VALUE self)
|
|
|
899
958
|
Computes the derivative of the Function and returns it as a new Function.
|
|
900
959
|
The newly created function shares the X vector with the previous one.
|
|
901
960
|
|
|
902
|
-
WARNING: this is a very naive 3-points algorithm
|
|
961
|
+
WARNING: this is a very naive 3-points algorithm; you should
|
|
962
|
+
consider using diff_5p
|
|
903
963
|
*/
|
|
904
964
|
static VALUE function_derivative(VALUE self)
|
|
905
965
|
{
|
|
@@ -924,6 +984,139 @@ static VALUE function_derivative(VALUE self)
|
|
|
924
984
|
return Function_Create(get_x_vector(self), derivative);
|
|
925
985
|
}
|
|
926
986
|
|
|
987
|
+
/*
|
|
988
|
+
Computes a 4th order accurate derivative of the Function.
|
|
989
|
+
|
|
990
|
+
This function *requires* that there are at the very least 5 data
|
|
991
|
+
points !
|
|
992
|
+
*/
|
|
993
|
+
static VALUE function_diff_5p(VALUE self)
|
|
994
|
+
{
|
|
995
|
+
long size = function_sanity_check(self);
|
|
996
|
+
const double *x = Dvector_Data_for_Read(get_x_vector(self),NULL);
|
|
997
|
+
const double *y = Dvector_Data_for_Read(get_y_vector(self),NULL);
|
|
998
|
+
VALUE derivative = Dvector_Create();
|
|
999
|
+
long i = 0;
|
|
1000
|
+
double delta_1, delta_2, delta_3, delta_4;
|
|
1001
|
+
double alpha_1, alpha_2, alpha_3, alpha_4;
|
|
1002
|
+
double v0,v1,v2,v3,v4;
|
|
1003
|
+
/* TODO: what happens when there are less than 5 points ? */
|
|
1004
|
+
|
|
1005
|
+
for(i = 0; i < size; i++) {
|
|
1006
|
+
/* First initialize values, though this is very suboptimal */
|
|
1007
|
+
v0 = y[i];
|
|
1008
|
+
if(i == 0) {
|
|
1009
|
+
delta_1 = x[1] - x[0]; v1 = y[1];
|
|
1010
|
+
delta_2 = x[2] - x[0]; v2 = y[2];
|
|
1011
|
+
delta_3 = x[3] - x[0]; v3 = y[3];
|
|
1012
|
+
delta_4 = x[4] - x[0]; v4 = y[4];
|
|
1013
|
+
} else if(i == 1) {
|
|
1014
|
+
delta_1 = x[0] - x[1]; v1 = y[0];
|
|
1015
|
+
delta_2 = x[2] - x[1]; v2 = y[2];
|
|
1016
|
+
delta_3 = x[3] - x[1]; v3 = y[3];
|
|
1017
|
+
delta_4 = x[4] - x[1]; v4 = y[4];
|
|
1018
|
+
} else if(i == size - 2) {
|
|
1019
|
+
delta_1 = x[size-1] - x[size-2]; v1 = y[size-1];
|
|
1020
|
+
delta_2 = x[size-3] - x[size-2]; v2 = y[size-3];
|
|
1021
|
+
delta_3 = x[size-4] - x[size-2]; v3 = y[size-4];
|
|
1022
|
+
delta_4 = x[size-5] - x[size-2]; v4 = y[size-5];
|
|
1023
|
+
} else if(i == size - 1) {
|
|
1024
|
+
delta_1 = x[size-2] - x[size-1]; v1 = y[size-2];
|
|
1025
|
+
delta_2 = x[size-3] - x[size-1]; v2 = y[size-3];
|
|
1026
|
+
delta_3 = x[size-4] - x[size-1]; v3 = y[size-4];
|
|
1027
|
+
delta_4 = x[size-5] - x[size-1]; v4 = y[size-5];
|
|
1028
|
+
} else {
|
|
1029
|
+
delta_1 = x[i-2] - x[i]; v1 = y[i-2];
|
|
1030
|
+
delta_2 = x[i-1] - x[i]; v2 = y[i-1];
|
|
1031
|
+
delta_3 = x[i+2] - x[i]; v3 = y[i+2];
|
|
1032
|
+
delta_4 = x[i+1] - x[i]; v4 = y[i+1];
|
|
1033
|
+
}
|
|
1034
|
+
alpha_1 = delta_2*delta_3*delta_4/
|
|
1035
|
+
(delta_1 * (delta_2 - delta_1) * (delta_3 - delta_1)
|
|
1036
|
+
* (delta_4 - delta_1));
|
|
1037
|
+
alpha_2 = delta_1*delta_3*delta_4/
|
|
1038
|
+
(delta_2 * (delta_1 - delta_2) * (delta_3 - delta_2)
|
|
1039
|
+
* (delta_4 - delta_2));
|
|
1040
|
+
alpha_3 = delta_1*delta_2*delta_4/
|
|
1041
|
+
(delta_3 * (delta_1 - delta_3) * (delta_2 - delta_3)
|
|
1042
|
+
* (delta_4 - delta_3));
|
|
1043
|
+
alpha_4 = delta_1*delta_2*delta_3/
|
|
1044
|
+
(delta_4 * (delta_1 - delta_4) * (delta_2 - delta_4)
|
|
1045
|
+
* (delta_3 - delta_4));
|
|
1046
|
+
Dvector_Push_Double(derivative,
|
|
1047
|
+
-(alpha_1 + alpha_2 + alpha_3 + alpha_4) * v0 +
|
|
1048
|
+
alpha_1 * v1 + alpha_2 * v2 +
|
|
1049
|
+
alpha_3 * v3 + alpha_4 * v4);
|
|
1050
|
+
}
|
|
1051
|
+
return Function_Create(get_x_vector(self), derivative);
|
|
1052
|
+
}
|
|
1053
|
+
|
|
1054
|
+
/*
|
|
1055
|
+
Computes a 4th order accurate second derivative of the Function.
|
|
1056
|
+
|
|
1057
|
+
This function *requires* that there are at the very least 5 data
|
|
1058
|
+
points!
|
|
1059
|
+
*/
|
|
1060
|
+
static VALUE function_diff2_5p(VALUE self)
|
|
1061
|
+
{
|
|
1062
|
+
long size = function_sanity_check(self);
|
|
1063
|
+
const double *x = Dvector_Data_for_Read(get_x_vector(self),NULL);
|
|
1064
|
+
const double *y = Dvector_Data_for_Read(get_y_vector(self),NULL);
|
|
1065
|
+
VALUE derivative = Dvector_Create();
|
|
1066
|
+
long i = 0;
|
|
1067
|
+
double delta_1, delta_2, delta_3, delta_4;
|
|
1068
|
+
double alpha_1, alpha_2, alpha_3, alpha_4;
|
|
1069
|
+
double v0,v1,v2,v3,v4;
|
|
1070
|
+
|
|
1071
|
+
for(i = 0; i < size; i++) {
|
|
1072
|
+
/* First initialize values, though this is very suboptimal */
|
|
1073
|
+
v0 = y[i];
|
|
1074
|
+
if(i == 0) {
|
|
1075
|
+
delta_1 = x[1] - x[0]; v1 = y[1];
|
|
1076
|
+
delta_2 = x[2] - x[0]; v2 = y[2];
|
|
1077
|
+
delta_3 = x[3] - x[0]; v3 = y[3];
|
|
1078
|
+
delta_4 = x[4] - x[0]; v4 = y[4];
|
|
1079
|
+
} else if(i == 1) {
|
|
1080
|
+
delta_1 = x[0] - x[1]; v1 = y[0];
|
|
1081
|
+
delta_2 = x[2] - x[1]; v2 = y[2];
|
|
1082
|
+
delta_3 = x[3] - x[1]; v3 = y[3];
|
|
1083
|
+
delta_4 = x[4] - x[1]; v4 = y[4];
|
|
1084
|
+
} else if(i == size - 2) {
|
|
1085
|
+
delta_1 = x[size-1] - x[size-2]; v1 = y[size-1];
|
|
1086
|
+
delta_2 = x[size-3] - x[size-2]; v2 = y[size-3];
|
|
1087
|
+
delta_3 = x[size-4] - x[size-2]; v3 = y[size-4];
|
|
1088
|
+
delta_4 = x[size-5] - x[size-2]; v4 = y[size-5];
|
|
1089
|
+
} else if(i == size - 1) {
|
|
1090
|
+
delta_1 = x[size-2] - x[size-1]; v1 = y[size-2];
|
|
1091
|
+
delta_2 = x[size-3] - x[size-1]; v2 = y[size-3];
|
|
1092
|
+
delta_3 = x[size-4] - x[size-1]; v3 = y[size-4];
|
|
1093
|
+
delta_4 = x[size-5] - x[size-1]; v4 = y[size-5];
|
|
1094
|
+
} else {
|
|
1095
|
+
delta_1 = x[i-2] - x[i]; v1 = y[i-2];
|
|
1096
|
+
delta_2 = x[i-1] - x[i]; v2 = y[i-1];
|
|
1097
|
+
delta_3 = x[i+2] - x[i]; v3 = y[i+2];
|
|
1098
|
+
delta_4 = x[i+1] - x[i]; v4 = y[i+1];
|
|
1099
|
+
}
|
|
1100
|
+
alpha_1 = -2 * (delta_2*delta_3 + delta_2*delta_4 + delta_3*delta_4)/
|
|
1101
|
+
(delta_1 * (delta_2 - delta_1) * (delta_3 - delta_1)
|
|
1102
|
+
* (delta_4 - delta_1));
|
|
1103
|
+
alpha_2 = -2 * (delta_1*delta_3 + delta_1*delta_4 + delta_3*delta_4)/
|
|
1104
|
+
(delta_2 * (delta_1 - delta_2) * (delta_3 - delta_2)
|
|
1105
|
+
* (delta_4 - delta_2));
|
|
1106
|
+
alpha_3 = -2 * (delta_2*delta_1 + delta_2*delta_4 + delta_1*delta_4)/
|
|
1107
|
+
(delta_3 * (delta_1 - delta_3) * (delta_2 - delta_3)
|
|
1108
|
+
* (delta_4 - delta_3));
|
|
1109
|
+
alpha_4 = -2 * (delta_2*delta_3 + delta_2*delta_1 + delta_3*delta_1)/
|
|
1110
|
+
(delta_4 * (delta_1 - delta_4) * (delta_2 - delta_4)
|
|
1111
|
+
* (delta_3 - delta_4));
|
|
1112
|
+
Dvector_Push_Double(derivative,
|
|
1113
|
+
-(alpha_1 + alpha_2 + alpha_3 + alpha_4) * v0 +
|
|
1114
|
+
alpha_1 * v1 + alpha_2 * v2 +
|
|
1115
|
+
alpha_3 * v3 + alpha_4 * v4);
|
|
1116
|
+
}
|
|
1117
|
+
return Function_Create(get_x_vector(self), derivative);
|
|
1118
|
+
}
|
|
1119
|
+
|
|
927
1120
|
/*
|
|
928
1121
|
Returns the number of points inside the function.
|
|
929
1122
|
*/
|
|
@@ -1026,6 +1219,418 @@ static VALUE function_bound_values(VALUE self,
|
|
|
1026
1219
|
return Function_Create(x_out, y_out);
|
|
1027
1220
|
}
|
|
1028
1221
|
|
|
1222
|
+
/* Reverses the function. Equivalent to doing
|
|
1223
|
+
|
|
1224
|
+
x.reverse!
|
|
1225
|
+
y.reverse!
|
|
1226
|
+
|
|
1227
|
+
excepted that it is faster (though not *much* faster).
|
|
1228
|
+
*/
|
|
1229
|
+
static VALUE function_reverse(VALUE self)
|
|
1230
|
+
{
|
|
1231
|
+
long len = function_sanity_check(self);
|
|
1232
|
+
double *xs = Dvector_Data_for_Write(get_x_vector(self),NULL);
|
|
1233
|
+
double *ys = Dvector_Data_for_Write(get_y_vector(self),NULL);
|
|
1234
|
+
|
|
1235
|
+
double *xe = xs+len-1;
|
|
1236
|
+
double *ye = ys+len-1;
|
|
1237
|
+
double tmp;
|
|
1238
|
+
long i;
|
|
1239
|
+
for(i = 0; i < len/2; i++, xs++, ys++, xe--, ye--) {
|
|
1240
|
+
tmp = *xe; *xe = *xs; *xs = tmp;
|
|
1241
|
+
tmp = *ye; *ye = *ys; *ys = tmp;
|
|
1242
|
+
}
|
|
1243
|
+
return self;
|
|
1244
|
+
}
|
|
1245
|
+
|
|
1246
|
+
/* Computes the linear regression of the dataset. */
|
|
1247
|
+
static void reglin(const double *x, const double *y, long nb,
|
|
1248
|
+
double *a, double *b)
|
|
1249
|
+
{
|
|
1250
|
+
double sx = 0;
|
|
1251
|
+
double sy = 0;
|
|
1252
|
+
double sxx = 0;
|
|
1253
|
+
double sxy = 0;
|
|
1254
|
+
long i = 0;
|
|
1255
|
+
double det;
|
|
1256
|
+
for(i = 0; i < nb; i++, x++, y++) {
|
|
1257
|
+
sx += *x;
|
|
1258
|
+
sy += *y;
|
|
1259
|
+
sxx += *x * *x;
|
|
1260
|
+
sxy += *x * *y;
|
|
1261
|
+
}
|
|
1262
|
+
det = nb*sxx - sx*sx;
|
|
1263
|
+
if(det == 0) {
|
|
1264
|
+
*a = 0; /* Whichever, we only have one point */
|
|
1265
|
+
*b = sy/nb;
|
|
1266
|
+
}
|
|
1267
|
+
else {
|
|
1268
|
+
*a = (nb *sxy - sx*sy)/det;
|
|
1269
|
+
*b = (sxx * sy - sx * sxy)/(det);
|
|
1270
|
+
}
|
|
1271
|
+
}
|
|
1272
|
+
|
|
1273
|
+
|
|
1274
|
+
/*
|
|
1275
|
+
Performs a linear regression of the Function; returns the pair
|
|
1276
|
+
[ a, b]
|
|
1277
|
+
where f(x) = a*x + b
|
|
1278
|
+
|
|
1279
|
+
if the optional arguments _first_ and _last_ are provided, they
|
|
1280
|
+
represent the indices of the first and last elements.
|
|
1281
|
+
*/
|
|
1282
|
+
static VALUE function_reglin(int argc, VALUE *argv, VALUE self)
|
|
1283
|
+
{
|
|
1284
|
+
long len = function_sanity_check(self);
|
|
1285
|
+
const double *x = Dvector_Data_for_Read(get_x_vector(self),NULL);
|
|
1286
|
+
const double *y = Dvector_Data_for_Read(get_y_vector(self),NULL);
|
|
1287
|
+
VALUE ret = rb_funcall(cDvector, idNew, 1, INT2NUM(2));
|
|
1288
|
+
double * dat = Dvector_Data_for_Write(ret, NULL);
|
|
1289
|
+
long nb;
|
|
1290
|
+
if(argc == 2) {
|
|
1291
|
+
long f = NUM2LONG(argv[0]);
|
|
1292
|
+
long l = NUM2LONG(argv[1]);
|
|
1293
|
+
if(f < 0)
|
|
1294
|
+
f = len + f;
|
|
1295
|
+
if(l < 0)
|
|
1296
|
+
l = len + l;
|
|
1297
|
+
x += f;
|
|
1298
|
+
y += f;
|
|
1299
|
+
nb = l - f;
|
|
1300
|
+
}
|
|
1301
|
+
else if(argc == 0) {
|
|
1302
|
+
nb = len;
|
|
1303
|
+
}
|
|
1304
|
+
else {
|
|
1305
|
+
rb_raise(rb_eArgError, "reglin should have 0 or 2 parameters");
|
|
1306
|
+
}
|
|
1307
|
+
reglin(x,y,nb,dat,dat+1);
|
|
1308
|
+
return ret;
|
|
1309
|
+
}
|
|
1310
|
+
|
|
1311
|
+
|
|
1312
|
+
/* Simply returns the sign */
|
|
1313
|
+
static int signof(double x)
|
|
1314
|
+
{
|
|
1315
|
+
if(x > 0)
|
|
1316
|
+
return 1;
|
|
1317
|
+
else if(x < 0)
|
|
1318
|
+
return -1;
|
|
1319
|
+
else
|
|
1320
|
+
return 0;
|
|
1321
|
+
}
|
|
1322
|
+
|
|
1323
|
+
/*
|
|
1324
|
+
Returns a "smoothed" value, according to the algorithm implented
|
|
1325
|
+
for "smooth" markers in Soas. See DOI:
|
|
1326
|
+
10.1016/j.bioelechem.2009.02.010
|
|
1327
|
+
|
|
1328
|
+
Basically, we start at a given range, and narrow the range until
|
|
1329
|
+
the number of consecutive residuals of the same sign is lower than
|
|
1330
|
+
a quarter of the interval.
|
|
1331
|
+
|
|
1332
|
+
It works
|
|
1333
|
+
|
|
1334
|
+
*/
|
|
1335
|
+
double smooth_pick(const double *x, const double *y,
|
|
1336
|
+
long nb, long idx, long range)
|
|
1337
|
+
{
|
|
1338
|
+
long left, right,i,nb_same_sign;
|
|
1339
|
+
double a,b;
|
|
1340
|
+
int last_sign;
|
|
1341
|
+
do {
|
|
1342
|
+
left = idx - range/2;
|
|
1343
|
+
if(left < 0)
|
|
1344
|
+
left = 0;
|
|
1345
|
+
right = idx + range/2;
|
|
1346
|
+
if(right > nb)
|
|
1347
|
+
right = nb;
|
|
1348
|
+
reglin(x+left, y+left, right-left,&a,&b);
|
|
1349
|
+
if(range == 6)
|
|
1350
|
+
break; /* We stop here */
|
|
1351
|
+
last_sign = 0;
|
|
1352
|
+
for(i = left; i < right; i++) {
|
|
1353
|
+
double residual = y[i] - a * x[i] - b;
|
|
1354
|
+
if(! last_sign)
|
|
1355
|
+
last_sign = signof(residual);
|
|
1356
|
+
else if(last_sign == signof(residual))
|
|
1357
|
+
nb_same_sign ++;
|
|
1358
|
+
else {
|
|
1359
|
+
nb_same_sign = 1;
|
|
1360
|
+
last_sign = signof(residual);
|
|
1361
|
+
}
|
|
1362
|
+
}
|
|
1363
|
+
if(nb_same_sign * 4 <= right - left)
|
|
1364
|
+
break;
|
|
1365
|
+
range -= (nb_same_sign * 4 -range)/2 + 2;
|
|
1366
|
+
if(range < 6)
|
|
1367
|
+
range = 6;
|
|
1368
|
+
} while(1);
|
|
1369
|
+
/* Now, we have a and b for the last range measured. */
|
|
1370
|
+
return a*x[idx] + b;
|
|
1371
|
+
}
|
|
1372
|
+
|
|
1373
|
+
/*
|
|
1374
|
+
Attempts to pick a smooth value for a point, according to the
|
|
1375
|
+
algorithm implented for "smooth" markers in Soas. See DOI:
|
|
1376
|
+
10.1016/j.bioelechem.2009.02.010
|
|
1377
|
+
|
|
1378
|
+
Warning: be wary of this function as it will return a correct
|
|
1379
|
+
value only for rather noisy data !
|
|
1380
|
+
*/
|
|
1381
|
+
static VALUE function_smooth_pick(int argc, VALUE *argv, VALUE self)
|
|
1382
|
+
{
|
|
1383
|
+
long len = function_sanity_check(self);
|
|
1384
|
+
const double *x = Dvector_Data_for_Read(get_x_vector(self),NULL);
|
|
1385
|
+
const double *y = Dvector_Data_for_Read(get_y_vector(self),NULL);
|
|
1386
|
+
long idx;
|
|
1387
|
+
long range;
|
|
1388
|
+
switch(argc) {
|
|
1389
|
+
case 2:
|
|
1390
|
+
range = NUM2LONG(argv[1]);
|
|
1391
|
+
break;
|
|
1392
|
+
case 1:
|
|
1393
|
+
range = len > 500 ? 50 : len/10;
|
|
1394
|
+
break;
|
|
1395
|
+
default:
|
|
1396
|
+
rb_raise(rb_eArgError, "smooth_a=t should have 1 or 2 parameters");
|
|
1397
|
+
}
|
|
1398
|
+
idx = NUM2LONG(argv[0]);
|
|
1399
|
+
if(idx < 0)
|
|
1400
|
+
idx = len + idx;
|
|
1401
|
+
return rb_float_new(smooth_pick(x,y,len,idx,range));
|
|
1402
|
+
}
|
|
1403
|
+
|
|
1404
|
+
/*
|
|
1405
|
+
Computes the convolution of the kernel with the dataset; the
|
|
1406
|
+
overall result is scaled
|
|
1407
|
+
*/
|
|
1408
|
+
static double norm_convolve(const double *y, long len, long idx,
|
|
1409
|
+
const double * kernel, long klen, long kmid)
|
|
1410
|
+
{
|
|
1411
|
+
double ret = 0;
|
|
1412
|
+
long ki,yi;
|
|
1413
|
+
double norm = 0;
|
|
1414
|
+
yi = idx - kmid;
|
|
1415
|
+
/* We ensure we don't go */
|
|
1416
|
+
if(yi < 0) {
|
|
1417
|
+
ki -= yi;
|
|
1418
|
+
yi = 0;
|
|
1419
|
+
}
|
|
1420
|
+
for(; ki < klen && yi < len; yi++, ki++) {
|
|
1421
|
+
norm += kernel[ki];
|
|
1422
|
+
ret += kernel[ki] * y[yi];
|
|
1423
|
+
}
|
|
1424
|
+
return ret/norm;
|
|
1425
|
+
}
|
|
1426
|
+
|
|
1427
|
+
/*
|
|
1428
|
+
This functions tries to approximate the given data using a spline.
|
|
1429
|
+
|
|
1430
|
+
The algorithm is the following:
|
|
1431
|
+
* one starts with 3 points: 2 on the sides and one at the middle
|
|
1432
|
+
* then, we pick an interval between the points where the sum of the
|
|
1433
|
+
square of the residuals is the greatest, and place a point there.
|
|
1434
|
+
* then, we repeat until we reach a maximum number of points (_nbmax_)
|
|
1435
|
+
|
|
1436
|
+
Point positions are averaged over _nbavg_ using a gaussian-like
|
|
1437
|
+
filter.
|
|
1438
|
+
|
|
1439
|
+
Interpolation is returned into the _xi_, _yi_ and _y2i_ vectors
|
|
1440
|
+
|
|
1441
|
+
TODO: try to place the points more in the middle ? (provide a factor
|
|
1442
|
+
governing this)
|
|
1443
|
+
|
|
1444
|
+
TODO: use moments to decide of the precise position of the
|
|
1445
|
+
points ?
|
|
1446
|
+
|
|
1447
|
+
*/
|
|
1448
|
+
static void internal_spline_approximation(const double *x, const double *y,
|
|
1449
|
+
long len,
|
|
1450
|
+
double *xi, double *yi,
|
|
1451
|
+
double *y2i,
|
|
1452
|
+
long nbmax,
|
|
1453
|
+
long nbavg,
|
|
1454
|
+
double * target)
|
|
1455
|
+
{
|
|
1456
|
+
double left_slope; /* Derivative on the left */
|
|
1457
|
+
double right_slope; /* Same on the right */
|
|
1458
|
+
|
|
1459
|
+
/* The gaussian kernel for the average */
|
|
1460
|
+
double kernel[nbavg];
|
|
1461
|
+
|
|
1462
|
+
/* The indices of the point where the residuals are maximal */
|
|
1463
|
+
long max_res_idx[nbmax-1];
|
|
1464
|
+
|
|
1465
|
+
/* The indices of the corner points*/
|
|
1466
|
+
long indices[nbmax];
|
|
1467
|
+
|
|
1468
|
+
long i;
|
|
1469
|
+
long cur_size = 3;
|
|
1470
|
+
double tmp,tmp2;
|
|
1471
|
+
/* Initialization of the kernel */
|
|
1472
|
+
long mid = nbavg/2; /* Middle of the kernel */
|
|
1473
|
+
for(i = 0,tmp=0; i < nbavg; i++) {
|
|
1474
|
+
tmp = (3.2 * (i - nbavg/2))/nbavg; /* Gives about 7% left on the
|
|
1475
|
+
side elements */
|
|
1476
|
+
tmp = exp(-tmp*tmp);
|
|
1477
|
+
kernel[i] = tmp;
|
|
1478
|
+
}
|
|
1479
|
+
|
|
1480
|
+
/* Left side */
|
|
1481
|
+
xi[0] = x[0];
|
|
1482
|
+
reglin(x,y, mid+1, &left_slope, &tmp2);
|
|
1483
|
+
yi[0] = left_slope * x[0] + tmp2;
|
|
1484
|
+
indices[0] = 0;
|
|
1485
|
+
|
|
1486
|
+
/* Middle */
|
|
1487
|
+
xi[1] = x[len/2];
|
|
1488
|
+
yi[1] = norm_convolve(y, len, len/2, kernel, nbavg, mid);
|
|
1489
|
+
indices[1] = len/2;
|
|
1490
|
+
|
|
1491
|
+
/* Right */
|
|
1492
|
+
xi[2] = x[len-1];
|
|
1493
|
+
reglin(x+(len-(mid+2)),y + (len-(mid+2)), mid+1, &right_slope, &tmp2);
|
|
1494
|
+
yi[2] = right_slope * x[len-1] + tmp2;
|
|
1495
|
+
indices[2] = len - 1;
|
|
1496
|
+
|
|
1497
|
+
do {
|
|
1498
|
+
long cur_seg;
|
|
1499
|
+
long max_res_seg = 0; /* The segment where the residuals are
|
|
1500
|
+
the greatest */
|
|
1501
|
+
double max_res = 0;
|
|
1502
|
+
|
|
1503
|
+
long max_deviation_seg = 0; /* The segment where the deviation
|
|
1504
|
+
(square of the average) is the
|
|
1505
|
+
greatest */
|
|
1506
|
+
double max_deviation = 0;
|
|
1507
|
+
|
|
1508
|
+
long chosen_seg; /* The segment in which we'll add a point */
|
|
1509
|
+
/* Compute interpolation */
|
|
1510
|
+
function_fill_second_derivatives(cur_size, xi, yi, y2i,
|
|
1511
|
+
left_slope, right_slope);
|
|
1512
|
+
|
|
1513
|
+
|
|
1514
|
+
/* We stop here if we have reached the max number and we're not
|
|
1515
|
+
interested in Y values */
|
|
1516
|
+
if(cur_size >= nbmax && !target)
|
|
1517
|
+
break;
|
|
1518
|
+
|
|
1519
|
+
/* Now we compute the residuals */
|
|
1520
|
+
for(cur_seg = 0; cur_seg < cur_size - 1; cur_seg++) {
|
|
1521
|
+
double residuals = 0;
|
|
1522
|
+
double a,b,int_y,delta,h = xi[cur_seg+1] - xi[cur_seg];
|
|
1523
|
+
double imr = 0; /* Internal max residuals */
|
|
1524
|
+
double deviation = 0;
|
|
1525
|
+
/* printf("seg: %ld/%ld indices %ld -- %ld\n", cur_seg, cur_size-1, */
|
|
1526
|
+
/* indices[cur_seg], indices[cur_seg+1]); */
|
|
1527
|
+
for(i = indices[cur_seg] + 1; i < indices[cur_seg+1]; i++) {
|
|
1528
|
+
a = (xi[cur_seg+1] - x[i])/h;
|
|
1529
|
+
b = (x[i] - xi[cur_seg])/h;
|
|
1530
|
+
int_y = a * yi[cur_seg] + b * yi[cur_seg + 1]
|
|
1531
|
+
+ ((a*a*a - a) * y2i[cur_seg] +
|
|
1532
|
+
(b*b*b - b) * y2i[cur_seg + 1]) *
|
|
1533
|
+
(h * h)/6.0;
|
|
1534
|
+
if(target) /* We set the value if applicable. */
|
|
1535
|
+
target[i] = int_y;
|
|
1536
|
+
delta = int_y - y[i];
|
|
1537
|
+
deviation += delta;
|
|
1538
|
+
delta *= delta;
|
|
1539
|
+
residuals += delta;
|
|
1540
|
+
if(delta > imr) {
|
|
1541
|
+
imr = delta;
|
|
1542
|
+
max_res_idx[cur_seg] = i;
|
|
1543
|
+
}
|
|
1544
|
+
}
|
|
1545
|
+
if(max_res < residuals) {
|
|
1546
|
+
max_res = residuals;
|
|
1547
|
+
max_res_seg = cur_seg;
|
|
1548
|
+
}
|
|
1549
|
+
deviation *= deviation;
|
|
1550
|
+
if(deviation > max_deviation) {
|
|
1551
|
+
max_deviation_seg = cur_seg;
|
|
1552
|
+
max_deviation = deviation;
|
|
1553
|
+
}
|
|
1554
|
+
/* printf(" -> residuals %g\n", cur_seg, cur_size-1, */
|
|
1555
|
+
/* residuals); */
|
|
1556
|
+
}
|
|
1557
|
+
/* printf("-> max residuals at segment %d\n", max_res_seg); */
|
|
1558
|
+
|
|
1559
|
+
if(cur_size >= nbmax)
|
|
1560
|
+
break;
|
|
1561
|
+
|
|
1562
|
+
|
|
1563
|
+
/* OK, so now we know in which segment the residuals are the
|
|
1564
|
+
greatest, and which point of this segment is holds the max
|
|
1565
|
+
residuals. So we just add a point there */
|
|
1566
|
+
chosen_seg = max_deviation_seg;
|
|
1567
|
+
|
|
1568
|
+
/* We shift the positions */
|
|
1569
|
+
for(i = cur_size; i > chosen_seg + 1; i--) {
|
|
1570
|
+
xi[i] = xi[i-1];
|
|
1571
|
+
yi[i] = yi[i-1];
|
|
1572
|
+
y2i[i] = y2i[i-1];
|
|
1573
|
+
indices[i] = indices[i-1];
|
|
1574
|
+
}
|
|
1575
|
+
cur_size++;
|
|
1576
|
+
xi[chosen_seg + 1] = x[max_res_idx[chosen_seg]];
|
|
1577
|
+
yi[chosen_seg + 1] = norm_convolve(y, len, max_res_idx[chosen_seg],
|
|
1578
|
+
kernel, nbavg, mid);
|
|
1579
|
+
indices[chosen_seg + 1] = max_res_idx[chosen_seg];
|
|
1580
|
+
} while(1);
|
|
1581
|
+
|
|
1582
|
+
/* Now fill in the missing values of y, since we do not evaluate them */
|
|
1583
|
+
if(target) {
|
|
1584
|
+
for(i = 0; i < nbmax; i++)
|
|
1585
|
+
target[indices[i]] = yi[i];
|
|
1586
|
+
}
|
|
1587
|
+
|
|
1588
|
+
|
|
1589
|
+
}
|
|
1590
|
+
|
|
1591
|
+
/*
|
|
1592
|
+
Filters the Function through interpolation. _params_ holds a
|
|
1593
|
+
hash with the following values:
|
|
1594
|
+
* ??
|
|
1595
|
+
|
|
1596
|
+
It returns a hash.
|
|
1597
|
+
*/
|
|
1598
|
+
static VALUE function_spline_approximation(VALUE self, VALUE params)
|
|
1599
|
+
{
|
|
1600
|
+
long len = function_sanity_check(self);
|
|
1601
|
+
const double *x = Dvector_Data_for_Read(get_x_vector(self),NULL);
|
|
1602
|
+
const double *y = Dvector_Data_for_Read(get_y_vector(self),NULL);
|
|
1603
|
+
VALUE xiret, yiret, y2iret, yintret,ret;
|
|
1604
|
+
double * xi, *yi, *y2i, *yint;
|
|
1605
|
+
long nbavg = 9;
|
|
1606
|
+
long nbmax = 20;
|
|
1607
|
+
if(RTEST(rb_hash_aref(params, rb_str_new2("number"))))
|
|
1608
|
+
nbmax = NUM2LONG(rb_hash_aref(params, rb_str_new2("number")));
|
|
1609
|
+
if(RTEST(rb_hash_aref(params, rb_str_new2("average"))))
|
|
1610
|
+
nbavg = NUM2LONG(rb_hash_aref(params, rb_str_new2("average")));
|
|
1611
|
+
|
|
1612
|
+
/* TODO: add checks that monotonic and growing. */
|
|
1613
|
+
|
|
1614
|
+
xiret = rb_funcall(cDvector, idNew, 1, INT2NUM(nbmax));
|
|
1615
|
+
xi = Dvector_Data_for_Write(xiret, NULL);
|
|
1616
|
+
yiret = rb_funcall(cDvector, idNew, 1, INT2NUM(nbmax));
|
|
1617
|
+
yi = Dvector_Data_for_Write(yiret, NULL);
|
|
1618
|
+
y2iret = rb_funcall(cDvector, idNew, 1, INT2NUM(nbmax));
|
|
1619
|
+
y2i = Dvector_Data_for_Write(y2iret, NULL);
|
|
1620
|
+
yintret = rb_funcall(cDvector, idNew, 1, INT2NUM(len));
|
|
1621
|
+
yint = Dvector_Data_for_Write(yintret, NULL);
|
|
1622
|
+
|
|
1623
|
+
internal_spline_approximation(x, y, len, xi, yi, y2i,
|
|
1624
|
+
nbmax, nbavg, yint);
|
|
1625
|
+
ret = rb_hash_new();
|
|
1626
|
+
rb_hash_aset(ret, rb_str_new2("xi"), xiret);
|
|
1627
|
+
rb_hash_aset(ret, rb_str_new2("yi"), yiret);
|
|
1628
|
+
rb_hash_aset(ret, rb_str_new2("y2i"), y2iret);
|
|
1629
|
+
rb_hash_aset(ret, rb_str_new2("y"), yintret);
|
|
1630
|
+
return ret;
|
|
1631
|
+
}
|
|
1632
|
+
|
|
1633
|
+
|
|
1029
1634
|
/*
|
|
1030
1635
|
Document-class: Dobjects::Function
|
|
1031
1636
|
|
|
@@ -1035,16 +1640,21 @@ static VALUE function_bound_values(VALUE self,
|
|
|
1035
1640
|
- facilities for sorting the X while keeping the Y matching, with #sort and
|
|
1036
1641
|
Function.joint_sort;
|
|
1037
1642
|
- to check if X data is sorted: #sorted?, #is_sorted;
|
|
1038
|
-
- interpolation, with #compute_spline, #compute_spline_data and #interpolate
|
|
1643
|
+
- interpolation, with #compute_spline, #compute_spline_data and #interpolate
|
|
1039
1644
|
- some functions for data access : #x, #y, #point;
|
|
1040
|
-
- some utiliy functions: #split_monotonic, #strip_nan
|
|
1645
|
+
- some utiliy functions: #split_monotonic, #strip_nan, #reverse!
|
|
1041
1646
|
- data inspection: #min, #max;
|
|
1042
|
-
- some computational functions: #integrate, #primitive, #derivative
|
|
1647
|
+
- some computational functions: #integrate, #primitive, #derivative,
|
|
1648
|
+
and now 4th-order accurate first and second derivatives: #diff_5p
|
|
1649
|
+
and #diff2_5p
|
|
1043
1650
|
- utility for fuzzy operations, when the X values of two functions
|
|
1044
1651
|
differ, but only slightly, of when points are missing:
|
|
1045
1652
|
#fuzzy_sub!
|
|
1653
|
+
- linear regression #reglin
|
|
1654
|
+
- a function to approximate data using a low-order spline:
|
|
1655
|
+
#spline_approximation
|
|
1046
1656
|
|
|
1047
|
-
And getting bigger everyday...
|
|
1657
|
+
And getting bigger (almost) everyday...
|
|
1048
1658
|
*/
|
|
1049
1659
|
void Init_Function()
|
|
1050
1660
|
{
|
|
@@ -1059,6 +1669,7 @@ void Init_Function()
|
|
|
1059
1669
|
|
|
1060
1670
|
rb_define_method(cFunction, "initialize", function_initialize, 2);
|
|
1061
1671
|
rb_define_method(cFunction, "sorted?", function_is_sorted, 0);
|
|
1672
|
+
rb_define_method(cFunction, "reverse!", function_reverse, 0);
|
|
1062
1673
|
rb_define_alias(cFunction, "is_sorted", "sorted?");
|
|
1063
1674
|
|
|
1064
1675
|
rb_define_singleton_method(cFunction, "joint_sort", function_joint_sort, 2);
|
|
@@ -1074,15 +1685,24 @@ void Init_Function()
|
|
|
1074
1685
|
function_interpolate, 1);
|
|
1075
1686
|
rb_define_method(cFunction, "make_interpolant",
|
|
1076
1687
|
function_make_interpolant, 0);
|
|
1688
|
+
rb_define_method(cFunction, "spline_approximation",
|
|
1689
|
+
function_spline_approximation, 1);
|
|
1690
|
+
|
|
1077
1691
|
|
|
1078
1692
|
/* access to data */
|
|
1079
1693
|
rb_define_method(cFunction, "point", function_point, 1);
|
|
1694
|
+
rb_define_method(cFunction, "[]", function_point, 1);
|
|
1080
1695
|
rb_define_method(cFunction, "x", get_x_vector, 0);
|
|
1081
1696
|
rb_define_method(cFunction, "y", get_y_vector, 0);
|
|
1082
1697
|
|
|
1083
1698
|
|
|
1084
1699
|
rb_define_method(cFunction, "size", function_size, 0);
|
|
1085
1700
|
rb_define_alias(cFunction, "length", "size");
|
|
1701
|
+
|
|
1702
|
+
/* Soas-like functions ;-) */
|
|
1703
|
+
rb_define_method(cFunction, "reglin", function_reglin, -1);
|
|
1704
|
+
rb_define_method(cFunction, "smooth_pick", function_smooth_pick, -1);
|
|
1705
|
+
|
|
1086
1706
|
|
|
1087
1707
|
|
|
1088
1708
|
/* iterator */
|
|
@@ -1092,8 +1712,9 @@ void Init_Function()
|
|
|
1092
1712
|
/* stripping of NaNs */
|
|
1093
1713
|
rb_define_method(cFunction, "strip_nan", function_strip_nan, 0);
|
|
1094
1714
|
|
|
1095
|
-
/* split into
|
|
1715
|
+
/* split into subfunctions with given properties */
|
|
1096
1716
|
rb_define_method(cFunction, "split_monotonic", function_split_monotonic, 0);
|
|
1717
|
+
rb_define_method(cFunction, "split_on_nan", function_split_on_nan, 1);
|
|
1097
1718
|
|
|
1098
1719
|
/* integration between two integer boundaries */
|
|
1099
1720
|
rb_define_method(cFunction, "integrate", function_integrate, -1);
|
|
@@ -1102,6 +1723,10 @@ void Init_Function()
|
|
|
1102
1723
|
/* derivative */
|
|
1103
1724
|
rb_define_method(cFunction, "derivative", function_derivative, 0);
|
|
1104
1725
|
|
|
1726
|
+
/* 5-points derivatives */
|
|
1727
|
+
rb_define_method(cFunction, "diff_5p", function_diff_5p, 0);
|
|
1728
|
+
rb_define_method(cFunction, "diff2_5p", function_diff2_5p, 0);
|
|
1729
|
+
|
|
1105
1730
|
/* distance to a point */
|
|
1106
1731
|
rb_define_method(cFunction, "distance", function_distance, -1);
|
|
1107
1732
|
|