test squareform

function test_suite = test_squareform
% tests for cosmo_squareform
%
% #   For CoSMoMVPA's copyright information and license terms,   #
% #   see the COPYING file distributed with CoSMoMVPA.           #
    try % assignment of 'localfunctions' is necessary in Matlab >= 2016
        test_functions=localfunctions();
    catch % no problem; early Matlab versions can use initTestSuite fine
    end
    initTestSuite;


function test_squareform_()
    vec=1:6;
    mx=[0 1 2 3; 1 0 4 5; 2 4 0 6; 3 5 6 0];

    sf=@cosmo_squareform;

    % numeric input
    assertElementsAlmostEqual(sf(vec),mx);
    assertElementsAlmostEqual(sf(vec,'tomatrix'),mx);
    assertElementsAlmostEqual(sf(mx),vec);
    assertElementsAlmostEqual(sf(mx,'tovector'),vec);

    % logical input
    vec2=logical(vec);
    mx2=logical(mx);
    assertEqual(sf(vec2),mx2);
    assertEqual(sf(vec2,'tomatrix'),mx2);
    assertEqual(sf(mx2),vec2);
    assertEqual(sf(mx2,'tovector'),vec2);

    % exceptions
    assertExceptionThrown(@() sf(vec,'foo'),'');
    assertExceptionThrown(@() sf(mx,'foo'),'');
    assertExceptionThrown(@() sf(vec,struct()),...
                                    '');
    assertExceptionThrown(@() sf(struct()),'');
    assertExceptionThrown(@() sf(struct(),'tovector'),'');
    assertExceptionThrown(@() sf(struct(),'tomatrix'),'');
    assertExceptionThrown(@() sf(zeros(2,3),'tovector'),'');
    assertExceptionThrown(@() sf(zeros(2),'tomatrix'),'');
    assertExceptionThrown(@() sf(zeros([2,2,2])),'');
    assertExceptionThrown(@() sf(zeros([2,2,2]),'tovector'),'');
    assertExceptionThrown(@() sf(zeros([2,2,2]),'tomatrix'),'');

    assertExceptionThrown(@() sf([vec 1]),'');
    assertExceptionThrown(@() sf([vec 1],'tomatrix'),'');
    assertExceptionThrown(@() sf(cell(0,0),'tomatrix'),'');
    assertExceptionThrown(@() sf(cell(0,0),'tovector'),'');
    assertExceptionThrown(@() sf(cell(0,0),''),'');


    assertExceptionThrown(@() sf(eye(4)+mx),'');
    assertExceptionThrown(@() sf(eye(4)+mx,'tovector'),'');

    mx(2,1)=3;
    assertExceptionThrown(@() sf(mx,'tovector'),'');

function test_squareform_matlab_agreement()
    if cosmo_wtf('is_octave') || ~cosmo_check_external('@stats',false)
        cosmo_notify_test_skipped('Matlab''s squareform is not available');
        return
    end

    for side=1:10
        n=side*(side-1)/2;
        data=rand(n,1);

        helper_assert_squareform_equal_to_matlab(data);
        helper_assert_squareform_equal_to_matlab(data,'tomatrix');
        helper_assert_squareform_equal_to_matlab(data','tomatrix');

        mx=squareform(data);
        helper_assert_squareform_equal_to_matlab(mx);
        helper_assert_squareform_equal_to_matlab(mx,'tovector');
    end

function helper_assert_squareform_equal_to_matlab(varargin)
    assertEqual(squareform(varargin{:}),cosmo_squareform(varargin{:}));


function test_squareform_random_data_without_nans()
    helper_test_squareform_with_random_data(false);

function test_squareform_random_data_with_nans()
    helper_test_squareform_with_random_data(true);

function helper_test_squareform_with_random_data(has_nan)
    for side=1:10
        data=randn(side);
        data=data+data';
        data=data-diag(diag(data));

        if has_nan
            if side==1
                continue;
            end

            data(side,1)=NaN;
            data(1,side)=NaN;
        end

        data_sq=cosmo_squareform(data,'tovector');
        nelem=numel(data_sq);
        assertEqual(nelem,side*(side-1)/2);

        counter=0;
        for col=1:(side-1)
            for row=(col+1):side
                counter=counter+1;
                assertEqual(data(row,col),data_sq(counter));
            end
        end

        data_back=cosmo_squareform(data_sq,'tomatrix');
        if side==1
            assert(isempty(data_back));
        else
            assertEqual(data,data_back);
        end
    end