<commit_before>/*
   Copyright (c) 2009-2013, Jack Poulson
   All rights reserved.

   This file is part of Elemental and is under the BSD 2-Clause License,
   which can be found in the LICENSE file in the root directory, or at
   http://opensource.org/licenses/BSD-2-Clause
*/
// NOTE: It is possible to simply include "elemental.hpp" instead
#include "elemental-lite.hpp"
#include "elemental/blas-like/level1/Axpy.hpp"
#include "elemental/blas-like/level1/Scale.hpp"
#include "elemental/lapack-like/Norm/Frobenius.hpp"
#include "elemental/lapack-like/Norm/EntrywiseOne.hpp"
#include "elemental/lapack-like/Norm/Max.hpp"
#include "elemental/lapack-like/Norm/Two.hpp"
#include "elemental/lapack-like/Norm/Zero.hpp"
#include "elemental/convex/SingularValueSoftThreshold.hpp"
#include "elemental/matrices/Uniform.hpp"
using namespace elem;

//
// This driver generates a random low-rank matrix and then randomly corrupts
// a large percentage of the entries (by default 10%). Robust Principal
// Component Analysis (RPCA) is then used to recover both the underlying
// low-rank and sparse matrices.
//
// Please see <http://perception.csl.illinois.edu/matrix-rank/sample_code.html>
// for references and documentation on the Augmented Lagrange Multiplier (ALM)
// and Alternating Direction Method of Multipliers (ADMM) for Robust PCA.
//

// Corrupt a portion of the entries with uniform samples from the unit ball
template<typename F>
int Corrupt( DistMatrix<F>& A, double probCorrupt )
{
#ifndef RELEASE
    PushCallStack("Corrupt");
#endif
    typedef typename Base<F>::type R;

    int numLocalCorrupt = 0;
    const int localHeight = A.LocalHeight();
    const int localWidth = A.LocalWidth();
    for( int jLocal=0; jLocal<localWidth; ++jLocal )
    {
        for( int iLocal=0; iLocal<localHeight; ++iLocal )
        {
            if( Abs(SampleUnitBall<R>()) <= probCorrupt )
            {
                ++numLocalCorrupt;
                const F perturb = SampleUnitBall<F>();
                A.SetLocal( iLocal, jLocal, A.GetLocal(iLocal,jLocal)+perturb );
            }
        }
    }

    int numCorrupt;
    mpi::AllReduce
    ( &numLocalCorrupt, &numCorrupt, 1, mpi::SUM, A.Grid().VCComm() );
#ifndef RELEASE
    PopCallStack();
#endif
    return numCorrupt;
}

template<typename F,Distribution U,Distribution V>
void Sign( DistMatrix<F,U,V>& A )
{
    const int localHeight = A.LocalHeight();
    const int localWidth = A.LocalWidth();
    for( int jLocal=0; jLocal<localWidth; ++jLocal )
    {
        for( int iLocal=0; iLocal<localHeight; ++iLocal )
        {
            const F alpha = A.GetLocal( iLocal, jLocal );
            A.SetLocal( iLocal, jLocal, alpha/Abs(alpha) );
        }
    }
}

template<typename F>
void RPCA_ADMM
( const DistMatrix<F>& M, DistMatrix<F>& L, DistMatrix<F>& S,
  typename Base<F>::type beta,
  typename Base<F>::type tau,
  typename Base<F>::type tol,
  int maxIts,
  bool print )
{
    typedef typename Base<F>::type R;

    if( beta <= R(0) )
        throw std::logic_error("beta cannot be non-positive");
    if( tau <= R(0) )
        throw std::logic_error("tau cannot be non-positive");
    if( tol <= R(0) )
        throw std::logic_error("tol cannot be non-positive");

    const int m = M.Height();
    const int n = M.Width();
    const int commRank = mpi::CommRank( M.Grid().Comm() );

    DistMatrix<F> E( M.Grid() ), Y( M.Grid() );
    Zeros( m, n, Y );

    const R frobM = FrobeniusNorm( M );
    if( commRank == 0 )
        std::cout << "|| M ||_F = " << frobM << std::endl;

    int numIts = 0;
    while( true )
    {
        ++numIts;

        // ST_{tau/beta}(M - L + Y/beta)
        S = M;
        Axpy( F(-1), L, S );
        Axpy( F(1)/beta, Y, S );
        SoftThreshold( S, tau/beta );
        const int numNonzeros = ZeroNorm( S );

        // SVT_{1/beta}(M - S + Y/beta)
        L = M;
        Axpy( F(-1), S, L );
        Axpy( F(1)/beta, Y, L );
        const int rank = SingularValueSoftThreshold( L, R(1)/beta );

        // E := M - (L + S)
        E = M;
        Axpy( F(-1), L, E );
        Axpy( F(-1), S, E );
        const R frobE = FrobeniusNorm( E );

        if( frobE/frobM <= tol )
        {
            if( commRank == 0 )
                std::cout << "Converged after " << numIts << " iterations "
                          << " with rank=" << rank
                          << ", numNonzeros=" << numNonzeros << " and "
                          << "|| E ||_F / || M ||_F = " << frobE/frobM
                          << std::endl;
            break;
        }
        else if( numIts >= maxIts )
        {
            if( commRank == 0 )
                std::cout << "Aborting after " << maxIts << " iterations"
                          << std::endl;
            break;
        }
        else
        {
            if( commRank == 0 )
                std::cout << numIts << ": || E ||_F / || M ||_F = "
                          << frobE/frobM << ", rank=" << rank
                          << ", numNonzeros=" << numNonzeros << std::endl;
        }

        // Y := Y + beta E
        Axpy( beta, E, Y );
    }
}

// If 'beta' or 'tau' is passed in as zero, then an estimate is used instead
template<typename F>
void RPCA_ALM
( const DistMatrix<F>& M, DistMatrix<F>& L, DistMatrix<F>& S,
  typename Base<F>::type beta,
  typename Base<F>::type tau,
  typename Base<F>::type rho,
  typename Base<F>::type tol,
  int maxIts,
  bool print )
{
    typedef typename Base<F>::type R;

    const int m = M.Height();
    const int n = M.Width();
    const int commRank = mpi::CommRank( M.Grid().Comm() );

    if( tol <= R(0) )
        throw std::logic_error("tol cannot be non-positive");
    if( tau < R(0) )
        throw std::logic_error("tau cannot be negative");
    else if( tau == R(0) )
        tau = R(1) / sqrt(R(1)*m);

    DistMatrix<F> Y( M );
    Sign( Y );
    const R twoNorm = TwoNorm( Y );
    const R maxNorm = MaxNorm( Y );
    const R infNorm = maxNorm / tau;
    const R dualNorm = std::max( twoNorm, infNorm );
    Scale( F(1)/dualNorm, Y );

    if( beta < R(0) )
        throw std::logic_error("beta cannot be negative");
    else if( beta == R(0) )
        beta = R(1) / (2*twoNorm);

    const R frobM = FrobeniusNorm( M );
    if( commRank == 0 )
        std::cout << "|| M ||_F = " << frobM << std::endl;

    int numIts=0, numPrimalIts=0;
    DistMatrix<F> LLast( M.Grid() ), SLast( M.Grid() ), E( M.Grid() );
    while( true )
    {
        ++numIts;

        int rank, numNonzeros;
        while( true )
        {
            ++numPrimalIts;

            LLast = L;
            SLast = S;

            // ST_{tau/beta}(M - L + Y/beta)
            S = M;
            Axpy( F(-1), L, S );
            Axpy( F(1)/beta, Y, S );
            SoftThreshold( S, tau/beta );
            numNonzeros = ZeroNorm( S );

            // SVT_{1/beta}(M - S + Y/beta)
            L = M;
            Axpy( F(-1), S, L );
            Axpy( F(1)/beta, Y, L );
            rank = SingularValueSoftThreshold( L, R(1)/beta );

            Axpy( F(-1), L, LLast );
            Axpy( F(-1), S, SLast );
            const R frobLDiff = FrobeniusNorm( LLast );
            const R frobSDiff = FrobeniusNorm( SLast );

            if( frobLDiff/frobM < tol && frobSDiff/frobM < tol )
            {
                if( commRank == 0 )
                    std::cout << "Primal loop converged" << std::endl;
                break;
            }
            else
            {
                if( commRank == 0 )
                    std::cout << "  " << numPrimalIts
                              << ": \n"
                              << "   || Delta L ||_F / || M ||_F = "
                              << frobLDiff/frobM << "\n"
                              << "   || Delta S ||_F / || M ||_F = "
                              << frobSDiff/frobM << "\n"
                              << "   rank=" << rank
                              << ", numNonzeros=" << numNonzeros << std::endl;
            }
        }

        // E := M - (L + S)
        E = M;
        Axpy( -1., L, E );
        Axpy( -1., S, E );
        const R frobE = FrobeniusNorm( E );

        if( frobE/frobM <= tol )
        {
            if( commRank == 0 )
                std::cout << "Converged after " << numIts << " iterations and "
                          << numPrimalIts << " primal iterations with rank="
                          << rank << ", numNonzeros=" << numNonzeros << " and "
                          << "|| E ||_F / || M ||_F = " << frobE/frobM
                          << std::endl;
            break;
        }
        else if( numIts >= maxIts )
        {
            if( commRank == 0 )
                std::cout << "Aborting after " << maxIts << " iterations"
                          << std::endl;
            break;
        }
        else
        {
            if( commRank == 0 )
                std::cout << numPrimalIts << ": || E ||_F / || M ||_F = "
                          << frobE/frobM << ", rank=" << rank
                          << ", numNonzeros=" << numNonzeros << std::endl;
        }

        // Y := Y + beta E
        Axpy( beta, E, Y );
        beta *= rho;
    }
}

int
main( int argc, char* argv[] )
{
    Initialize( argc, argv );
    mpi::Comm comm = mpi::COMM_WORLD;
    const int commRank = mpi::CommRank( comm );

    typedef Complex<double> C;

    try
    {
        const int m = Input("--height","height of matrix",100);
        const int n = Input("--width","width of matrix",100);
        const int rank = Input("--rank","rank of structured matrix",10);
        const double probCorrupt =
            Input("--probCorrupt","probability of corruption",0.1);
        const double tau = Input("--tau","sparse weighting factor",0.1);
        const double beta = Input("--beta","step size",1.);
        const double rho = Input("--rho","stepsize multiple in ALM",6.);
        const int maxIts = Input("--maxIts","maximum iterations",1000);
        const double tol = Input("--tol","tolerance",1.e-6);
        const bool useALM = Input("--useALM","use ALM algorithm?",true);
        const bool print = Input("--print","print matrices",false);
        ProcessInput();
        PrintInputReport();

        DistMatrix<C> LTrue;
        {
            DistMatrix<C> U, V;
            Uniform( m, rank, U );
            Uniform( n, rank, V );
            Zeros( m, n, LTrue );
            Gemm( NORMAL, ADJOINT, C(1./std::max(m,n)), U, V, C(0), LTrue );
        }
        const double frobLTrue = FrobeniusNorm( LTrue );
        if( commRank == 0 )
            std::cout << "|| L ||_F = " << frobLTrue << std::endl;
        if( print )
            LTrue.Print("True L");

        DistMatrix<C> STrue;
        Zeros( m, n, STrue );
        const int numCorrupt = Corrupt( STrue, probCorrupt );
        const double frobSTrue = FrobeniusNorm( STrue );
        if( commRank == 0 )
            std::cout << "number of corrupted entries: " << numCorrupt << "\n"
                      << "|| S ||_F = " << frobSTrue << std::endl;
        if( print )
            STrue.Print("True S");

        // M = LTrue + STrue
        DistMatrix<C> M( LTrue );
        Axpy( C(1), STrue, M );

        DistMatrix<C> L, S;
        Zeros( m, n, L );
        Zeros( m, n, S );

        if( useALM )
            RPCA_ALM( M, L, S, beta, tau, rho, tol, maxIts, print );
        else
            RPCA_ADMM( M, L, S, beta, tau, tol, maxIts, print );

        if( print )
        {
            L.Print("L");
            S.Print("S");
        }
        Axpy( C(-1), LTrue, L );
        Axpy( C(-1), STrue, S );
        const double frobLDiff = FrobeniusNorm( L );
        const double frobSDiff = FrobeniusNorm( S );
        if( commRank == 0 )
            std::cout << "\n"
                      << "Error in computed decomposition:\n"
                      << "  || L - LTrue ||_F / || LTrue ||_F = "
                      << frobLDiff/frobLTrue << "\n"
                      << "  || S - STrue ||_F / || STrue ||_F = "
                      << frobSDiff/frobSTrue << "\n"
                      << std::endl;
        if( print )
        {
            L.Print("L - LTrue");
            S.Print("S - STrue");
        }
    }
    catch( ArgException& e )
    {
        // There is nothing to do
    }
    catch( std::exception& e )
    {
        std::ostringstream os;
        os << "Process " << commRank << " caught error message:\n" << e.what()
           << std::endl;
        std::cerr << os.str();
#ifndef RELEASE
        DumpCallStack();
#endif
    }

    Finalize();
    return 0;
}
<commit_msg>Defaulting to the choice of tau=1/sqrt(max(m,n)) in RPCA example<commit_after>/*
   Copyright (c) 2009-2013, Jack Poulson
   All rights reserved.

   This file is part of Elemental and is under the BSD 2-Clause License,
   which can be found in the LICENSE file in the root directory, or at
   http://opensource.org/licenses/BSD-2-Clause
*/
// NOTE: It is possible to simply include "elemental.hpp" instead
#include "elemental-lite.hpp"
#include "elemental/blas-like/level1/Axpy.hpp"
#include "elemental/blas-like/level1/Scale.hpp"
#include "elemental/lapack-like/Norm/Frobenius.hpp"
#include "elemental/lapack-like/Norm/EntrywiseOne.hpp"
#include "elemental/lapack-like/Norm/Max.hpp"
#include "elemental/lapack-like/Norm/Two.hpp"
#include "elemental/lapack-like/Norm/Zero.hpp"
#include "elemental/convex/SingularValueSoftThreshold.hpp"
#include "elemental/matrices/Uniform.hpp"
using namespace elem;

