carray-calculus 1.0.0

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.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: e00ee8dc33750df8eb85835a3d3752789c1ba9c7d109de0f4879080eb091aa20
4
+ data.tar.gz: 604d60ac2d8e239af4d94da05bfbd7de80a53d8740ceb8a76f40357a3d79d965
5
+ SHA512:
6
+ metadata.gz: 1a13531450e20471ec60f6163c8b9fcd6050dd15dfb79784d2a44050d5a98c121ccd325089246171474448d3c9f8cf3cc026d415314211eb2fd394fe4061fc96
7
+ data.tar.gz: 2e9919c89518d1468ec6a1a8d193cf907b96f4f3ae7265b117456074d3d0b7b6c44ae0294c00cea7719a787a8c7e97e544a82090f3f1b36523adb1b301b83835
data/Rakefile ADDED
@@ -0,0 +1,11 @@
1
+ GEMSPEC = "carray-calculus.gemspec"
2
+
3
+ task :install do
4
+ spec = eval File.read(GEMSPEC)
5
+ system %{
6
+ gem build #{GEMSPEC}; gem install #{spec.full_name}.gem
7
+ }
8
+ end
9
+
10
+ require 'rspec/core/rake_task'
11
+ RSpec::Core::RakeTask.new
@@ -0,0 +1,25 @@
1
+ Gem::Specification::new do |s|
2
+ version = "1.0.0"
3
+ files = Dir.glob("**/*") - [
4
+ Dir.glob("carray-calculus-*.gem"),
5
+ Dir.glob("test/**/*"),
6
+ Dir.glob("work/**/*"),
7
+ ].flatten
8
+
9
+ s.platform = Gem::Platform::RUBY
10
+ s.name = "carray-calculus"
11
+ s.summary = "CArray methods on basic calculus"
12
+ s.description = <<-HERE
13
+ CArray methods on basic calculus
14
+ HERE
15
+ s.version = version
16
+ s.licenses = ['MIT']
17
+ s.author = "Hiroki Motoyoshi"
18
+ s.email = ""
19
+ s.homepage = 'https://github.com/himotoyoshi/carray-calculus'
20
+ s.files = files
21
+ s.extensions = [ "ext/extconf.rb" ]
22
+ s.required_ruby_version = ">= 2.4.0"
23
+ s.add_runtime_dependency 'carray', '~> 1.5', ">= 1.5"
24
+ end
25
+
data/ext/Makefile ADDED
@@ -0,0 +1,264 @@
1
+
2
+ SHELL = /bin/sh
3
+
4
+ # V=0 quiet, V=1 verbose. other values don't work.
5
+ V = 0
6
+ Q1 = $(V:1=)
7
+ Q = $(Q1:0=@)
8
+ ECHO1 = $(V:1=@ :)
9
+ ECHO = $(ECHO1:0=@ echo)
10
+ NULLCMD = :
11
+
12
+ #### Start of system configuration section. ####
13
+
14
+ srcdir = .
15
+ topdir = /Users/himotoyoshi/.rbenv/versions/2.4.2/include/ruby-2.4.0
16
+ hdrdir = $(topdir)
17
+ arch_hdrdir = /Users/himotoyoshi/.rbenv/versions/2.4.2/include/ruby-2.4.0/x86_64-darwin16
18
+ PATH_SEPARATOR = :
19
+ VPATH = $(srcdir):$(arch_hdrdir)/ruby:$(hdrdir)/ruby
20
+ prefix = $(DESTDIR)/Users/himotoyoshi/.rbenv/versions/2.4.2
21
+ rubysitearchprefix = $(rubylibprefix)/$(sitearch)
22
+ rubyarchprefix = $(rubylibprefix)/$(arch)
23
+ rubylibprefix = $(libdir)/$(RUBY_BASE_NAME)
24
+ exec_prefix = $(prefix)
25
+ vendorarchhdrdir = $(vendorhdrdir)/$(sitearch)
26
+ sitearchhdrdir = $(sitehdrdir)/$(sitearch)
27
+ rubyarchhdrdir = $(rubyhdrdir)/$(arch)
28
+ vendorhdrdir = $(rubyhdrdir)/vendor_ruby
29
+ sitehdrdir = $(rubyhdrdir)/site_ruby
30
+ rubyhdrdir = $(includedir)/$(RUBY_VERSION_NAME)
31
+ vendorarchdir = $(vendorlibdir)/$(sitearch)
32
+ vendorlibdir = $(vendordir)/$(ruby_version)
33
+ vendordir = $(rubylibprefix)/vendor_ruby
34
+ sitearchdir = $(sitelibdir)/$(sitearch)
35
+ sitelibdir = $(sitedir)/$(ruby_version)
36
+ sitedir = $(rubylibprefix)/site_ruby
37
+ rubyarchdir = $(rubylibdir)/$(arch)
38
+ rubylibdir = $(rubylibprefix)/$(ruby_version)
39
+ sitearchincludedir = $(includedir)/$(sitearch)
40
+ archincludedir = $(includedir)/$(arch)
41
+ sitearchlibdir = $(libdir)/$(sitearch)
42
+ archlibdir = $(libdir)/$(arch)
43
+ ridir = $(datarootdir)/$(RI_BASE_NAME)
44
+ mandir = $(datarootdir)/man
45
+ localedir = $(datarootdir)/locale
46
+ libdir = $(exec_prefix)/lib
47
+ psdir = $(docdir)
48
+ pdfdir = $(docdir)
49
+ dvidir = $(docdir)
50
+ htmldir = $(docdir)
51
+ infodir = $(datarootdir)/info
52
+ docdir = $(datarootdir)/doc/$(PACKAGE)
53
+ oldincludedir = $(SDKROOT)/usr/include
54
+ includedir = $(prefix)/include
55
+ localstatedir = $(prefix)/var
56
+ sharedstatedir = $(prefix)/com
57
+ sysconfdir = $(prefix)/etc
58
+ datadir = $(datarootdir)
59
+ datarootdir = $(prefix)/share
60
+ libexecdir = $(exec_prefix)/libexec
61
+ sbindir = $(exec_prefix)/sbin
62
+ bindir = $(exec_prefix)/bin
63
+ archdir = $(rubyarchdir)
64
+
65
+
66
+ CC = clang
67
+ CXX = clang++
68
+ LIBRUBY = $(LIBRUBY_A)
69
+ LIBRUBY_A = lib$(RUBY_SO_NAME)-static.a
70
+ LIBRUBYARG_SHARED =
71
+ LIBRUBYARG_STATIC = -l$(RUBY_SO_NAME)-static -framework CoreFoundation
72
+ empty =
73
+ OUTFLAG = -o $(empty)
74
+ COUTFLAG = -o $(empty)
75
+ CSRCFLAG = $(empty)
76
+
77
+ RUBY_EXTCONF_H =
78
+ cflags = $(optflags) $(debugflags) $(warnflags)
79
+ cxxflags = $(optflags) $(debugflags) $(warnflags)
80
+ optflags = -O3 -fno-fast-math
81
+ debugflags = -ggdb3
82
+ warnflags = -Wall -Wextra -Wno-unused-parameter -Wno-parentheses -Wno-long-long -Wno-missing-field-initializers -Wno-tautological-compare -Wno-parentheses-equality -Wno-constant-logical-operand -Wno-self-assign -Wunused-variable -Wimplicit-int -Wpointer-arith -Wwrite-strings -Wdeclaration-after-statement -Wshorten-64-to-32 -Wimplicit-function-declaration -Wdivision-by-zero -Wdeprecated-declarations -Wextra-tokens
83
+ CCDLFLAGS = -fno-common
84
+ CFLAGS = $(CCDLFLAGS) $(cflags) -pipe $(ARCH_FLAG)
85
+ INCFLAGS = -I. -I$(arch_hdrdir) -I$(hdrdir)/ruby/backward -I$(hdrdir) -I$(srcdir)
86
+ DEFS =
87
+ CPPFLAGS = -DHAVE_CARRAY_H -I/Users/himotoyoshi/.rbenv/versions/2.4.2/lib/ruby/gems/2.4.0/gems/carray-1.5.0/lib -I/Users/himotoyoshi/.rbenv/versions/2.4.2/include -I/usr/local/opt/qt/include: -D_XOPEN_SOURCE -D_DARWIN_C_SOURCE -D_DARWIN_UNLIMITED_SELECT -D_REENTRANT $(DEFS) $(cppflags)
88
+ CXXFLAGS = $(CCDLFLAGS) $(cxxflags) $(ARCH_FLAG)
89
+ ldflags = -L. -L/Users/himotoyoshi/.rbenv/versions/2.4.2/lib -L/usr/local/opt/qt/lib: -fstack-protector -L/usr/local/lib
90
+ dldflags = -L/Users/himotoyoshi/.rbenv/versions/2.4.2/lib -L/usr/local/opt/qt/lib: -Wl,-undefined,dynamic_lookup -Wl,-multiply_defined,suppress
91
+ ARCH_FLAG =
92
+ DLDFLAGS = $(ldflags) $(dldflags) $(ARCH_FLAG)
93
+ LDSHARED = $(CC) -dynamic -bundle
94
+ LDSHAREDXX = $(CXX) -dynamic -bundle
95
+ AR = ar
96
+ EXEEXT =
97
+
98
+ RUBY_INSTALL_NAME = $(RUBY_BASE_NAME)
99
+ RUBY_SO_NAME = ruby
100
+ RUBYW_INSTALL_NAME =
101
+ RUBY_VERSION_NAME = $(RUBY_BASE_NAME)-$(ruby_version)
102
+ RUBYW_BASE_NAME = rubyw
103
+ RUBY_BASE_NAME = ruby
104
+
105
+ arch = x86_64-darwin16
106
+ sitearch = $(arch)
107
+ ruby_version = 2.4.0
108
+ ruby = $(bindir)/$(RUBY_BASE_NAME)
109
+ RUBY = $(ruby)
110
+ ruby_headers = $(hdrdir)/ruby.h $(hdrdir)/ruby/backward.h $(hdrdir)/ruby/ruby.h $(hdrdir)/ruby/defines.h $(hdrdir)/ruby/missing.h $(hdrdir)/ruby/intern.h $(hdrdir)/ruby/st.h $(hdrdir)/ruby/subst.h $(arch_hdrdir)/ruby/config.h
111
+
112
+ RM = rm -f
113
+ RM_RF = $(RUBY) -run -e rm -- -rf
114
+ RMDIRS = rmdir -p
115
+ MAKEDIRS = mkdir -p
116
+ INSTALL = /usr/bin/install -c
117
+ INSTALL_PROG = $(INSTALL) -m 0755
118
+ INSTALL_DATA = $(INSTALL) -m 644
119
+ COPY = cp
120
+ TOUCH = exit >
121
+
122
+ #### End of system configuration section. ####
123
+
124
+ preload =
125
+ libpath = . $(libdir) /Users/himotoyoshi/.rbenv/versions/2.4.2/lib/ruby/gems/2.4.0/gems/carray-1.5.0/lib
126
+ LIBPATH = -L. -L$(libdir) -L/Users/himotoyoshi/.rbenv/versions/2.4.2/lib/ruby/gems/2.4.0/gems/carray-1.5.0/lib
127
+ DEFFILE =
128
+
129
+ CLEANFILES = mkmf.log
130
+ DISTCLEANFILES =
131
+ DISTCLEANDIRS =
132
+
133
+ extout =
134
+ extout_prefix =
135
+ target_prefix =
136
+ LOCAL_LIBS =
137
+ LIBS = -lpthread -lgmp -ldl -lobjc
138
+ ORIG_SRCS = carray_calculus.c carray_interp.c
139
+ SRCS = $(ORIG_SRCS)
140
+ OBJS = carray_calculus.o carray_interp.o
141
+ HDRS =
142
+ LOCAL_HDRS =
143
+ TARGET = carray_calculus
144
+ TARGET_NAME = carray_calculus
145
+ TARGET_ENTRY = Init_$(TARGET_NAME)
146
+ DLLIB = $(TARGET).bundle
147
+ EXTSTATIC =
148
+ STATIC_LIB =
149
+
150
+ TIMESTAMP_DIR = .
151
+ BINDIR = $(bindir)
152
+ RUBYCOMMONDIR = $(sitedir)$(target_prefix)
153
+ RUBYLIBDIR = $(sitelibdir)$(target_prefix)
154
+ RUBYARCHDIR = $(sitearchdir)$(target_prefix)
155
+ HDRDIR = $(rubyhdrdir)/ruby$(target_prefix)
156
+ ARCHHDRDIR = $(rubyhdrdir)/$(arch)/ruby$(target_prefix)
157
+ TARGET_SO_DIR =
158
+ TARGET_SO = $(TARGET_SO_DIR)$(DLLIB)
159
+ CLEANLIBS = $(TARGET_SO)
160
+ CLEANOBJS = *.o *.bak
161
+
162
+ all: $(DLLIB)
163
+ static: $(STATIC_LIB)
164
+ .PHONY: all install static install-so install-rb
165
+ .PHONY: clean clean-so clean-static clean-rb
166
+
167
+ clean-static::
168
+ clean-rb-default::
169
+ clean-rb::
170
+ clean-so::
171
+ clean: clean-so clean-static clean-rb-default clean-rb
172
+ -$(Q)$(RM) $(CLEANLIBS) $(CLEANOBJS) $(CLEANFILES) .*.time
173
+
174
+ distclean-rb-default::
175
+ distclean-rb::
176
+ distclean-so::
177
+ distclean-static::
178
+ distclean: clean distclean-so distclean-static distclean-rb-default distclean-rb
179
+ -$(Q)$(RM) Makefile $(RUBY_EXTCONF_H) conftest.* mkmf.log
180
+ -$(Q)$(RM) core ruby$(EXEEXT) *~ $(DISTCLEANFILES)
181
+ -$(Q)$(RMDIRS) $(DISTCLEANDIRS) 2> /dev/null || true
182
+
183
+ realclean: distclean
184
+ install: install-so install-rb
185
+
186
+ install-so: $(DLLIB) $(TIMESTAMP_DIR)/.sitearchdir.time
187
+ $(INSTALL_PROG) $(DLLIB) $(RUBYARCHDIR)
188
+ clean-static::
189
+ -$(Q)$(RM) $(STATIC_LIB)
190
+ install-rb: pre-install-rb do-install-rb install-rb-default
191
+ install-rb-default: pre-install-rb-default do-install-rb-default
192
+ pre-install-rb: Makefile
193
+ pre-install-rb-default: Makefile
194
+ do-install-rb:
195
+ do-install-rb-default:
196
+ pre-install-rb-default:
197
+ @$(NULLCMD)
198
+ $(TIMESTAMP_DIR)/.sitearchdir.time:
199
+ $(Q) $(MAKEDIRS) $(@D) $(RUBYARCHDIR)
200
+ $(Q) $(TOUCH) $@
201
+
202
+ site-install: site-install-so site-install-rb
203
+ site-install-so: install-so
204
+ site-install-rb: install-rb
205
+
206
+ .SUFFIXES: .c .m .cc .mm .cxx .cpp .o .S
207
+
208
+ .cc.o:
209
+ $(ECHO) compiling $(<)
210
+ $(Q) $(CXX) $(INCFLAGS) $(CPPFLAGS) $(CXXFLAGS) $(COUTFLAG)$@ -c $(CSRCFLAG)$<
211
+
212
+ .cc.S:
213
+ $(ECHO) translating $(<)
214
+ $(Q) $(CXX) $(INCFLAGS) $(CPPFLAGS) $(CXXFLAGS) $(COUTFLAG)$@ -S $(CSRCFLAG)$<
215
+
216
+ .mm.o:
217
+ $(ECHO) compiling $(<)
218
+ $(Q) $(CXX) $(INCFLAGS) $(CPPFLAGS) $(CXXFLAGS) $(COUTFLAG)$@ -c $(CSRCFLAG)$<
219
+
220
+ .mm.S:
221
+ $(ECHO) translating $(<)
222
+ $(Q) $(CXX) $(INCFLAGS) $(CPPFLAGS) $(CXXFLAGS) $(COUTFLAG)$@ -S $(CSRCFLAG)$<
223
+
224
+ .cxx.o:
225
+ $(ECHO) compiling $(<)
226
+ $(Q) $(CXX) $(INCFLAGS) $(CPPFLAGS) $(CXXFLAGS) $(COUTFLAG)$@ -c $(CSRCFLAG)$<
227
+
228
+ .cxx.S:
229
+ $(ECHO) translating $(<)
230
+ $(Q) $(CXX) $(INCFLAGS) $(CPPFLAGS) $(CXXFLAGS) $(COUTFLAG)$@ -S $(CSRCFLAG)$<
231
+
232
+ .cpp.o:
233
+ $(ECHO) compiling $(<)
234
+ $(Q) $(CXX) $(INCFLAGS) $(CPPFLAGS) $(CXXFLAGS) $(COUTFLAG)$@ -c $(CSRCFLAG)$<
235
+
236
+ .cpp.S:
237
+ $(ECHO) translating $(<)
238
+ $(Q) $(CXX) $(INCFLAGS) $(CPPFLAGS) $(CXXFLAGS) $(COUTFLAG)$@ -S $(CSRCFLAG)$<
239
+
240
+ .c.o:
241
+ $(ECHO) compiling $(<)
242
+ $(Q) $(CC) $(INCFLAGS) $(CPPFLAGS) $(CFLAGS) $(COUTFLAG)$@ -c $(CSRCFLAG)$<
243
+
244
+ .c.S:
245
+ $(ECHO) translating $(<)
246
+ $(Q) $(CC) $(INCFLAGS) $(CPPFLAGS) $(CFLAGS) $(COUTFLAG)$@ -S $(CSRCFLAG)$<
247
+
248
+ .m.o:
249
+ $(ECHO) compiling $(<)
250
+ $(Q) $(CC) $(INCFLAGS) $(CPPFLAGS) $(CFLAGS) $(COUTFLAG)$@ -c $(CSRCFLAG)$<
251
+
252
+ .m.S:
253
+ $(ECHO) translating $(<)
254
+ $(Q) $(CC) $(INCFLAGS) $(CPPFLAGS) $(CFLAGS) $(COUTFLAG)$@ -S $(CSRCFLAG)$<
255
+
256
+ $(TARGET_SO): $(OBJS) Makefile
257
+ $(ECHO) linking shared-object $(DLLIB)
258
+ -$(Q)$(RM) $(@)
259
+ $(Q) $(LDSHARED) -o $@ $(OBJS) $(LIBPATH) $(DLDFLAGS) $(LOCAL_LIBS) $(LIBS)
260
+ $(Q) $(POSTLINK)
261
+
262
+
263
+
264
+ $(OBJS): $(HDRS) $(ruby_headers)
@@ -0,0 +1,864 @@
1
+ /* ---------------------------------------------------------------------------
2
+
3
+ carray/carray_calculus.c
4
+
5
+ This file is part of Ruby/CArray extension library.
6
+ You can redistribute it and/or modify it under the terms of
7
+ the Ruby Licence.
8
+
9
+ Copyright (C) 2005 Hiroki Motoyoshi
10
+
11
+ ---------------------------------------------------------------------------- */
12
+
13
+ #include "ruby.h"
14
+ #include "carray.h"
15
+ #include <math.h>
16
+ #include <float.h>
17
+
18
+ /* ----------------------------------------------------------------- */
19
+
20
+ static double
21
+ simpson (double *x, double *y, ca_size_t n)
22
+ {
23
+ double s;
24
+
25
+ if ( n < 2 ) {
26
+ return 0.0/0.0;
27
+ }
28
+ else if ( n == 2 ) {
29
+ s = (x[1]-x[0])*(y[1]+y[0])*0.5;
30
+ return s;
31
+ }
32
+ else if ( n % 2 == 0 ) {
33
+ double x0, x1, x2, x3;
34
+ double h, m, a1, a2, c0, c1, c2, c3;
35
+ x0 = x[0];
36
+ x1 = x[1];
37
+ x2 = x[2];
38
+ x3 = x[3];
39
+ h = x3 - x0;
40
+ m = (x3 + x0)/2;
41
+ a1 = x1 - m;
42
+ a2 = x2 - m;
43
+ c0 = 1.0 + 2.0*a1*a2/((x0-x1)*(x0-x2));
44
+ c1 = h*h*a2/((x1-x2)*(x1-x0)*(x1-x3));
45
+ c2 = h*h*a1/((x2-x1)*(x2-x0)*(x2-x3));
46
+ c3 = 1.0 + 2.0*a1*a2/((x3-x1)*(x3-x2));
47
+ s = (c0*y[0]+c1*y[1]+c2*y[2]+c3*y[3])*h/6.0;
48
+ if ( n > 4 ) {
49
+ s += simpson(x+3, y+3, n-3);
50
+ }
51
+ return s;
52
+ }
53
+ else {
54
+ double x0, x1, x2;
55
+ double h, m, c0, c1, c2;
56
+ ca_size_t i;
57
+ s = 0.0;
58
+ for (i=0; i<n-2; i+=2) {
59
+ x0 = x[i];
60
+ x1 = x[i+1];
61
+ x2 = x[i+2];
62
+ h = x2-x0;
63
+ m = 0.5*(x2+x0);
64
+ c0 = 3.0 - h/(x1-x0);
65
+ c1 = h*(x2-x0)/((x2-x1)*(x1-x0));
66
+ c2 = 3.0 - h/(x2-x1);
67
+ s += (c0*y[i]+c1*y[i+1]+c2*y[i+2])*h/6.0;
68
+ }
69
+ return s;
70
+ }
71
+ }
72
+
73
+ static VALUE
74
+ rb_ca_integrate (volatile VALUE self, volatile VALUE vsc)
75
+ {
76
+ CArray *sc, *ca;
77
+ double ans;
78
+
79
+ ca = ca_wrap_readonly(self, CA_DOUBLE);
80
+ sc = ca_wrap_readonly(vsc, CA_DOUBLE);
81
+
82
+ if ( ca->elements != sc->elements ) {
83
+ rb_raise(rb_eRuntimeError, "data num mismatch");
84
+ }
85
+
86
+ if ( ca_is_any_masked(ca) || ca_is_any_masked(sc) ) {
87
+ rb_raise(rb_eRuntimeError,
88
+ "can't calculate integrattion when masked elements exist");
89
+ }
90
+
91
+ ca_attach_n(2, ca, sc);
92
+
93
+ ans = simpson((double*)sc->ptr, (double*)ca->ptr, ca->elements);
94
+
95
+ ca_detach_n(2, ca, sc);
96
+
97
+ return rb_float_new(ans);
98
+ }
99
+
100
+
101
+ /* ----------------------------------------------------------------- */
102
+
103
+ static ca_size_t
104
+ linear_index (ca_size_t n, double *y, double yy, double *idx)
105
+ {
106
+ ca_size_t a, b, c, x1;
107
+ double ya, yb, yc;
108
+ double y1, y2;
109
+ double rest;
110
+
111
+ if ( yy <= y[0] ) {
112
+ x1 = 0;
113
+ goto found;
114
+ }
115
+
116
+ if ( yy >= y[n-1] ) {
117
+ x1 = n-2;
118
+ goto found;
119
+ }
120
+
121
+ /* check for equally spaced scale */
122
+
123
+ a = (ca_size_t)((yy-y[0])/(y[n-1]-y[0])*(n-1));
124
+
125
+ if ( a >= 0 && a < n-1 ) {
126
+ if ( (y[a] - yy) * (y[a+1] - yy) <= 0 ) { /* lucky case */
127
+ x1 = a;
128
+ goto found;
129
+ }
130
+ }
131
+
132
+ /* binary section method */
133
+
134
+ a = 0;
135
+ b = n-1;
136
+
137
+ ya = y[a];
138
+ yb = y[b];
139
+
140
+ if ( ya > yb ) {
141
+ return -1; /* input scale array should have accending order */
142
+ }
143
+
144
+ while ( (b - a) >= 1 ) {
145
+
146
+ c = (a + b)/2;
147
+ yc = y[c];
148
+ if ( a == c ) {
149
+ break;
150
+ }
151
+
152
+ if ( yc == yy ) {
153
+ a = c;
154
+ break;
155
+ }
156
+ else if ( (ya - yy) * (yc - yy) <= 0 ) {
157
+ b = c;
158
+ yb = yc;
159
+ }
160
+ else {
161
+ a = c;
162
+ ya = yc;
163
+ }
164
+
165
+ if ( ya > yb ) {
166
+ return -1; /* input scale array should have accending order */
167
+ }
168
+ }
169
+
170
+ x1 = a;
171
+
172
+ found:
173
+
174
+ y1 = y[x1];
175
+ y2 = y[x1+1];
176
+ rest = (yy-y1)/(y2-y1);
177
+
178
+ if ( fabs(y2-yy)/fabs(y2) < DBL_EPSILON*100 ) {
179
+ *idx = (double) (x1 + 1);
180
+ }
181
+ else if ( fabs(y1-yy)/fabs(y1) < DBL_EPSILON*100 ) {
182
+ *idx = (double) x1;
183
+ }
184
+ else {
185
+ *idx = rest + (double) x1;
186
+ }
187
+
188
+ return 0;
189
+ }
190
+
191
+ static double
192
+ interp_lin (double *x, double *y, double xx)
193
+ {
194
+ double a, b;
195
+ double xa, xb;
196
+ double ab;
197
+ double fa, fb;
198
+ a = x[0];
199
+ b = x[1];
200
+ fa = y[0];
201
+ fb = y[1];
202
+ xa = xx - a;
203
+ xb = xx - b;
204
+ ab = a - b;
205
+ return -xa*fb/ab + xb*fa/ab;
206
+ }
207
+
208
+ static double
209
+ deriv_lin (double *x, double *y, double xx)
210
+ {
211
+ double a, b;
212
+ double ab;
213
+ double fa, fb;
214
+ a = x[0];
215
+ b = x[1];
216
+ fa = y[0];
217
+ fb = y[1];
218
+ ab = a - b;
219
+ return -fb/ab + fa/ab;
220
+ }
221
+
222
+ static double
223
+ interp_qual (double *x, double *y, double xx)
224
+ {
225
+ double a, b, c;
226
+ double xa, xb, xc;
227
+ double ab, bc, ca;
228
+ double fa, fb, fc;
229
+ a = x[0];
230
+ b = x[1];
231
+ c = x[2];
232
+ fa = y[0];
233
+ fb = y[1];
234
+ fc = y[2];
235
+ xa = xx - a;
236
+ xb = xx - b;
237
+ xc = xx - c;
238
+ ab = a - b;
239
+ bc = b - c;
240
+ ca = c - a;
241
+ return -(xa*xb*fc/ca/bc + xb*xc*fa/ab/ca + xc*xa*fb/bc/ab);
242
+ }
243
+
244
+ static double
245
+ deriv_qual (double *x, double *y, double xx)
246
+ {
247
+ double a, b, c;
248
+ double xa, xb, xc;
249
+ double ab, bc, ca;
250
+ double fa, fb, fc;
251
+ a = x[0];
252
+ b = x[1];
253
+ c = x[2];
254
+ fa = y[0];
255
+ fb = y[1];
256
+ fc = y[2];
257
+ xa = xx - a;
258
+ xb = xx - b;
259
+ xc = xx - c;
260
+ ab = a - b;
261
+ bc = b - c;
262
+ ca = c - a;
263
+ return - (xa+xb)*fc/ca/bc
264
+ - (xb+xc)*fa/ab/ca
265
+ - (xc+xa)*fb/bc/ab;
266
+ }
267
+
268
+ static double
269
+ interp_cubic (double *x, double *y, double xx)
270
+ {
271
+ double a, b, c, d;
272
+ double xa, xb, xc, xd;
273
+ double ab, bc, cd, da, db, ac;
274
+ double fa, fb, fc, fd;
275
+ a = x[0];
276
+ b = x[1];
277
+ c = x[2];
278
+ d = x[3];
279
+ fa = y[0];
280
+ fb = y[1];
281
+ fc = y[2];
282
+ fd = y[3];
283
+ xa = xx - a;
284
+ xb = xx - b;
285
+ xc = xx - c;
286
+ xd = xx - d;
287
+ ab = a - b;
288
+ bc = b - c;
289
+ cd = c - d;
290
+ da = d - a;
291
+ db = d - b;
292
+ ac = a - c;
293
+ return -xa*xb*xc*fd/da/db/cd - xb*xc*xd*fa/ab/ac/da +
294
+ xc*xd*xa*fb/bc/db/ab + xd*xa*xb*fc/cd/ac/bc;
295
+ }
296
+
297
+ static double
298
+ deriv_cubic (double *x, double *y, double xx)
299
+ {
300
+ double a, b, c, d;
301
+ double xa, xb, xc, xd;
302
+ double ab, bc, cd, da, db, ac;
303
+ double fa, fb, fc, fd;
304
+ a = x[0];
305
+ b = x[1];
306
+ c = x[2];
307
+ d = x[3];
308
+ fa = y[0];
309
+ fb = y[1];
310
+ fc = y[2];
311
+ fd = y[3];
312
+ xa = xx - a;
313
+ xb = xx - b;
314
+ xc = xx - c;
315
+ xd = xx - d;
316
+ ab = a - b;
317
+ bc = b - c;
318
+ cd = c - d;
319
+ da = d - a;
320
+ db = d - b;
321
+ ac = a - c;
322
+ return - (xb*xc+xa*xc+xa*xb)*fd/da/db/cd
323
+ - (xc*xd+xb*xd+xb*xc)*fa/ab/ac/da
324
+ + (xd*xa+xc*xa+xc*xd)*fb/bc/db/ab
325
+ + (xa*xb+xd*xb+xd*xa)*fc/cd/ac/bc;
326
+ }
327
+
328
+ static double
329
+ interp_penta (double *x, double *y, double xx)
330
+ {
331
+ double a, b, c, d, e, f;
332
+ double xa, xb, xc, xd, xe, xf;
333
+ double ya, yb, yc, yd, ye, yf;
334
+ double ab, ac, ad, ae, af;
335
+ double bc, bd, be, bf;
336
+ double cd, ce, cf;
337
+ double de, df;
338
+ double ef;
339
+ a = x[0];
340
+ b = x[1];
341
+ c = x[2];
342
+ d = x[3];
343
+ e = x[4];
344
+ f = x[5];
345
+ ya = y[0];
346
+ yb = y[1];
347
+ yc = y[2];
348
+ yd = y[3];
349
+ ye = y[4];
350
+ yf = y[5];
351
+ xa = xx - a;
352
+ xb = xx - b;
353
+ xc = xx - c;
354
+ xd = xx - d;
355
+ xe = xx - e;
356
+ xf = xx - f;
357
+ ab = a - b;
358
+ ac = a - c;
359
+ ad = a - d;
360
+ ae = a - e;
361
+ af = a - f;
362
+ bc = b - c;
363
+ bd = b - d;
364
+ be = b - e;
365
+ bf = b - f;
366
+ cd = c - d;
367
+ ce = c - e;
368
+ cf = c - f;
369
+ de = d - e;
370
+ df = d - f;
371
+ ef = e - f;
372
+ return ya*xb*xc*xd*xe*xf/(ab*ac*ad*ae*af)
373
+ - xa*yb*xc*xd*xe*xf/(ab*bc*bd*be*bf)
374
+ + xa*xb*yc*xd*xe*xf/(ac*bc*cd*ce*cf)
375
+ - xa*xb*xc*yd*xe*xf/(ad*bd*cd*de*df)
376
+ + xa*xb*xc*xd*ye*xf/(ae*be*ce*de*ef)
377
+ - xa*xb*xc*xd*xe*yf/(af*bf*cf*df*ef);
378
+ }
379
+
380
+
381
+ static double
382
+ deriv_penta (double *x, double *y, double xx)
383
+ {
384
+ double a, b, c, d, e, f;
385
+ double xa, xb, xc, xd, xe, xf;
386
+ double ya, yb, yc, yd, ye, yf;
387
+ double ab, ac, ad, ae, af;
388
+ double bc, bd, be, bf;
389
+ double cd, ce, cf;
390
+ double de, df;
391
+ double ef;
392
+ a = x[0];
393
+ b = x[1];
394
+ c = x[2];
395
+ d = x[3];
396
+ e = x[4];
397
+ f = x[5];
398
+ ya = y[0];
399
+ yb = y[1];
400
+ yc = y[2];
401
+ yd = y[3];
402
+ ye = y[4];
403
+ yf = y[5];
404
+ xa = xx - a;
405
+ xb = xx - b;
406
+ xc = xx - c;
407
+ xd = xx - d;
408
+ xe = xx - e;
409
+ xf = xx - f;
410
+ ab = a - b;
411
+ ac = a - c;
412
+ ad = a - d;
413
+ ae = a - e;
414
+ af = a - f;
415
+ bc = b - c;
416
+ bd = b - d;
417
+ be = b - e;
418
+ bf = b - f;
419
+ cd = c - d;
420
+ ce = c - e;
421
+ cf = c - f;
422
+ de = d - e;
423
+ df = d - f;
424
+ ef = e - f;
425
+ return (xc*xd*xe*xf+xb*xd*xe*xf+xb*xc*xe*xf+xb*xc*xd*xf+xb*xc*xd*xe)*ya/(ab*ac*ad*ae*af)
426
+ - (xc*xd*xe*xf+xa*xd*xe*xf+xa*xc*xe*xf+xa*xc*xd*xf+xa*xc*xd*xe)*yb/(ab*bc*bd*be*bf)
427
+ + (xb*xd*xe*xf+xa*xd*xe*xf+xa*xb*xe*xf+xa*xb*xd*xf+xa*xb*xd*xe)*yc/(ac*bc*cd*ce*cf)
428
+ - (xb*xc*xe*xf+xa*xc*xe*xf+xa*xb*xe*xf+xa*xb*xc*xf+xa*xb*xc*xe)*yd/(ad*bd*cd*de*df)
429
+ + (xb*xc*xd*xf+xa*xc*xd*xf+xa*xb*xd*xf+xa*xb*xc*xf+xa*xb*xc*xd)*ye/(ae*be*ce*de*ef)
430
+ - (xb*xc*xd*xe+xa*xc*xd*xe+xa*xb*xd*xe+xa*xb*xc*xe+xa*xb*xc*xd)*yf/(af*bf*cf*df*ef);
431
+ }
432
+
433
+ static double
434
+ interpolate_linear (double *x, double *y, ca_size_t n, double xx)
435
+ {
436
+ double xt[2];
437
+ double ri;
438
+ ca_size_t i0;
439
+ if ( n == 1) {
440
+ return y[0];
441
+ }
442
+ if ( x != NULL ) {
443
+ if ( xx == x[0] ) {
444
+ return y[0];
445
+ }
446
+ if ( xx == x[1] ) {
447
+ return y[1];
448
+ }
449
+ if ( n == 2 ) {
450
+ return interp_lin(x, y, xx);
451
+ }
452
+ linear_index(n, x, xx, &ri);
453
+ i0 = floor(ri);
454
+ if ( i0 <= 0 ) {
455
+ i0 = 0;
456
+ }
457
+ else if ( i0 + 1 >= n - 1 ) {
458
+ i0 = n - 2;
459
+ }
460
+ return interp_lin(&x[i0], &y[i0], xx);
461
+ }
462
+ else {
463
+ if ( xx == 0 ) {
464
+ return y[0];
465
+ }
466
+ if ( xx == 1 ) {
467
+ return y[1];
468
+ }
469
+ if ( n == 2 ) {
470
+ xt[0] = 0.0;
471
+ xt[1] = 1.0;
472
+ return interp_lin(xt, y, xx);
473
+ }
474
+ i0 = floor(xx);
475
+ if ( i0 <= 0 ) {
476
+ i0 = 0;
477
+ }
478
+ else if ( i0 + 1 >= n - 1 ) {
479
+ i0 = n - 2;
480
+ }
481
+ xt[0] = i0;
482
+ xt[1] = i0+1;
483
+ return interp_lin(xt, &y[i0], xx);
484
+ }
485
+ }
486
+
487
+ static double
488
+ interpolate_cubic (double *x, double *y, ca_size_t n, double xx)
489
+ {
490
+ static double xt[4];
491
+ double ri;
492
+ ca_size_t i0;
493
+ if ( n == 1) {
494
+ return y[0];
495
+ }
496
+ if ( x != NULL ) {
497
+ if ( xx == x[0] ) {
498
+ return y[0];
499
+ }
500
+ if ( xx == x[1] ) {
501
+ return y[1];
502
+ }
503
+ if ( xx == x[2] ) {
504
+ return y[2];
505
+ }
506
+ if ( n == 2 ) {
507
+ return interp_lin(x, y, xx);
508
+ }
509
+ if ( n == 3 ) {
510
+ return interp_qual(x, y, xx);
511
+ }
512
+ linear_index(n, x, xx, &ri);
513
+ i0 = floor(ri) - 1;
514
+ if ( i0 <= 0 ) {
515
+ i0 = 0;
516
+ }
517
+ else if ( i0 + 3 >= n - 1 ) {
518
+ i0 = n - 4;
519
+ }
520
+ return interp_cubic(&x[i0], &y[i0], xx);
521
+ }
522
+ else {
523
+ if ( xx == 0 ) {
524
+ return y[0];
525
+ }
526
+ if ( xx == 1 ) {
527
+ return y[1];
528
+ }
529
+ if ( xx == 2 ) {
530
+ return y[2];
531
+ }
532
+ if ( n == 2 ) {
533
+ xt[0] = 0.0;
534
+ xt[1] = 1.0;
535
+ return interp_lin(xt, y, xx);
536
+ }
537
+ if ( n == 3 ) {
538
+ xt[0] = 0.0;
539
+ xt[1] = 1.0;
540
+ xt[2] = 2.0;
541
+ return interp_qual(xt, y, xx);
542
+ }
543
+ ri = xx;
544
+ i0 = floor(ri) - 1;
545
+ if ( i0 <= 0 ) {
546
+ i0 = 0;
547
+ }
548
+ else if ( i0 + 3 >= n - 1 ) {
549
+ i0 = n - 4;
550
+ }
551
+ xt[0] = i0;
552
+ xt[1] = i0+1;
553
+ xt[2] = i0+2;
554
+ xt[3] = i0+3;
555
+ return interp_cubic(xt, &y[i0], xx);
556
+ }
557
+ }
558
+
559
+ static double
560
+ differentiate (double *x, double *y, ca_size_t n, double xx)
561
+ {
562
+ double ri;
563
+ ca_size_t i0;
564
+ switch ( n ) {
565
+ case 1:
566
+ return 0.0/0.0;
567
+ case 2:
568
+ return deriv_lin(x, y, xx);
569
+ case 3:
570
+ return deriv_qual(x, y, xx);
571
+ case 4:
572
+ return deriv_cubic(x, y, xx);
573
+ }
574
+ linear_index(n, x, xx, &ri);
575
+ i0 = floor(ri) - 1;
576
+ if ( i0 <= 0 ) {
577
+ i0 = 0;
578
+ }
579
+ else if ( n == 5 && i0 + 4 > n - 1 ) {
580
+ i0 = n - 5;
581
+ }
582
+ else if ( i0 + 5 > n - 1 ) {
583
+ i0 = n - 6;
584
+ }
585
+ if ( n == 5 ) {
586
+ return deriv_cubic(&x[i0], &y[i0], xx);
587
+ }
588
+ else {
589
+ return deriv_penta(&x[i0], &y[i0], xx);
590
+ }
591
+ }
592
+
593
+ static VALUE
594
+ rb_ca_interpolate (int argc, VALUE *argv, VALUE self)
595
+ {
596
+ volatile VALUE rval = self;
597
+ volatile VALUE vsc, vx, ropt, rtype = Qnil, out0, out;
598
+ CArray *ca, *sc, *cv, *cx, *co0, *co;
599
+ char *typename = NULL;
600
+ int type = 0;
601
+ double *px, *po;
602
+ ca_size_t i;
603
+
604
+ Data_Get_Struct(self, CArray, ca);
605
+
606
+ rb_scan_args(argc, argv, "21", &vsc, &vx, &ropt);
607
+ rb_scan_options(ropt, "type", &rtype);
608
+
609
+ if ( ! NIL_P(rtype) ) {
610
+ Check_Type(rtype, T_STRING);
611
+ typename = StringValuePtr(rtype);
612
+ }
613
+
614
+ if ( typename == NULL || ! strncmp("cubic", typename, 5) ) {
615
+ type = 3;
616
+ }
617
+ else if ( ! strncmp("linear", typename, 6) ) {
618
+ type = 1;
619
+ }
620
+ else {
621
+ volatile VALUE inspect = rb_inspect(rtype);
622
+ rb_raise(rb_eRuntimeError,
623
+ "invalid interpolation type <%s>", StringValuePtr(inspect));
624
+ }
625
+
626
+ if ( ! NIL_P(vsc) ) {
627
+
628
+ cv = ca_wrap_readonly(rval, CA_DOUBLE);
629
+ sc = ca_wrap_readonly(vsc, CA_DOUBLE);
630
+
631
+ if ( ca_is_any_masked(cv) || ca_is_any_masked(sc) ) {
632
+ rb_raise(rb_eRuntimeError,
633
+ "can't calculate interpolation when masked elements exist");
634
+ }
635
+
636
+ if ( cv->elements != sc->elements ) {
637
+ rb_raise(rb_eRuntimeError, "data num mismatch with scale");
638
+ }
639
+
640
+ cx = ca_wrap_readonly(vx, CA_DOUBLE);
641
+
642
+ co0 = carray_new(ca->data_type, cx->ndim, cx->dim, 0, NULL);
643
+ out = out0 = ca_wrap_struct(co0);
644
+ co = ca_wrap_writable(out, CA_DOUBLE);
645
+
646
+ ca_attach_n(4, cv, sc, cx, co);
647
+
648
+ px = (double*) cx->ptr;
649
+ po = (double*) co->ptr;
650
+
651
+ ca_update_mask(cx);
652
+ if ( cx->mask ) {
653
+ boolean8_t *mx, *mo;
654
+ ca_create_mask(co);
655
+ mx = (boolean8_t *) cx->mask->ptr;
656
+ mo = (boolean8_t *) co->mask->ptr;
657
+ if ( type == 3 ) {
658
+ for (i=0; i<cx->elements; i++) {
659
+ if ( ! *mx ) {
660
+ *po = interpolate_cubic((double*)sc->ptr, (double*)cv->ptr,
661
+ cv->elements, *px);
662
+ }
663
+ else {
664
+ *mo = 1;
665
+ }
666
+ mx++; mo++; po++; px++;
667
+ }
668
+ }
669
+ else {
670
+ for (i=0; i<cx->elements; i++) {
671
+ if ( ! *mx ) {
672
+ *po = interpolate_linear((double*)sc->ptr, (double*)cv->ptr,
673
+ cv->elements, *px);
674
+ }
675
+ else {
676
+ *mo = 1;
677
+ }
678
+ mx++; mo++; po++; px++;
679
+ }
680
+ }
681
+ }
682
+ else {
683
+ if ( type == 3 ) {
684
+ for (i=0; i<cx->elements; i++) {
685
+ *po++ = interpolate_cubic((double*)sc->ptr, (double*)cv->ptr,
686
+ cv->elements, *px++);
687
+ }
688
+ }
689
+ else {
690
+ for (i=0; i<cx->elements; i++) {
691
+ *po++ = interpolate_linear((double*)sc->ptr, (double*)cv->ptr,
692
+ cv->elements, *px++);
693
+ }
694
+ }
695
+ }
696
+
697
+ ca_sync(co);
698
+ ca_detach_n(4, cv, sc, cx, co);
699
+
700
+ }
701
+ else {
702
+
703
+
704
+ cv = ca_wrap_readonly(rval, CA_DOUBLE);
705
+
706
+
707
+ if ( ca_is_any_masked(cv) ) {
708
+ rb_raise(rb_eRuntimeError,
709
+ "can't calculate interpolation when masked elements exist");
710
+ }
711
+
712
+ cx = ca_wrap_readonly(vx, CA_DOUBLE);
713
+
714
+ co0 = carray_new(ca->data_type, cx->ndim, cx->dim, 0, NULL);
715
+ out = out0 = ca_wrap_struct(co0);
716
+ co = ca_wrap_writable(out, CA_DOUBLE);
717
+
718
+ ca_attach_n(3, cv, cx, co);
719
+
720
+ px = (double*) cx->ptr;
721
+ po = (double*) co->ptr;
722
+
723
+ ca_update_mask(cx);
724
+ if ( cx->mask ) {
725
+ boolean8_t *mx, *mo;
726
+ ca_create_mask(co);
727
+ mx = (boolean8_t *) cx->mask->ptr;
728
+ mo = (boolean8_t *) co->mask->ptr;
729
+ if ( type == 3 ) {
730
+ for (i=0; i<cx->elements; i++) {
731
+ if ( ! *mx ) {
732
+ *po = interpolate_cubic(NULL, (double*)cv->ptr,
733
+ cv->elements, *px);
734
+ }
735
+ else {
736
+ *mo = 1;
737
+ }
738
+ mx++; mo++; po++; px++;
739
+ }
740
+ }
741
+ else {
742
+ for (i=0; i<cx->elements; i++) {
743
+ if ( ! *mx ) {
744
+ *po = interpolate_linear(NULL, (double*)cv->ptr,
745
+ cv->elements, *px);
746
+ }
747
+ else {
748
+ *mo = 1;
749
+ }
750
+ mx++; mo++; po++; px++;
751
+ }
752
+ }
753
+ }
754
+ else {
755
+ if ( type == 3 ) {
756
+ for (i=0; i<cx->elements; i++) {
757
+ *po++ = interpolate_cubic(NULL, (double*)cv->ptr,
758
+ cv->elements, *px++);
759
+ }
760
+ }
761
+ else {
762
+ for (i=0; i<cx->elements; i++) {
763
+ *po++ = interpolate_linear(NULL, (double*)cv->ptr,
764
+ cv->elements, *px++);
765
+ }
766
+ }
767
+ }
768
+
769
+ ca_sync(co);
770
+ ca_detach_n(3, cv, cx, co);
771
+
772
+ }
773
+
774
+ if ( rb_ca_is_scalar(vx) ) {
775
+ return rb_funcall(out0, rb_intern("[]"), 1, INT2NUM(0));
776
+ }
777
+ else {
778
+ return out0;
779
+ }
780
+ }
781
+
782
+ static VALUE
783
+ rb_ca_differentiate (volatile VALUE self,
784
+ volatile VALUE vsc, volatile VALUE vx)
785
+ {
786
+ volatile VALUE rval = self;
787
+ volatile VALUE out0, out;
788
+ CArray *ca, *cv, *sc, *cx, *co0, *co;
789
+ double *px, *po;
790
+ ca_size_t i;
791
+
792
+ Data_Get_Struct(self, CArray, ca);
793
+
794
+ sc = ca_wrap_readonly(vsc, CA_DOUBLE);
795
+
796
+ if ( ca_is_any_masked(ca) || ca_is_any_masked(sc) ) {
797
+ rb_raise(rb_eRuntimeError,
798
+ "can't calculate differentiation when masked elements exist");
799
+ }
800
+
801
+ if ( ca->elements != sc->elements ) {
802
+ rb_raise(rb_eRuntimeError, "data num mismatch with scale");
803
+ }
804
+
805
+ cv = ca_wrap_readonly(rval, CA_DOUBLE);
806
+ cx = ca_wrap_readonly(vx, CA_DOUBLE);
807
+
808
+ co0 = carray_new(ca->data_type, cx->ndim, cx->dim, 0, NULL);
809
+ out = out0 = ca_wrap_struct(co0);
810
+ co = ca_wrap_writable(out, CA_DOUBLE);
811
+
812
+ ca_attach_n(4, cv, sc, cx, co);
813
+
814
+ px = (double*) cx->ptr;
815
+ po = (double*) co->ptr;
816
+
817
+ ca_update_mask(cx);
818
+ if ( cx->mask ) {
819
+ boolean8_t *mx, *mo;
820
+ ca_create_mask(co);
821
+ mx = (boolean8_t *) cx->mask->ptr;
822
+ mo = (boolean8_t *) co->mask->ptr;
823
+ for (i=0; i<cx->elements; i++) {
824
+ if ( ! *mx ) {
825
+ *po = differentiate((double*)sc->ptr, (double*)cv->ptr,
826
+ cv->elements, *px);
827
+ }
828
+ else {
829
+ *mo = 1;
830
+ }
831
+ mx++; mo++; px++, po++;
832
+ }
833
+ }
834
+ else {
835
+ for (i=0; i<cx->elements; i++) {
836
+ *po = differentiate((double*)sc->ptr, (double*)cv->ptr,
837
+ cv->elements, *px);
838
+ px++, po++;
839
+ }
840
+ }
841
+
842
+ ca_sync(co);
843
+ ca_detach_n(4, cv, sc, cx, co);
844
+
845
+ if ( rb_ca_is_scalar(vx) ) {
846
+ return rb_funcall(out0, rb_intern("[]"), 1, INT2NUM(0));
847
+ }
848
+ else {
849
+ return out0;
850
+ }
851
+ }
852
+
853
+ void
854
+ Init_carray_interpolate ();
855
+
856
+ void
857
+ Init_carray_calculus ()
858
+ {
859
+ rb_define_method(rb_cCArray, "integrate", rb_ca_integrate, 1);
860
+ rb_define_method(rb_cCArray, "interpolate", rb_ca_interpolate, -1);
861
+ rb_define_method(rb_cCArray, "differentiate", rb_ca_differentiate, 2);
862
+
863
+ Init_carray_interpolate();
864
+ }