function [out1,coefs,n,k,d] = spbrk(sp,part)
%SPBRK Part(s) of a B-form or a BBform.
%
%   [KNOTS,COEFS,N,K,D] = SPBRK(SP) breaks the B-form in SP into its parts and 
%   returns as many of them as are specified by the output arguments.
%
%   OUT1 = SPBRK(SP,PART) returns the part specified by the string PART which 
%   may be (the beginning character(s) of) one of the following strings: 
%   'knots' or 't', 'coefs', 'number', 'order', 'dimension', 'interval' 
%
%   If PART is the 1-by-2 matrix [A,B], the restriction/extension of the spline
%   in SP to the interval with endpoints A and B is returned, in the same form.
%
%   SPBRK(SP) returns nothing, but prints out all the parts.
%
%   See also PPBRK, FNBRK, RSBRK, RPBRK.

%   Carl de Boor 25 feb 89
%   cb : 28 aug 94 (enlarge the options)
%   cb : 20 nov 95 (enlarge the options), 29aug96 (add BB-form)
%   cb : 18oct97 (change to structure, also cover multivariate spline)
%   cb : 22apr98 (accept array version of form; standardize help) 
%   cb : 09jan00 (minor  improvements in programming style and help)
%   cb : 12feb00 (check that second argin is string)
%   cb : 16apr00 (provide change of basic interval)
%   Copyright 1987-2000 by C. de Boor and The MathWorks, Inc.
%   $Revision: 1.13 $

if ~isstruct(sp)
  if sp(1)~=11&sp(1)~=12
     error('The input array does not seem to describe a function in B-form.')
  else
     di=sp(2);ni=sp(3);
     ci=reshape(sp(3+[1:di*ni]),di,ni);
     kk=sp(4+di*ni);ki=sp(4+di*ni+[1:kk+ni]);
     sp = spmak(ki,ci);
  end
end

if sp.form(1)~='B'
   error('The input does not seem to describe a spline in B-form.')
end
if nargin>1
   if nargout>1, error('Too many output arguments for the given input.')
   elseif ~isstr(part)
      if iscell(part)  % we must be dealing with a tensor-product spline
         c = sp.coefs; knots = sp.knots; m = length(knots);
         sizec = size(c);
         if length(sizec)~=m+1 % in trouble because of trailing singleton dims
            sizec = [sp.dim,sp.number]; c = reshape(c,sizec);
         end
         for i=m:-1:1
            dd = prod(sizec(1:m));
            spi = spcut(spmak(knots{i},reshape(c,dd,sp.number(i))), part{i});
            knots{i} = spi.knots; sizec(m+1) = spi.number;
            c = reshape(spi.coefs,sizec);
            if m>1
               c = permute(c,[1,m+1,2:m]);
               sizec(2:m+1) = sizec([m+1,2:m]);
            end
         end
         out1 = spmak(knots,c,sizec);

      else             % we must be dealing with a univariate spline
         out1 = spcut(sp,part);
      end
   else
      switch part(1)
      case 'd',       out1 = sp.dim;
      case 'n',       out1 = sp.number;
      case {'k','t'}, out1 = sp.knots;
      case 'o',       out1 = sp.order;
      case 'c',       out1 = sp.coefs;
      case 'i', % this must be treated differently in multivariate case
         if iscell(sp.knots)
            for i=length(sp.knots):-1:1  % loop backward to avoid redef.
               out1{i} = sp.knots{i}([1 end]);
            end
         else
           out1 = sp.knots([1 end]);
         end
      otherwise
         error(['''',part,''' is not part of a B-form.'])
      end
      return
   end
else
   if nargout==0
     if iscell(sp.knots) % we have a multivariate spline and, at present,
                         % I can't think of anything clever to do; so...
       disp(sp)
     else
       disp('knots(1:n+k)'),disp(sp.knots),
       disp('coefficients(d,n)'),disp(sp.coefs),
       disp('number n of coefficients'),disp(sp.number),
       disp('order k'),disp(sp.order),
       disp('dimension d of target'),disp(sp.dim),
     end
   else
    out1 = sp.knots; coefs = sp.coefs; n = sp.number; k = sp.order; d = sp.dim;
   end
end
function out1 = spcut(sp,interv)
%SPCUT change the basic interval
   if isempty(interv), out1 = sp; return, end
   sizei = size(interv);
   if sizei(2)>1 % we are to change the basic interval
      tl = interv(1,1); tr = interv(1,2);
      if tl==tr
         warning('No changes made since the given end points are equal.')
         out1 = sp; return
      end
      if tl>tr, tl = tr; tr = interv(1); end

      index = sorted(sp.knots,[tl,tr]); mults = knt2mlt(sp.knots);
      if tl<sp.knots(1),      m1 = 1;
      elseif tl==sp.knots(1), m1 = 0;
      else,                   m1 = sp.order;                    
         if tl==sp.knots(index(1)), m1 = m1-mults(index(1))-1; end
      end
      if tr>sp.knots(end),      m2 = 1;
      elseif tr==sp.knots(end), m2 = 0;
      else,                     m2 = sp.order;                    
         if tr==sp.knots(index(2)), m2 = m2-mults(index(2))-1; end
      end
      sp = fnrfn(sp, [repmat(tl,1,m1),repmat(tr,1,m2)]);
      index = sorted(sp.knots,[tl tr]);
      if sp.knots(end)>tr
         sp = spmak(sp.knots(1:index(2)),sp.coefs(:,1:(index(2)-sp.order)));
      end
      if sp.knots(1)<tl
         sp = spmak(sp.knots(index(1)-sp.order+1:end), ...
                    sp.coefs(:,index(1)-sp.order+1:end));
      end
      out1 = sp;
   else 
      error('The second argument should be a string or an interval.')
   end