//
// This driver generates a random low-rank matrix and then randomly corrupts
// a large percentage of the entries (by default 10%). Robust Principal
// Component Analysis (RPCA) is then used to recover both the underlying
// low-rank and sparse matrices.
//
// Please see <http://perception.csl.illinois.edu/matrix-rank/sample_code.html>
// for references and documentation on the Augmented Lagrange Multiplier (ALM)
// and Alternating Direction Method of Multipliers (ADMM) for Robust PCA.
//

// Corrupt a portion of the entries with uniform samples from the unit ball
template<typename F>
int Corrupt( DistMatrix<F>& A, double probCorrupt )
{
#ifndef RELEASE
    PushCallStack("Corrupt");
#endif
    typedef typename Base<F>::type R;

    int numLocalCorrupt = 0;
    const int localHeight = A.LocalHeight();
    const int localWidth = A.LocalWidth();
    for( int jLocal=0; jLocal<localWidth; ++jLocal )
    {
        for( int iLocal=0; iLocal<localHeight; ++iLocal )
        {
            if( Abs(SampleUnitBall<R>()) <= probCorrupt )
            {
                ++numLocalCorrupt;
                const F perturb = SampleUnitBall<F>();
                A.SetLocal( iLocal, jLocal, A.GetLocal(iLocal,jLocal)+perturb );
            }
        }
    }

    int numCorrupt;
    mpi::AllReduce
    ( &numLocalCorrupt, &numCorrupt, 1, mpi::SUM, A.Grid().VCComm() );
#ifndef RELEASE
    PopCallStack();
#endif
    return numCorrupt;
}

template<typename F,Distribution U,Distribution V>
void Sign( DistMatrix<F,U,V>& A )
{
    const int localHeight = A.LocalHeight();
    const int localWidth = A.LocalWidth();
    for( int jLocal=0; jLocal<localWidth; ++jLocal )
    {
        for( int iLocal=0; iLocal<localHeight; ++iLocal )
        {
            const F alpha = A.GetLocal( iLocal, jLocal );
            A.SetLocal( iLocal, jLocal, alpha/Abs(alpha) );
        }
    }
}

// If 'tau' is passed in as zero, it is set to 1/sqrt(max(m,n))
template<typename F>
void RPCA_ADMM
( const DistMatrix<F>& M, DistMatrix<F>& L, DistMatrix<F>& S,
  typename Base<F>::type beta,
  typename Base<F>::type tau,
  typename Base<F>::type tol,
  int maxIts,
  bool print )
{
    typedef typename Base<F>::type R;
    const int m = M.Height();
    const int n = M.Width();
    const int commRank = mpi::CommRank( M.Grid().Comm() );

    // If tau is not specified, then set it to 1/sqrt(max(m,n))
    if( tau == R(0) )
        tau = R(1)/sqrt(R(std::max(m,n)));

    if( beta <= R(0) )
        throw std::logic_error("beta cannot be non-positive");
    if( tau <=  R(0) )
        throw std::logic_error("tau cannot be non-positive");
    if( tol <= R(0) )
        throw std::logic_error("tol cannot be non-positive");

    DistMatrix<F> E( M.Grid() ), Y( M.Grid() );
    Zeros( m, n, Y );

    const R frobM = FrobeniusNorm( M );
    if( commRank == 0 )
        std::cout << "|| M ||_F = " << frobM << std::endl;

    int numIts = 0;
    while( true )
    {
        ++numIts;

        // ST_{tau/beta}(M - L + Y/beta)
        S = M;
        Axpy( F(-1), L, S );
        Axpy( F(1)/beta, Y, S );
        SoftThreshold( S, tau/beta );
        const int numNonzeros = ZeroNorm( S );

        // SVT_{1/beta}(M - S + Y/beta)
        L = M;
        Axpy( F(-1), S, L );
        Axpy( F(1)/beta, Y, L );
        const int rank = SingularValueSoftThreshold( L, R(1)/beta );

        // E := M - (L + S)
        E = M;
        Axpy( F(-1), L, E );
        Axpy( F(-1), S, E );
        const R frobE = FrobeniusNorm( E );

        if( frobE/frobM <= tol )
        {
            if( commRank == 0 )
                std::cout << "Converged after " << numIts << " iterations "
                          << " with rank=" << rank
                          << ", numNonzeros=" << numNonzeros << " and "
                          << "|| E ||_F / || M ||_F = " << frobE/frobM
                          << std::endl;
            break;
        }
        else if( numIts >= maxIts )
        {
            if( commRank == 0 )
                std::cout << "Aborting after " << maxIts << " iterations"
                          << std::endl;
            break;
        }
        else
        {
            if( commRank == 0 )
                std::cout << numIts << ": || E ||_F / || M ||_F = "
                          << frobE/frobM << ", rank=" << rank
                          << ", numNonzeros=" << numNonzeros << std::endl;
        }

        // Y := Y + beta E
        Axpy( beta, E, Y );
    }
}

// If 'beta' or 'tau' is passed in as zero, then an estimate is used instead
template<typename F>
void RPCA_ALM
( const DistMatrix<F>& M, DistMatrix<F>& L, DistMatrix<F>& S,
  typename Base<F>::type beta,
  typename Base<F>::type tau,
  typename Base<F>::type rho,
  typename Base<F>::type tol,
  int maxIts,
  bool print )
{
    typedef typename Base<F>::type R;

    const int m = M.Height();
    const int n = M.Width();
    const int commRank = mpi::CommRank( M.Grid().Comm() );

    // If tau is unspecified, set it to 1/sqrt(max(m,n))
    if( tau == R(0) )
        tau = R(1) / sqrt(R(std::max(m,n)));

    if( tol <= R(0) )
        throw std::logic_error("tol cannot be non-positive");
    if( tau <= R(0) )
        throw std::logic_error("tau cannot be non-positive");

    DistMatrix<F> Y( M );
    Sign( Y );
    const R twoNorm = TwoNorm( Y );
    const R maxNorm = MaxNorm( Y );
    const R infNorm = maxNorm / tau;
    const R dualNorm = std::max( twoNorm, infNorm );
    Scale( F(1)/dualNorm, Y );

    // If beta is unspecified, set it to 1 / 2 || sign(M) ||_2
    if( beta == R(0) )
        beta = R(1) / (2*twoNorm);

    if( beta <= R(0) )
        throw std::logic_error("beta cannot be non-positive");

    const R frobM = FrobeniusNorm( M );
    if( commRank == 0 )
        std::cout << "|| M ||_F = " << frobM << std::endl;

    int numIts=0, numPrimalIts=0;
    DistMatrix<F> LLast( M.Grid() ), SLast( M.Grid() ), E( M.Grid() );
    while( true )
    {
        ++numIts;

        int rank, numNonzeros;
        while( true )
        {
            ++numPrimalIts;

            LLast = L;
            SLast = S;

            // ST_{tau/beta}(M - L + Y/beta)
            S = M;
            Axpy( F(-1), L, S );
            Axpy( F(1)/beta, Y, S );
            SoftThreshold( S, tau/beta );
            numNonzeros = ZeroNorm( S );

            // SVT_{1/beta}(M - S + Y/beta)
            L = M;
            Axpy( F(-1), S, L );
            Axpy( F(1)/beta, Y, L );
            rank = SingularValueSoftThreshold( L, R(1)/beta );

            Axpy( F(-1), L, LLast );
            Axpy( F(-1), S, SLast );
            const R frobLDiff = FrobeniusNorm( LLast );
            const R frobSDiff = FrobeniusNorm( SLast );

            if( frobLDiff/frobM < tol && frobSDiff/frobM < tol )
            {
                if( commRank == 0 )
                    std::cout << "Primal loop converged" << std::endl;
                break;
            }
            else
            {
                if( commRank == 0 )
                    std::cout << "  " << numPrimalIts
                              << ": \n"
                              << "   || Delta L ||_F / || M ||_F = "
                              << frobLDiff/frobM << "\n"
                              << "   || Delta S ||_F / || M ||_F = "
                              << frobSDiff/frobM << "\n"
                              << "   rank=" << rank
                              << ", numNonzeros=" << numNonzeros << std::endl;
            }
        }

        // E := M - (L + S)
        E = M;
        Axpy( -1., L, E );
        Axpy( -1., S, E );
        const R frobE = FrobeniusNorm( E );

        if( frobE/frobM <= tol )
        {
            if( commRank == 0 )
                std::cout << "Converged after " << numIts << " iterations and "
                          << numPrimalIts << " primal iterations with rank="
                          << rank << ", numNonzeros=" << numNonzeros << " and "
                          << "|| E ||_F / || M ||_F = " << frobE/frobM
                          << std::endl;
            break;
        }
        else if( numIts >= maxIts )
        {
            if( commRank == 0 )
                std::cout << "Aborting after " << maxIts << " iterations"
                          << std::endl;
            break;
        }
        else
        {
            if( commRank == 0 )
                std::cout << numPrimalIts << ": || E ||_F / || M ||_F = "
                          << frobE/frobM << ", rank=" << rank
                          << ", numNonzeros=" << numNonzeros << std::endl;
        }

        // Y := Y + beta E
        Axpy( beta, E, Y );
        beta *= rho;
    }
}

