classdef SparseAssembler < handle
    %SPARSEASSEMBLER Easy and efficient assembly of sparse matrices
    
    properties (Constant)
        DefaultCapacity = 1000;
    end
    
    properties
        Indices     % two column array of matrix row and column indices
        Values      % matrix elements, each column corresponds to a matrix
        N           % number of entries stored
    end
    
    methods
        function obj = SparseAssembler(nMatrices, capacity)
            if nargin < 2
                capacity = SparseAssembler.DefaultCapacity;
            end
            obj.Indices = zeros(capacity, 2);
            obj.Values = zeros(capacity, nMatrices);
            obj.N = 0;
        end
        
        function add(obj, i, j, varargin)
            [J, I] = meshgrid(i,j);
            idx = obj.N + (1:numel(J));
            if max(idx) > size(obj.Indices,1)
                obj.Indices(2*size(obj.Indices,1),1) = 0;
                obj.Values(2*size(obj.Values,1),1) = 0;
            end
            obj.Indices(idx,1) = I(:);
            obj.Indices(idx,2) = J(:);
            for v = 1 : size(obj.Values,2)
                obj.Values(idx,v) = varargin{v}(:);
            end
            obj.N = obj.N + numel(J);
        end
        
        function [i,j,varargout] = finish(obj)
            obj.Indices = obj.Indices(1:obj.N,:);
            obj.Values = obj.Values(1:obj.N,:);
            i = obj.Indices(:,1);
            j = obj.Indices(:,2);
            for v = 1 : nargout-2
                varargout{v} = obj.Values(:,v);
            end
        end
    end % of public methods
end % of class
