ICC-Profile

 view release on metacpan or  search on metacpan

lib/ICC/Shared.pm  view on Meta::CPAN

			} else {
				
				# use lower source value
				$vector_out->[$i] = $vector_in->[$low];
				
			}
			
		}
		
	}

	# return
	return($vector_out);

}

# compute cubic spline interpolation matrix
# input/output range structure: [start_nm, end_nm, increment]
# optional extrapolation method is 'copy' or 'linear', none returns zeros
# parameters: (input_range, output_range, [extrapolation_method])
# returns: (interpolation_matrix)
sub cspline_matrix {

	# get parameters
	my ($range_in, $range_out, $ext) = @_;

	# local variables
	my ($ix, $ox, $rhs, $info, $derv, $mat);
	my ($w, $low, $t, $tc, $h00, $h01, $h10, $h11);

	# check if ICC::Support::Lapack module is loaded
	state $lapack = defined($INC{'ICC/Support/Lapack.pm'});

	# compute input vector size from range
	$ix = round(($range_in->[1] - $range_in->[0])/$range_in->[2]);

	# verify input range
	($ix > 0 && abs($ix * $range_in->[2] - $range_in->[1] + $range_in->[0]) < 1E-12 && $range_in->[2] > 0) || croak('invalid input range');

	# compute output vector size from range
	$ox = round(($range_out->[1] - $range_out->[0])/$range_out->[2]);

	# verify output range
	($ox > 0 && abs($ox * $range_out->[2] - $range_out->[1] + $range_out->[0]) < 1E-12 && $range_out->[2] > 0) || croak('invalid output range');

	# if ICC::Support::Lapack module is loaded
	if ($lapack) {
		
		# make rhs matrix (filled with zeros)
		$rhs = ICC::Support::Lapack::zeros($ix + 1);
		
		# for each row
		for my $i (1 .. $ix - 1) {
			
			# set diagonal values
			$rhs->[$i - 1][$i] = 3;
			$rhs->[$i + 1][$i] = -3;
			
		}
		
		# set endpoint values
		$rhs->[0][0] = -3;
		$rhs->[1][0] = -3;
		$rhs->[$ix][$ix] = 3;
		$rhs->[$ix - 1][$ix] = 3;
		
		# solve for derivative matrix
		($info, $derv) = ICC::Support::Lapack::trisolve([(1) x $ix], [2, (4) x ($ix - 1), 2], [(1) x $ix], $rhs);
		
		# make matrix of zeros
		$mat = ICC::Support::Lapack::zeros($ox + 1, $ix + 1);
		
	# otherwise, use Math::Matrix package (slow)
	} else {
		
		# make rhs matrix (fill with zeros)
		$rhs = bless([map {[(0) x ($ix + 1)]} (0 .. $ix)], 'Math::Matrix');
		
		# for each row
		for my $i (1 .. $ix - 1) {
			
			# set diagonal values
			$rhs->[$i - 1][$i] = 3;
			$rhs->[$i + 1][$i] = -3;
			
		}
		
		# set endpoint values
		$rhs->[0][0] = -3;
		$rhs->[1][0] = -3;
		$rhs->[$ix][$ix] = 3;
		$rhs->[$ix - 1][$ix] = 3;
		
		# solve for derivative matrix
		$derv = Math::Matrix->tridiagonal([2, (4) x ($ix - 1), 2])->concat($rhs)->solve();
		
		# make matrix of zeros
		$mat = [map {[(0) x ($ix + 1)]} (0 .. $ox)];
		
	}

	# for each output
	for my $i (0 .. $ox) {
		
		# compute wavelength
		$w = $range_out->[0] + $i * $range_out->[2];
		
		# if wavelength < start of source
		if ($w < $range_in->[0]) {
			
			# if extrapolation defined
			if (defined($ext)) {
				
				# if linear extrapolation
				if ($ext eq 'linear') {
					
					# compute ratio
					$t = ($w - $range_in->[0])/$range_in->[2];
					
					# for each input
					for my $j (0 .. $ix) {
						
						# set element to linear value
						$mat->[$i][$j] = ($j == 0 ? 1 : 0) + $derv->[0][$j] * $t;
						
					}
					
				# if copy extrapolation
				} elsif ('copy') {
					
					# set element to first knot
					$mat->[$i][0] = 1;
					
				} else {
					
					# error
					croak('invalid extrapolation type');
					
				}
				
			}
			
		# if wavelength > end of source
		} elsif ($w > $range_in->[1]) {
			
			# if extrapolation defined
			if (defined($ext)) {
				



( run in 0.874 second using v1.01-cache-2.11-cpan-524268b4103 )