int
main( int argc, char* argv[] )
{
    Initialize( argc, argv );
    mpi::Comm comm = mpi::COMM_WORLD;
    const int commRank = mpi::CommRank( comm );

    typedef Complex<double> C;

    try
    {
        const int m = Input("--height","height of matrix",100);
        const int n = Input("--width","width of matrix",100);
        const int rank = Input("--rank","rank of structured matrix",10);
        const double probCorrupt =
            Input("--probCorrupt","probability of corruption",0.1);
        const double tau = Input("--tau","sparse weighting factor",0.);
        const double beta = Input("--beta","step size",1.);
        const double rho = Input("--rho","stepsize multiple in ALM",6.);
        const int maxIts = Input("--maxIts","maximum iterations",1000);
        const double tol = Input("--tol","tolerance",1.e-6);
        const bool useALM = Input("--useALM","use ALM algorithm?",true);
        const bool print = Input("--print","print matrices",false);
        ProcessInput();
        PrintInputReport();

        DistMatrix<C> LTrue;
        {
            DistMatrix<C> U, V;
            Uniform( m, rank, U );
            Uniform( n, rank, V );
            Zeros( m, n, LTrue );
            Gemm( NORMAL, ADJOINT, C(1./std::max(m,n)), U, V, C(0), LTrue );
        }
        const double frobLTrue = FrobeniusNorm( LTrue );
        if( commRank == 0 )
            std::cout << "|| L ||_F = " << frobLTrue << std::endl;
        if( print )
            LTrue.Print("True L");

        DistMatrix<C> STrue;
        Zeros( m, n, STrue );
        const int numCorrupt = Corrupt( STrue, probCorrupt );
        const double frobSTrue = FrobeniusNorm( STrue );
        if( commRank == 0 )
            std::cout << "number of corrupted entries: " << numCorrupt << "\n"
                      << "|| S ||_F = " << frobSTrue << std::endl;
        if( print )
            STrue.Print("True S");

        // M = LTrue + STrue
        DistMatrix<C> M( LTrue );
        Axpy( C(1), STrue, M );

        DistMatrix<C> L, S;
        Zeros( m, n, L );
        Zeros( m, n, S );

        if( useALM )
            RPCA_ALM( M, L, S, beta, tau, rho, tol, maxIts, print );
        else
            RPCA_ADMM( M, L, S, beta, tau, tol, maxIts, print );

        if( print )
        {
            L.Print("L");
            S.Print("S");
        }
        Axpy( C(-1), LTrue, L );
        Axpy( C(-1), STrue, S );
        const double frobLDiff = FrobeniusNorm( L );
        const double frobSDiff = FrobeniusNorm( S );
        if( commRank == 0 )
            std::cout << "\n"
                      << "Error in computed decomposition:\n"
                      << "  || L - LTrue ||_F / || LTrue ||_F = "
                      << frobLDiff/frobLTrue << "\n"
                      << "  || S - STrue ||_F / || STrue ||_F = "
                      << frobSDiff/frobSTrue << "\n"
                      << std::endl;
        if( print )
        {
            L.Print("L - LTrue");
            S.Print("S - STrue");
        }
    }
    catch( ArgException& e )
    {
        // There is nothing to do
    }
    catch( std::exception& e )
    {
        std::ostringstream os;
        os << "Process " << commRank << " caught error message:\n" << e.what()
           << std::endl;
        std::cerr << os.str();
#ifndef RELEASE
        DumpCallStack();
#endif
    }

    Finalize();
    return 0;
}
<|endoftext|>


<commit_before>#include <Utils.h>

#ifdef HX_WINDOWS
#include <windows.h>
#include <time.h>
#else
#include <sys/time.h>
#include <stdint.h>
typedef uint64_t __int64;
#endif

#ifdef HX_MACOS
#include <mach/mach_time.h>
#endif

#ifdef ANDROID
#include <android/log.h>
#endif

#ifdef IPHONE
#include <QuartzCore/QuartzCore.h>
#endif

#include "ByteArray.h"

namespace nme
{

std::string gAssetBase = "";

ByteArray *ByteArray::FromFile(const OSChar *inFilename)
{
   FILE *file = OpenRead(inFilename);
   if (!file)
   {
      #ifdef ANDROID
      return AndroidGetAssetBytes(inFilename);
      #endif
      return 0;
   }

   fseek(file,0,SEEK_END);
   int len = ftell(file);
   fseek(file,0,SEEK_SET);

   ByteArray *result = new ByteArray;
   result->mBytes.resize(len);
   fread(&result->mBytes[0],len,1,file);
   fclose(file);

   return result;
}

#ifdef HX_WINDOWS
ByteArray *ByteArray::FromFile(const char *inFilename)
{
   FILE *file = fopen(inFilename,"rb");
   if (!file)
      return 0;

   fseek(file,0,SEEK_END);
   int len = ftell(file);
   fseek(file,0,SEEK_SET);

   ByteArray *result = new ByteArray;
   result->mBytes.resize(len);
   fread(&result->mBytes[0],len,1,file);
   fclose(file);

   return result;
}
#endif

#ifndef HX_WINDOWS

std::string WideToUTF8(const WString &inWideString)
{
  int len = 0;
  const wchar_t *chars = inWideString.c_str();
  for(int i=0;i<inWideString.length();i++)
   {
      int c = chars[i];
      if( c <= 0x7F ) len++;
      else if( c <= 0x7FF ) len+=2;
      else if( c <= 0xFFFF ) len+=3;
      else len+= 4;
   }

   std::string result;
   result.resize(len);
   unsigned char *data =  (unsigned char *) &result[0];
   for(int i=0;i<inWideString.length();i++)
   {
      int c = chars[i];
      if( c <= 0x7F )
         *data++ = c;
      else if( c <= 0x7FF )
      {
         *data++ = 0xC0 | (c >> 6);
         *data++ = 0x80 | (c & 63);
      }
      else if( c <= 0xFFFF )
      {
         *data++ = 0xE0 | (c >> 12);
         *data++ = 0x80 | ((c >> 6) & 63);
         *data++ = 0x80 | (c & 63);
      }
      else
      {
         *data++ = 0xF0 | (c >> 18);
         *data++ = 0x80 | ((c >> 12) & 63);
         *data++ = 0x80 | ((c >> 6) & 63);
         *data++ = 0x80 | (c & 63);
      }
   }

   return result;
}

wchar_t *UTF8ToWideCStr(const char *inStr, int &outLen)
{
   int l = 0;

   unsigned char *b = (unsigned char *)inStr;
   for(int i=0;1;)
   {
      int c = b[i];
      if (c==0) break;
      l++;
      if (c==0) break;
      else if( c < 0x80 ) i++;
      else if( c < 0xE0 ) i+=2;
      else if( c < 0xF0 ) i+=3;
      else i=4;
   }

   wchar_t *result = new wchar_t[l+1];
   l = 0;

   for(int i=0;1;)
   {
      int c = b[i++];
      if (c==0) break;
      else if( c < 0x80 )
      {
        result[l++] = c;
      }
      else if( c < 0xE0 )
        result[l++] = ( ((c & 0x3F) << 6) | (b[i++] & 0x7F) );
      else if( c < 0xF0 )
      {
        int c2 = b[i++];
        result[l++] += ( ((c & 0x1F) << 12) | ((c2 & 0x7F) << 6) | ( b[i++] & 0x7F) );
      }
      else
      {
        int c2 = b[i++];
        int c3 = b[i++];
        result[l++] += ( ((c & 0x0F) << 18) | ((c2 & 0x7F) << 12) | ((c3 << 6) & 0x7F) | (b[i++] & 0x7F) );
      }
   }
   result[l] = '\0';
   outLen = l;
   return result;
}

void UTF8ToWideVec(QuickVec<wchar_t,0> &outString,const char *inStr)
{
   int l = 0;

   unsigned char *b = (unsigned char *)inStr;
   for(int i=0;1;)
   {
      int c = b[i];
      if (c==0) break;
      l++;
      if (c==0) break;
      else if( c < 0x80 ) i++;
      else if( c < 0xE0 ) i+=2;
      else if( c < 0xF0 ) i+=3;
      else i=4;
   }

	outString.resize(l);
	wchar_t *result = outString.mPtr;

   l = 0;
   for(int i=0;1;)
   {
      int c = b[i++];
      if (c==0) break;
      else if( c < 0x80 )
      {
        result[l++] = c;
      }
      else if( c < 0xE0 )
        result[l++] = ( ((c & 0x3F) << 6) | (b[i++] & 0x7F) );
      else if( c < 0xF0 )
      {
        int c2 = b[i++];
        result[l++] += ( ((c & 0x1F) << 12) | ((c2 & 0x7F) << 6) | ( b[i++] & 0x7F) );
      }
      else
      {
        int c2 = b[i++];
        int c3 = b[i++];
        result[l++] += ( ((c & 0x0F) << 18) | ((c2 & 0x7F) << 12) | ((c3 << 6) & 0x7F) | (b[i++] & 0x7F) );
      }
   }
}

WString UTF8ToWide(const char *inStr)
{
   int len=0;
   wchar_t *s = UTF8ToWideCStr(inStr,len);
   WString result(s,len);
   delete [] s;
   return result;
}

#else
#include <windows.h>

std::string WideToUTF8(const WString &inWideString)
{
  int len = WideCharToMultiByte( CP_UTF8, 0, inWideString.c_str(), inWideString.length(),
	  0, 0, 0, 0);

  if (len<1)
	  return std::string();

  std::string result;
  result.resize(len);
  WideCharToMultiByte( CP_UTF8, 0, inWideString.c_str(), inWideString.length(),
      &result[0], len, 0, 0 );

  return result;
}

wchar_t *UTF8ToWideCStr(const char *inStr, int &outLen)
{
   outLen =  MultiByteToWideChar( CP_UTF8, 0, inStr, -1, 0, 0 );
	if (outLen<1)
		return 0;

	// No null character ...
	outLen--;

	wchar_t *buf = new wchar_t[outLen];

   MultiByteToWideChar( CP_UTF8, 0, inStr, outLen, buf, outLen );

	return buf;
}

void UTF8ToWideVec(QuickVec<wchar_t,0> &outString,const char *inStr)
{
   int len =  MultiByteToWideChar( CP_UTF8, 0, inStr, -1, 0, 0 );
	if (len<1)
	{
		outString.clear();
		return;
	}

	// No null character ...
	len--;
	outString.resize(len);

   MultiByteToWideChar( CP_UTF8, 0, inStr, len, outString.mPtr, len );
}

WString UTF8ToWide(const char *inStr)
{
   int len =  MultiByteToWideChar( CP_UTF8, 0, inStr, -1, 0, 0 );
	if (len<1)
		return WString();

	WString result;
	result.resize(len-1);

   MultiByteToWideChar( CP_UTF8, 0, inStr, len-1, &result[0], len-1 );

	return result;
}
#endif

static double t0 = 0;
double  GetTimeStamp()
{
#ifdef _WIN32
   static __int64 t0=0;
   static double period=0;
   __int64 now;

   if (QueryPerformanceCounter((LARGE_INTEGER*)&now))
   {
      if (t0==0)
      {
         t0 = now;
         __int64 freq;
         QueryPerformanceFrequency((LARGE_INTEGER*)&freq);
         if (freq!=0)
            period = 1.0/freq;
      }
      if (period!=0)
         return (now-t0)*period;
   }

   return (double)clock() / ( (double)CLOCKS_PER_SEC);
#elif defined(HX_MACOS)
   static double time_scale = 0.0;
   if (time_scale==0.0)
   {
      mach_timebase_info_data_t info;
      mach_timebase_info(&info);
      time_scale = 1e-9 * (double)info.numer / info.denom;
   }
   double r =  mach_absolute_time() * time_scale;
   return mach_absolute_time() * time_scale;
#else
   #if  defined(IPHONE)
      double t = CACurrentMediaTime();
   #elif defined(GPH)
	     struct timeval tv;
        if( gettimeofday(&tv,NULL) )
          return 0;
        double t =  ( tv.tv_sec + ((double)tv.tv_usec) / 1000000.0 );
   #else
	    struct timespec ts;
       clock_gettime(CLOCK_MONOTONIC, &ts);
       double t =  ( ts.tv_sec + ((double)ts.tv_nsec)*1e-9  );
   #endif
    if (t0==0) t0 = t;
    return t-t0;
#endif
}

#ifdef ANDROID

WString::WString(const WString &inRHS)
{
   mLength = inRHS.mLength;
   if (mLength==0)
      mString = 0;
   else
   {
      mString = new wchar_t[mLength+1];
      memcpy(mString,inRHS.mString,mLength*sizeof(wchar_t));
      mString[mLength] = '\0';
   }
}

WString::WString(const wchar_t *inStr)
{
   mLength = 0;
   if (inStr==0 || *inStr=='\0')
   {
      mString = 0;
   }
   else
   {
      while(inStr[mLength]) mLength++;
      mString = new wchar_t[mLength+1];
      memcpy(mString,inStr,mLength*sizeof(wchar_t));
      mString[mLength] = '\0';
   }

}

WString::WString(const wchar_t *inStr,int inLen)
{
   if (inLen==0)
   {
      mString = 0;
   }
   else
   {
      mString = new wchar_t[inLen+1];
      if (mString && inStr)
         memcpy(mString,inStr,inLen*sizeof(wchar_t));
      mString[inLen] = '\0';
   }

   mLength = inLen;
}

WString::~WString()
{
   delete [] mString;
}

WString &WString::operator=(const WString &inRHS)
{
   if (inRHS.mString != mString)
   {
      delete [] mString;
      mLength = inRHS.mLength;
      if (mLength==0)
         mString = 0;
      else
      {
         mString = new wchar_t[mLength+1];
         memcpy(mString,inRHS.mString,mLength*sizeof(wchar_t));
         mString[mLength] = '\0';
      }
   }
}

WString &WString::operator +=(const WString &inRHS)
{
   *this = *this + inRHS;
   return *this;
}

WString WString::operator +(const WString &inRHS) const
{
   int len = mLength + inRHS.mLength;
   if (len==0)
      return WString();

   WString result(0,len);
   memcpy(result.mString, mString, mLength*sizeof(wchar_t));
   memcpy(result.mString + mLength, inRHS.mString, inRHS.mLength*sizeof(wchar_t));
   return result;
}

bool WString::operator<(const WString &inRHS) const
{
   int len = mLength<inRHS.mLength ? mLength : inRHS.mLength;
   for(int i=0;i<len;i++)
      if (mString[i] < inRHS.mString[i])
         return true;
      else if (mString[i]>inRHS.mString[i])
         return false;

   return mLength<inRHS.mLength;
}

bool WString::operator>(const WString &inRHS) const
{
   int len = mLength<inRHS.mLength ? mLength : inRHS.mLength;
   for(int i=0;i<len;i++)
      if (mString[i] > inRHS.mString[i])
         return true;
      else if (mString[i]<inRHS.mString[i])
         return false;

   return mLength>inRHS.mLength;
}

bool WString::operator==(const WString &inRHS) const
{
   if (mLength!=inRHS.mLength)
      return false;

   for(int i=0;i<mLength;i++)
      if (mString[i]!=inRHS.mString[i])
         return false;

   return true;
}

bool WString::operator!=(const WString &inRHS) const
{
   if (mLength!=inRHS.mLength)
      return true;

   for(int i=0;i<mLength;i++)
      if (mString[i]!=inRHS.mString[i])
         return true;

   return false;
}

WString WString::substr(int inPos,int inLen) const
{
   return WString(mString+inPos,inLen);
}

#endif

}
<commit_msg>Use timeofdata on linux<commit_after>#include <Utils.h>

