carray-calculus 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
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
+ }