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

  Program:   Visualization Toolkit
  Module:    TestRandomPContingencyStatisticsMPI.cxx

  Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
  All rights reserved.
  See Copyright.txt or http://www.kitware.com/Copyright.htm for details.

     This software is distributed WITHOUT ANY WARRANTY; without even
     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
     PURPOSE.  See the above copyright notice for more information.

=========================================================================*/
/*
 * Copyright 2009 Sandia Corporation.
 * Under the terms of Contract DE-AC04-94AL85000, there is a non-exclusive
 * license for use of this work by or on behalf of the
 * U.S. Government. Redistribution and use in source and binary forms, with
 * or without modification, are permitted provided that this Notice and any
 * statement of authorship are reproduced on all copies.
 */
// .SECTION Thanks
// Thanks to Philippe Pebay for implementing this test.

#include <mpi.h>

#include "vtkContingencyStatistics.h"
#include "vtkPContingencyStatistics.h"

#include "vtkDoubleArray.h"
#include "vtkIdTypeArray.h"
#include "vtkIntArray.h"
#include "vtkMath.h"
#include "vtkMPIController.h"
#include "vtkMultiBlockDataSet.h"
#include "vtkStdString.h"
#include "vtkTable.h"
#include "vtkTimerLog.h"
#include "vtkVariantArray.h"

// For debugging purposes, output contingency table, which may be huge: it has the size O(span^2).
#define DEBUG_CONTINGENCY_TABLE 0

struct RandomContingencyStatisticsArgs
{
  int nVals;
  double span;
  double absTol;
  int* retVal;
  int ioRank;
  int argc;
  char** argv;
};

// This will be called by all processes
void RandomContingencyStatistics( vtkMultiProcessController* controller, void* arg )
{
  // Get test parameters
  RandomContingencyStatisticsArgs* args = reinterpret_cast<RandomContingencyStatisticsArgs*>( arg );
  *(args->retVal) = 0;

  // Get MPI communicator
  vtkMPICommunicator* com = vtkMPICommunicator::SafeDownCast( controller->GetCommunicator() );

  // Get local rank
  int myRank = com->GetLocalProcessId();

  // Seed random number generator
  vtkMath::RandomSeed( static_cast<int>( time( NULL ) ) * ( myRank + 1 ) );

  // Generate an input table that contains samples of mutually independent discrete random variables
  int nVariables = 2;
  vtkIntArray* intArray[2];
  vtkStdString columnNames[] = { "Rounded Normal 0",
                                 "Rounded Normal 1" };

  vtkTable* inputData = vtkTable::New();
  // Discrete rounded normal samples
  for ( int c = 0; c < nVariables; ++ c )
    {
    intArray[c] = vtkIntArray::New();
    intArray[c]->SetNumberOfComponents( 1 );
    intArray[c]->SetName( columnNames[c] );

    for ( int r = 0; r < args->nVals; ++ r )
      {
      intArray[c]->InsertNextValue( static_cast<int>( round( vtkMath::Gaussian() * args->span ) ) );
      }

    inputData->AddColumn( intArray[c] );
    intArray[c]->Delete();
    }

  // Entropies in the summary table should normally be retrieved as follows:
  //   column 2: H(X,Y)
  //   column 3: H(Y|X)
  //   column 4: H(X|Y)
  int iEntropies[] = { 2,
                       3,
                       4 };
  int nEntropies = 3; // correct number of entropies reported in the summary table
  double* H = new double[nEntropies];

  // ************************** Contingency Statistics **************************

  // Synchronize and start clock
  com->Barrier();
  vtkTimerLog *timer=vtkTimerLog::New();
  timer->StartTimer();

  // Instantiate a parallel contingency statistics engine and set its ports
  vtkPContingencyStatistics* pcs = vtkPContingencyStatistics::New();
  pcs->SetInput( 0, inputData );
  vtkMultiBlockDataSet* outputMetaDS = vtkMultiBlockDataSet::SafeDownCast( pcs->GetOutputDataObject( 1 ) );

  // Select column pairs (uniform vs. uniform, normal vs. normal)
  pcs->AddColumnPair( columnNames[0], columnNames[1] );

  // Test (in parallel) with Learn, Derive, and Assess options turned on
  pcs->SetLearn( true );
  pcs->SetDerive( true );
  pcs->SetAssess( true );
  pcs->Update();

    // Synchronize and stop clock
  com->Barrier();
  timer->StopTimer();

  if ( com->GetLocalProcessId() == args->ioRank )
    {
    cout << "\n## Completed parallel calculation of contingency statistics (with assessment):\n"
         << "   Wall time: "
         << timer->GetElapsedTime()
         << " sec.\n";
    }

  // Verify that information entropies on all processes make sense
  if ( com->GetLocalProcessId() == args->ioRank )
    {
    cout << "\n## Verifying that information entropies are consistent on all processes.\n";
    }

  vtkTable* outputSummary = vtkTable::SafeDownCast( outputMetaDS->GetBlock( 0 ) );
  vtkTable* outputContingency = vtkTable::SafeDownCast( outputMetaDS->GetBlock( 1 ) );

  int testIntValue = 0;
  double testDoubleValue = 0;

  // Synchronize
  com->Barrier();

  vtkIdType card = outputContingency->GetValueByName( 0, "Cardinality" ).ToInt();
  cout << "   On process "
       << com->GetLocalProcessId()
       << " ( grand total: "
       << card
       << " ): ";

  testIntValue = outputSummary->GetNumberOfColumns();

  if ( testIntValue != nEntropies + 2 )
    {
    vtkGenericWarningMacro("Reported an incorrect number of columns in the summary table: "
                           << testIntValue
                           << " != "
                           << nEntropies + 2
                           << ".");
    *(args->retVal) = 1;
    }
  else
    {
    // For each row in the summary table, fetch variable names and information entropies
    for ( vtkIdType r = 0; r < outputSummary->GetNumberOfRows(); ++ r )
      {
      // Variable names
      cout << "("
           << outputSummary->GetValue( r, 0 ).ToString()
           << ", "
           << outputSummary->GetValue( r, 1 ).ToString()
           << "):";

      // Information entropies
      for ( vtkIdType c = 0; c < nEntropies; ++ c )
        {
        H[c] = outputSummary->GetValue( r, iEntropies[c] ).ToDouble();

        cout << " "
             << outputSummary->GetColumnName( iEntropies[c] )
             << "="
             << H[c];
        }
      cout << "\n";

      // Make sure that H(X,Y) > H(Y|X)+ H(X|Y)
      testDoubleValue = H[1] + H[2]; // H(Y|X)+ H(X|Y)

      if ( testDoubleValue > H[0] )
        {
        vtkGenericWarningMacro("Reported inconsistent information entropies: H(X,Y) = "
                               << H[0]
                               << " < "
                               << testDoubleValue
                               << " = H(Y|X)+ H(X|Y).");
        *(args->retVal) = 1;
        }
      }
    }

  // Synchronize
  com->Barrier();

  // Verify that the broadcasted reduced contingency tables all result in a CDF value of 1
  if ( com->GetLocalProcessId() == args->ioRank )
    {
    cout << "\n## Verifying that broadcasted CDF sum to 1 on all processes.\n";
    }

  vtkIdTypeArray* keys = vtkIdTypeArray::SafeDownCast( outputContingency->GetColumnByName( "Key" ) );
  if ( ! keys )
    {
    cout << "*** Error: "
         << "Empty contingency table column 'Key' on process "
         << com->GetLocalProcessId()
         << ".\n";
    }

  vtkStdString proName = "P";
  vtkDoubleArray* prob = vtkDoubleArray::SafeDownCast( outputContingency->GetColumnByName( proName ) );
  if ( ! prob )
    {
    cout << "*** Error: "
         << "Empty contingency table column '"
         << proName
         << "' on process "
         << com->GetLocalProcessId()
         << ".\n";
    }

  // Calculate local CDFs
  double cdf_l = 0.;
  vtkIdType key = 0;
  int n = outputContingency->GetNumberOfRows();
  vtkIdType k;

  // Skip first entry which is reserved for the cardinality
  for ( vtkIdType r = 1; r < n; ++ r )
    {
    k = keys->GetValue( r );

    if ( k == key )
      {
      cdf_l += prob->GetValue( r );
      }
    }

  // Gather all local CDFs
  int numProcs = controller->GetNumberOfProcesses();
  double* cdf_g = new double[numProcs];
  com->AllGather( &cdf_l,
                  cdf_g,
                  1 );

  // Print out all CDFs
  if ( com->GetLocalProcessId() == args->ioRank )
    {
    for ( int i = 0; i < numProcs; ++ i )
      {
      cout << "   On process "
           << i
           << ", CDF = "
           << cdf_g[i]
           << "\n";

      if ( fabs ( 1. - cdf_g[i] ) > args->absTol )
        {
        vtkGenericWarningMacro("Incorrect CDF.");
        *(args->retVal) = 1;
        }
      }
    }

#if DEBUG_CONTINGENCY_TABLE
  outputContingency->Dump();
#endif // DEBUG_CONTINGENCY_TABLE

  // Clean up
  delete [] cdf_g;
  pcs->Delete();
  inputData->Delete();
  timer->Delete();
}

//----------------------------------------------------------------------------
int main( int argc, char** argv )
{
  // **************************** MPI Initialization ***************************
  vtkMPIController* controller = vtkMPIController::New();
  controller->Initialize( &argc, &argv );

  // If an MPI controller was not created, terminate in error.
  if ( ! controller->IsA( "vtkMPIController" ) )
    {
    vtkGenericWarningMacro("Failed to initialize a MPI controller.");
    controller->Delete();
    return 1;
    }

  vtkMPICommunicator* com = vtkMPICommunicator::SafeDownCast( controller->GetCommunicator() );

  // ************************** Find an I/O node ********************************
  int* ioPtr;
  int ioRank;
  int flag;

  MPI_Attr_get( MPI_COMM_WORLD,
                MPI_IO,
                &ioPtr,
                &flag );

  if ( ( ! flag ) || ( *ioPtr == MPI_PROC_NULL ) )
    {
    // Getting MPI attributes did not return any I/O node found.
    ioRank = MPI_PROC_NULL;
    vtkGenericWarningMacro("No MPI I/O nodes found.");

    // As no I/O node was found, we need an unambiguous way to report the problem.
    // This is the only case when a testValue of -1 will be returned
    controller->Finalize();
    controller->Delete();

    return -1;
    }
  else
    {
    if ( *ioPtr == MPI_ANY_SOURCE )
      {
      // Anyone can do the I/O trick--just pick node 0.
      ioRank = 0;
      }
    else
      {
      // Only some nodes can do I/O. Make sure everyone agrees on the choice (min).
      com->AllReduce( ioPtr,
                      &ioRank,
                      1,
                      vtkCommunicator::MIN_OP );
      }
    }

  // ************************** Initialize test *********************************
  if ( com->GetLocalProcessId() == ioRank )
    {
    cout << "\n# Process "
         << ioRank
         << " will be the I/O node.\n";
    }

  // Check how many processes have been made available
  int numProcs = controller->GetNumberOfProcesses();
  if ( controller->GetLocalProcessId() == ioRank )
    {
    cout << "\n# Running test with "
         << numProcs
         << " processes...\n";
    }

  // Parameters for regression test.
  int testValue = 0;
  RandomContingencyStatisticsArgs args;
  args.nVals = 1000000;
  args.span = 50.;
  args.absTol = 1.e-6;
  args.retVal = &testValue;
  args.ioRank = ioRank;
  args.argc = argc;
  args.argv = argv;

  // Execute the function named "process" on both processes
  controller->SetSingleMethod( RandomContingencyStatistics, &args );
  controller->SingleMethodExecute();

  // Clean up and exit
  if ( com->GetLocalProcessId() == ioRank )
    {
    cout << "\n# Test completed.\n\n";
    }

  controller->Finalize();
  controller->Delete();

  return testValue;
}
<commit_msg>ENH: better testing and reporting (entropies, per processor, etc.)<commit_after>/*=========================================================================

  Program:   Visualization Toolkit
  Module:    TestRandomPContingencyStatisticsMPI.cxx

  Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
  All rights reserved.
  See Copyright.txt or http://www.kitware.com/Copyright.htm for details.

     This software is distributed WITHOUT ANY WARRANTY; without even
     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
     PURPOSE.  See the above copyright notice for more information.

=========================================================================*/
/*
 * Copyright 2009 Sandia Corporation.
 * Under the terms of Contract DE-AC04-94AL85000, there is a non-exclusive
 * license for use of this work by or on behalf of the
 * U.S. Government. Redistribution and use in source and binary forms, with
 * or without modification, are permitted provided that this Notice and any
 * statement of authorship are reproduced on all copies.
 */