#ifdef HX_WINDOWS
#include <windows.h>
#include <time.h>
#else
#include <sys/time.h>
#include <stdint.h>
typedef uint64_t __int64;
#endif

#ifdef HX_MACOS
#include <mach/mach_time.h>
#endif

#ifdef ANDROID
#include <android/log.h>
#endif

#ifdef IPHONE
#include <QuartzCore/QuartzCore.h>
#endif

#include "ByteArray.h"

namespace nme
{

std::string gAssetBase = "";

ByteArray *ByteArray::FromFile(const OSChar *inFilename)
{
   FILE *file = OpenRead(inFilename);
   if (!file)
   {
      #ifdef ANDROID
      return AndroidGetAssetBytes(inFilename);
      #endif
      return 0;
   }

   fseek(file,0,SEEK_END);
   int len = ftell(file);
   fseek(file,0,SEEK_SET);

   ByteArray *result = new ByteArray;
   result->mBytes.resize(len);
   fread(&result->mBytes[0],len,1,file);
   fclose(file);

   return result;
}

#ifdef HX_WINDOWS
ByteArray *ByteArray::FromFile(const char *inFilename)
{
   FILE *file = fopen(inFilename,"rb");
   if (!file)
      return 0;

   fseek(file,0,SEEK_END);
   int len = ftell(file);
   fseek(file,0,SEEK_SET);

   ByteArray *result = new ByteArray;
   result->mBytes.resize(len);
   fread(&result->mBytes[0],len,1,file);
   fclose(file);

   return result;
}
#endif

#ifndef HX_WINDOWS

std::string WideToUTF8(const WString &inWideString)
{
  int len = 0;
  const wchar_t *chars = inWideString.c_str();
  for(int i=0;i<inWideString.length();i++)
   {
      int c = chars[i];
      if( c <= 0x7F ) len++;
      else if( c <= 0x7FF ) len+=2;
      else if( c <= 0xFFFF ) len+=3;
      else len+= 4;
   }

   std::string result;
   result.resize(len);
   unsigned char *data =  (unsigned char *) &result[0];
   for(int i=0;i<inWideString.length();i++)
   {
      int c = chars[i];
      if( c <= 0x7F )
         *data++ = c;
      else if( c <= 0x7FF )
      {
         *data++ = 0xC0 | (c >> 6);
         *data++ = 0x80 | (c & 63);
      }
      else if( c <= 0xFFFF )
      {
         *data++ = 0xE0 | (c >> 12);
         *data++ = 0x80 | ((c >> 6) & 63);
         *data++ = 0x80 | (c & 63);
      }
      else
      {
         *data++ = 0xF0 | (c >> 18);
         *data++ = 0x80 | ((c >> 12) & 63);
         *data++ = 0x80 | ((c >> 6) & 63);
         *data++ = 0x80 | (c & 63);
      }
   }

   return result;
}

wchar_t *UTF8ToWideCStr(const char *inStr, int &outLen)
{
   int l = 0;

   unsigned char *b = (unsigned char *)inStr;
   for(int i=0;1;)
   {
      int c = b[i];
      if (c==0) break;
      l++;
      if (c==0) break;
      else if( c < 0x80 ) i++;
      else if( c < 0xE0 ) i+=2;
      else if( c < 0xF0 ) i+=3;
      else i=4;
   }

   wchar_t *result = new wchar_t[l+1];
   l = 0;

   for(int i=0;1;)
   {
      int c = b[i++];
      if (c==0) break;
      else if( c < 0x80 )
      {
        result[l++] = c;
      }
      else if( c < 0xE0 )
        result[l++] = ( ((c & 0x3F) << 6) | (b[i++] & 0x7F) );
      else if( c < 0xF0 )
      {
        int c2 = b[i++];
        result[l++] += ( ((c & 0x1F) << 12) | ((c2 & 0x7F) << 6) | ( b[i++] & 0x7F) );
      }
      else
      {
        int c2 = b[i++];
        int c3 = b[i++];
        result[l++] += ( ((c & 0x0F) << 18) | ((c2 & 0x7F) << 12) | ((c3 << 6) & 0x7F) | (b[i++] & 0x7F) );
      }
   }
   result[l] = '\0';
   outLen = l;
   return result;
}

void UTF8ToWideVec(QuickVec<wchar_t,0> &outString,const char *inStr)
{
   int l = 0;

   unsigned char *b = (unsigned char *)inStr;
   for(int i=0;1;)
   {
      int c = b[i];
      if (c==0) break;
      l++;
      if (c==0) break;
      else if( c < 0x80 ) i++;
      else if( c < 0xE0 ) i+=2;
      else if( c < 0xF0 ) i+=3;
      else i=4;
   }

	outString.resize(l);
	wchar_t *result = outString.mPtr;

   l = 0;
   for(int i=0;1;)
   {
      int c = b[i++];
      if (c==0) break;
      else if( c < 0x80 )
      {
        result[l++] = c;
      }
      else if( c < 0xE0 )
        result[l++] = ( ((c & 0x3F) << 6) | (b[i++] & 0x7F) );
      else if( c < 0xF0 )
      {
        int c2 = b[i++];
        result[l++] += ( ((c & 0x1F) << 12) | ((c2 & 0x7F) << 6) | ( b[i++] & 0x7F) );
      }
      else
      {
        int c2 = b[i++];
        int c3 = b[i++];
        result[l++] += ( ((c & 0x0F) << 18) | ((c2 & 0x7F) << 12) | ((c3 << 6) & 0x7F) | (b[i++] & 0x7F) );
      }
   }
}

WString UTF8ToWide(const char *inStr)
{
   int len=0;
   wchar_t *s = UTF8ToWideCStr(inStr,len);
   WString result(s,len);
   delete [] s;
   return result;
}

#else
#include <windows.h>

std::string WideToUTF8(const WString &inWideString)
{
  int len = WideCharToMultiByte( CP_UTF8, 0, inWideString.c_str(), inWideString.length(),
	  0, 0, 0, 0);

  if (len<1)
	  return std::string();

  std::string result;
  result.resize(len);
  WideCharToMultiByte( CP_UTF8, 0, inWideString.c_str(), inWideString.length(),
      &result[0], len, 0, 0 );

  return result;
}

wchar_t *UTF8ToWideCStr(const char *inStr, int &outLen)
{
   outLen =  MultiByteToWideChar( CP_UTF8, 0, inStr, -1, 0, 0 );
	if (outLen<1)
		return 0;

	// No null character ...
	outLen--;

	wchar_t *buf = new wchar_t[outLen];

   MultiByteToWideChar( CP_UTF8, 0, inStr, outLen, buf, outLen );

	return buf;
}

void UTF8ToWideVec(QuickVec<wchar_t,0> &outString,const char *inStr)
{
   int len =  MultiByteToWideChar( CP_UTF8, 0, inStr, -1, 0, 0 );
	if (len<1)
	{
		outString.clear();
		return;
	}

	// No null character ...
	len--;
	outString.resize(len);

   MultiByteToWideChar( CP_UTF8, 0, inStr, len, outString.mPtr, len );
}

WString UTF8ToWide(const char *inStr)
{
   int len =  MultiByteToWideChar( CP_UTF8, 0, inStr, -1, 0, 0 );
	if (len<1)
		return WString();

	WString result;
	result.resize(len-1);

   MultiByteToWideChar( CP_UTF8, 0, inStr, len-1, &result[0], len-1 );

	return result;
}
#endif

static double t0 = 0;
double  GetTimeStamp()
{
#ifdef _WIN32
   static __int64 t0=0;
   static double period=0;
   __int64 now;

   if (QueryPerformanceCounter((LARGE_INTEGER*)&now))
   {
      if (t0==0)
      {
         t0 = now;
         __int64 freq;
         QueryPerformanceFrequency((LARGE_INTEGER*)&freq);
         if (freq!=0)
            period = 1.0/freq;
      }
      if (period!=0)
         return (now-t0)*period;
   }

   return (double)clock() / ( (double)CLOCKS_PER_SEC);
#elif defined(HX_MACOS)
   static double time_scale = 0.0;
   if (time_scale==0.0)
   {
      mach_timebase_info_data_t info;
      mach_timebase_info(&info);
      time_scale = 1e-9 * (double)info.numer / info.denom;
   }
   double r =  mach_absolute_time() * time_scale;
   return mach_absolute_time() * time_scale;
#else
   #if  defined(IPHONE)
      double t = CACurrentMediaTime();
   #elif defined(GPH) || defined(HX_LINUX)
	     struct timeval tv;
        if( gettimeofday(&tv,NULL) )
          return 0;
        double t =  ( tv.tv_sec + ((double)tv.tv_usec) / 1000000.0 );
   #else
	    struct timespec ts;
       clock_gettime(CLOCK_MONOTONIC, &ts);
       double t =  ( ts.tv_sec + ((double)ts.tv_nsec)*1e-9  );
   #endif
    if (t0==0) t0 = t;
    return t-t0;
#endif
}

#ifdef ANDROID

WString::WString(const WString &inRHS)
{
   mLength = inRHS.mLength;
   if (mLength==0)
      mString = 0;
   else
   {
      mString = new wchar_t[mLength+1];
      memcpy(mString,inRHS.mString,mLength*sizeof(wchar_t));
      mString[mLength] = '\0';
   }
}

WString::WString(const wchar_t *inStr)
{
   mLength = 0;
   if (inStr==0 || *inStr=='\0')
   {
      mString = 0;
   }
   else
   {
      while(inStr[mLength]) mLength++;
      mString = new wchar_t[mLength+1];
      memcpy(mString,inStr,mLength*sizeof(wchar_t));
      mString[mLength] = '\0';
   }

}

WString::WString(const wchar_t *inStr,int inLen)
{
   if (inLen==0)
   {
      mString = 0;
   }
   else
   {
      mString = new wchar_t[inLen+1];
      if (mString && inStr)
         memcpy(mString,inStr,inLen*sizeof(wchar_t));
      mString[inLen] = '\0';
   }

   mLength = inLen;
}

WString::~WString()
{
   delete [] mString;
}

WString &WString::operator=(const WString &inRHS)
{
   if (inRHS.mString != mString)
   {
      delete [] mString;
      mLength = inRHS.mLength;
      if (mLength==0)
         mString = 0;
      else
      {
         mString = new wchar_t[mLength+1];
         memcpy(mString,inRHS.mString,mLength*sizeof(wchar_t));
         mString[mLength] = '\0';
      }
   }
}

WString &WString::operator +=(const WString &inRHS)
{
   *this = *this + inRHS;
   return *this;
}

WString WString::operator +(const WString &inRHS) const
{
   int len = mLength + inRHS.mLength;
   if (len==0)
      return WString();

   WString result(0,len);
   memcpy(result.mString, mString, mLength*sizeof(wchar_t));
   memcpy(result.mString + mLength, inRHS.mString, inRHS.mLength*sizeof(wchar_t));
   return result;
}

bool WString::operator<(const WString &inRHS) const
{
   int len = mLength<inRHS.mLength ? mLength : inRHS.mLength;
   for(int i=0;i<len;i++)
      if (mString[i] < inRHS.mString[i])
         return true;
      else if (mString[i]>inRHS.mString[i])
         return false;

   return mLength<inRHS.mLength;
}

bool WString::operator>(const WString &inRHS) const
{
   int len = mLength<inRHS.mLength ? mLength : inRHS.mLength;
   for(int i=0;i<len;i++)
      if (mString[i] > inRHS.mString[i])
         return true;
      else if (mString[i]<inRHS.mString[i])
         return false;

   return mLength>inRHS.mLength;
}

bool WString::operator==(const WString &inRHS) const
{
   if (mLength!=inRHS.mLength)
      return false;

   for(int i=0;i<mLength;i++)
      if (mString[i]!=inRHS.mString[i])
         return false;

   return true;
}

bool WString::operator!=(const WString &inRHS) const
{
   if (mLength!=inRHS.mLength)
      return true;

   for(int i=0;i<mLength;i++)
      if (mString[i]!=inRHS.mString[i])
         return true;

   return false;
}

WString WString::substr(int inPos,int inLen) const
{
   return WString(mString+inPos,inLen);
}

#endif

}
<|endoftext|>


