function Phi = MatrixEnsemble(n,m,ensemble)
% MatrixEnsemble: Generates a random matrix of size n by m.
%
%  Usage:
%     Phi = MatrixEnsemble(n,m,ensemble)
%  Inputs:
%    n          number of rows
%    m          number of columns
%    ensemble   string containing name of matrix ensemble:
%               'USE', 'RSE', 'Fourier', 'RST', 'Hadamard', 'URP', 'IR'. 
%               Default is 'USE'.
%  Outputs:
%    Phi        n by m matrix from the specified ensemble
%  Description:
%    This function creates a matrix from the specified random matrix 
%    ensemble. The following random ensembles are implemented:
%
%      'USE' - Uniform spherical ensemble. Columns are n-vectors, 
%      uniformly distributed on the sphere S^{n-1} (default).
%
%      'RSE' - Random signs ensemble. Entries in the matrix are 
%      chosen from a bernoulli +/-1 distribution, and columns are 
%      normalized to have unit euclidean length.
%
%      'Fourier' - Partial Fourier ensemble. Matrices in this ensemble 
%      are generated by taking the m by m Fourier matrix, sampling 
%      n rows at random, and scaling columns to have unit euclidean length.
%
%      'RST' - Partial RST (Real Fourier) ensemble. See 'Fourier' above.
%
%      'Hadamard' - Partial Hadamard ensemble. Matrices in this ensemble 
%      are generated by taking the m by m Hadamard matrix, sampling 
%      n rows at random, and scaling columns to have unit euclidean length.
%
%      'URP' - Uniform Random Projection ensemble. Matrices in this 
%      ensemble are generated by sampling n rows of an m by m 
%      random orthogonal matrix.
%
%      'IR' - Identity and Random otho-basis. An n by 2n matrix is 
%      constructed, as the concatenation of the n by n identity and 
%      an n x n random ortho-basis. 
%
%  See Also
%    SparseVector

if nargin < 3,
    ensemble = 'USE';
end

switch upper(ensemble)
    case 'USE'
        Phi = randn(n,m);

        % Normalize the columns of Phi
        for j = 1:m
            Phi(:,j) = Phi(:,j) ./ twonorm(Phi(:,j));
        end
        
    case 'RSE'
        Phi = sign(rand([n m]) - 0.5);
        zz = find(Phi == 0);
        Phi(zz) = ones(size(zz));

        % Normalize the columns of Phi
        for ii = 1:size(Phi,2)
            Phi(:,ii) = Phi(:,ii) ./ twonorm(Phi(:,ii));
        end
        
    case 'HADAMARD'
        H = hadamard(m);
        p = randperm(m);
        Phi = H(p(1:n), :);
    
        % Normalize the columns of Phi
        for ii = 1:size(Phi,2)
            Phi(:,ii) = Phi(:,ii) ./ twonorm(Phi(:,ii));
        end
        
    case 'FOURIER'
        H = FourierMat(m);
        p = randperm(m);
        Phi = H(p(1:n), :);
    
        % Normalize the columns of Phi
        for ii = 1:size(Phi,2)
            Phi(:,ii) = Phi(:,ii) ./ twonorm(Phi(:,ii));
        end

    case 'RST'
        H = RSTMat(m);
        p = randperm(m);
        Phi = H(p(1:n), :);
    
        % Normalize the columns of Phi
        for ii = 1:size(Phi,2)
            Phi(:,ii) = Phi(:,ii) ./ twonorm(Phi(:,ii));
        end

    case 'URP'
        [U,S,V] = svd(rand(n,m),'econ');
        Phi = V';

        % Normalize the columns of Phi
        for ii = 1:size(Phi,2)
            Phi(:,ii) = Phi(:,ii) ./ twonorm(Phi(:,ii));
        end
        
    case 'IR'
        [Q,R] = qr(rand(n));
        Phi = [eye(n) Q];
        
end%
% Part of SparseLab Version:100
% Created Tuesday March 28, 2006
% This is Copyrighted Material
% For Copying permissions see COPYING.m
% Comments? e-mail sparselab@stanford.edu
%
