tioga 1.11 → 1.13
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
|