<commit_before>/*
This file is part of cphVB and copyright (c) 2012 the cphVB team:
http://cphvb.bitbucket.org

cphVB is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as
published by the Free Software Foundation, either version 3
of the License, or (at your option) any later version.

cphVB is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the
GNU Lesser General Public License along with cphVB.

If not, see <http://www.gnu.org/licenses/>.
*/

#include <cphvb.h>
#include <cassert>
#include "cphvb_vem_cluster.h"
#include "dispatch.h"
#include "pgrid.h"
#include "exec.h"

int main()
{
    dispatch_msg *msg;
    cphvb_error e;

    //Initiate the process grid
    if((e = pgrid_init()) != CPHVB_SUCCESS)
        return e;

    while(1)
    {
        if((e = dispatch_reset()) != CPHVB_SUCCESS)
            return e;

        if((e = dispatch_recv(&msg)) != CPHVB_SUCCESS)
            return e;

        switch(msg->type)
        {
            case CPHVB_CLUSTER_DISPATCH_INIT:
            {
                char *name = msg->payload;
                printf("Slave (rank %d) received INIT. name: %s\n", pgrid_myrank, name);
                if((e = exec_init(name)) != CPHVB_SUCCESS)
                    return e;
                break;
            }
            case CPHVB_CLUSTER_DISPATCH_SHUTDOWN:
            {
                printf("Slave (rank %d) received SHUTDOWN\n",pgrid_myrank);
                return exec_shutdown();
            }
            case CPHVB_CLUSTER_DISPATCH_UFUNC:
            {
                cphvb_intp *id = (cphvb_intp *)msg->payload;
                char *fun = msg->payload+sizeof(cphvb_intp);
                printf("Slave (rank %d) received UFUNC. fun: %s, id: %ld\n",pgrid_myrank, fun, *id);
                if((e = exec_reg_func(fun, id)) != CPHVB_SUCCESS)
                    return e;
                break;
            }
            case CPHVB_CLUSTER_DISPATCH_EXEC:
            {
                cphvb_intp *noi = (cphvb_intp *)msg->payload; //number of instructions
                cphvb_instruction *inst_list = (cphvb_instruction *)msg->payload+sizeof(cphvb_intp);

                printf("Slave (rank %d) received EXEC. noi %ld\n",pgrid_myrank, *noi);

//                cphvb_pprint_instr_list(inst_list, *noi, "SLAVE");

//                if((e = exec_execute(count, list)) != CPHVB_SUCCESS)
//                    return e;
                break;
            }
            default:
                fprintf(stderr, "[VEM-CLUSTER] Slave (rank %d) "
                        "received unknown message type\n", pgrid_myrank);
                MPI_Abort(MPI_COMM_WORLD,CPHVB_ERROR);
        }
    }
    return CPHVB_SUCCESS;
}
<commit_msg>The cluster slave will now save the instruction list including operands<commit_after>/*
This file is part of cphVB and copyright (c) 2012 the cphVB team:
http://cphvb.bitbucket.org

cphVB is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as
published by the Free Software Foundation, either version 3
of the License, or (at your option) any later version.

cphVB is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the
GNU Lesser General Public License along with cphVB.

If not, see <http://www.gnu.org/licenses/>.
*/

#include <cphvb.h>
#include <cassert>
#include <map>
#include <StaticStore.hpp>
#include "cphvb_vem_cluster.h"
#include "dispatch.h"
#include "pgrid.h"
#include "exec.h"
#include "darray_extension.h"

//Local array information and storage
static std::map<cphvb_intp, cphvb_array*> map_dary2ary;
static std::map<cphvb_array*,darray*> map_ary2dary;
static StaticStore<darray> ary_store(512);

int main()
{
    dispatch_msg *msg;
    cphvb_error e;

    //Initiate the process grid
    if((e = pgrid_init()) != CPHVB_SUCCESS)
        return e;

    while(1)
    {
        if((e = dispatch_reset()) != CPHVB_SUCCESS)
            return e;

        if((e = dispatch_recv(&msg)) != CPHVB_SUCCESS)
            return e;

        switch(msg->type)
        {
            case CPHVB_CLUSTER_DISPATCH_INIT:
            {
                char *name = msg->payload;
                printf("Slave (rank %d) received INIT. name: %s\n", pgrid_myrank, name);
                if((e = exec_init(name)) != CPHVB_SUCCESS)
                    return e;
                break;
            }
            case CPHVB_CLUSTER_DISPATCH_SHUTDOWN:
            {
                printf("Slave (rank %d) received SHUTDOWN\n",pgrid_myrank);
                return exec_shutdown();
            }
            case CPHVB_CLUSTER_DISPATCH_UFUNC:
            {
                cphvb_intp *id = (cphvb_intp *)msg->payload;
                char *fun = msg->payload+sizeof(cphvb_intp);
                printf("Slave (rank %d) received UFUNC. fun: %s, id: %ld\n",pgrid_myrank, fun, *id);
                if((e = exec_reg_func(fun, id)) != CPHVB_SUCCESS)
                    return e;
                break;
            }
            case CPHVB_CLUSTER_DISPATCH_EXEC:
            {
                //The number of instructions
                cphvb_intp *noi = (cphvb_intp *)msg->payload;
                //The master-instruction list
                cphvb_instruction *master_list = (cphvb_instruction *)(msg->payload+sizeof(cphvb_intp));
                //The number of new arrays
                cphvb_intp *noa = (cphvb_intp *)(master_list + *noi);
                //The list of new arrays
                darray *darys = (darray*)(noa+1); //number of new arrays

                printf("Slave (rank %d) received EXEC. noi: %ld, noa: %ld\n",pgrid_myrank, *noi, *noa);

                //Insert the new array into the array store and the array maps
                for(cphvb_intp i=0; i < *noa; ++i)
                {
                    darray *dary = ary_store.c_next();
                    *dary = darys[i];
                    dary->global_ary.data = NULL;//We will copy the data at a later time.
                    assert(map_dary2ary.count(dary->id) == 0);
                    assert(map_ary2dary.count(&dary->global_ary) == 0);
                    map_dary2ary[dary->id] = &dary->global_ary;
                    map_ary2dary[&dary->global_ary] = dary;
                }

                //Update the base-array-pointers
                for(cphvb_intp i=0; i < *noa; ++i)
                {
                    cphvb_array *ary = map_dary2ary[darys[i].id];
                    if(ary->base != NULL)
                    {
                        assert(map_dary2ary.count((cphvb_intp)ary->base) == 1);
                        ary->base = map_dary2ary[(cphvb_intp)ary->base];
                    }
                }

                //Create the local instruction list that reference local arrays
                cphvb_instruction *local_list = (cphvb_instruction *)malloc(*noi*sizeof(cphvb_instruction));
                if(local_list == NULL)
                    return CPHVB_OUT_OF_MEMORY;
                for(cphvb_intp i=0; i < *noi; ++i)
                {
                    cphvb_instruction *master = &master_list[i];
                    cphvb_instruction *local = &local_list[i];
                    int nop = cphvb_operands_in_instruction(master);
                    *local = *master;//Copy instruction
                    //Convert all instructon operands
                    for(cphvb_intp j=0; j<nop; ++j)
                    {
                        assert(map_dary2ary.count((cphvb_intp)master->operand[j]) == 1);
                        local->operand[j] = map_dary2ary[(cphvb_intp)master->operand[j]];
                        assert(map_ary2dary.count(local->operand[j]) == 1);
                    }
                }

                cphvb_pprint_instr_list(local_list, *noi, "SLAVE");

//                if((e = exec_execute(count, list)) != CPHVB_SUCCESS)
//                    return e;
                free(local_list);
                break;
            }
            default:
                fprintf(stderr, "[VEM-CLUSTER] Slave (rank %d) "
                        "received unknown message type\n", pgrid_myrank);
                MPI_Abort(MPI_COMM_WORLD,CPHVB_ERROR);
        }
    }
    return CPHVB_SUCCESS;
}
<|endoftext|>


<commit_before>#pragma once

#include "point.hpp"

namespace plot
{

struct Rect;

constexpr Rect operator+(Rect const& lhs, Point const& rhs);
constexpr Rect operator-(Rect const& lhs, Point const& rhs);
constexpr Rect operator*(Rect const& lhs, Coord const& rhs);
constexpr Rect operator*(Coord const& lhs, Rect const& rhs);
constexpr Rect operator/(Rect const& lhs, Coord const& rhs);
constexpr Rect operator/(Coord const& lhs, Rect const& rhs);

struct Rect
{
    constexpr Rect() = default;

    constexpr Rect(Point const& p1, Point const& p2)
        : p1(p1), p2(p2)
        {}

    constexpr Rect(Size const& size)
        : p1(), p2(size)
        {}

    constexpr Rect sorted() const {
        auto x = utils::minmax(p1.x, p2.x);
        auto y = utils::minmax(p1.y, p2.y);
        return {
            { x.first, y.first },
            { x.second, y.second }
        };
    }

    constexpr Point size() const {
        return { utils::abs(p2.x - p1.x), utils::abs(p2.y - p1.y) };
    }

    constexpr bool contains(Point p) const {
        return p.x >= p1.x && p.x < p2.x && p.y >= p1.y && p.y < p2.y;
    }

