function xyz = lab2xyz(lab,white)
% 
%  xyz = lab2xyz(lab,white)
%
%    Return the xyz values from a set of La*b* values.
% 
% ARUGMENTS:
%    lab is a 3 x N matrix of Lab values
%    white is 3 vector specifying the white point
%
% 
% 01.19.98 BW.  Modified by inserting new tests (find, isempty)
% for Matlab 5.0 syntax.  The old strategy produced errors under 5.0

% DEBUGGING
% lab = grayLAB;
% white = whiteXYZ;

if length(white) ~= 3,
  error('White point is not a three-vector');
elseif size(lab,1) ~= 3,
  error('lab argument must have three rows');
end

Lstar = lab(1,:);
astar = lab(2,:);
bstar = lab(3,:);

Xn = white(1);
Yn = white(2);
Zn = white(3);


%
%	Allocate space
%
fX = zeros(1,size(lab,2));
fY = zeros(1,size(lab,2));
fZ = zeros(1,size(lab,2));

Xratio = zeros(1,size(lab,2));
Yratio = zeros(1,size(lab,2));
Zratio = zeros(1,size(lab,2));


% Usual formula for Lstar
Y = Yn .*  ( (Lstar + 16.0) ./ 116.0) .^ 3.0;

% but if Y/Yn is too small, use other formula
l = (Y/Yn) < 0.008856;
l = find(l > 0) ;
if ~isempty(l)
  Y(l) =  (Lstar(l) / 903.3) * Yn;
end
%
%	Now, we estimate X/Xn, Y/Yn, and Z/Zn
%
Yratio = (Y/Yn);
l = find(Yratio > .008856);
if ~isempty(l)
  fY(l) = Yratio(l).^(1/3);
end

l = find(Yratio <= .008856);
if ~isempty(l)
  fY(l) = 7.787 * Yratio(l) + 16/116;
end


% Inverse range for Lab ratios
fX = (astar/500.0) + fY;

l = find(fX > 0.206893);
if ~isempty(l)
  Xratio(l) = fX(l) .^ 3;
end

l = find(fX <= 0.206893);
if ~isempty(l)
  Xratio(l) = (fX(l) - (16/116)) / 7.787;
end

% Inverse range for Lab ratios
fZ = fY - (bstar/200.0);

l = find(fZ > 0.206893);
if ~isempty(l)
  Zratio(l) = fZ(l) .^ 3;
end
l = find(fZ <= 0.206893);
if ~isempty(l)
  Zratio(l) = (fZ(l) - (16/116)) / 7.787;
end

%	Finally, we deduce X, Y and Z
X = Xratio * Xn;
Z = Zratio * Zn;

xyz = [X;Y;Z];

