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