    Rect& operator+=(Point const& other) {
        return (*this) = (*this) + other;
    }

    Rect& operator-=(Point const& other) {
        return (*this) = (*this) - other;
    }

    Rect& operator*=(Coord n) {
        return (*this) = (*this) * n;
    }

    Rect& operator/=(Coord n) {
        return (*this) = (*this) / n;
    }

    constexpr bool operator==(Rect const& other) const {
        return p1 == other.p1 && p2 == other.p2;
    }

    constexpr bool operator!=(Rect const& other) const {
        return p1 != other.p1 || p2 != other.p2;
    }

    Point p1{}, p2{};
};

inline constexpr Rect operator+(Rect const& lhs, Point const& rhs) {
    return {
        lhs.p1 + rhs,
        lhs.p2 + rhs
    };
}

inline constexpr Rect operator-(Rect const& lhs, Point const& rhs) {
    return {
        lhs.p1 - rhs,
        lhs.p2 - rhs
    };
}

inline constexpr Rect operator*(Rect const& lhs, Coord const& rhs) {
    return {
        lhs.p1*rhs,
        lhs.p2*rhs
    };
}

inline constexpr Rect operator*(Coord const& lhs, Rect const& rhs) {
    return {
        lhs*rhs.p1,
        lhs*rhs.p2
    };
}

inline constexpr Rect operator/(Rect const& lhs, Coord const& rhs) {
    return {
        lhs.p1/rhs,
        lhs.p2/rhs
    };
}

inline constexpr Rect operator/(Coord const& lhs, Rect const& rhs) {
    return {
        lhs/rhs.p1,
        lhs/rhs.p2
    };
}

} /* namespace plot */
<commit_msg>Add useful Rect methods<commit_after>#pragma once

#include "point.hpp"

namespace plot
{

struct Rect;

constexpr Rect operator+(Rect const& lhs, Point const& rhs);
constexpr Rect operator-(Rect const& lhs, Point const& rhs);
constexpr Rect operator*(Rect const& lhs, Coord const& rhs);
constexpr Rect operator*(Coord const& lhs, Rect const& rhs);
constexpr Rect operator/(Rect const& lhs, Coord const& rhs);
constexpr Rect operator/(Coord const& lhs, Rect const& rhs);

struct Rect
{
    constexpr Rect() = default;

    constexpr Rect(Point const& p1, Point const& p2)
        : p1(p1), p2(p2)
        {}

    constexpr Rect(Size const& size)
        : p1(), p2(size)
        {}

    constexpr Rect sorted() const {
        auto x = utils::minmax(p1.x, p2.x);
        auto y = utils::minmax(p1.y, p2.y);
        return {
            { x.first, y.first },
            { x.second, y.second }
        };
    }

    constexpr Rect sorted_x() const {
        return (p1.x > p2.x) ? Rect(p2, p1) : *this;
    }

    constexpr Rect sorted_y() const {
        return (p1.y > p2.y) ? Rect(p2, p1) : *this;
    }

    constexpr Point size() const {
        return { utils::abs(p2.x - p1.x), utils::abs(p2.y - p1.y) };
    }

    // XXX: Calling on unsorted rectangles is undefined behavior
    constexpr bool contains(Point p) const {
        return p.x >= p1.x && p.x < p2.x && p.y >= p1.y && p.y < p2.y;
    }

    // XXX: Calling on unsorted rectangles is undefined behavior
    constexpr bool contains(Rect const& r) const {
        return r.p1.x >= p1.x && r.p2.x <= p2.x && r.p1.y >= p1.y && r.p2.y <= p2.y;
    }

    constexpr Rect clamp(Rect const& r) const {
        return { p1.clamp(r.p1, r.p2), p2.clamp(r.p1, r.p2) };
    }

    Rect& operator+=(Point const& other) {
        return (*this) = (*this) + other;
    }

    Rect& operator-=(Point const& other) {
        return (*this) = (*this) - other;
    }

    Rect& operator*=(Coord n) {
        return (*this) = (*this) * n;
    }

    Rect& operator/=(Coord n) {
        return (*this) = (*this) / n;
    }

    constexpr bool operator==(Rect const& other) const {
        return p1 == other.p1 && p2 == other.p2;
    }

    constexpr bool operator!=(Rect const& other) const {
        return p1 != other.p1 || p2 != other.p2;
    }

    Point p1{}, p2{};
};

inline constexpr Rect operator+(Rect const& lhs, Point const& rhs) {
    return {
        lhs.p1 + rhs,
        lhs.p2 + rhs
    };
}

inline constexpr Rect operator-(Rect const& lhs, Point const& rhs) {
    return {
        lhs.p1 - rhs,
        lhs.p2 - rhs
    };
}

inline constexpr Rect operator*(Rect const& lhs, Coord const& rhs) {
    return {
        lhs.p1*rhs,
        lhs.p2*rhs
    };
}

inline constexpr Rect operator*(Coord const& lhs, Rect const& rhs) {
    return {
        lhs*rhs.p1,
        lhs*rhs.p2
    };
}

inline constexpr Rect operator/(Rect const& lhs, Coord const& rhs) {
    return {
        lhs.p1/rhs,
        lhs.p2/rhs
    };
}

inline constexpr Rect operator/(Coord const& lhs, Rect const& rhs) {
    return {
        lhs/rhs.p1,
        lhs/rhs.p2
    };
}

} /* namespace plot */
<|endoftext|>


<commit_before>/*===================================================================

The Medical Imaging Interaction Toolkit (MITK)

Copyright (c) German Cancer Research Center,
Division of Medical and Biological Informatics.
All rights reserved.

This software is distributed WITHOUT ANY WARRANTY; without
even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE.

See LICENSE.txt or http://www.mitk.org for details.

===================================================================*/

#include "QmitkNDIToolDelegate.h"
#include <QStringList>
#include <QComboBox>
#include <QLabel>
#include <QFileDialog>

#include "QmitkEnums.h"
#include "QmitkDataStorageComboBox.h"
#include "QmitkCustomVariants.h"
#include "mitkDataStorage.h"
#include "mitkNodePredicateBase.h"
#include "QmitkDataStorageComboBox.h"
#include "mitkNDIPassiveTool.h"

Q_DECLARE_METATYPE(mitk::NDIPassiveTool*)

QmitkNDIToolDelegate::QmitkNDIToolDelegate(QObject * parent) : QStyledItemDelegate(parent),
m_Types(), m_DataStorage(NULL), m_Predicate(NULL), m_TagProperty(NULL), m_TagPropertyName()
{
}

QWidget* QmitkNDIToolDelegate::createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const
{
  if (index.isValid() == false)
    return QStyledItemDelegate::createEditor(parent, option, index);

  switch (index.column())
  {
  case SROMCol:
    {
      return new QLabel("", parent);
    }
  case TypeCol:
    {
      QComboBox* c = new QComboBox(parent);
      c->addItems(m_Types);
      return c;
    }
  case NodeCol:
    {
      return new QmitkDataStorageComboBox(m_DataStorage, m_Predicate, parent);
    }
  case IndexCol:
  case NameCol:
  case StatusCol:
  default:
    return QStyledItemDelegate::createEditor(parent, option, index);
  }
}

void QmitkNDIToolDelegate::setEditorData(QWidget *editor, const QModelIndex &index) const
{
  if (index.isValid() == false)
    return;

  switch (index.column())
  {
  case SROMCol:
    {
      QLabel* l = qobject_cast<QLabel*>(editor);
      if (l->text().isEmpty())
      {
        QString fileName = qVariantValue<QString>(index.data(/*mitk::FileNameRole*/));
        fileName = QFileDialog::getOpenFileName(editor, "Open SROM file", fileName, "SROM files (*.rom)");
        QLabel* l = qobject_cast<QLabel*>(editor);
        l->setText(fileName);
      }
      return;
    }
  case TypeCol:
    {
      QString type = qVariantValue<QString>(index.data(/*mitk::TypeRole*/));
      QComboBox* c = qobject_cast<QComboBox*>(editor);
      c->setCurrentIndex(c->findText(type));
      connect(c, SIGNAL(currentIndexChanged(int)), this, SLOT(ComboBoxCurrentIndexChanged(int)));
      return;
    }
  case NodeCol:
    {
      mitk::DataNode::Pointer n = qVariantValue<mitk::DataNode::Pointer>(index.data(/*mitk::OrganNodeRole*/));
      if (n.IsNotNull())
      {
        QmitkDataStorageComboBox* dsc = qobject_cast<QmitkDataStorageComboBox*>(editor);
        dsc->setCurrentIndex(dsc->findText(QString::fromStdString(n->GetName())));
        connect(dsc, SIGNAL(currentIndexChanged(int)), this, SLOT(ComboBoxCurrentIndexChanged(int)));
      }
      return;
    }
  case IndexCol:
  case NameCol:
  case StatusCol:
  default:
    QStyledItemDelegate::setEditorData(editor, index);
  }
}

void QmitkNDIToolDelegate::setModelData(QWidget *editor, QAbstractItemModel* model, const QModelIndex &index) const
{
  if (index.isValid() == false)
    return;

  switch (index.column())
  {
  case SROMCol:
    {
      QLabel* l = qobject_cast<QLabel*>(editor);
      //model->setData(index, l->text(), mitk::FileNameRole);
      //model->setData(index, l->text(), Qt::DisplayRole);  // use for display too
      model->setData(index, l->text());  // use for display too
      return;
    }
  case TypeCol:
    {
      QComboBox* c = qobject_cast<QComboBox*>(editor);
      //model->setData(index, c->currentText(), mitk::TypeRole);
      model->setData(index, c->currentText(), Qt::DisplayRole);
      return;
    }
  case NodeCol:
    {
      QmitkDataStorageComboBox* dsc = qobject_cast<QmitkDataStorageComboBox*>(editor);
      if (dsc->GetSelectedNode().IsNotNull())
      {
        model->setData(index, qVariantFromValue(dsc->GetSelectedNode()), OrganNodeRole);
        //model->setData(index, QString::fromStdString(dsc->GetSelectedNode()->GetName()), Qt::DisplayRole);
        model->setData(index, QString::fromStdString(dsc->GetSelectedNode()->GetName()));
        if ((m_TagProperty.IsNotNull()) && (m_TagPropertyName.empty() == false))  // tag this node as selected
          dsc->GetSelectedNode()->SetProperty(m_TagPropertyName.c_str(), m_TagProperty);
      }
    }
    return;
  case IndexCol:
  case NameCol:
  case StatusCol:
  default:
    QStyledItemDelegate::setModelData(editor, model, index);
  }
}

void QmitkNDIToolDelegate::commitAndCloseEditor()
{
  //QWidget* editor = 0;
  //if(QPushButton *pushBtn = qobject_cast<QPushButton *>(sender()))
  //{

  //}

  //if(editor)
  //{
    //emit commitData(editor);
    //emit closeEditor(editor);
  //}

}

void QmitkNDIToolDelegate::ComboBoxCurrentIndexChanged( int  /*index*/ )
{
  if(QComboBox *comboBox = qobject_cast<QComboBox *>(sender()))
  {
    emit commitData(comboBox);
    emit closeEditor(comboBox);
  }
}

void QmitkNDIToolDelegate::SetTypes( const QStringList& types )
{
  m_Types = types;
}

void QmitkNDIToolDelegate::SetDataStorage(mitk::DataStorage* ds)
{
  m_DataStorage = ds;
}

void QmitkNDIToolDelegate::SetPredicate(mitk::NodePredicateBase::Pointer p)
{
  m_Predicate = p;
}

void QmitkNDIToolDelegate::SetTagProperty(mitk::BaseProperty::Pointer prop)
{
  m_TagProperty = prop;
}

void QmitkNDIToolDelegate::SetTagPropertyName( const std::string& name )
{
  m_TagPropertyName = name;
}
<commit_msg>Replaced qVariantValue<T>() function calls with QVariant::value<T>() calls.<commit_after>/*===================================================================

The Medical Imaging Interaction Toolkit (MITK)

Copyright (c) German Cancer Research Center,
Division of Medical and Biological Informatics.
All rights reserved.

This software is distributed WITHOUT ANY WARRANTY; without
even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE.

See LICENSE.txt or http://www.mitk.org for details.

===================================================================*/