// .SECTION Thanks
// Thanks to Philippe Pebay for implementing this test.

#include <mpi.h>

#include "vtkContingencyStatistics.h"
#include "vtkPContingencyStatistics.h"

#include "vtkDoubleArray.h"
#include "vtkIdTypeArray.h"
#include "vtkIntArray.h"
#include "vtkMath.h"
#include "vtkMPIController.h"
#include "vtkMultiBlockDataSet.h"
#include "vtkStdString.h"
#include "vtkTable.h"
#include "vtkTimerLog.h"
#include "vtkVariantArray.h"

// For debugging purposes, output contingency table, which may be huge: it has the size O(span^2).
#define DEBUG_CONTINGENCY_TABLE 0

struct RandomContingencyStatisticsArgs
{
  int nVals;
  double span;
  double absTol;
  int* retVal;
  int ioRank;
  int argc;
  char** argv;
};

// This will be called by all processes
void RandomContingencyStatistics( vtkMultiProcessController* controller, void* arg )
{
  // Get test parameters
  RandomContingencyStatisticsArgs* args = reinterpret_cast<RandomContingencyStatisticsArgs*>( arg );
  *(args->retVal) = 0;

  // Get MPI communicator
  vtkMPICommunicator* com = vtkMPICommunicator::SafeDownCast( controller->GetCommunicator() );

  // Get local rank
  int myRank = com->GetLocalProcessId();

  // Seed random number generator
  vtkMath::RandomSeed( static_cast<int>( time( NULL ) ) * ( myRank + 1 ) );

  // Generate an input table that contains samples of mutually independent discrete random variables
  int nVariables = 2;
  vtkIntArray* intArray[2];
  vtkStdString columnNames[] = { "Rounded Normal 0",
                                 "Rounded Normal 1" };

  vtkTable* inputData = vtkTable::New();
  // Discrete rounded normal samples
  for ( int c = 0; c < nVariables; ++ c )
    {
    intArray[c] = vtkIntArray::New();
    intArray[c]->SetNumberOfComponents( 1 );
    intArray[c]->SetName( columnNames[c] );

    for ( int r = 0; r < args->nVals; ++ r )
      {
      intArray[c]->InsertNextValue( static_cast<int>( round( vtkMath::Gaussian() * args->span ) ) );
      }

    inputData->AddColumn( intArray[c] );
    intArray[c]->Delete();
    }

  // Entropies in the summary table should normally be retrieved as follows:
  //   column 2: H(X,Y)
  //   column 3: H(Y|X)
  //   column 4: H(X|Y)
  int iEntropies[] = { 2,
                       3,
                       4 };
  int nEntropies = 3; // correct number of entropies reported in the summary table

  // ************************** Contingency Statistics **************************

  // Synchronize and start clock
  com->Barrier();
  vtkTimerLog *timer=vtkTimerLog::New();
  timer->StartTimer();

  // Instantiate a parallel contingency statistics engine and set its ports
  vtkPContingencyStatistics* pcs = vtkPContingencyStatistics::New();
  pcs->SetInput( 0, inputData );
  vtkMultiBlockDataSet* outputMetaDS = vtkMultiBlockDataSet::SafeDownCast( pcs->GetOutputDataObject( 1 ) );

  // Select column pairs (uniform vs. uniform, normal vs. normal)
  pcs->AddColumnPair( columnNames[0], columnNames[1] );

  // Test (in parallel) with Learn, Derive, and Assess options turned on
  pcs->SetLearn( true );
  pcs->SetDerive( true );
  pcs->SetAssess( true );
  pcs->Update();

    // Synchronize and stop clock
  com->Barrier();
  timer->StopTimer();

  if ( com->GetLocalProcessId() == args->ioRank )
    {
    cout << "\n## Completed parallel calculation of contingency statistics (with assessment):\n"
         << "   Wall time: "
         << timer->GetElapsedTime()
         << " sec.\n";
    }

  // Verify that information entropies on all processes make sense
  if ( com->GetLocalProcessId() == args->ioRank )
    {
    cout << "\n## Verifying that information entropies are consistent on all processes.\n";
    }

  vtkTable* outputSummary = vtkTable::SafeDownCast( outputMetaDS->GetBlock( 0 ) );
  vtkTable* outputContingency = vtkTable::SafeDownCast( outputMetaDS->GetBlock( 1 ) );

  int testIntValue = 0;
  double testDoubleValue = 0;
  int numProcs = controller->GetNumberOfProcesses();

  testIntValue = outputSummary->GetNumberOfColumns();

  if ( testIntValue != nEntropies + 2 )
    {
    vtkGenericWarningMacro("Reported an incorrect number of columns in the summary table: "
                           << testIntValue
                           << " != "
                           << nEntropies + 2
                           << ".");
    *(args->retVal) = 1;
    }
  else
    {
    // For each row in the summary table, fetch variable names and information entropies
    for ( vtkIdType r = 0; r < outputSummary->GetNumberOfRows(); ++ r )
      {
      // Get local information entropies from summary table
      double* H_l = new double[nEntropies];
      for ( vtkIdType c = 0; c < nEntropies; ++ c )
        {
        H_l[c] = outputSummary->GetValue( r, iEntropies[c] ).ToDouble();
        }

      // Gather all local entropies
      double* H_g = new double[nEntropies * numProcs];
      com->AllGather( H_l,
                      H_g,
                      nEntropies );

      // Print out all entropies
      if ( com->GetLocalProcessId() == args->ioRank )
        {
        // Get variable names
        cout << "   (X,Y) = ("
             << outputSummary->GetValue( r, 0 ).ToString()
             << ", "
             << outputSummary->GetValue( r, 1 ).ToString()
             << "), grand total: "
             << outputContingency->GetValueByName( 0, "Cardinality" ).ToInt()
             << ",\n";

        for ( int i = 0; i < numProcs; ++ i )
          {
          cout << "     On process "
               << i;

          for ( vtkIdType c = 0; c < nEntropies; ++ c )
            {
            cout << ", "
                 << outputSummary->GetColumnName( iEntropies[c] )
                 << "="
                 << H_g[nEntropies * i + c];
            }

          cout << "\n";

          // Make sure that H(X,Y) > H(Y|X)+ H(X|Y)
          testDoubleValue = H_g[nEntropies * i + 1] + H_g[nEntropies * i + 2]; // H(Y|X)+ H(X|Y)

          if ( testDoubleValue > H_g[nEntropies * i] )
            {
            vtkGenericWarningMacro("Reported inconsistent information entropies: H(X,Y) = "
                                   << H_g[nEntropies * i]
                                   << " < "
                                   << testDoubleValue
                                   << " = H(Y|X)+ H(X|Y).");
            *(args->retVal) = 1;
            }
          }
        }

      // Clean up
      delete [] H_l;
      delete [] H_g;
      }
    }

  // Verify that the broadcasted reduced contingency tables all result in a CDF value of 1
  if ( com->GetLocalProcessId() == args->ioRank )
    {
    cout << "\n## Verifying that broadcasted CDF sum to 1 on all processes.\n";
    }

  vtkIdTypeArray* keys = vtkIdTypeArray::SafeDownCast( outputContingency->GetColumnByName( "Key" ) );
  if ( ! keys )
    {
    cout << "*** Error: "
         << "Empty contingency table column 'Key' on process "
         << com->GetLocalProcessId()
         << ".\n";
    }

  vtkStdString proName = "P";
  vtkDoubleArray* prob = vtkDoubleArray::SafeDownCast( outputContingency->GetColumnByName( proName ) );
  if ( ! prob )
    {
    cout << "*** Error: "
         << "Empty contingency table column '"
         << proName
         << "' on process "
         << com->GetLocalProcessId()
         << ".\n";
    }

  // Calculate local CDFs
  double cdf_l = 0.;
  vtkIdType key = 0;
  int n = outputContingency->GetNumberOfRows();
  vtkIdType k;

  // Skip first entry which is reserved for the cardinality
  for ( vtkIdType r = 1; r < n; ++ r )
    {
    k = keys->GetValue( r );

    if ( k == key )
      {
      cdf_l += prob->GetValue( r );
      }
    }

  // Gather all local CDFs
  double* cdf_g = new double[numProcs];
  com->AllGather( &cdf_l,
                  cdf_g,
                  1 );

  // Print out all CDFs
  if ( com->GetLocalProcessId() == args->ioRank )
    {
    for ( int i = 0; i < numProcs; ++ i )
      {
      cout << "   On process "
           << i
           << ", CDF = "
           << cdf_g[i]
           << "\n";

      if ( fabs ( 1. - cdf_g[i] ) > args->absTol )
        {
        vtkGenericWarningMacro("Incorrect CDF.");
        *(args->retVal) = 1;
        }
      }
    }

#if DEBUG_CONTINGENCY_TABLE
  outputContingency->Dump();
#endif // DEBUG_CONTINGENCY_TABLE

  // Clean up
  delete [] cdf_g;
  pcs->Delete();
  inputData->Delete();
  timer->Delete();
}

//----------------------------------------------------------------------------
int main( int argc, char** argv )
{
  // **************************** MPI Initialization ***************************
  vtkMPIController* controller = vtkMPIController::New();
  controller->Initialize( &argc, &argv );

  // If an MPI controller was not created, terminate in error.
  if ( ! controller->IsA( "vtkMPIController" ) )
    {
    vtkGenericWarningMacro("Failed to initialize a MPI controller.");
    controller->Delete();
    return 1;
    }

  vtkMPICommunicator* com = vtkMPICommunicator::SafeDownCast( controller->GetCommunicator() );

  // ************************** Find an I/O node ********************************
  int* ioPtr;
  int ioRank;
  int flag;

  MPI_Attr_get( MPI_COMM_WORLD,
                MPI_IO,
                &ioPtr,
                &flag );

  if ( ( ! flag ) || ( *ioPtr == MPI_PROC_NULL ) )
    {
    // Getting MPI attributes did not return any I/O node found.
    ioRank = MPI_PROC_NULL;
    vtkGenericWarningMacro("No MPI I/O nodes found.");

    // As no I/O node was found, we need an unambiguous way to report the problem.
    // This is the only case when a testValue of -1 will be returned
    controller->Finalize();
    controller->Delete();

    return -1;
    }
  else
    {
    if ( *ioPtr == MPI_ANY_SOURCE )
      {
      // Anyone can do the I/O trick--just pick node 0.
      ioRank = 0;
      }
    else
      {
      // Only some nodes can do I/O. Make sure everyone agrees on the choice (min).
      com->AllReduce( ioPtr,
                      &ioRank,
                      1,
                      vtkCommunicator::MIN_OP );
      }
    }

  // ************************** Initialize test *********************************
  if ( com->GetLocalProcessId() == ioRank )
    {
    cout << "\n# Process "
         << ioRank
         << " will be the I/O node.\n";
    }

  // Check how many processes have been made available
  int numProcs = controller->GetNumberOfProcesses();
  if ( controller->GetLocalProcessId() == ioRank )
    {
    cout << "\n# Running test with "
         << numProcs
         << " processes...\n";
    }

  // Parameters for regression test.
  int testValue = 0;
  RandomContingencyStatisticsArgs args;
  args.nVals = 1000000;
  args.span = 50.;
  args.absTol = 1.e-6;
  args.retVal = &testValue;
  args.ioRank = ioRank;
  args.argc = argc;
  args.argv = argv;

  // Execute the function named "process" on both processes
  controller->SetSingleMethod( RandomContingencyStatistics, &args );
  controller->SingleMethodExecute();

  // Clean up and exit
  if ( com->GetLocalProcessId() == ioRank )
    {
    cout << "\n# Test completed.\n\n";
    }

  controller->Finalize();
  controller->Delete();

  return testValue;
}
<|endoftext|>


<commit_before>/******************************************************************************
 * Copyright (C) 2018 Kitsune Ral <kitsune-ral@users.sf.net>
 *
 * This library 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 2.1 of the License, or (at your option) any later version.
 *
 * This library 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
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 */

#include "util.h"

