39
|
1 |
#======================================================================
|
|
2 |
# . I N T E R P . S P L I N E
|
|
3 |
# doc: Wed Nov 22 21:01:09 2000
|
|
4 |
# dlm: Tue Aug 5 14:20:39 2008
|
|
5 |
# (c) 2000 A.M. Thurnherr
|
|
6 |
# uE-Info: 31 0 NIL 0 0 72 10 2 4 NIL ofnI
|
|
7 |
#======================================================================
|
|
8 |
|
|
9 |
# spline interpolation
|
|
10 |
|
|
11 |
# HISTORY:
|
|
12 |
# May 27, 2003: - adapted from [.interp.linear]
|
|
13 |
# Jul 19, 2004: - BUG: i instead of $i --- 'orrible!
|
|
14 |
# May 15, 2006: - BUG: assertion did not work on -e
|
|
15 |
# Jul 28, 2006: - Version 3.3 [HISTORY]
|
|
16 |
# - made 100% compatible with [.interp.spline]
|
|
17 |
# - added xf to ISInit() args
|
|
18 |
# Jul 30, 2006: - continued debugging
|
|
19 |
# Aug 22, 2006: - adapted to work with [match]
|
|
20 |
# Aug 5, 2008: - added idr param to IS_init()
|
|
21 |
|
|
22 |
# see [.interp.linear] for documentation of interface
|
|
23 |
|
|
24 |
# EXAMPLE:
|
|
25 |
# Matlab: x = 0:10; y = sin(x); xx = 0:.25:10;
|
|
26 |
# yy = spline(x,y,xx); plot(x,y,'o',xx,yy)
|
|
27 |
# gnuplot/ANTS:
|
|
28 |
# set style function points;
|
|
29 |
# set style data lines;
|
|
30 |
# plot [0:10] sin(x), \
|
|
31 |
# '<Cat -f x:0,1,10 | list x y=sin($x) | resample -s spline x \#0-10:0.25'
|
|
32 |
|
|
33 |
$IS_opts = "B:";
|
|
34 |
$IS_optsUsage = "[-B)oundary cond <1st/last>]";
|
|
35 |
|
|
36 |
#----------------------------------------------------------------------
|
|
37 |
|
|
38 |
my($yp1,$ypn);
|
|
39 |
|
|
40 |
sub IS_usage()
|
|
41 |
{
|
|
42 |
if (defined($opt_B)) { # NR p.115
|
|
43 |
($yp1,$ypn) = split('/',$opt_B);
|
|
44 |
croak("$0: can't decode -B $opt_B\n")
|
|
45 |
unless (numberp($yp1) && numberp($ypn));
|
|
46 |
}
|
|
47 |
}
|
|
48 |
|
|
49 |
#----------------------------------------------------------------------
|
|
50 |
|
|
51 |
sub IS_init($$$$) {
|
|
52 |
my($bR,$idR,$f,$xf) = @_;
|
|
53 |
my($i,$k,$p,$qn,$sig,$un,@u);
|
|
54 |
my($n) = scalar(@{$bR});
|
|
55 |
|
|
56 |
if (defined($opt_B)) { # handle boundary cond
|
|
57 |
$idR->[1][$f] = -0.5;
|
|
58 |
$u[1] = (3/($bR->[1][$xf]-$bR->[0][$xf])) *
|
|
59 |
(($bR->[1][$f]-$bR->[0][$f]) /
|
|
60 |
($bR->[1][$xf]-$bR->[0][$xf]) - $yp1);
|
|
61 |
} else {
|
|
62 |
$idR->[1][$f] = $u[1] = 0;
|
|
63 |
}
|
|
64 |
|
|
65 |
for ($i=2; $i<=$n-1; $i++) {
|
|
66 |
$sig = ($bR->[$i-1][$xf]-$bR->[$i-2][$xf]) /
|
|
67 |
($bR->[$i][$xf]-$bR->[$i-2][$xf]);
|
|
68 |
$p = $sig*$idR->[$i-1][$f] + 2;
|
|
69 |
$idR->[$i][$f] = ($sig-1)/$p;
|
|
70 |
$u[$i] = ($bR->[$i][$f]-$bR->[$i-1][$f]) /
|
|
71 |
($bR->[$i][$xf]-$bR->[$i-1][$xf])
|
|
72 |
- ($bR->[$i-1][$f]-$bR->[$i-2][$f]) /
|
|
73 |
($bR->[$i-1][$xf]-$bR->[$i-2][$xf]);
|
|
74 |
$u[$i] = (6*$u[$i]/($bR->[$i][$xf]-$bR->[$i-2][$xf]) -
|
|
75 |
$sig * $u[$i-1]) / $p;
|
|
76 |
}
|
|
77 |
|
|
78 |
if (defined($opt_B)) {
|
|
79 |
$qn = 0.5;
|
|
80 |
$un = (3/($bR->[$n-1][$xf]-$bR->[$n-2][$xf])) *
|
|
81 |
($ypn-($bR->[$n-1][$f]-$bR->[$n-2][$f]) /
|
|
82 |
($bR->[$n-1][$xf]-$bR->[$n-2][$xf]));
|
|
83 |
} else {
|
|
84 |
$qn = $un = 0;
|
|
85 |
}
|
|
86 |
|
|
87 |
$idR->[$n][$f] = ($un-$qn*$u[$n-1]) / ($qn*$idR->[$n-1][$f]+1);
|
|
88 |
for ($k=$n-1;$k>=1;$k--) {
|
|
89 |
$idR->[$k][$f] = $idR->[$k][$f] * $idR->[$k+1][$f] + $u[$k];
|
|
90 |
}
|
|
91 |
}
|
|
92 |
|
|
93 |
#----------------------------------------------------------------------
|
|
94 |
|
|
95 |
sub IS_interpolate($$$$$$)
|
|
96 |
{
|
|
97 |
my($bR,$idR,$xf,$xv,$xi,$f) = @_;
|
|
98 |
|
|
99 |
return $xv if ($xf == $f);
|
|
100 |
|
|
101 |
return $bR->[$xi][$f] # edge values are ok
|
|
102 |
if equal($xv,$bR->[$xi][$xf]);
|
|
103 |
return $bR->[$xi+1][$f]
|
|
104 |
if equal($xv,$bR->[$xi+1][$xf]);
|
|
105 |
|
|
106 |
return nan unless (numberp($bR->[$xi][$f]) &&
|
|
107 |
numberp($bR->[$xi+1][$f]));
|
|
108 |
|
|
109 |
croak("$0: assertion $bR->[$xi+1][$xf] >= $xv >= $bR->[$xi][$xf] failed")
|
|
110 |
unless (defined($opt_e) || $bR->[$xi+1][$xf] >= $xv && $xv >= $bR->[$xi][$xf]);
|
|
111 |
|
|
112 |
my($h) = $bR->[$xi+1][$xf] - $bR->[$xi][$xf];
|
|
113 |
croak("$0: assertion #2 failed") unless ($h > 0);
|
|
114 |
my($a) = ($bR->[$xi+1][$xf] - $xv) / $h;
|
|
115 |
my($b) = ($xv - $bR->[$xi][$xf]) / $h;
|
|
116 |
|
|
117 |
return $a*$bR->[$xi][$f] + $b*$bR->[$xi+1][$f] +
|
|
118 |
(($a*$a*$a-$a) * $idR->[$xi+1][$f] +
|
|
119 |
($b*$b*$b-$b) * $idR->[$xi+2][$f]) *
|
|
120 |
($h*$h)/6;
|
|
121 |
}
|
|
122 |
|
|
123 |
#----------------------------------------------------------------------
|
|
124 |
|
|
125 |
1;
|