#include "QmitkNDIToolDelegate.h"
#include <QStringList>
#include <QComboBox>
#include <QLabel>
#include <QFileDialog>

#include "QmitkEnums.h"
#include "QmitkDataStorageComboBox.h"
#include "QmitkCustomVariants.h"
#include "mitkDataStorage.h"
#include "mitkNodePredicateBase.h"
#include "QmitkDataStorageComboBox.h"
#include "mitkNDIPassiveTool.h"

Q_DECLARE_METATYPE(mitk::NDIPassiveTool*)

QmitkNDIToolDelegate::QmitkNDIToolDelegate(QObject * parent) : QStyledItemDelegate(parent),
m_Types(), m_DataStorage(NULL), m_Predicate(NULL), m_TagProperty(NULL), m_TagPropertyName()
{
}

QWidget* QmitkNDIToolDelegate::createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const
{
  if (index.isValid() == false)
    return QStyledItemDelegate::createEditor(parent, option, index);

  switch (index.column())
  {
  case SROMCol:
    {
      return new QLabel("", parent);
    }
  case TypeCol:
    {
      QComboBox* c = new QComboBox(parent);
      c->addItems(m_Types);
      return c;
    }
  case NodeCol:
    {
      return new QmitkDataStorageComboBox(m_DataStorage, m_Predicate, parent);
    }
  case IndexCol:
  case NameCol:
  case StatusCol:
  default:
    return QStyledItemDelegate::createEditor(parent, option, index);
  }
}

void QmitkNDIToolDelegate::setEditorData(QWidget *editor, const QModelIndex &index) const
{
  if (index.isValid() == false)
    return;

  switch (index.column())
  {
  case SROMCol:
    {
      QLabel* l = qobject_cast<QLabel*>(editor);
      if (l->text().isEmpty())
      {
        QString fileName = index.data(/*mitk::FileNameRole*/).value<QString>();
        fileName = QFileDialog::getOpenFileName(editor, "Open SROM file", fileName, "SROM files (*.rom)");
        QLabel* l = qobject_cast<QLabel*>(editor);
        l->setText(fileName);
      }
      return;
    }
  case TypeCol:
    {
      QString type = index.data(/*mitk::TypeRole*/).value<QString>();
      QComboBox* c = qobject_cast<QComboBox*>(editor);
      c->setCurrentIndex(c->findText(type));
      connect(c, SIGNAL(currentIndexChanged(int)), this, SLOT(ComboBoxCurrentIndexChanged(int)));
      return;
    }
  case NodeCol:
    {
      mitk::DataNode::Pointer n = index.data(/*mitk::OrganNodeRole*/).value<mitk::DataNode::Pointer>();
      if (n.IsNotNull())
      {
        QmitkDataStorageComboBox* dsc = qobject_cast<QmitkDataStorageComboBox*>(editor);
        dsc->setCurrentIndex(dsc->findText(QString::fromStdString(n->GetName())));
        connect(dsc, SIGNAL(currentIndexChanged(int)), this, SLOT(ComboBoxCurrentIndexChanged(int)));
      }
      return;
    }
  case IndexCol:
  case NameCol:
  case StatusCol:
  default:
    QStyledItemDelegate::setEditorData(editor, index);
  }
}

void QmitkNDIToolDelegate::setModelData(QWidget *editor, QAbstractItemModel* model, const QModelIndex &index) const
{
  if (index.isValid() == false)
    return;

  switch (index.column())
  {
  case SROMCol:
    {
      QLabel* l = qobject_cast<QLabel*>(editor);
      //model->setData(index, l->text(), mitk::FileNameRole);
      //model->setData(index, l->text(), Qt::DisplayRole);  // use for display too
      model->setData(index, l->text());  // use for display too
      return;
    }
  case TypeCol:
    {
      QComboBox* c = qobject_cast<QComboBox*>(editor);
      //model->setData(index, c->currentText(), mitk::TypeRole);
      model->setData(index, c->currentText(), Qt::DisplayRole);
      return;
    }
  case NodeCol:
    {
      QmitkDataStorageComboBox* dsc = qobject_cast<QmitkDataStorageComboBox*>(editor);
      if (dsc->GetSelectedNode().IsNotNull())
      {
        model->setData(index, qVariantFromValue(dsc->GetSelectedNode()), OrganNodeRole);
        //model->setData(index, QString::fromStdString(dsc->GetSelectedNode()->GetName()), Qt::DisplayRole);
        model->setData(index, QString::fromStdString(dsc->GetSelectedNode()->GetName()));
        if ((m_TagProperty.IsNotNull()) && (m_TagPropertyName.empty() == false))  // tag this node as selected
          dsc->GetSelectedNode()->SetProperty(m_TagPropertyName.c_str(), m_TagProperty);
      }
    }
    return;
  case IndexCol:
  case NameCol:
  case StatusCol:
  default:
    QStyledItemDelegate::setModelData(editor, model, index);
  }
}

void QmitkNDIToolDelegate::commitAndCloseEditor()
{
  //QWidget* editor = 0;
  //if(QPushButton *pushBtn = qobject_cast<QPushButton *>(sender()))
  //{

  //}

  //if(editor)
  //{
    //emit commitData(editor);
    //emit closeEditor(editor);
  //}

}

void QmitkNDIToolDelegate::ComboBoxCurrentIndexChanged( int  /*index*/ )
{
  if(QComboBox *comboBox = qobject_cast<QComboBox *>(sender()))
  {
    emit commitData(comboBox);
    emit closeEditor(comboBox);
  }
}

void QmitkNDIToolDelegate::SetTypes( const QStringList& types )
{
  m_Types = types;
}

void QmitkNDIToolDelegate::SetDataStorage(mitk::DataStorage* ds)
{
  m_DataStorage = ds;
}

void QmitkNDIToolDelegate::SetPredicate(mitk::NodePredicateBase::Pointer p)
{
  m_Predicate = p;
}

void QmitkNDIToolDelegate::SetTagProperty(mitk::BaseProperty::Pointer prop)
{
  m_TagProperty = prop;
}

void QmitkNDIToolDelegate::SetTagPropertyName( const std::string& name )
{
  m_TagPropertyName = name;
}
<|endoftext|>