#include <QtCore/QRegularExpression>
#include <QtCore/QStandardPaths>
#include <QtCore/QDir>
#include <QtCore/QStringBuilder>

static const auto RegExpOptions =
    QRegularExpression::CaseInsensitiveOption
    | QRegularExpression::OptimizeOnFirstUsageOption
    | QRegularExpression::UseUnicodePropertiesOption;

// Converts all that looks like a URL into HTML links
static void linkifyUrls(QString& htmlEscapedText)
{
    // regexp is originally taken from Konsole (https://github.com/KDE/konsole)
    // full url:
    // protocolname:// or www. followed by anything other than whitespaces,
    // <, >, ' or ", and ends before whitespaces, <, >, ', ", ], !, ), :,
    // comma or dot
    // Note: outer parentheses are a part of C++ raw string delimiters, not of
    // the regex (see http://en.cppreference.com/w/cpp/language/string_literal).
    static const QRegularExpression FullUrlRegExp(QStringLiteral(
            R"(((www\.(?!\.)|(https?|ftp|magnet)://)(&(?![lg]t;)|[^&\s<>'"])+(&(?![lg]t;)|[^&!,.\s<>'"\]):])))"
        ), RegExpOptions);
    // email address:
    // [word chars, dots or dashes]@[word chars, dots or dashes].[word chars]
    static const QRegularExpression EmailAddressRegExp(QStringLiteral(
            R"((mailto:)?(\b(\w|\.|-)+@(\w|\.|-)+\.\w+\b))"
        ), RegExpOptions);

    // NOTE: htmlEscapedText is already HTML-escaped! No literal <,>,&

    htmlEscapedText.replace(EmailAddressRegExp,
                 QStringLiteral(R"(\1\2)"));
    htmlEscapedText.replace(FullUrlRegExp,
                 QStringLiteral(R"(\1)"));
}