<commit_before>/*
 * Copyright (c) 2018, ARM Limited, All Rights Reserved
 * SPDX-License-Identifier: Apache-2.0
 *
 * Licensed under the Apache License, Version 2.0 (the "License"); you may
 * not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#define WIFI 2
#if !defined(MBED_CONF_TARGET_NETWORK_DEFAULT_INTERFACE_TYPE) || \
    (MBED_CONF_TARGET_NETWORK_DEFAULT_INTERFACE_TYPE == WIFI && !defined(MBED_CONF_NSAPI_DEFAULT_WIFI_SSID))
#error [NOT_SUPPORTED] No network configuration found for this target.
#endif

#include "mbed.h"
#include "greentea-client/test_env.h"
#include "unity.h"
#include "utest.h"
#include "nsapi_dns.h"
#include "EventQueue.h"
#include "dns_tests.h"

using namespace utest::v1;

namespace {
NetworkInterface *net;
}

const char dns_test_hosts[MBED_CONF_APP_DNS_TEST_HOSTS_NUM][DNS_TEST_HOST_LEN] = MBED_CONF_APP_DNS_TEST_HOSTS;
const char dns_test_hosts_second[MBED_CONF_APP_DNS_TEST_HOSTS_NUM][DNS_TEST_HOST_LEN] = MBED_CONF_APP_DNS_TEST_HOSTS_SECOND;

// Callback used for asynchronous DNS result
void hostbyname_cb(void *data, nsapi_error_t result, SocketAddress *address)
{
    dns_application_data *app_data = static_cast<dns_application_data *>(data);
    app_data->result = result;
    if (address) {
        app_data->addr = *address;
    }
    app_data->semaphore->release();
    app_data->value_set = true;
}

// General function to do asynchronous DNS host name resolution
void do_asynchronous_gethostbyname(const char hosts[][DNS_TEST_HOST_LEN], unsigned int op_count, int *exp_ok, int *exp_no_mem, int *exp_dns_failure, int *exp_timeout)
{
    // Verify that there is enough hosts in the host list
    TEST_ASSERT(op_count <= MBED_CONF_APP_DNS_TEST_HOSTS_NUM)

    // Reset counters
    (*exp_ok) = 0;
    (*exp_no_mem) = 0;
    (*exp_dns_failure) = 0;
    (*exp_timeout) = 0;

    // Create callback semaphore and data
    rtos::Semaphore semaphore;
    dns_application_data *data = new dns_application_data[op_count];

    unsigned int count = 0;
    for (unsigned int i = 0; i < op_count; i++) {
        data[i].semaphore = &semaphore;
        nsapi_error_t err = net->gethostbyname_async(hosts[i], mbed::Callback<void(nsapi_error_t, SocketAddress *)>(hostbyname_cb, (void *) &data[i]));
        TEST_ASSERT(err >= 0 || err == NSAPI_ERROR_NO_MEMORY);
        if (err >= 0) {
            // Callback will be called
            count++;
        } else {
            // No memory to initiate DNS query, callback will not be called
            data[i].result = NSAPI_ERROR_NO_MEMORY;
        }
    }

    // Wait for callback(s) to complete
    for (unsigned int i = 0; i < count; i++) {
        semaphore.wait();
    }

    // Print result
    for (unsigned int i = 0; i < op_count; i++) {
        TEST_ASSERT(data[i].result == NSAPI_ERROR_OK || data[i].result == NSAPI_ERROR_NO_MEMORY || data[i].result == NSAPI_ERROR_DNS_FAILURE || data[i].result == NSAPI_ERROR_TIMEOUT);
        if (data[i].result == NSAPI_ERROR_OK) {
            (*exp_ok)++;
            printf("DNS: query \"%s\" => \"%s\"\n",
                   hosts[i], data[i].addr.get_ip_address());
        } else if (data[i].result == NSAPI_ERROR_DNS_FAILURE) {
            (*exp_dns_failure)++;
            printf("DNS: query \"%s\" => DNS failure\n", hosts[i]);
        } else if (data[i].result == NSAPI_ERROR_TIMEOUT) {
            (*exp_timeout)++;
            printf("DNS: query \"%s\" => timeout\n", hosts[i]);
        } else if (data[i].result == NSAPI_ERROR_NO_MEMORY) {
            (*exp_no_mem)++;
            printf("DNS: query \"%s\" => no memory\n", hosts[i]);
        }
    }

    delete[] data;
}

void do_gethostbyname(const char hosts[][DNS_TEST_HOST_LEN], unsigned int op_count, int *exp_ok, int *exp_no_mem, int *exp_dns_failure, int *exp_timeout)
{
    // Verify that there is enough hosts in the host list
    TEST_ASSERT(op_count <= MBED_CONF_APP_DNS_TEST_HOSTS_NUM)

    // Reset counters
    (*exp_ok) = 0;
    (*exp_no_mem) = 0;
    (*exp_dns_failure) = 0;
    (*exp_timeout) = 0;

    for (unsigned int i = 0; i < op_count; i++) {
        SocketAddress address;
        nsapi_error_t err = net->gethostbyname(hosts[i], &address);

        TEST_ASSERT(err == NSAPI_ERROR_OK || err == NSAPI_ERROR_NO_MEMORY || err == NSAPI_ERROR_DNS_FAILURE || err == NSAPI_ERROR_TIMEOUT);
        if (err == NSAPI_ERROR_OK) {
            (*exp_ok)++;
            printf("DNS: query \"%s\" => \"%s\"\n",
                   hosts[i], address.get_ip_address());
        } else if (err == NSAPI_ERROR_DNS_FAILURE) {
            (*exp_dns_failure)++;
            printf("DNS: query \"%s\" => DNS failure\n", hosts[i]);
        } else if (err == NSAPI_ERROR_TIMEOUT) {
            (*exp_timeout)++;
            printf("DNS: query \"%s\" => timeout\n", hosts[i]);
        } else if (err == NSAPI_ERROR_NO_MEMORY) {
            (*exp_no_mem)++;
            printf("DNS: query \"%s\" => no memory\n", hosts[i]);
        }
    }
}

NetworkInterface *get_interface()
{
    return net;
}

static void net_bringup()
{
    MBED_ASSERT(MBED_CONF_APP_DNS_TEST_HOSTS_NUM >= MBED_CONF_NSAPI_DNS_CACHE_SIZE && MBED_CONF_APP_DNS_TEST_HOSTS_NUM >= MBED_CONF_APP_DNS_SIMULT_QUERIES + 1);

    net = NetworkInterface::get_default_instance();
    nsapi_error_t err = net->connect();
    TEST_ASSERT_EQUAL(NSAPI_ERROR_OK, err);
    printf("MBED: IP address is '%s'\n", net->get_ip_address());
}

// Test setup
utest::v1::status_t test_setup(const size_t number_of_cases)
{
    GREENTEA_SETUP(120, "default_auto");
    net_bringup();
    return verbose_test_setup_handler(number_of_cases);
}

Case cases[] = {
    Case("ASYNCHRONOUS_DNS", ASYNCHRONOUS_DNS),
    Case("ASYNCHRONOUS_DNS_SIMULTANEOUS", ASYNCHRONOUS_DNS_SIMULTANEOUS),
    Case("ASYNCHRONOUS_DNS_SIMULTANEOUS_CACHE", ASYNCHRONOUS_DNS_SIMULTANEOUS_CACHE),
    Case("ASYNCHRONOUS_DNS_CACHE", ASYNCHRONOUS_DNS_CACHE),
    Case("ASYNCHRONOUS_DNS_NON_ASYNC_AND_ASYNC", ASYNCHRONOUS_DNS_NON_ASYNC_AND_ASYNC),
    Case("ASYNCHRONOUS_DNS_CANCEL", ASYNCHRONOUS_DNS_CANCEL),
    Case("ASYNCHRONOUS_DNS_EXTERNAL_EVENT_QUEUE", ASYNCHRONOUS_DNS_EXTERNAL_EVENT_QUEUE),
    Case("ASYNCHRONOUS_DNS_INVALID_HOST", ASYNCHRONOUS_DNS_INVALID_HOST),
    Case("ASYNCHRONOUS_DNS_TIMEOUTS", ASYNCHRONOUS_DNS_TIMEOUTS),
#ifdef MBED_EXTENDED_TESTS
    Case("ASYNCHRONOUS_DNS_SIMULTANEOUS_REPEAT",  ASYNCHRONOUS_DNS_SIMULTANEOUS_REPEAT),
#endif
    Case("SYNCHRONOUS_DNS", SYNCHRONOUS_DNS),
    Case("SYNCHRONOUS_DNS_MULTIPLE", SYNCHRONOUS_DNS_MULTIPLE),
#ifdef MBED_EXTENDED_TESTS
    Case("SYNCHRONOUS_DNS_CACHE", SYNCHRONOUS_DNS_CACHE),
#endif
    Case("SYNCHRONOUS_DNS_INVALID", SYNCHRONOUS_DNS_INVALID),
};

Specification specification(test_setup, cases);

int main()
{
    return !Harness::run(specification);
}
<commit_msg>Remove the unstable SYNCHRONOUS_DNS_CACHE testcase<commit_after>/*
 * Copyright (c) 2018, ARM Limited, All Rights Reserved
 * SPDX-License-Identifier: Apache-2.0
 *
 * Licensed under the Apache License, Version 2.0 (the "License"); you may
 * not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#define WIFI 2
#if !defined(MBED_CONF_TARGET_NETWORK_DEFAULT_INTERFACE_TYPE) || \
    (MBED_CONF_TARGET_NETWORK_DEFAULT_INTERFACE_TYPE == WIFI && !defined(MBED_CONF_NSAPI_DEFAULT_WIFI_SSID))
#error [NOT_SUPPORTED] No network configuration found for this target.
#endif

#include "mbed.h"
#include "greentea-client/test_env.h"
#include "unity.h"
#include "utest.h"
#include "nsapi_dns.h"
#include "EventQueue.h"
#include "dns_tests.h"

using namespace utest::v1;

namespace {
NetworkInterface *net;
}

const char dns_test_hosts[MBED_CONF_APP_DNS_TEST_HOSTS_NUM][DNS_TEST_HOST_LEN] = MBED_CONF_APP_DNS_TEST_HOSTS;
const char dns_test_hosts_second[MBED_CONF_APP_DNS_TEST_HOSTS_NUM][DNS_TEST_HOST_LEN] = MBED_CONF_APP_DNS_TEST_HOSTS_SECOND;

// Callback used for asynchronous DNS result
void hostbyname_cb(void *data, nsapi_error_t result, SocketAddress *address)
{
    dns_application_data *app_data = static_cast<dns_application_data *>(data);
    app_data->result = result;
    if (address) {
        app_data->addr = *address;
    }
    app_data->semaphore->release();
    app_data->value_set = true;
}

// General function to do asynchronous DNS host name resolution
void do_asynchronous_gethostbyname(const char hosts[][DNS_TEST_HOST_LEN], unsigned int op_count, int *exp_ok, int *exp_no_mem, int *exp_dns_failure, int *exp_timeout)
{
    // Verify that there is enough hosts in the host list
    TEST_ASSERT(op_count <= MBED_CONF_APP_DNS_TEST_HOSTS_NUM)

    // Reset counters
    (*exp_ok) = 0;
    (*exp_no_mem) = 0;
    (*exp_dns_failure) = 0;
    (*exp_timeout) = 0;

    // Create callback semaphore and data
    rtos::Semaphore semaphore;
    dns_application_data *data = new dns_application_data[op_count];

    unsigned int count = 0;
    for (unsigned int i = 0; i < op_count; i++) {
        data[i].semaphore = &semaphore;
        nsapi_error_t err = net->gethostbyname_async(hosts[i], mbed::Callback<void(nsapi_error_t, SocketAddress *)>(hostbyname_cb, (void *) &data[i]));
        TEST_ASSERT(err >= 0 || err == NSAPI_ERROR_NO_MEMORY);
        if (err >= 0) {
            // Callback will be called
            count++;
        } else {
            // No memory to initiate DNS query, callback will not be called
            data[i].result = NSAPI_ERROR_NO_MEMORY;
        }
    }

    // Wait for callback(s) to complete
    for (unsigned int i = 0; i < count; i++) {
        semaphore.wait();
    }

    // Print result
    for (unsigned int i = 0; i < op_count; i++) {
        TEST_ASSERT(data[i].result == NSAPI_ERROR_OK || data[i].result == NSAPI_ERROR_NO_MEMORY || data[i].result == NSAPI_ERROR_DNS_FAILURE || data[i].result == NSAPI_ERROR_TIMEOUT);
        if (data[i].result == NSAPI_ERROR_OK) {
            (*exp_ok)++;
            printf("DNS: query \"%s\" => \"%s\"\n",
                   hosts[i], data[i].addr.get_ip_address());
        } else if (data[i].result == NSAPI_ERROR_DNS_FAILURE) {
            (*exp_dns_failure)++;
            printf("DNS: query \"%s\" => DNS failure\n", hosts[i]);
        } else if (data[i].result == NSAPI_ERROR_TIMEOUT) {
            (*exp_timeout)++;
            printf("DNS: query \"%s\" => timeout\n", hosts[i]);
        } else if (data[i].result == NSAPI_ERROR_NO_MEMORY) {
            (*exp_no_mem)++;
            printf("DNS: query \"%s\" => no memory\n", hosts[i]);
        }
    }

    delete[] data;
}

void do_gethostbyname(const char hosts[][DNS_TEST_HOST_LEN], unsigned int op_count, int *exp_ok, int *exp_no_mem, int *exp_dns_failure, int *exp_timeout)
{
    // Verify that there is enough hosts in the host list
    TEST_ASSERT(op_count <= MBED_CONF_APP_DNS_TEST_HOSTS_NUM)

    // Reset counters
    (*exp_ok) = 0;
    (*exp_no_mem) = 0;
    (*exp_dns_failure) = 0;
    (*exp_timeout) = 0;

    for (unsigned int i = 0; i < op_count; i++) {
        SocketAddress address;
        nsapi_error_t err = net->gethostbyname(hosts[i], &address);

        TEST_ASSERT(err == NSAPI_ERROR_OK || err == NSAPI_ERROR_NO_MEMORY || err == NSAPI_ERROR_DNS_FAILURE || err == NSAPI_ERROR_TIMEOUT);
        if (err == NSAPI_ERROR_OK) {
            (*exp_ok)++;
            printf("DNS: query \"%s\" => \"%s\"\n",
                   hosts[i], address.get_ip_address());
        } else if (err == NSAPI_ERROR_DNS_FAILURE) {
            (*exp_dns_failure)++;
            printf("DNS: query \"%s\" => DNS failure\n", hosts[i]);
        } else if (err == NSAPI_ERROR_TIMEOUT) {
            (*exp_timeout)++;
            printf("DNS: query \"%s\" => timeout\n", hosts[i]);
        } else if (err == NSAPI_ERROR_NO_MEMORY) {
            (*exp_no_mem)++;
            printf("DNS: query \"%s\" => no memory\n", hosts[i]);
        }
    }
}

NetworkInterface *get_interface()
{
    return net;
}

static void net_bringup()
{
    MBED_ASSERT(MBED_CONF_APP_DNS_TEST_HOSTS_NUM >= MBED_CONF_NSAPI_DNS_CACHE_SIZE && MBED_CONF_APP_DNS_TEST_HOSTS_NUM >= MBED_CONF_APP_DNS_SIMULT_QUERIES + 1);

    net = NetworkInterface::get_default_instance();
    nsapi_error_t err = net->connect();
    TEST_ASSERT_EQUAL(NSAPI_ERROR_OK, err);
    printf("MBED: IP address is '%s'\n", net->get_ip_address());
}

// Test setup
utest::v1::status_t test_setup(const size_t number_of_cases)
{
    GREENTEA_SETUP(120, "default_auto");
    net_bringup();
    return verbose_test_setup_handler(number_of_cases);
}

Case cases[] = {
    Case("ASYNCHRONOUS_DNS", ASYNCHRONOUS_DNS),
    Case("ASYNCHRONOUS_DNS_SIMULTANEOUS", ASYNCHRONOUS_DNS_SIMULTANEOUS),
    Case("ASYNCHRONOUS_DNS_SIMULTANEOUS_CACHE", ASYNCHRONOUS_DNS_SIMULTANEOUS_CACHE),
    Case("ASYNCHRONOUS_DNS_CACHE", ASYNCHRONOUS_DNS_CACHE),
    Case("ASYNCHRONOUS_DNS_NON_ASYNC_AND_ASYNC", ASYNCHRONOUS_DNS_NON_ASYNC_AND_ASYNC),
    Case("ASYNCHRONOUS_DNS_CANCEL", ASYNCHRONOUS_DNS_CANCEL),
    Case("ASYNCHRONOUS_DNS_EXTERNAL_EVENT_QUEUE", ASYNCHRONOUS_DNS_EXTERNAL_EVENT_QUEUE),
    Case("ASYNCHRONOUS_DNS_INVALID_HOST", ASYNCHRONOUS_DNS_INVALID_HOST),
    Case("ASYNCHRONOUS_DNS_TIMEOUTS", ASYNCHRONOUS_DNS_TIMEOUTS),
#ifdef MBED_EXTENDED_TESTS
    Case("ASYNCHRONOUS_DNS_SIMULTANEOUS_REPEAT",  ASYNCHRONOUS_DNS_SIMULTANEOUS_REPEAT),
#endif
    Case("SYNCHRONOUS_DNS", SYNCHRONOUS_DNS),
    Case("SYNCHRONOUS_DNS_MULTIPLE", SYNCHRONOUS_DNS_MULTIPLE),
    Case("SYNCHRONOUS_DNS_INVALID", SYNCHRONOUS_DNS_INVALID),
};

Specification specification(test_setup, cases);

int main()
{
    return !Harness::run(specification);
}
<|endoftext|>