QString QMatrixClient::prettyPrint(const QString& plainText)
{
    auto pt = QStringLiteral("") +
            plainText.toHtmlEscaped() + QStringLiteral("");
    pt.replace('\n', QStringLiteral("
"));

    linkifyUrls(pt);
    return pt;
}

QString QMatrixClient::cacheLocation(const QString& dirName)
{
    const QString cachePath =
        QStandardPaths::writableLocation(QStandardPaths::CacheLocation)
            % '/' % dirName % '/';
    QDir dir;
    if (!dir.exists(cachePath))
        dir.mkpath(cachePath);
    return cachePath;
}

// Tests for function_traits<>

#ifdef Q_CC_CLANG
#pragma clang diagnostic push
#pragma ide diagnostic ignored "OCSimplifyInspection"
#endif
using namespace QMatrixClient;

int f();
static_assert(std::is_same<fn_return_t<decltype(f)>, int>::value,
              "Test fn_return_t<>");

void f1(int);
static_assert(function_traits<decltype(f1)>::arg_number == 1,
              "Test fn_arg_number");

void f2(int, QString);
static_assert(std::is_same<fn_arg_t<decltype(f2), 1>, QString>::value,
              "Test fn_arg_t<>");

struct S { int mf(); };
static_assert(is_callable_v<decltype(&S::mf)>, "Test member function");
static_assert(returns<int, decltype(&S::mf)>(), "Test returns<> with member function");

struct Fo { int operator()(); };
static_assert(is_callable_v<Fo>, "Test is_callable<> with function object");
static_assert(function_traits<Fo>::arg_number == 0, "Test function object");
static_assert(std::is_same<fn_return_t<Fo>, int>::value,
              "Test return type of function object");

struct Fo1 { void operator()(int); };
static_assert(function_traits<Fo1>::arg_number == 1, "Test function object 1");
static_assert(is_callable_v<Fo1>, "Test is_callable<> with function object 1");
static_assert(std::is_same<fn_arg_t<Fo1>, int>(),
              "Test fn_arg_t defaulting to first argument");

#if (!defined(_MSC_VER) || _MSC_VER >= 1910)
static auto l = [] { return 1; };
static_assert(is_callable_v<decltype(l)>, "Test is_callable_v<> with lambda");
static_assert(std::is_same<fn_return_t<decltype(l)>, int>::value,
              "Test fn_return_t<> with lambda");
#endif

template <typename T>
struct fn_object
{
    static int smf(double) { return 0; }
};
template <>
struct fn_object<QString>
{
    void operator()(QString);
};
static_assert(is_callable_v<fn_object<QString>>, "Test function object");
static_assert(returns<void, fn_object<QString>>(),
              "Test returns<> with function object");
static_assert(!is_callable_v<fn_object<int>>, "Test non-function object");
// FIXME: These two don't work
//static_assert(is_callable_v<decltype(&fn_object<int>::smf)>,
//              "Test static member function");
//static_assert(returns<int, decltype(&fn_object<int>::smf)>(),
//              "Test returns<> with static member function");

template <typename T>
QString ft(T&&);
static_assert(std::is_same<fn_arg_t<decltype(ft<QString>)>, QString&&>(),
              "Test function templates");

#ifdef Q_CC_CLANG
#pragma clang diagnostic pop
#endif
<commit_msg>Linkify Matrix identifiers<commit_after>/******************************************************************************
 * Copyright (C) 2018 Kitsune Ral <kitsune-ral@users.sf.net>
 *
 * This library 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 2.1 of the License, or (at your option) any later version.
 *
 * This library 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
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 */

#include "util.h"

#include <QtCore/QRegularExpression>
#include <QtCore/QStandardPaths>
#include <QtCore/QDir>
#include <QtCore/QStringBuilder>

static const auto RegExpOptions =
    QRegularExpression::CaseInsensitiveOption
    | QRegularExpression::OptimizeOnFirstUsageOption
    | QRegularExpression::UseUnicodePropertiesOption;

// Converts all that looks like a URL into HTML links
static void linkifyUrls(QString& htmlEscapedText)
{
    // regexp is originally taken from Konsole (https://github.com/KDE/konsole)
    // full url:
    // protocolname:// or www. followed by anything other than whitespaces,
    // <, >, ' or ", and ends before whitespaces, <, >, ', ", ], !, ), :,
    // comma or dot
    // Note: outer parentheses are a part of C++ raw string delimiters, not of
    // the regex (see http://en.cppreference.com/w/cpp/language/string_literal).
    // Note2: yet another pair of outer parentheses are \1 in the replacement.
    static const QRegularExpression FullUrlRegExp(QStringLiteral(
            R"(((www\.(?!\.)|(https?|ftp|magnet)://)(&(?![lg]t;)|[^&\s<>'"])+(&(?![lg]t;)|[^&!,.\s<>'"\]):])))"
        ), RegExpOptions);
    // email address:
    // [word chars, dots or dashes]@[word chars, dots or dashes].[word chars]
    static const QRegularExpression EmailAddressRegExp(QStringLiteral(
            R"((mailto:)?(\b(\w|\.|-)+@(\w|\.|-)+\.\w+\b))"
        ), RegExpOptions);
    // An interim liberal implementation of
    // https://matrix.org/docs/spec/appendices.html#identifier-grammar
    static const QRegularExpression MxIdRegExp(QStringLiteral(
            R"((^|[^<>/])([!#@][-a-z0-9_=/.]{1,252}:[-.a-z0-9]+))"
        ), RegExpOptions);

    // NOTE: htmlEscapedText is already HTML-escaped! No literal <,>,&

    htmlEscapedText.replace(EmailAddressRegExp,
                 QStringLiteral(R"(\1\2)"));
    htmlEscapedText.replace(FullUrlRegExp,
                 QStringLiteral(R"(\1)"));
    htmlEscapedText.replace(MxIdRegExp,
                 QStringLiteral(R"(\1\2)"));
}

QString QMatrixClient::prettyPrint(const QString& plainText)
{
    auto pt = QStringLiteral("") +
            plainText.toHtmlEscaped() + QStringLiteral("");
    pt.replace('\n', QStringLiteral("
"));

    linkifyUrls(pt);
    return pt;
}

QString QMatrixClient::cacheLocation(const QString& dirName)
{
    const QString cachePath =
        QStandardPaths::writableLocation(QStandardPaths::CacheLocation)
            % '/' % dirName % '/';
    QDir dir;
    if (!dir.exists(cachePath))
        dir.mkpath(cachePath);
    return cachePath;
}

// Tests for function_traits<>

#ifdef Q_CC_CLANG
#pragma clang diagnostic push
#pragma ide diagnostic ignored "OCSimplifyInspection"
#endif
using namespace QMatrixClient;

int f();
static_assert(std::is_same<fn_return_t<decltype(f)>, int>::value,
              "Test fn_return_t<>");

void f1(int);
static_assert(function_traits<decltype(f1)>::arg_number == 1,
              "Test fn_arg_number");

void f2(int, QString);
static_assert(std::is_same<fn_arg_t<decltype(f2), 1>, QString>::value,
              "Test fn_arg_t<>");

struct S { int mf(); };
static_assert(is_callable_v<decltype(&S::mf)>, "Test member function");
static_assert(returns<int, decltype(&S::mf)>(), "Test returns<> with member function");

struct Fo { int operator()(); };
static_assert(is_callable_v<Fo>, "Test is_callable<> with function object");
static_assert(function_traits<Fo>::arg_number == 0, "Test function object");
static_assert(std::is_same<fn_return_t<Fo>, int>::value,
              "Test return type of function object");

struct Fo1 { void operator()(int); };
static_assert(function_traits<Fo1>::arg_number == 1, "Test function object 1");
static_assert(is_callable_v<Fo1>, "Test is_callable<> with function object 1");
static_assert(std::is_same<fn_arg_t<Fo1>, int>(),
              "Test fn_arg_t defaulting to first argument");

#if (!defined(_MSC_VER) || _MSC_VER >= 1910)
static auto l = [] { return 1; };
static_assert(is_callable_v<decltype(l)>, "Test is_callable_v<> with lambda");
static_assert(std::is_same<fn_return_t<decltype(l)>, int>::value,
              "Test fn_return_t<> with lambda");
#endif

template <typename T>
struct fn_object
{
    static int smf(double) { return 0; }
};
template <>
struct fn_object<QString>
{
    void operator()(QString);
};
static_assert(is_callable_v<fn_object<QString>>, "Test function object");
static_assert(returns<void, fn_object<QString>>(),
              "Test returns<> with function object");
static_assert(!is_callable_v<fn_object<int>>, "Test non-function object");
// FIXME: These two don't work
//static_assert(is_callable_v<decltype(&fn_object<int>::smf)>,
//              "Test static member function");
//static_assert(returns<int, decltype(&fn_object<int>::smf)>(),
//              "Test returns<> with static member function");

template <typename T>
QString ft(T&&);
static_assert(std::is_same<fn_arg_t<decltype(ft<QString>)>, QString&&>(),
              "Test function templates");

#ifdef Q_CC_CLANG
#pragma clang diagnostic pop
#endif
<|endoftext|>


<commit_before>/*=========================================================================
 *
 *  Copyright Insight Software Consortium
 *
 *  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.txt
 *
 *  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.
 *
 *=========================================================================*/
#include "itkFloatingPointExceptions.h"
#include "itkMacro.h"
#include <iostream>
#include <float.h>

int
itkFloatingPointExceptionsTest(int argc, char *argv[] )
{
  itk::FloatingPointExceptions::Enable();
  itk::FloatingPointExceptions::
    SetExceptionAction(itk::FloatingPointExceptions::EXIT);
  if(argc < 2)
    {
    std::cout << "No test specified" << std::endl;
    return 1;
    }
  int error_return(0);
  double force_zero_denom(0.0),test1(0.0);
  int force_int_zero(0);
  // this will fool the compiler into not complaining at
  // compile time about divide by zero
  if(argc > 32767)
    {
    force_zero_denom = 1.0;
    test1 = 1.0;
    force_int_zero = 1;
    }

  std::string testName(argv[1]);
  if(testName == "DivByZero")
    {
    std::cout << "Testing floating point divide by zero" << std::endl;
    std::cout.flush();
    try
      {
      double s = 1.0 / force_zero_denom;
      //
      // should never reach here
      std::cout << "Divide by Zero Exception not caught"
                << " result is " << s << std::endl;
      error_return++;
      }
    catch (itk::ExceptionObject &e)
      {
      std::cout << "Expected divide by zero exception caught" << std::endl;
      std::cout << e;
      std::cout.flush();
      }
    }
  if(testName == "ZeroDivByZero")
    {
    std::cout << "Testing floating point zero divided by zero" << std::endl;
    std::cout.flush();
    try
      {
      double s = test1 / force_zero_denom;
      //
      // should never reach here
      std::cout << "Zero divide by Zero Exception not caught"
                << " result is " << s << std::endl;
      error_return++;
      }
    catch (itk::ExceptionObject &e)
      {
      std::cout << "Expected 0.0 / 0.0  exception caught" << std::endl;
      std::cout << e;
      std::cout.flush();
      }
    }
  if(testName == "FPOverFlow")
    {
    std::cout << "Testing floating point overflow" << std::endl;
    std::cout.flush();
    try
      {
      double s = DBL_MAX;
      s = s * s;
      //
      // should never reach here
      std::cout << "Overflow Exception not caught"
                << " result is " << s << std::endl;
      error_return++;
      }
    catch (itk::ExceptionObject &e)
      {
      std::cout << "Overflow exception caught" << std::endl;
      std::cout << e;
      std::cout.flush();
      }
    }
  if(testName == "FPUnderFlow")
    {
    std::cout << "Testing floating point underflow" << std::endl;
    std::cout.flush();
    // not caught as SIGFPE apparently
    try
      {
      double s = DBL_MIN;
      s = s / DBL_MAX;
      //
      // should never reach here
      std::cout << "Underflow Exception not caught"
                << " result is " << s << std::endl;
      error_return++;
      }
    catch (itk::ExceptionObject &e)
      {
      std::cout << "Underflow exception caught" << std::endl;
      std::cout << e;
      }
    }

  if(testName == "IntDivByZero")
    {
    std::cout << "Testing integer divide by zero" << std::endl;
    std::cout.flush();
    try
      {
      int s = 1 / force_int_zero;
      //
      // should never reach here
      std::cout << "Integer divide by zero Exception not caught"
                << " result is " << s << std::endl;
      error_return++;
      }
    catch (itk::ExceptionObject &e)
      {
      std::cout << "Integer divide by zero  exception caught" << std::endl;
      std::cout << e;
      std::cout.flush();
      }
    }
  return error_return;
}
<commit_msg>COMP: disable warning for VS<commit_after>/*=========================================================================
 *
 *  Copyright Insight Software Consortium
 *
 *  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.txt
 *
 *  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.
 *
 *=========================================================================*/
#include "itkFloatingPointExceptions.h"
#include "itkMacro.h"
#include <iostream>
#include <float.h>

/** Disable some common warnings in MS VC++ */
#if defined( _MSC_VER )
#pragma warning ( disable : 4756 )
#endif

int
itkFloatingPointExceptionsTest(int argc, char *argv[] )
{
  itk::FloatingPointExceptions::Enable();
  itk::FloatingPointExceptions::
    SetExceptionAction(itk::FloatingPointExceptions::EXIT);
  if(argc < 2)
    {
    std::cout << "No test specified" << std::endl;
    return 1;
    }
  int error_return(0);
  double force_zero_denom(0.0),test1(0.0);
  int force_int_zero(0);
  // this will fool the compiler into not complaining at
  // compile time about divide by zero
  if(argc > 32767)
    {
    force_zero_denom = 1.0;
    test1 = 1.0;
    force_int_zero = 1;
    }

  std::string testName(argv[1]);
  if(testName == "DivByZero")
    {
    std::cout << "Testing floating point divide by zero" << std::endl;
    std::cout.flush();
    try
      {
      double s = 1.0 / force_zero_denom;
      //
      // should never reach here
      std::cout << "Divide by Zero Exception not caught"
                << " result is " << s << std::endl;
      error_return++;
      }
    catch (itk::ExceptionObject &e)
      {
      std::cout << "Expected divide by zero exception caught" << std::endl;
      std::cout << e;
      std::cout.flush();
      }
    }
  if(testName == "ZeroDivByZero")
    {
    std::cout << "Testing floating point zero divided by zero" << std::endl;
    std::cout.flush();
    try
      {
      double s = test1 / force_zero_denom;
      //
      // should never reach here
      std::cout << "Zero divide by Zero Exception not caught"
                << " result is " << s << std::endl;
      error_return++;
      }
    catch (itk::ExceptionObject &e)
      {
      std::cout << "Expected 0.0 / 0.0  exception caught" << std::endl;
      std::cout << e;
      std::cout.flush();
      }
    }
  if(testName == "FPOverFlow")
    {
    std::cout << "Testing floating point overflow" << std::endl;
    std::cout.flush();
    try
      {
      double s = DBL_MAX;
      s = s * s;
      //
      // should never reach here
      std::cout << "Overflow Exception not caught"
                << " result is " << s << std::endl;
      error_return++;
      }
    catch (itk::ExceptionObject &e)
      {
      std::cout << "Overflow exception caught" << std::endl;
      std::cout << e;
      std::cout.flush();
      }
    }
  if(testName == "FPUnderFlow")
    {
    std::cout << "Testing floating point underflow" << std::endl;
    std::cout.flush();
    // not caught as SIGFPE apparently
    try
      {
      double s = DBL_MIN;
      s = s / DBL_MAX;
      //
      // should never reach here
      std::cout << "Underflow Exception not caught"
                << " result is " << s << std::endl;
      error_return++;
      }
    catch (itk::ExceptionObject &e)
      {
      std::cout << "Underflow exception caught" << std::endl;
      std::cout << e;
      }
    }

  if(testName == "IntDivByZero")
    {
    std::cout << "Testing integer divide by zero" << std::endl;
    std::cout.flush();
    try
      {
      int s = 1 / force_int_zero;
      //
      // should never reach here
      std::cout << "Integer divide by zero Exception not caught"
                << " result is " << s << std::endl;
      error_return++;
      }
    catch (itk::ExceptionObject &e)
      {
      std::cout << "Integer divide by zero  exception caught" << std::endl;
      std::cout << e;
      std::cout.flush();
      }
    }
  return error_return;
}
<|endoftext|>


<commit_before>#include "MoveDummy.h"
#include "ObjectDummy.h"
#include "BodyDummy.h"
#include "ShapeCapsule.h"

#include "Utils.h"
#include "Engine.h"
#include "Physics.h"
#include "Game.h"
#include "World.h"

#define MOVE_DUMMY_IFPS			(1.0f/100.0f)
#define MOVE_DUMMY_CLAMP           89.9f
#define MOVE_DUMMY_COLLISIONS		1

using namespace MathLib;

CMoveDummy::CMoveDummy()		//캯
{
	m_pObject = new CObjectDummy();		//һʵ
	m_pDummy = new CBodyDummy();
	m_pShape = new CShapeCapsule(0.5f, 1.0f);

	SetCollisionMask(1);
	Clear();
}

CMoveDummy::~CMoveDummy()
{
	m_pDummy->SetObject(NULL);
	SAFE_DELETE(m_pObject);
	SAFE_DELETE(m_pDummy);
}

void CMoveDummy::SetCollision(int c)
{
	m_nCollision = c;
}

int CMoveDummy::GetCollision() const
{
	return m_nCollision;
}

void CMoveDummy::SetCollisionMask(int m)
{
	m_pShape->SetCollisionMask(m);
}

int CMoveDummy::GetCollisionMask() const
{
	return m_nCollisionMask;
}

void CMoveDummy::SetGround(int g)
{
	m_nGround = g;
}

<commit_msg>Signed-off-by: mrlitong <litongtongxue@gmail.com><commit_after>#include "MoveDummy.h"
#include "ObjectDummy.h"
#include "BodyDummy.h"
#include "ShapeCapsule.h"

#include "Utils.h"
#include "Engine.h"
#include "Physics.h"
#include "Game.h"
#include "World.h"

#define MOVE_DUMMY_IFPS			(1.0f/100.0f)
#define MOVE_DUMMY_CLAMP           89.9f
#define MOVE_DUMMY_COLLISIONS		1

using namespace MathLib;

CMoveDummy::CMoveDummy()		//캯
{
	m_pObject = new CObjectDummy();		//һʵ
	m_pDummy = new CBodyDummy();
	m_pShape = new CShapeCapsule(0.5f, 1.0f);

	SetCollisionMask(1);
	Clear();
}

CMoveDummy::~CMoveDummy()
{
	m_pDummy->SetObject(NULL);
	SAFE_DELETE(m_pObject);
	SAFE_DELETE(m_pDummy);
}

void CMoveDummy::SetCollision(int c)
{
	m_nCollision = c;
}

int CMoveDummy::GetCollision() const
{
	return m_nCollision;
}

void CMoveDummy::SetCollisionMask(int m)
{
	m_pShape->SetCollisionMask(m);
}

int CMoveDummy::GetCollisionMask() const
{
	return m_nCollisionMask;
}

void CMoveDummy::SetGround(int g)
{
	m_nGround = g;
}

int CMoveDummy::GetGround() const
{
	return m_nGround;
}<|endoftext|>


<commit_before>//
// Copyright (C) 2012
// Alessio Sclocco <a.sclocco@vu.nl>
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program 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 General Public License
// along with this program.  If not, see <http://www.gnu.org/licenses/>.
//

#include <iostream>
using std::cout;
using std::cerr;
using std::endl;
#include <string>
using std::string;
#include <vector>
using std::vector;
#include <exception>
using std::exception;
#include <iomanip>
using std::fixed;
using std::setprecision;
#include <limits>
using std::numeric_limits;
#include <cmath>
#include <ctime>

#include <ArgumentList.hpp>
using isa::utils::ArgumentList;
#include <Observation.hpp>
using AstroData::Observation;
#include <InitializeOpenCL.hpp>
using isa::OpenCL::initializeOpenCL;
#include <CLData.hpp>
using isa::OpenCL::CLData;
#include <utils.hpp>
using isa::utils::same;
#include <Folding.hpp>
using PulsarSearch::Folding;
#include <FoldingCPU.hpp>
using PulsarSearch::folding;
#include <Bins.hpp>
using PulsarSearch::getNrSamplesPerBin;

typedef float dataType;
const string typeName("float");
const unsigned int padding = 32;

// LOFAR
//const unsigned int nrSamplesPerSecond = 200000;
// Apertif
const unsigned int nrSamplesPerSecond = 20000;
// DMs
const unsigned int nrDMs = 256;
// Periods
const unsigned int nrPeriods = 128;
const unsigned int nrBins = 256;
const unsigned int periodStep = 64;

int main(int argc, char *argv[]) {
	unsigned int clPlatformID = 0;
	unsigned int clDeviceID = 0;
	long long unsigned int wrongValues = 0;
	Observation< dataType > observation("FoldingTest", typeName);
	CLData< dataType > * dedispersedData = new CLData< dataType >("DedispersedData", true);
	CLData< dataType > * foldedData = new CLData<dataType >("FoldedData", true);
	CLData< unsigned int > * readCounterData = new CLData< unsigned int >("ReadCounterData", true);
	CLData< unsigned int > * writeCounterData = new CLData< unsigned int >("WriteCounterData", true);
	CLData< unsigned int > * nrSamplesPerBin = new CLData< unsigned int >("NrSamplesPerBin", true);

	try {
		ArgumentList args(argc, argv);

		clPlatformID = args.getSwitchArgument< unsigned int >("-opencl_platform");
		clDeviceID = args.getSwitchArgument< unsigned int >("-opencl_device");

	} catch ( exception &err ) {
		cerr << err.what() << endl;
		return 1;
	}

	// Setup of the observation
	observation.setPadding(padding);
	observation.setNrSamplesPerSecond(nrSamplesPerSecond);
	observation.setNrDMs(nrDMs);
	observation.setNrPeriods(nrPeriods);
	observation.setFirstPeriod(nrBins);
	observation.setPeriodStep(periodStep);
	observation.setNrBins(nrBins);

	cl::Context * clContext = new cl::Context();
	vector< cl::Platform > * clPlatforms = new vector< cl::Platform >();
	vector< cl::Device > * clDevices = new vector< cl::Device >();
	vector< vector< cl::CommandQueue > > * clQueues = new vector< vector < cl::CommandQueue > >();

	initializeOpenCL(clPlatformID, 1, clPlatforms, clContext, clDevices, clQueues);

	// Allocate memory
	dedispersedData->allocateHostData(observation.getNrSamplesPerSecond() * observation.getNrPaddedDMs());
	foldedData->allocateHostData(observation.getNrPaddedDMs() * observation.getNrBins() * observation.getNrPeriods());
	foldedData->blankHostData();
	readCounterData->allocateHostData(observation.getNrPeriods() * 2 * observation.getNrPaddedBins());
	readCounterData->blankHostData();
	writeCounterData->allocateHostData(observation.getNrPeriods() * 2 * observation.getNrPaddedBins());
	writeCounterData->blankHostData();
	vector< unsigned int > * nrSamplesPerBinData = getNrSamplesPerBin(observation);
	nrSamplesPerBin->allocateHostData(*nrSamplesPerBinData);

	dedispersedData->setCLContext(clContext);
	dedispersedData->setCLQueue(&((clQueues->at(clDeviceID)).at(0)));
	foldedData->setCLContext(clContext);
	foldedData->setCLQueue(&((clQueues->at(clDeviceID)).at(0)));
	readCounterData->setCLContext(clContext);
	readCounterData->setCLQueue(&((clQueues->at(clDeviceID)).at(0)));
	writeCounterData->setCLContext(clContext);
	writeCounterData->setCLQueue(&((clQueues->at(clDeviceID)).at(0)));
	nrSamplesPerBin->setCLContext(clContext);
	nrSamplesPerBin->setCLQueue(&((clQueues->at(clDeviceID)).at(0)));
	nrSamplesPerBin->setDeviceReadOnly();

	try {
		dedispersedData->allocateDeviceData();
		foldedData->allocateDeviceData();
		foldedData->copyHostToDevice();
		readCounterData->allocateDeviceData();
		readCounterData->copyHostToDevice();
		writeCounterData->allocateDeviceData();
		writeCounterData->copyHostToDevice();
		nrSamplesPerBin->allocateDeviceData();
		nrSamplesPerBin->copyHostToDevice();
	} catch ( OpenCLError err ) {
		cerr << err.what() << endl;
		return 1;
	}

	srand(time(NULL));
	for ( unsigned int sample = 0; sample < observation.getNrSamplesPerSecond(); sample++ ) {
		for ( unsigned int DM = 0; DM < observation.getNrDMs(); DM++ ) {
			dedispersedData->setHostDataItem((sample * observation.getNrPaddedDMs()) + DM, rand() % 100);
		}
	}

	// Test
	try {
		// Generate kernel
		Folding< dataType > clFold("clFold", typeName);
		clFold.bindOpenCL(clContext, &(clDevices->at(clDeviceID)), &((clQueues->at(clDeviceID)).at(0)));
		clFold.setObservation(&observation);
		clFold.setNrSamplesPerBin(nrSamplesPerBin);
		clFold.setNrDMsPerBlock(128);
		clFold.setNrPeriodsPerBlock(2);
		clFold.setNrBinsPerBlock(1);
		clFold.setNrDMsPerThread(2);
		clFold.setNrPeriodsPerThread(2);
		clFold.setNrBinsPerThread(4);
		clFold.generateCode();

		dedispersedData->copyHostToDevice();
		clFold(0, dedispersedData, foldedData, readCounterData, writeCounterData);
		foldedData->copyDeviceToHost();
	} catch ( OpenCLError err ) {
		cerr << err.what() << endl;
		return 1;
	}

	// Check
	CLData< dataType > * CPUFolded = new CLData<dataType >("CPUFolded", true);
	CLData< unsigned int > * CPUCounter = new CLData< unsigned int >("CPUCounter", true);
	CPUFolded->allocateHostData(observation.getNrBins() * observation.getNrPeriods() * observation.getNrPaddedDMs());
	CPUCounter->allocateHostData(observation.getNrPeriods() * 2 * observation.getNrPaddedBins());
	CPUCounter->blankHostData();
	folding(0, observation, dedispersedData->getHostData(), CPUFolded->getHostData(), CPUCounter->getHostData());
	for ( unsigned int bin = 0; bin < observation.getNrBins(); bin++ ) {
		long long unsigned int wrongValuesBin = 0;

		for ( unsigned int period = 0; period < observation.getNrPeriods(); period++ ) {
			for ( unsigned int DM = 0; DM < observation.getNrDMs(); DM++ ) {
				const unsigned int dataItem = (bin * observation.getNrPeriods() * observation.getNrPaddedDMs()) + (period * observation.getNrPaddedDMs()) + DM;
				if ( !same(CPUFolded->getHostDataItem(dataItem), foldedData->getHostDataItem(dataItem)) ) {
					wrongValues++;
					wrongValuesBin++;
				}
			}
		}

		if ( wrongValuesBin > 0 ) {
			cout << "Wrong samples bin " << bin << ": " << wrongValuesBin << " (" << (wrongValuesBin * 100) / (static_cast< long long unsigned int >(observation.getNrDMs()) * observation.getNrPeriods()) << "%)." << endl;
		}
	}

	cout << endl;
	cout << "Wrong samples: " << wrongValues << " (" << (wrongValues * 100) / (static_cast< long long unsigned int >(observation.getNrDMs()) * observation.getNrPeriods() * observation.getNrBins()) << "%)." << endl;
	cout << endl;

	return 0;
}

<commit_msg>I was allocating too much memory for the counters.<commit_after>//
// Copyright (C) 2012
// Alessio Sclocco <a.sclocco@vu.nl>
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program 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 General Public License
// along with this program.  If not, see <http://www.gnu.org/licenses/>.
//

#include <iostream>
using std::cout;
using std::cerr;
using std::endl;
#include <string>
using std::string;
#include <vector>
using std::vector;
#include <exception>
using std::exception;
#include <iomanip>
using std::fixed;
using std::setprecision;
#include <limits>
using std::numeric_limits;
#include <cmath>
#include <ctime>

#include <ArgumentList.hpp>
using isa::utils::ArgumentList;
#include <Observation.hpp>
using AstroData::Observation;
#include <InitializeOpenCL.hpp>
using isa::OpenCL::initializeOpenCL;
#include <CLData.hpp>
using isa::OpenCL::CLData;
#include <utils.hpp>
using isa::utils::same;
#include <Folding.hpp>
using PulsarSearch::Folding;
#include <FoldingCPU.hpp>
using PulsarSearch::folding;
#include <Bins.hpp>
using PulsarSearch::getNrSamplesPerBin;

typedef float dataType;
const string typeName("float");
const unsigned int padding = 32;

// LOFAR
//const unsigned int nrSamplesPerSecond = 200000;
// Apertif
const unsigned int nrSamplesPerSecond = 20000;
// DMs
const unsigned int nrDMs = 256;
// Periods
const unsigned int nrPeriods = 128;
const unsigned int nrBins = 256;
const unsigned int periodStep = 64;

int main(int argc, char *argv[]) {
	unsigned int clPlatformID = 0;
	unsigned int clDeviceID = 0;
	long long unsigned int wrongValues = 0;
	Observation< dataType > observation("FoldingTest", typeName);
	CLData< dataType > * dedispersedData = new CLData< dataType >("DedispersedData", true);
	CLData< dataType > * foldedData = new CLData<dataType >("FoldedData", true);
	CLData< unsigned int > * readCounterData = new CLData< unsigned int >("ReadCounterData", true);
	CLData< unsigned int > * writeCounterData = new CLData< unsigned int >("WriteCounterData", true);
	CLData< unsigned int > * nrSamplesPerBin = new CLData< unsigned int >("NrSamplesPerBin", true);

	try {
		ArgumentList args(argc, argv);

		clPlatformID = args.getSwitchArgument< unsigned int >("-opencl_platform");
		clDeviceID = args.getSwitchArgument< unsigned int >("-opencl_device");

	} catch ( exception &err ) {
		cerr << err.what() << endl;
		return 1;
	}

	// Setup of the observation
	observation.setPadding(padding);
	observation.setNrSamplesPerSecond(nrSamplesPerSecond);
	observation.setNrDMs(nrDMs);
	observation.setNrPeriods(nrPeriods);
	observation.setFirstPeriod(nrBins);
	observation.setPeriodStep(periodStep);
	observation.setNrBins(nrBins);

	cl::Context * clContext = new cl::Context();
	vector< cl::Platform > * clPlatforms = new vector< cl::Platform >();
	vector< cl::Device > * clDevices = new vector< cl::Device >();
	vector< vector< cl::CommandQueue > > * clQueues = new vector< vector < cl::CommandQueue > >();

	initializeOpenCL(clPlatformID, 1, clPlatforms, clContext, clDevices, clQueues);

	// Allocate memory
	dedispersedData->allocateHostData(observation.getNrSamplesPerSecond() * observation.getNrPaddedDMs());
	foldedData->allocateHostData(observation.getNrPaddedDMs() * observation.getNrBins() * observation.getNrPeriods());
	foldedData->blankHostData();
	readCounterData->allocateHostData(observation.getNrPeriods() * observation.getNrPaddedBins());
	readCounterData->blankHostData();
	writeCounterData->allocateHostData(observation.getNrPeriods() * observation.getNrPaddedBins());
	writeCounterData->blankHostData();
	vector< unsigned int > * nrSamplesPerBinData = getNrSamplesPerBin(observation);
	nrSamplesPerBin->allocateHostData(*nrSamplesPerBinData);

	dedispersedData->setCLContext(clContext);
	dedispersedData->setCLQueue(&((clQueues->at(clDeviceID)).at(0)));
	foldedData->setCLContext(clContext);
	foldedData->setCLQueue(&((clQueues->at(clDeviceID)).at(0)));
	readCounterData->setCLContext(clContext);
	readCounterData->setCLQueue(&((clQueues->at(clDeviceID)).at(0)));
	writeCounterData->setCLContext(clContext);
	writeCounterData->setCLQueue(&((clQueues->at(clDeviceID)).at(0)));
	nrSamplesPerBin->setCLContext(clContext);
	nrSamplesPerBin->setCLQueue(&((clQueues->at(clDeviceID)).at(0)));
	nrSamplesPerBin->setDeviceReadOnly();

	try {
		dedispersedData->allocateDeviceData();
		foldedData->allocateDeviceData();
		foldedData->copyHostToDevice();
		readCounterData->allocateDeviceData();
		readCounterData->copyHostToDevice();
		writeCounterData->allocateDeviceData();
		writeCounterData->copyHostToDevice();
		nrSamplesPerBin->allocateDeviceData();
		nrSamplesPerBin->copyHostToDevice();
	} catch ( OpenCLError err ) {
		cerr << err.what() << endl;
		return 1;
	}

	srand(time(NULL));
	for ( unsigned int sample = 0; sample < observation.getNrSamplesPerSecond(); sample++ ) {
		for ( unsigned int DM = 0; DM < observation.getNrDMs(); DM++ ) {
			dedispersedData->setHostDataItem((sample * observation.getNrPaddedDMs()) + DM, rand() % 100);
		}
	}

	// Test
	try {
		// Generate kernel
		Folding< dataType > clFold("clFold", typeName);
		clFold.bindOpenCL(clContext, &(clDevices->at(clDeviceID)), &((clQueues->at(clDeviceID)).at(0)));
		clFold.setObservation(&observation);
		clFold.setNrSamplesPerBin(nrSamplesPerBin);
		clFold.setNrDMsPerBlock(128);
		clFold.setNrPeriodsPerBlock(2);
		clFold.setNrBinsPerBlock(1);
		clFold.setNrDMsPerThread(2);
		clFold.setNrPeriodsPerThread(2);
		clFold.setNrBinsPerThread(4);
		clFold.generateCode();

		dedispersedData->copyHostToDevice();
		clFold(0, dedispersedData, foldedData, readCounterData, writeCounterData);
		foldedData->copyDeviceToHost();
	} catch ( OpenCLError err ) {
		cerr << err.what() << endl;
		return 1;
	}

	// Check
	CLData< dataType > * CPUFolded = new CLData<dataType >("CPUFolded", true);
	CLData< unsigned int > * CPUCounter = new CLData< unsigned int >("CPUCounter", true);
	CPUFolded->allocateHostData(observation.getNrBins() * observation.getNrPeriods() * observation.getNrPaddedDMs());
	CPUCounter->allocateHostData(observation.getNrPeriods() * observation.getNrPaddedBins());
	CPUCounter->blankHostData();
	folding(0, observation, dedispersedData->getHostData(), CPUFolded->getHostData(), CPUCounter->getHostData());
	for ( unsigned int bin = 0; bin < observation.getNrBins(); bin++ ) {
		long long unsigned int wrongValuesBin = 0;

		for ( unsigned int period = 0; period < observation.getNrPeriods(); period++ ) {
			for ( unsigned int DM = 0; DM < observation.getNrDMs(); DM++ ) {
				const unsigned int dataItem = (bin * observation.getNrPeriods() * observation.getNrPaddedDMs()) + (period * observation.getNrPaddedDMs()) + DM;
				if ( !same(CPUFolded->getHostDataItem(dataItem), foldedData->getHostDataItem(dataItem)) ) {
					wrongValues++;
					wrongValuesBin++;
				}
			}
		}

		if ( wrongValuesBin > 0 ) {
			cout << "Wrong samples bin " << bin << ": " << wrongValuesBin << " (" << (wrongValuesBin * 100) / (static_cast< long long unsigned int >(observation.getNrDMs()) * observation.getNrPeriods()) << "%)." << endl;
		}
	}

	cout << endl;
	cout << "Wrong samples: " << wrongValues << " (" << (wrongValues * 100) / (static_cast< long long unsigned int >(observation.getNrDMs()) * observation.getNrPeriods() * observation.getNrBins()) << "%)." << endl;
	cout << endl;

	return 0;
}

<|endoftext|>


<commit_before>/*
 * Copyright (C) 2012
 * Alessio Sclocco <a.sclocco@vu.nl>
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program 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 General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 *
 */

#include <iostream>
#include <string>
#include <vector>
#include <exception>
#include <fstream>
#include <iomanip>
#include <limits>
#include <cmath>
#include <ctime>
using std::cout;
using std::cerr;
using std::endl;
using std::string;
using std::vector;
using std::exception;
using std::ofstream;
using std::fixed;
using std::setprecision;
using std::numeric_limits;

#include <ArgumentList.hpp>
#include <Observation.hpp>
#include <InitializeOpenCL.hpp>
#include <CLData.hpp>
#include <utils.hpp>
#include <Folding.hpp>
#include <FoldingCPU.hpp>
using isa::utils::ArgumentList;
using isa::utils::same;
using AstroData::Observation;
using isa::OpenCL::initializeOpenCL;
using isa::OpenCL::CLData;
using PulsarSearch::folding;
using PulsarSearch::Folding;

typedef float dataType;
const string typeName("float");
const unsigned int padding = 32;

// Common parameters
const unsigned int nrBeams = 1;
const unsigned int nrStations = 64;
// LOFAR
/*const float minFreq = 138.965f;
const float channelBandwidth = 0.195f;
const unsigned int nrSamplesPerSecond = 200000;
const unsigned int nrChannels = 32;*/
// Apertif
const float minFreq = 1425.0f;
const float channelBandwidth = 0.2929f;
const unsigned int nrSamplesPerSecond = 20000;
const unsigned int nrChannels = 1024;
// DMs
const unsigned int nrDMs = 256;
// Periods
const unsigned int nrPeriods = 128;
const unsigned int nrBins = 256;

int main(int argc, char *argv[]) {
	unsigned int clPlatformID = 0;
	unsigned int clDeviceID = 0;
	long long unsigned int wrongValues = 0;
	Observation< dataType > observation("FoldingTest", typeName);
	CLData< dataType > * dedispersedData = new CLData< dataType >("DedispersedData", true);
	CLData< dataType > * foldedData = new CLData<dataType >("FoldedData", true);
	CLData< unsigned int > * counterData = new CLData< unsigned int >("CounterData", true);

	try {
		ArgumentList args(argc, argv);

		clPlatformID = args.getSwitchArgument< unsigned int >("-opencl_platform");
		clDeviceID = args.getSwitchArgument< unsigned int >("-opencl_device");

	} catch ( exception &err ) {
		cerr << err.what() << endl;
		return 1;
	}

	// Setup of the observation
	observation.setPadding(padding);
	observation.setNrSamplesPerSecond(nrSamplesPerSecond);
	observation.setNrDMs(nrDMs);
	observation.setNrPeriods(nrPeriods);
	observation.setFirstPeriod(nrBins);
	observation.setPeriodStep(nrBins);
	observation.setNrBins(nrBins);

	cl::Context * clContext = new cl::Context();
	vector< cl::Platform > * clPlatforms = new vector< cl::Platform >();
	vector< cl::Device > * clDevices = new vector< cl::Device >();
	vector< vector< cl::CommandQueue > > * clQueues = new vector< vector < cl::CommandQueue > >();

	initializeOpenCL(clPlatformID, 1, clPlatforms, clContext, clDevices, clQueues);

	// Allocate memory
	dedispersedData->allocateHostData(observation.getNrSamplesPerSecond() * observation.getNrPaddedDMs());
	foldedData->allocateHostData(observation.getNrPaddedDMs() * observation.getNrBins() * observation.getNrPeriods());
	foldedData->blankHostData();
	counterData->allocateHostData(observation.getNrPaddedDMs() * observation.getNrBins() * observation.getNrPeriods());
	counterData->blankHostData();

	dedispersedData->setCLContext(clContext);
	dedispersedData->setCLQueue(&((clQueues->at(clDeviceID)).at(0)));
	foldedData->setCLContext(clContext);
	foldedData->setCLQueue(&((clQueues->at(clDeviceID)).at(0)));
	counterData->setCLContext(clContext);
	counterData->setCLQueue(&((clQueues->at(clDeviceID)).at(0)));

	try {
		dedispersedData->allocateDeviceData();
		foldedData->allocateDeviceData();
		foldedData->copyHostToDevice();
		counterData->allocateDeviceData();
		counterData->copyHostToDevice();
	} catch ( OpenCLError err ) {
		cerr << err.what() << endl;
		return 1;
	}

	srand(time(NULL));
	for ( unsigned int sample = 0; sample < observation.getNrSamplesPerSecond(); sample++ ) {
		for ( unsigned int DM = 0; DM < observation.getNrDMs(); DM++ ) {
			dedispersedData->setHostDataItem((sample * observation.getNrPaddedDMs()) + DM, rand() % 100);
		}
	}

	// Test
	try {
		// Generate kernel
		Folding< dataType > clFold("clFold", typeName);
		clFold.bindOpenCL(clContext, &(clDevices->at(clDeviceID)), &((clQueues->at(clDeviceID)).at(0)));
		clFold.setObservation(&observation);
		clFold.setNrDMsPerBlock(128);
		clFold.setNrPeriodsPerBlock(2);
		clFold.setNrBinsPerBlock(1);
		clFold.setNrDMsPerThread(2);
		clFold.setNrPeriodsPerThread(2);
		clFold.setNrBinsPerThread(4);
		clFold.generateCode();

		dedispersedData->copyHostToDevice();
		clFold(dedispersedData, foldedData, counterData);
		foldedData->copyDeviceToHost();
	} catch ( OpenCLError err ) {
		cerr << err.what() << endl;
		return 1;
	}

	// Check
	CLData< dataType > * CPUFolded = new CLData<dataType >("CPUFolded", true);
	CLData< unsigned int > * CPUCounter = new CLData< unsigned int >("CPUCounter", true);
	CPUFolded->allocateHostData(observation.getNrBins() * observation.getNrPeriods() * observation.getNrPaddedDMs());
	CPUCounter->allocateHostData(observation.getNrBins() * observation.getNrPeriods() * observation.getNrPaddedDMs());
	folding(0, observation, dedispersedData->getHostData(), CPUFolded->getHostData(), CPUCounter->getHostData());
	for ( unsigned int bin = 0; bin < observation.getNrBins(); bin++ ) {
		long long unsigned int wrongValuesBin = 0;

		for ( unsigned int period = 0; period < observation.getNrPeriods(); period++ ) {
			for ( unsigned int DM = 0; DM < observation.getNrDMs(); DM++ ) {
				const unsigned int dataItem = (bin * observation.getNrPeriods() * observation.getNrPaddedDMs()) + (period * observation.getNrPaddedDMs()) + DM;
				if ( !same(CPUFolded->getHostDataItem(dataItem), foldedData->getHostDataItem(dataItem)) ) {
					wrongValues++;
					wrongValuesBin++;
				}
			}
		}

		cout << "Wrong samples bin " + bin + ": " << wrongValuesBin << " (" << (wrongValuesBin * 100) / (static_cast< long long unsigned int >(observation.getNrDMs()) * observation.getNrPeriods()) << "%)." << endl;
	}

	cout << endl;
	cout << "Wrong samples: " << wrongValues << " (" << (wrongValues * 100) / (static_cast< long long unsigned int >(observation.getNrDMs()) * observation.getNrPeriods() * observation.getNrBins()) << "%)." << endl;
	cout << endl;

	return 0;
}

<commit_msg>Typo.<commit_after>/*
 * Copyright (C) 2012
 * Alessio Sclocco <a.sclocco@vu.nl>
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program 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 General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 *
 */

#include <iostream>
#include <string>
#include <vector>
#include <exception>
#include <fstream>
#include <iomanip>
#include <limits>
#include <cmath>
#include <ctime>
using std::cout;
using std::cerr;
using std::endl;
using std::string;
using std::vector;
using std::exception;
using std::ofstream;
using std::fixed;
using std::setprecision;
using std::numeric_limits;

#include <ArgumentList.hpp>
#include <Observation.hpp>
#include <InitializeOpenCL.hpp>
#include <CLData.hpp>
#include <utils.hpp>
#include <Folding.hpp>
#include <FoldingCPU.hpp>
using isa::utils::ArgumentList;
using isa::utils::same;
using AstroData::Observation;
using isa::OpenCL::initializeOpenCL;
using isa::OpenCL::CLData;
using PulsarSearch::folding;
using PulsarSearch::Folding;

typedef float dataType;
const string typeName("float");
const unsigned int padding = 32;

// Common parameters
const unsigned int nrBeams = 1;
const unsigned int nrStations = 64;
// LOFAR
/*const float minFreq = 138.965f;
const float channelBandwidth = 0.195f;
const unsigned int nrSamplesPerSecond = 200000;
const unsigned int nrChannels = 32;*/
// Apertif
const float minFreq = 1425.0f;
const float channelBandwidth = 0.2929f;
const unsigned int nrSamplesPerSecond = 20000;
const unsigned int nrChannels = 1024;
// DMs
const unsigned int nrDMs = 256;
// Periods
const unsigned int nrPeriods = 128;
const unsigned int nrBins = 256;

int main(int argc, char *argv[]) {
	unsigned int clPlatformID = 0;
	unsigned int clDeviceID = 0;
	long long unsigned int wrongValues = 0;
	Observation< dataType > observation("FoldingTest", typeName);
	CLData< dataType > * dedispersedData = new CLData< dataType >("DedispersedData", true);
	CLData< dataType > * foldedData = new CLData<dataType >("FoldedData", true);
	CLData< unsigned int > * counterData = new CLData< unsigned int >("CounterData", true);

	try {
		ArgumentList args(argc, argv);

		clPlatformID = args.getSwitchArgument< unsigned int >("-opencl_platform");
		clDeviceID = args.getSwitchArgument< unsigned int >("-opencl_device");

	} catch ( exception &err ) {
		cerr << err.what() << endl;
		return 1;
	}

	// Setup of the observation
	observation.setPadding(padding);
	observation.setNrSamplesPerSecond(nrSamplesPerSecond);
	observation.setNrDMs(nrDMs);
	observation.setNrPeriods(nrPeriods);
	observation.setFirstPeriod(nrBins);
	observation.setPeriodStep(nrBins);
	observation.setNrBins(nrBins);

	cl::Context * clContext = new cl::Context();
	vector< cl::Platform > * clPlatforms = new vector< cl::Platform >();
	vector< cl::Device > * clDevices = new vector< cl::Device >();
	vector< vector< cl::CommandQueue > > * clQueues = new vector< vector < cl::CommandQueue > >();

	initializeOpenCL(clPlatformID, 1, clPlatforms, clContext, clDevices, clQueues);

	// Allocate memory
	dedispersedData->allocateHostData(observation.getNrSamplesPerSecond() * observation.getNrPaddedDMs());
	foldedData->allocateHostData(observation.getNrPaddedDMs() * observation.getNrBins() * observation.getNrPeriods());
	foldedData->blankHostData();
	counterData->allocateHostData(observation.getNrPaddedDMs() * observation.getNrBins() * observation.getNrPeriods());
	counterData->blankHostData();

	dedispersedData->setCLContext(clContext);
	dedispersedData->setCLQueue(&((clQueues->at(clDeviceID)).at(0)));
	foldedData->setCLContext(clContext);
	foldedData->setCLQueue(&((clQueues->at(clDeviceID)).at(0)));
	counterData->setCLContext(clContext);
	counterData->setCLQueue(&((clQueues->at(clDeviceID)).at(0)));

	try {
		dedispersedData->allocateDeviceData();
		foldedData->allocateDeviceData();
		foldedData->copyHostToDevice();
		counterData->allocateDeviceData();
		counterData->copyHostToDevice();
	} catch ( OpenCLError err ) {
		cerr << err.what() << endl;
		return 1;
	}

	srand(time(NULL));
	for ( unsigned int sample = 0; sample < observation.getNrSamplesPerSecond(); sample++ ) {
		for ( unsigned int DM = 0; DM < observation.getNrDMs(); DM++ ) {
			dedispersedData->setHostDataItem((sample * observation.getNrPaddedDMs()) + DM, rand() % 100);
		}
	}

	// Test
	try {
		// Generate kernel
		Folding< dataType > clFold("clFold", typeName);
		clFold.bindOpenCL(clContext, &(clDevices->at(clDeviceID)), &((clQueues->at(clDeviceID)).at(0)));
		clFold.setObservation(&observation);
		clFold.setNrDMsPerBlock(128);
		clFold.setNrPeriodsPerBlock(2);
		clFold.setNrBinsPerBlock(1);
		clFold.setNrDMsPerThread(2);
		clFold.setNrPeriodsPerThread(2);
		clFold.setNrBinsPerThread(4);
		clFold.generateCode();

		dedispersedData->copyHostToDevice();
		clFold(dedispersedData, foldedData, counterData);
		foldedData->copyDeviceToHost();
	} catch ( OpenCLError err ) {
		cerr << err.what() << endl;
		return 1;
	}

	// Check
	CLData< dataType > * CPUFolded = new CLData<dataType >("CPUFolded", true);
	CLData< unsigned int > * CPUCounter = new CLData< unsigned int >("CPUCounter", true);
	CPUFolded->allocateHostData(observation.getNrBins() * observation.getNrPeriods() * observation.getNrPaddedDMs());
	CPUCounter->allocateHostData(observation.getNrBins() * observation.getNrPeriods() * observation.getNrPaddedDMs());
	folding(0, observation, dedispersedData->getHostData(), CPUFolded->getHostData(), CPUCounter->getHostData());
	for ( unsigned int bin = 0; bin < observation.getNrBins(); bin++ ) {
		long long unsigned int wrongValuesBin = 0;

		for ( unsigned int period = 0; period < observation.getNrPeriods(); period++ ) {
			for ( unsigned int DM = 0; DM < observation.getNrDMs(); DM++ ) {
				const unsigned int dataItem = (bin * observation.getNrPeriods() * observation.getNrPaddedDMs()) + (period * observation.getNrPaddedDMs()) + DM;
				if ( !same(CPUFolded->getHostDataItem(dataItem), foldedData->getHostDataItem(dataItem)) ) {
					wrongValues++;
					wrongValuesBin++;
				}
			}
		}

		cout << "Wrong samples bin " << bin << ": " << wrongValuesBin << " (" << (wrongValuesBin * 100) / (static_cast< long long unsigned int >(observation.getNrDMs()) * observation.getNrPeriods()) << "%)." << endl;
	}

	cout << endl;
	cout << "Wrong samples: " << wrongValues << " (" << (wrongValues * 100) / (static_cast< long long unsigned int >(observation.getNrDMs()) * observation.getNrPeriods() * observation.getNrBins()) << "%)." << endl;
	cout << endl;

	return 0;
}

<|endoftext|>


<commit_before>////////////////////////////////////////////////////////////////////////////////
/// DISCLAIMER
///
/// Copyright 2014-2016 ArangoDB GmbH, Cologne, Germany
/// Copyright 2004-2014 triAGENS GmbH, Cologne, Germany
///
/// 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.
///
/// Copyright holder is ArangoDB GmbH, Cologne, Germany
///
/// @author Kaveh Vahedipour
////////////////////////////////////////////////////////////////////////////////

#include "FailedLeader.h"

#include "Agent.h"
#include "Job.h"

using namespace arangodb::consensus;

FailedLeader::FailedLeader(Node const& snapshot, Agent* agent,
                           std::string const& jobId, std::string const& creator,
                           std::string const& agencyPrefix,
                           std::string const& database,
                           std::string const& collection,
                           std::string const& shard, std::string const& from,
                           std::string const& to)
    : Job(snapshot, agent, jobId, creator, agencyPrefix),
      _database(database),
      _collection(collection),
      _shard(shard),
      _from(from),
      _to(to) {
  try {
    JOB_STATUS js = status();

    if (js == TODO) {
      start();
    } else if (js == NOTFOUND) {
      if (create()) {
        start();
      }
    }
  } catch (std::exception const& e) {
    LOG_TOPIC(WARN, Logger::AGENCY) << e.what() << " " << __FILE__ << __LINE__;
    finish("Shards/" + _shard, false, e.what());
  }
}

FailedLeader::~FailedLeader() {}

bool FailedLeader::create() {
  LOG_TOPIC(INFO, Logger::AGENCY)
      << "Todo: failed Leader for " + _shard + " from " + _from + " to " + _to;

  std::string path = _agencyPrefix + toDoPrefix + _jobId;

  _jb = std::make_shared<Builder>();
  _jb->openArray();
  _jb->openObject();

  // Todo entry
  _jb->add(path, VPackValue(VPackValueType::Object));
  _jb->add("creator", VPackValue(_creator));
  _jb->add("type", VPackValue("failedLeader"));
  _jb->add("database", VPackValue(_database));
  _jb->add("collection", VPackValue(_collection));
  _jb->add("shard", VPackValue(_shard));
  _jb->add("fromServer", VPackValue(_from));
  _jb->add("toServer", VPackValue(_to));
  _jb->add("isLeader", VPackValue(true));
  _jb->add("jobId", VPackValue(_jobId));
  _jb->add("timeCreated",
           VPackValue(timepointToString(std::chrono::system_clock::now())));
  _jb->close();

  // Add shard to /arango/Target/FailedServers/<server> array
  path = _agencyPrefix + failedServersPrefix + "/" + _from;
  _jb->add(path, VPackValue(VPackValueType::Object));
  _jb->add("op", VPackValue("push"));
  _jb->add("new", VPackValue(_shard));
  _jb->close();

  _jb->close();
  _jb->close();

  write_ret_t res = transact(_agent, *_jb);

  if (res.accepted && res.indices.size() == 1 && res.indices[0]) {
    return true;
  }

  LOG_TOPIC(INFO, Logger::AGENCY) << "Failed to insert job " + _jobId;
  return false;
}

bool FailedLeader::start() {
  // DBservers
  std::string planPath =
      planColPrefix + _database + "/" + _collection + "/shards/" + _shard;
  std::string curPath =
      curColPrefix + _database + "/" + _collection + "/" + _shard + "/servers";

  Node const& current = _snapshot(curPath);

  if (current.slice().length() == 1) {
    LOG_TOPIC(ERR, Logger::AGENCY) << "Failed to change leadership for shard " +
                                          _shard + " from " + _from + " to " +
                                          _to + ". No in-sync followers:" +
                                          current.slice().toJson();
    return false;
  }

  // Copy todo to pending
  Builder todo, pending;

  // Get todo entry
  todo.openArray();
  if (_jb == nullptr) {
    try {
      _snapshot(toDoPrefix + _jobId).toBuilder(todo);
    } catch (std::exception const&) {
      LOG_TOPIC(INFO, Logger::AGENCY) << "Failed to get key " + toDoPrefix +
                                             _jobId + " from agency snapshot";
      return false;
    }
  } else {
    todo.add(_jb->slice().get(_agencyPrefix + toDoPrefix + _jobId).valueAt(0));
  }
  todo.close();

  // Transaction
  pending.openArray();

  // Apply
  // --- Add pending entry
  pending.openObject();
  pending.add(_agencyPrefix + pendingPrefix + _jobId,
              VPackValue(VPackValueType::Object));
  pending.add("timeStarted",
              VPackValue(timepointToString(std::chrono::system_clock::now())));
  for (auto const& obj : VPackObjectIterator(todo.slice()[0])) {
    pending.add(obj.key.copyString(), obj.value);
  }
  pending.close();

  // --- Remove todo entry
  pending.add(_agencyPrefix + toDoPrefix + _jobId,
              VPackValue(VPackValueType::Object));
  pending.add("op", VPackValue("delete"));
  pending.close();

  // --- Cyclic shift in sync servers
  pending.add(_agencyPrefix + planPath, VPackValue(VPackValueType::Array));
  for (size_t i = 1; i < current.slice().length(); ++i) {
    pending.add(current.slice()[i]);
  }
  pending.add(current.slice()[0]);
  pending.close();

  // --- Block shard
  pending.add(_agencyPrefix + blockedShardsPrefix + _shard,
              VPackValue(VPackValueType::Object));
  pending.add("jobId", VPackValue(_jobId));
  pending.close();

  // --- Increment Plan/Version
  pending.add(_agencyPrefix + planVersion, VPackValue(VPackValueType::Object));
  pending.add("op", VPackValue("increment"));
  pending.close();

  pending.close();

  // Precondition
  // --- Check that Current servers are as we expect
  pending.openObject();
  pending.add(_agencyPrefix + curPath, VPackValue(VPackValueType::Object));
  pending.add("old", current.slice());
  pending.close();

  // --- Check if shard is not blocked
  pending.add(_agencyPrefix + blockedShardsPrefix + _shard,
              VPackValue(VPackValueType::Object));
  pending.add("oldEmpty", VPackValue(true));
  pending.close();

  pending.close();
  pending.close();

  // Transact
  write_ret_t res = transact(_agent, pending);

  if (res.accepted && res.indices.size() == 1 && res.indices[0]) {
    LOG_TOPIC(INFO, Logger::AGENCY) << "Pending: Change leadership " + _shard +
                                           " from " + _from + " to " + _to;
    return true;
  }

  LOG_TOPIC(INFO, Logger::AGENCY)
      << "Precondition failed for starting job " + _jobId;
  return false;
}

JOB_STATUS FailedLeader::status() {
  auto status = exists();

  if (status != NOTFOUND) {  // Get job details from agency

    try {
      _database = _snapshot(pos[status] + _jobId + "/database").getString();
      _collection = _snapshot(pos[status] + _jobId + "/collection").getString();
      _from = _snapshot(pos[status] + _jobId + "/fromServer").getString();
      _to = _snapshot(pos[status] + _jobId + "/toServer").getString();
      _shard = _snapshot(pos[status] + _jobId + "/shard").getString();
    } catch (std::exception const& e) {
      std::stringstream err;
      err << "Failed to find job " << _jobId << " in agency: " << e.what();
      LOG_TOPIC(ERR, Logger::AGENCY) << err.str();
      finish("Shards/" + _shard, false, err.str());
      return FAILED;
    }
  }

  if (status == PENDING) {
    Node const& job = _snapshot(pendingPrefix + _jobId);
    std::string database = job("database").toJson(),
                collection = job("collection").toJson(),
                shard = job("shard").toJson();

    std::string planPath = planColPrefix + database + "/" + collection +
                           "/shards/" + shard,
                curPath = curColPrefix + database + "/" + collection + "/" +
                          shard + "/servers";

    Node const& planned = _snapshot(planPath);
    Node const& current = _snapshot(curPath);

    if (planned.slice()[0] == current.slice()[0]) {

      // Remove shard to /arango/Target/FailedServers/<server> array
      Builder del;
      del.openArray();
      del.openObject();
      std::string path = _agencyPrefix + failedServersPrefix + "/" + _from;
      del.add(path, VPackValue(VPackValueType::Object));
      del.add("op", VPackValue("erase"));
      del.add("val", VPackValue(_shard));
      del.close();
      del.close();
      del.close();
      write_ret_t res = transact(_agent, del);

      if (finish("Shards/" + shard)) {
        return FINISHED;
      }
    }
  }

  return status;
}
<commit_msg>FailedServer jobs can report when last FailedLeader has been processed<commit_after>////////////////////////////////////////////////////////////////////////////////
/// DISCLAIMER
///
/// Copyright 2014-2016 ArangoDB GmbH, Cologne, Germany
/// Copyright 2004-2014 triAGENS GmbH, Cologne, Germany
///
/// 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.
///
/// Copyright holder is ArangoDB GmbH, Cologne, Germany
///
/// @author Kaveh Vahedipour
////////////////////////////////////////////////////////////////////////////////

#include "FailedLeader.h"

#include "Agent.h"
#include "Job.h"

using namespace arangodb::consensus;

FailedLeader::FailedLeader(Node const& snapshot, Agent* agent,
                           std::string const& jobId, std::string const& creator,
                           std::string const& agencyPrefix,
                           std::string const& database,
                           std::string const& collection,
                           std::string const& shard, std::string const& from,
                           std::string const& to)
    : Job(snapshot, agent, jobId, creator, agencyPrefix),
      _database(database),
      _collection(collection),
      _shard(shard),
      _from(from),
      _to(to) {
  try {
    JOB_STATUS js = status();

    if (js == TODO) {
      start();
    } else if (js == NOTFOUND) {
      if (create()) {
        start();
      }
    }
  } catch (std::exception const& e) {
    LOG_TOPIC(DEBUG, Logger::AGENCY) << e.what() << " " << __FILE__ << __LINE__;
    finish("Shards/" + _shard, false, e.what());
  }
}

FailedLeader::~FailedLeader() {}

bool FailedLeader::create() {
  LOG_TOPIC(INFO, Logger::AGENCY)
      << "Todo: failed Leader for " + _shard + " from " + _from + " to " + _to;

  std::string path = _agencyPrefix + toDoPrefix + _jobId;

  _jb = std::make_shared<Builder>();
  _jb->openArray();
  _jb->openObject();

  // Todo entry
  _jb->add(path, VPackValue(VPackValueType::Object));
  _jb->add("creator", VPackValue(_creator));
  _jb->add("type", VPackValue("failedLeader"));
  _jb->add("database", VPackValue(_database));
  _jb->add("collection", VPackValue(_collection));
  _jb->add("shard", VPackValue(_shard));
  _jb->add("fromServer", VPackValue(_from));
  _jb->add("toServer", VPackValue(_to));
  _jb->add("isLeader", VPackValue(true));
  _jb->add("jobId", VPackValue(_jobId));
  _jb->add("timeCreated",
           VPackValue(timepointToString(std::chrono::system_clock::now())));
  _jb->close();

  // Add shard to /arango/Target/FailedServers/<server> array
  path = _agencyPrefix + failedServersPrefix + "/" + _from;
  _jb->add(path, VPackValue(VPackValueType::Object));
  _jb->add("op", VPackValue("push"));
  _jb->add("new", VPackValue(_shard));
  _jb->close();

  _jb->close();
  _jb->close();

  write_ret_t res = transact(_agent, *_jb);

  if (res.accepted && res.indices.size() == 1 && res.indices[0]) {
    return true;
  }

  LOG_TOPIC(INFO, Logger::AGENCY) << "Failed to insert job " + _jobId;
  return false;
}

bool FailedLeader::start() {
  // DBservers
  std::string planPath =
      planColPrefix + _database + "/" + _collection + "/shards/" + _shard;
  std::string curPath =
      curColPrefix + _database + "/" + _collection + "/" + _shard + "/servers";

  Node const& current = _snapshot(curPath);

  if (current.slice().length() == 1) {
    LOG_TOPIC(ERR, Logger::AGENCY) << "Failed to change leadership for shard " +
                                          _shard + " from " + _from + " to " +
                                          _to + ". No in-sync followers:" +
                                          current.slice().toJson();
    return false;
  }

  // Copy todo to pending
  Builder todo, pending;

  // Get todo entry
  todo.openArray();
  if (_jb == nullptr) {
    try {
      _snapshot(toDoPrefix + _jobId).toBuilder(todo);
    } catch (std::exception const&) {
      LOG_TOPIC(INFO, Logger::AGENCY) << "Failed to get key " + toDoPrefix +
                                             _jobId + " from agency snapshot";
      return false;
    }
  } else {
    todo.add(_jb->slice().get(_agencyPrefix + toDoPrefix + _jobId).valueAt(0));
  }
  todo.close();

  // Transaction
  pending.openArray();

  // Apply
  // --- Add pending entry
  pending.openObject();
  pending.add(_agencyPrefix + pendingPrefix + _jobId,
              VPackValue(VPackValueType::Object));
  pending.add("timeStarted",
              VPackValue(timepointToString(std::chrono::system_clock::now())));
  for (auto const& obj : VPackObjectIterator(todo.slice()[0])) {
    pending.add(obj.key.copyString(), obj.value);
  }
  pending.close();

  // --- Remove todo entry
  pending.add(_agencyPrefix + toDoPrefix + _jobId,
              VPackValue(VPackValueType::Object));
  pending.add("op", VPackValue("delete"));
  pending.close();

  // --- Cyclic shift in sync servers
  pending.add(_agencyPrefix + planPath, VPackValue(VPackValueType::Array));
  for (size_t i = 1; i < current.slice().length(); ++i) {
    pending.add(current.slice()[i]);
  }
  pending.add(current.slice()[0]);
  pending.close();

  // --- Block shard
  pending.add(_agencyPrefix + blockedShardsPrefix + _shard,
              VPackValue(VPackValueType::Object));
  pending.add("jobId", VPackValue(_jobId));
  pending.close();

  // --- Increment Plan/Version
  pending.add(_agencyPrefix + planVersion, VPackValue(VPackValueType::Object));
  pending.add("op", VPackValue("increment"));
  pending.close();

  pending.close();

  // Precondition
  // --- Check that Current servers are as we expect
  pending.openObject();
  pending.add(_agencyPrefix + curPath, VPackValue(VPackValueType::Object));
  pending.add("old", current.slice());
  pending.close();

  // --- Check if shard is not blocked
  pending.add(_agencyPrefix + blockedShardsPrefix + _shard,
              VPackValue(VPackValueType::Object));
  pending.add("oldEmpty", VPackValue(true));
  pending.close();

  pending.close();
  pending.close();

  // Transact
  write_ret_t res = transact(_agent, pending);

  if (res.accepted && res.indices.size() == 1 && res.indices[0]) {
    LOG_TOPIC(INFO, Logger::AGENCY) << "Pending: Change leadership " + _shard +
                                           " from " + _from + " to " + _to;
    return true;
  }

  LOG_TOPIC(INFO, Logger::AGENCY)
      << "Precondition failed for starting job " + _jobId;
  return false;
}

JOB_STATUS FailedLeader::status() {
  auto status = exists();

  if (status != NOTFOUND) {  // Get job details from agency

    try {
      _database = _snapshot(pos[status] + _jobId + "/database").getString();
      _collection = _snapshot(pos[status] + _jobId + "/collection").getString();
      _from = _snapshot(pos[status] + _jobId + "/fromServer").getString();
      _to = _snapshot(pos[status] + _jobId + "/toServer").getString();
      _shard = _snapshot(pos[status] + _jobId + "/shard").getString();
    } catch (std::exception const& e) {
      std::stringstream err;
      err << "Failed to find job " << _jobId << " in agency: " << e.what();
      LOG_TOPIC(ERR, Logger::AGENCY) << err.str();
      finish("Shards/" + _shard, false, err.str());
      return FAILED;
    }
  }

  if (status == PENDING) {
    Node const& job = _snapshot(pendingPrefix + _jobId);
    std::string database = job("database").toJson(),
                collection = job("collection").toJson(),
                shard = job("shard").toJson();

    std::string planPath = planColPrefix + database + "/" + collection +
                           "/shards/" + shard,
                curPath = curColPrefix + database + "/" + collection + "/" +
                          shard + "/servers";

    Node const& planned = _snapshot(planPath);
    Node const& current = _snapshot(curPath);

    if (planned.slice()[0] == current.slice()[0]) {

      // Remove shard to /arango/Target/FailedServers/<server> array
      Builder del;
      del.openArray();
      del.openObject();
      std::string path = _agencyPrefix + failedServersPrefix + "/" + _from;
      del.add(path, VPackValue(VPackValueType::Object));
      del.add("op", VPackValue("erase"));
      del.add("val", VPackValue(_shard));
      del.close();
      del.close();
      del.close();
      write_ret_t res = transact(_agent, del);

      if (finish("Shards/" + shard)) {
        return FINISHED;
      }
    }
  }

  return status;
}
<|endoftext|>


<commit_before>/*
-----------------------------------------------------------------------------
This source file is part of OGRE
    (Object-oriented Graphics Rendering Engine)
For the latest info, see http://www.ogre3d.org

Copyright (c) 2000-2009 Torus Knot Software Ltd

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
-----------------------------------------------------------------------------
*/

#include "OgreGLSLESExtSupport.h"
#include "OgreLogManager.h"

namespace Ogre
{
    //-----------------------------------------------------------------------------
	String logObjectInfo(const String& msg, const GLuint obj)
	{
		String logMessage = msg;

		if (obj > 0)
		{
			GLint infologLength = 0;

            if(glIsShader(obj))
            {
                glGetShaderiv(obj, GL_INFO_LOG_LENGTH, &infologLength);
                GL_CHECK_ERROR
            }
            else if(glIsProgram(obj))
            {
                glGetProgramiv(obj, GL_INFO_LOG_LENGTH, &infologLength);
                GL_CHECK_ERROR
            }

			if (infologLength > 0)
			{
				GLint charsWritten  = 0;

				//GLchar * infoLog = OGRE_NEW GLchar[infologLength];
				char * infoLog = new char [infologLength];
				infoLog[0] = 0;

                if(glIsShader(obj))
                {
                    glGetShaderInfoLog(obj, infologLength, &charsWritten, infoLog);
                    GL_CHECK_ERROR
                }
                else if(glIsProgram(obj))
                {
                    glGetProgramInfoLog(obj, infologLength, &charsWritten, infoLog);
                    GL_CHECK_ERROR
                }
				if (strlen(infoLog) > 0)
				{
					logMessage += "\n" + String(infoLog);
				}

                LogManager::getSingleton().logMessage(logMessage);

				OGRE_DELETE [] infoLog;
			}
		}

		return logMessage;
	}

} // namespace Ogre
<commit_msg>GLES2 render system: removed end of line chars from the compile result to log function -  - so there will be less empty lines in the log.<commit_after>/*
-----------------------------------------------------------------------------
This source file is part of OGRE
    (Object-oriented Graphics Rendering Engine)
For the latest info, see http://www.ogre3d.org

Copyright (c) 2000-2009 Torus Knot Software Ltd

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
-----------------------------------------------------------------------------
*/

#include "OgreGLSLESExtSupport.h"
#include "OgreLogManager.h"

namespace Ogre
{
    //-----------------------------------------------------------------------------
	String logObjectInfo(const String& msg, const GLuint obj)
	{
		String logMessage = msg;

		if (obj > 0)
		{
			GLint infologLength = 0;

            if(glIsShader(obj))
            {
                glGetShaderiv(obj, GL_INFO_LOG_LENGTH, &infologLength);
                GL_CHECK_ERROR
            }
            else if(glIsProgram(obj))
            {
                glGetProgramiv(obj, GL_INFO_LOG_LENGTH, &infologLength);
                GL_CHECK_ERROR
            }

			if (infologLength > 1)
			{
				GLint charsWritten  = 0;

				//GLchar * infoLog = OGRE_NEW GLchar[infologLength];
				char * infoLog = new char [infologLength];
				infoLog[0] = 0;

                if(glIsShader(obj))
                {
                    glGetShaderInfoLog(obj, infologLength, &charsWritten, infoLog);
                    GL_CHECK_ERROR
                }
                else if(glIsProgram(obj))
                {
                    glGetProgramInfoLog(obj, infologLength, &charsWritten, infoLog);
                    GL_CHECK_ERROR
                }
				if (strlen(infoLog) > 0)
				{
					logMessage += "\n" + String(infoLog);
				}

				OGRE_DELETE [] infoLog;

				if (logMessage.size() > 0)
				{
					// remove ends of line in the end - so there will be no empty lines in the log.
					while( logMessage[logMessage.size() - 1] == '\n' )
					{
						logMessage.erase(logMessage.size() - 1, 1);
					}
					LogManager::getSingleton().logMessage(logMessage);
				}
			}
		}

		return logMessage;
	}

} // namespace Ogre
<|endoftext|>