<commit_before>/**
 * Copyright (c) 2015, Jozef Stefan Institute, Quintelligence d.o.o. and contributors
 * All rights reserved.
 *
 * This source code is licensed under the FreeBSD license found in the
 * LICENSE file in the root directory of this source tree.
 */

//////////////////////////////////////////////////////////////////////////
// Kernel utilities
void TKernelUtil::CalcKernelMatrix(PSVMTrainSet Set, TFltVV& K) {
    const int Size = Set->Len(); K.Gen(Size, Size);
    for (int i = 0; i < Size; i++) {
        for (int j = i; j < Size; j++)
            K(i,j) = K(j,i) = Set->DotProduct(i,j);
    }
}

void TKernelUtil::CenterKernelMatrix(TFltVV& K) {
    IAssert(K.GetXDim() == K.GetYDim());
    const int l = K.GetYDim();

    TFltV jK(l);   // j'K
    double jKj = 0.0; // j'Kj
    for (int j = 0; j < l; j++) {
        jK[j] = 0.0;
        for (int i = 0; i < l; i++)
            jK[j] += K(i,j);
        jKj += jK[j];
    }

    double invl = 1.0/l;
    for (int i = 0; i < l; i++) {
        for (int j = 0; j < l; j++)
            K(i,j) = K(i,j) - invl*jK[j] - invl*jK[i] + invl*invl*jKj;
    }
}

//////////////////////////////////////////////////////////////////////////
// Partial-Gram-Schmidt
TPartialGS::TPartialGS(PSVMTrainSet BigSet, const int& Dim, const double& Eps) {
    IAssert(Dim <= BigSet->Len() && 0.0 <= Eps && Eps < 1.0);
    int Len = BigSet->Len();

    TVec<TKeyDat<TFlt, TBool> > NiV(Len);
    for (int i = 0; i < Len; i++) {
        //NiV[i].Key = BigSet->DotProduct(i, i);
        NiV[i].Key = BigSet->GetNorm2(i);
        NiV[i].Dat = false;
        /*IAssertR(NiV[i].Key.Val > 0.0 && _isnan(NiV[i].Key.Val) == 0,
                 TInt::GetStr(i) + TStr(":") + TFlt::GetStr(NiV[i].Key));*/
    }
    R.Gen(Dim, 0);
    //for (i = 0; i < Dim; i++) R[i].Gen(Len-i);
    IdV.Gen(Len);
    for (int i = 0; i < Len; i++) IdV[i] = i;

    TFltV BlufV(Dim, 0); int max = -1;
    for (int j = 0; j < Dim; j++) {
        // find element with bigest residual norm
        max = -1;
        for (int t = 0, l = Len; t < l; t++)
            if (!NiV[t].Dat && (max == -1 || NiV[t].Key > NiV[max].Key)) max = t;

        // if max residual norm is reached
        if (NiV[max].Key.Val < Eps) break;
        //printf("(%.2f)", NiV[max].Key.Val);

        // permute j-th and max-th column of R
        NiV[max].Dat = true;
        int mid = IdV.SearchForw(max, j);
        { int tmp = IdV[j]; IdV[j] = max; IdV[mid] = tmp; }
        for (int t = 0; t < j; t++) {
            double tmp = R[t][j-t];
            R[t][j-t] = R[t][mid-t];
            R[t][mid-t] = tmp;
        }

        // calculate j-th row of R and update NiV (residual norms)
        if (-0.001 < NiV[max].Key.Val && NiV[max].Key.Val < 0) NiV[max].Key.Val = 0.0;
        IAssertR(NiV[max].Key.Val >= 0.0, TInt::GetStr(j) + TStr(":") + TFlt::GetStr(NiV[max].Key.Val));
        IAssert(R.Len() == j);
        R.Add(TFltV()); R[j].Gen(Len-j); // NEW
        R[j][0] = sqrt(NiV[max].Key.Val);
        BlufV.Add(NiV[IdV[j]].Key.Val);
        for (int i = j+1; i < Len; i++) {
            double RR = BigSet->DotProduct(IdV[i], IdV[j]);
            for (int t = 0; t < j; t++)
                RR -= R[t][j-t] * R[t][i-t];
            IAssertR(NiV[IdV[j]].Key.Val>0, TInt::GetStr(i));
            RR /= sqrt(NiV[IdV[j]].Key.Val);
            //IAssertR(_isnan(RR) == 0, TInt::GetStr(IdV[j]) + TStr(":") + TFlt::GetStr(NiV[IdV[j]].Key.Val));
            R[j][i-j] = RR;
            NiV[IdV[i]].Key -= RR*RR;
        }
    }

    if (max == -1) max = 0;
    printf("stoped at %d/%d with residual norm %.3f\n", R.Len(), BigSet->Len(), NiV[max].Key.Val);

    NormV.Gen(Len);
    VecNormV.Gen(Len);
    for (int i = 0; i < Len; i++) {
        NormV[i] = NiV[IdV[i]].Key;
        VecNormV[i] = GetKernel(i,i);
    }
}

double TPartialGS::GetKernel(const int& VecId1, const int& VecId2) {
    double Result = 0.0;

    int Id1 = IdV.SearchForw(VecId1), Id2 = IdV.SearchForw(VecId2);
    int l = TInt::GetMn(R.Len()-1, Id1, Id2);
    for (int i = 0; i <= l; i++) {
        Result += R[i][Id1 - i] * R[i][Id2 - i];
    }

    return Result;
}

void TPartialGS::GetDocVV(TFltVV& DocVV) {
    IAssert(R.Len() > 0);
    const int DocN = R[0].Len();
    const int DimN = R.Len();
    DocVV.Gen(DimN, DocN);

    for (int DocC = 0; DocC < DocN; DocC++) {
        const int DId = IdV[DocC];
        int l = TInt::GetMn(DocC, DimN-1);
        for (int i = 0; i <= l; i++)
            DocVV(i,DId) = R[i][DocC - i];
        for (int i = l+1; i < DimN; i++)
            DocVV(i,DId) = 0.0;
    }
}

void TPartialGS::GetBasisV(TVec<TFltV>& q) {
    const int l = R.Len();

    q.Gen(l);
    for (int i = 0; i < l; i++) {
        q[i].Gen(l);
        q[i].PutAll(0.0);
    }

    for (int n = 0; n < l; n++) {
        double Rnn = R[n][0];
        for (int j = 0; j < n; j++) {
            TLinAlg::AddVec(-R[j][n-j]/Rnn, q[j], q[n], q[n]);
        }
        q[n][n] = 1/Rnn;
    }
}

double TPartialGS::DotProdoctWithCol(const int& ColId, const TFltV& w) {
    Assert(w.Len() == R.Len());
    int l = TInt::GetMn(ColId, R.Len()-1);
    double Result = 0.0;
    for (int i = 0; i <= l; i++)
        Result += R[i][ColId - i] * w[i];
    return Result;
}

void TPartialGS::Dump(const TStr& FName) {
    PSOut out = TFOut::New(FName);
    for (int i = 0; i < R.Len(); i++) {
        for (int j = 0; j < i; j++) {
            out->PutStr(TFlt::GetStr(0.0, 20, 18)); out->PutCh(' '); }
        for (int j = 0; j < R[i].Len(); j++) {
            out->PutStr(TFlt::GetStr(R[i][j], 20, 18)); out->PutCh(' '); }
        out->PutCh('\n');
    }
}
<commit_msg>tdigest namespace fix<commit_after>/**
 * Copyright (c) 2015, Jozef Stefan Institute, Quintelligence d.o.o. and contributors
 * All rights reserved.
 *
 * This source code is licensed under the FreeBSD license found in the
 * LICENSE file in the root directory of this source tree.
 */

//////////////////////////////////////////////////////////////////////////
// Kernel utilities
void TKernelUtil::CalcKernelMatrix(PSVMTrainSet Set, TFltVV& K) {
    const int Size = Set->Len(); K.Gen(Size, Size);
    for (int i = 0; i < Size; i++) {
        for (int j = i; j < Size; j++)
            K(i,j) = K(j,i) = Set->DotProduct(i,j);
    }
}

void TKernelUtil::CenterKernelMatrix(TFltVV& K) {
    IAssert(K.GetXDim() == K.GetYDim());
    const int l = K.GetYDim();

    TFltV jK(l);   // j'K
    double jKj = 0.0; // j'Kj
    for (int j = 0; j < l; j++) {
        jK[j] = 0.0;
        for (int i = 0; i < l; i++)
            jK[j] += K(i,j);
        jKj += jK[j];
    }

    double invl = 1.0/l;
    for (int i = 0; i < l; i++) {
        for (int j = 0; j < l; j++)
            K(i,j) = K(i,j) - invl*jK[j] - invl*jK[i] + invl*invl*jKj;
    }
}

//////////////////////////////////////////////////////////////////////////
// Partial-Gram-Schmidt
TPartialGS::TPartialGS(PSVMTrainSet BigSet, const int& Dim, const double& Eps) {
    IAssert(Dim <= BigSet->Len() && 0.0 <= Eps && Eps < 1.0);
    int Len = BigSet->Len();

    TVec<TKeyDat<TFlt, TBool> > NiV(Len);
    for (int i = 0; i < Len; i++) {
        //NiV[i].Key = BigSet->DotProduct(i, i);
        NiV[i].Key = BigSet->GetNorm2(i);
        NiV[i].Dat = false;
        IAssertR(NiV[i].Key.Val > 0.0 && _isnan(NiV[i].Key.Val) == 0,
                 TInt::GetStr(i) + TStr(":") + TFlt::GetStr(NiV[i].Key));
    }
    R.Gen(Dim, 0);
    //for (i = 0; i < Dim; i++) R[i].Gen(Len-i);
    IdV.Gen(Len);
    for (int i = 0; i < Len; i++) IdV[i] = i;

    TFltV BlufV(Dim, 0); int max = -1;
    for (int j = 0; j < Dim; j++) {
        // find element with bigest residual norm
        max = -1;
        for (int t = 0, l = Len; t < l; t++)
            if (!NiV[t].Dat && (max == -1 || NiV[t].Key > NiV[max].Key)) max = t;

        // if max residual norm is reached
        if (NiV[max].Key.Val < Eps) break;
        //printf("(%.2f)", NiV[max].Key.Val);

        // permute j-th and max-th column of R
        NiV[max].Dat = true;
        int mid = IdV.SearchForw(max, j);
        { int tmp = IdV[j]; IdV[j] = max; IdV[mid] = tmp; }
        for (int t = 0; t < j; t++) {
            double tmp = R[t][j-t];
            R[t][j-t] = R[t][mid-t];
            R[t][mid-t] = tmp;
        }

        // calculate j-th row of R and update NiV (residual norms)
        if (-0.001 < NiV[max].Key.Val && NiV[max].Key.Val < 0) NiV[max].Key.Val = 0.0;
        IAssertR(NiV[max].Key.Val >= 0.0, TInt::GetStr(j) + TStr(":") + TFlt::GetStr(NiV[max].Key.Val));
        IAssert(R.Len() == j);
        R.Add(TFltV()); R[j].Gen(Len-j); // NEW
        R[j][0] = sqrt(NiV[max].Key.Val);
        BlufV.Add(NiV[IdV[j]].Key.Val);
        for (int i = j+1; i < Len; i++) {
            double RR = BigSet->DotProduct(IdV[i], IdV[j]);
            for (int t = 0; t < j; t++)
                RR -= R[t][j-t] * R[t][i-t];
            IAssertR(NiV[IdV[j]].Key.Val>0, TInt::GetStr(i));
            RR /= sqrt(NiV[IdV[j]].Key.Val);
            IAssertR(_isnan(RR) == 0, TInt::GetStr(IdV[j]) + TStr(":") + TFlt::GetStr(NiV[IdV[j]].Key.Val));
            R[j][i-j] = RR;
            NiV[IdV[i]].Key -= RR*RR;
        }
    }

    if (max == -1) max = 0;
    printf("stoped at %d/%d with residual norm %.3f\n", R.Len(), BigSet->Len(), NiV[max].Key.Val);

    NormV.Gen(Len);
    VecNormV.Gen(Len);
    for (int i = 0; i < Len; i++) {
        NormV[i] = NiV[IdV[i]].Key;
        VecNormV[i] = GetKernel(i,i);
    }
}

double TPartialGS::GetKernel(const int& VecId1, const int& VecId2) {
    double Result = 0.0;

    int Id1 = IdV.SearchForw(VecId1), Id2 = IdV.SearchForw(VecId2);
    int l = TInt::GetMn(R.Len()-1, Id1, Id2);
    for (int i = 0; i <= l; i++) {
        Result += R[i][Id1 - i] * R[i][Id2 - i];
    }

    return Result;
}

void TPartialGS::GetDocVV(TFltVV& DocVV) {
    IAssert(R.Len() > 0);
    const int DocN = R[0].Len();
    const int DimN = R.Len();
    DocVV.Gen(DimN, DocN);

    for (int DocC = 0; DocC < DocN; DocC++) {
        const int DId = IdV[DocC];
        int l = TInt::GetMn(DocC, DimN-1);
        for (int i = 0; i <= l; i++)
            DocVV(i,DId) = R[i][DocC - i];
        for (int i = l+1; i < DimN; i++)
            DocVV(i,DId) = 0.0;
    }
}

void TPartialGS::GetBasisV(TVec<TFltV>& q) {
    const int l = R.Len();

    q.Gen(l);
    for (int i = 0; i < l; i++) {
        q[i].Gen(l);
        q[i].PutAll(0.0);
    }

    for (int n = 0; n < l; n++) {
        double Rnn = R[n][0];
        for (int j = 0; j < n; j++) {
            TLinAlg::AddVec(-R[j][n-j]/Rnn, q[j], q[n], q[n]);
        }
        q[n][n] = 1/Rnn;
    }
}

double TPartialGS::DotProdoctWithCol(const int& ColId, const TFltV& w) {
    Assert(w.Len() == R.Len());
    int l = TInt::GetMn(ColId, R.Len()-1);
    double Result = 0.0;
    for (int i = 0; i <= l; i++)
        Result += R[i][ColId - i] * w[i];
    return Result;
}

void TPartialGS::Dump(const TStr& FName) {
    PSOut out = TFOut::New(FName);
    for (int i = 0; i < R.Len(); i++) {
        for (int j = 0; j < i; j++) {
            out->PutStr(TFlt::GetStr(0.0, 20, 18)); out->PutCh(' '); }
        for (int j = 0; j < R[i].Len(); j++) {
            out->PutStr(TFlt::GetStr(R[i][j], 20, 18)); out->PutCh(' '); }
        out->PutCh('\n');
    }
}
<|endoftext|>


<commit_before>/*
 * Copyright (c) 2022, NVIDIA CORPORATION. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *  * Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 *  * Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *  * Neither the name of NVIDIA CORPORATION nor the names of its
 *    contributors may be used to endorse or promote products derived
 *    from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#pragma once

#include <memory>
#include <vector>

#include "src/Check.h"
#include "src/CudaUtils.h"
#include "src/common.h"
#include "nvcomp_common_deps/hlif_shared_types.h"
#include "PinnedPtrs.hpp"

namespace nvcomp {

/******************************************************************************
 * CLASSES ********************************************************************
 *****************************************************************************/

/**
 * @brief Config used to aggregate information about the compression of a particular buffer.
 *
 * Contains a "PinnedPtrHandle" to an nvcompStatus. After the compression is complete,
 * the user can check the result status which resides in pinned host memory.
 */
struct CompressionConfig {
private:
  std::shared_ptr<PinnedPtrPool<nvcompStatus_t>::PinnedPtrHandle> status;

public:
  size_t max_compressed_buffer_size;

  /**
   * @brief Construct the config given an nvcompStatus_t memory pool
   */
  CompressionConfig(
      PinnedPtrPool<nvcompStatus_t>& pool,
      size_t max_compressed_buffer_size)
    : status(pool.allocate()),
      max_compressed_buffer_size(max_compressed_buffer_size)
  {
    *get_status() = nvcompSuccess;
  }

  /**
   * @brief Get the raw nvcompStatus_t*
   */
  nvcompStatus_t* get_status() const {
    return status->get_ptr();
  }
};

/**
 * @brief Config used to aggregate information about a particular decompression.
 *
 * Contains a "PinnedPtrHandle" to an nvcompStatus. After the decompression is complete,
 * the user can check the result status which resides in pinned host memory.
 */
struct DecompressionConfig {
private:
  std::shared_ptr<PinnedPtrPool<nvcompStatus_t>::PinnedPtrHandle> status;

public:
  size_t decomp_data_size;
  uint32_t num_chunks;

  /**
   * @brief Construct the config given an nvcompStatus_t memory pool
   */
  DecompressionConfig(PinnedPtrPool<nvcompStatus_t>& pool)
    : status(pool.allocate()),
      decomp_data_size(),
      num_chunks()
  {
    *get_status() = nvcompSuccess;
  }

  /**
   * @brief Get the raw nvcompStatus_t*
   */
  nvcompStatus_t* get_status() const {
    return status->get_ptr();
  }
};

/**
 * @brief Abstract base class that defines the nvCOMP high level interface
 */
struct nvcompManagerBase {
  /**
   * @brief Configure the compression.
   *
   * This routine computes the size of the required result buffer. The result config also
   * contains the nvcompStatus* that allows error checking. Synchronizes the device (cudaMemcpy)
   *
   * @param decomp_buffer_size The uncompressed input data size.
   * \return comp_config Result
   */
  virtual CompressionConfig configure_compression(const size_t decomp_buffer_size) = 0;

  /**
   * @brief Perform compression asynchronously.
   *
   * @param decomp_buffer The uncompressed input data (GPU accessible).
   * @param decomp_buffer_size The length of the uncompressed input data.
   * @param comp_buffer The location to output the compressed data to (GPU accessible).
   * @param comp_config Resulted from configure_compression given this decomp_buffer_size.
   * Contains the nvcompStatus* that allows error checking.
   */
  virtual void compress(
      const uint8_t* decomp_buffer,
      const size_t decomp_buffer_size,
      uint8_t* comp_buffer,
      const CompressionConfig& comp_config) = 0;

  /**
   * @brief Configure the decompression.
   *
   * Synchronizes the user stream.
   *
   * In the base case, this only computes the size of the decompressed buffer from the compressed buffer header.
   *
   * @param comp_buffer The compressed input data (GPU accessible).
   * \return decomp_config Result
   */
  virtual DecompressionConfig configure_decompression(const uint8_t* comp_buffer) = 0;

  /**
   * @brief Perform decompression asynchronously.
   *
   * @param decomp_buffer The location to output the decompressed data to (GPU accessible).
   * @param comp_buffer The compressed input data (GPU accessible).
   * @param decomp_config Resulted from configure_decompression given this decomp_buffer_size.
   * Contains nvcompStatus* in CPU/GPU-accessible memory to allow error checking.
   */
  virtual void decompress(
      uint8_t* decomp_buffer,
      const uint8_t* comp_buffer,
      const DecompressionConfig& decomp_config) = 0;

  /**
   * @brief Allows the user to provide a user-allocated scratch buffer.
   *
   * If this routine is not called before compression / decompression is called, the manager
   * allocates the required scratch buffer. If this is called after the manager has allocated a
   * scratch buffer, the manager frees the scratch buffer it allocated then switches to use
   * the new user-provided one.
   *
   * @param new_scratch_buffer The location (GPU accessible) to use for comp/decomp scratch space
   *
   */
  virtual void set_scratch_buffer(uint8_t* new_scratch_buffer) = 0;

  /**
   * @brief Computes the size of the required scratch space
   *
   * This scratch space size is constant and based on the configuration of the manager and the
   * maximum occupancy on the device.
   *
   * \return The required scratch buffer size
   */
  virtual size_t get_required_scratch_buffer_size() = 0;

  /**
   * @brief Computes the compressed output size of a given buffer
   *
   * Synchronously copies the size of the compressed buffer to a stack variable for return.
   *
   * @param comp_buffer The start pointer of the compressed buffer to assess.
   * \return Size of the compressed buffer
   */
  virtual size_t get_compressed_output_size(uint8_t* comp_buffer) = 0;

  virtual ~nvcompManagerBase() = default;
};

/**
 * @brief ManagerBase contains shared functionality amongst the different nvcompManager types
 *
 * - Intended that all Managers will inherit from this class directly or indirectly.
 *
 * - Contains a CPU/GPU-accessible memory pool for result statuses to avoid repeated
 *   allocations when tasked with multiple compressions / decompressions.
 *
 * - Templated on the particular format's FormatSpecHeader so that some operations can be shared here.
 *   This is likely to be inherited by template classes. In this case,
 *   some usage trickery is suggested to get around dependent name lookup issues.
 *   https://en.cppreference.com/w/cpp/language/dependent_name
 *
 */
template <typename FormatSpecHeader>
struct ManagerBase : nvcompManagerBase {

protected: // members
  CommonHeader* common_header_cpu;
  cudaStream_t user_stream;
  uint8_t* scratch_buffer;
  size_t scratch_buffer_size;
  int device_id;
  PinnedPtrPool<nvcompStatus_t> status_pool;
  bool manager_filled_scratch_buffer;

private: // members
  bool scratch_buffer_filled;

protected: // members
  bool finished_init;

public: // API
  /**
   * @brief Construct a ManagerBase
   *
   * @param user_stream The stream to use for all operations. Optional, defaults to the default stream
   * @param device_id The default device ID to use for all operations. Optional, defaults to the default device
   */
  ManagerBase(cudaStream_t user_stream = 0, int device_id = 0)
    : common_header_cpu(),
      user_stream(user_stream),
      scratch_buffer(nullptr),
      scratch_buffer_size(0),
      device_id(device_id),
      status_pool(),
      manager_filled_scratch_buffer(false),
      scratch_buffer_filled(false),
      finished_init(false)
  {
    CudaUtils::check(cudaHostAlloc(&common_header_cpu, sizeof(CommonHeader), cudaHostAllocDefault));
  }

  size_t get_required_scratch_buffer_size() final override {
    return scratch_buffer_size;
  }

  // Disable copying
  ManagerBase(const ManagerBase&) = delete;
  ManagerBase& operator=(const ManagerBase&) = delete;
  ManagerBase() = delete;

  size_t get_compressed_output_size(uint8_t* comp_buffer) final override {
    CommonHeader* common_header = reinterpret_cast<CommonHeader*>(comp_buffer);

    CudaUtils::check(cudaMemcpy(common_header_cpu,
        common_header,
        sizeof(CommonHeader),
        cudaMemcpyDefault));

    return common_header_cpu->comp_data_size + common_header_cpu->comp_data_offset;
  };

  virtual ~ManagerBase() {
    CudaUtils::check(cudaFreeHost(common_header_cpu));
    if (scratch_buffer_filled) {
      if (manager_filled_scratch_buffer) {
        #if CUDART_VERSION >= 11020
          CudaUtils::check(cudaFreeAsync(scratch_buffer, user_stream));
        #else
          CudaUtils::check(cudaFree(scratch_buffer));
        #endif
      }
    }
  }

  CompressionConfig configure_compression(const size_t decomp_buffer_size) final override
  {
    const size_t max_comp_size = calculate_max_compressed_output_size(decomp_buffer_size);
    return CompressionConfig{status_pool, max_comp_size};
  }

  virtual DecompressionConfig configure_decompression(const uint8_t* comp_buffer) override
  {
    const CommonHeader* common_header = reinterpret_cast<const CommonHeader*>(comp_buffer);
    DecompressionConfig decomp_config{status_pool};

    CudaUtils::check(cudaMemcpyAsync(&decomp_config.decomp_data_size,
        &common_header->decomp_data_size,
        sizeof(size_t),
        cudaMemcpyDefault,
        user_stream));

    do_configure_decompression(decomp_config, common_header);

    return decomp_config;
}

  void set_scratch_buffer(uint8_t* new_scratch_buffer) final override
  {
    if (scratch_buffer_filled) {
      if (manager_filled_scratch_buffer) {
        #if CUDART_VERSION >= 11020
          CudaUtils::check(cudaFreeAsync(scratch_buffer, user_stream));
        #else
          CudaUtils::check(cudaFree(scratch_buffer));
        #endif
        manager_filled_scratch_buffer = false;
      }
    } else {
      scratch_buffer_filled = true;
    }
    scratch_buffer = new_scratch_buffer;
  }

  virtual void compress(
      const uint8_t* decomp_buffer,
      const size_t decomp_buffer_size,
      uint8_t* comp_buffer,
      const CompressionConfig& comp_config)
  {
    assert(finished_init);

    if (not scratch_buffer_filled) {
      #if CUDART_VERSION >= 11020
        CudaUtils::check(cudaMallocAsync(&scratch_buffer, scratch_buffer_size, user_stream));
      #else
        CudaUtils::check(cudaMalloc(&scratch_buffer, scratch_buffer_size));
      #endif
      scratch_buffer_filled = true;
      manager_filled_scratch_buffer = true;
    }

    CommonHeader* common_header = reinterpret_cast<CommonHeader*>(comp_buffer);
    FormatSpecHeader* comp_format_header = reinterpret_cast<FormatSpecHeader*>(common_header + 1);
    CudaUtils::check(cudaMemcpyAsync(comp_format_header, get_format_header(), sizeof(FormatSpecHeader), cudaMemcpyDefault, user_stream));

    CudaUtils::check(cudaMemsetAsync(&common_header->comp_data_size, 0, sizeof(uint64_t), user_stream));

    uint8_t* new_comp_buffer = comp_buffer + sizeof(CommonHeader) + sizeof(FormatSpecHeader);
    do_compress(common_header, decomp_buffer, decomp_buffer_size, new_comp_buffer, comp_config);
  }

  virtual void decompress(
      uint8_t* decomp_buffer,
      const uint8_t* comp_buffer,
      const DecompressionConfig& config)
  {
    assert(finished_init);

    if (not scratch_buffer_filled) {
      #if CUDART_VERSION >= 11020
        CudaUtils::check(cudaMallocAsync(&scratch_buffer, scratch_buffer_size, user_stream));
      #else
        CudaUtils::check(cudaMalloc(&scratch_buffer, scratch_buffer_size));
      #endif
      scratch_buffer_filled = true;
      manager_filled_scratch_buffer = true;
    }

    const uint8_t* new_comp_buffer = comp_buffer + sizeof(CommonHeader) + sizeof(FormatSpecHeader);

    do_decompress(decomp_buffer, new_comp_buffer, config);
  }

protected: // helpers
  virtual void finish_init() {
    scratch_buffer_size = compute_scratch_buffer_size();
    finished_init = true;
  }

private: // helpers

  /**
   * @brief Required helper that actually does the compression
   *
   * @param common_header header filled in by this routine (GPU accessible)
   * @param decomp_buffer The uncompressed input data (GPU accessible)
   * @param decomp_buffer_size The length of the uncompressed input data
   * @param comp_buffer The location to output the compressed data to (GPU accessible).
   * @param comp_config Resulted from configure_compression given this decomp_buffer_size.
   *
   */
  virtual void do_compress(
      CommonHeader* common_header,
      const uint8_t* decomp_buffer,
      const size_t decomp_buffer_size,
      uint8_t* comp_buffer,
      const CompressionConfig& comp_config) = 0;

  /**
   * @brief Required helper that actually does the decompression
   *
   * @param decomp_buffer The location to output the decompressed data to (GPU accessible).
   * @param comp_buffer The compressed input data (GPU accessible).
   * @param decomp_config Resulted from configure_decompression given this decomp_buffer_size.
   */
  virtual void do_decompress(
      uint8_t* decomp_buffer,
      const uint8_t* comp_buffer,
      const DecompressionConfig& config) = 0;

  /**
   * @brief Optionally does additional decompression configuration
   */
  virtual void do_configure_decompression(
      DecompressionConfig& decomp_config,
      const CommonHeader* common_header) = 0;

  /**
   * @brief Computes the required scratch buffer size
   */
  virtual size_t compute_scratch_buffer_size() = 0;

  /**
   * @brief Computes the maximum compressed output size for a given
   * uncompressed buffer.
   */
  virtual size_t calculate_max_compressed_output_size(size_t decomp_buffer_size) = 0;

  /**
   * @brief Retrieves a CPU-accessible pointer to the FormatSpecHeader
   */
  virtual FormatSpecHeader* get_format_header() = 0;
};

} // namespace nvcomp<commit_msg>Remove reliance on stream in Manager destructor<commit_after>/*
 * Copyright (c) 2022, NVIDIA CORPORATION. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *  * Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 *  * Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *  * Neither the name of NVIDIA CORPORATION nor the names of its
 *    contributors may be used to endorse or promote products derived
 *    from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#pragma once

#include <memory>
#include <vector>

#include "src/Check.h"
#include "src/CudaUtils.h"
#include "src/common.h"
#include "nvcomp_common_deps/hlif_shared_types.h"
#include "PinnedPtrs.hpp"

namespace nvcomp {

/******************************************************************************
 * CLASSES ********************************************************************
 *****************************************************************************/

/**
 * @brief Config used to aggregate information about the compression of a particular buffer.
 *
 * Contains a "PinnedPtrHandle" to an nvcompStatus. After the compression is complete,
 * the user can check the result status which resides in pinned host memory.
 */
struct CompressionConfig {
private:
  std::shared_ptr<PinnedPtrPool<nvcompStatus_t>::PinnedPtrHandle> status;

public:
  size_t max_compressed_buffer_size;

  /**
   * @brief Construct the config given an nvcompStatus_t memory pool
   */
  CompressionConfig(
      PinnedPtrPool<nvcompStatus_t>& pool,
      size_t max_compressed_buffer_size)
    : status(pool.allocate()),
      max_compressed_buffer_size(max_compressed_buffer_size)
  {
    *get_status() = nvcompSuccess;
  }

  /**
   * @brief Get the raw nvcompStatus_t*
   */
  nvcompStatus_t* get_status() const {
    return status->get_ptr();
  }
};

/**
 * @brief Config used to aggregate information about a particular decompression.
 *
 * Contains a "PinnedPtrHandle" to an nvcompStatus. After the decompression is complete,
 * the user can check the result status which resides in pinned host memory.
 */
struct DecompressionConfig {
private:
  std::shared_ptr<PinnedPtrPool<nvcompStatus_t>::PinnedPtrHandle> status;

public:
  size_t decomp_data_size;
  uint32_t num_chunks;

  /**
   * @brief Construct the config given an nvcompStatus_t memory pool
   */
  DecompressionConfig(PinnedPtrPool<nvcompStatus_t>& pool)
    : status(pool.allocate()),
      decomp_data_size(),
      num_chunks()
  {
    *get_status() = nvcompSuccess;
  }

  /**
   * @brief Get the raw nvcompStatus_t*
   */
  nvcompStatus_t* get_status() const {
    return status->get_ptr();
  }
};

/**
 * @brief Abstract base class that defines the nvCOMP high level interface
 */
struct nvcompManagerBase {
  /**
   * @brief Configure the compression.
   *
   * This routine computes the size of the required result buffer. The result config also
   * contains the nvcompStatus* that allows error checking. Synchronizes the device (cudaMemcpy)
   *
   * @param decomp_buffer_size The uncompressed input data size.
   * \return comp_config Result
   */
  virtual CompressionConfig configure_compression(const size_t decomp_buffer_size) = 0;

  /**
   * @brief Perform compression asynchronously.
   *
   * @param decomp_buffer The uncompressed input data (GPU accessible).
   * @param decomp_buffer_size The length of the uncompressed input data.
   * @param comp_buffer The location to output the compressed data to (GPU accessible).
   * @param comp_config Resulted from configure_compression given this decomp_buffer_size.
   * Contains the nvcompStatus* that allows error checking.
   */
  virtual void compress(
      const uint8_t* decomp_buffer,
      const size_t decomp_buffer_size,
      uint8_t* comp_buffer,
      const CompressionConfig& comp_config) = 0;

  /**
   * @brief Configure the decompression.
   *
   * Synchronizes the user stream.
   *
   * In the base case, this only computes the size of the decompressed buffer from the compressed buffer header.
   *
   * @param comp_buffer The compressed input data (GPU accessible).
   * \return decomp_config Result
   */
  virtual DecompressionConfig configure_decompression(const uint8_t* comp_buffer) = 0;

  /**
   * @brief Perform decompression asynchronously.
   *
   * @param decomp_buffer The location to output the decompressed data to (GPU accessible).
   * @param comp_buffer The compressed input data (GPU accessible).
   * @param decomp_config Resulted from configure_decompression given this decomp_buffer_size.
   * Contains nvcompStatus* in CPU/GPU-accessible memory to allow error checking.
   */
  virtual void decompress(
      uint8_t* decomp_buffer,
      const uint8_t* comp_buffer,
      const DecompressionConfig& decomp_config) = 0;

  /**
   * @brief Allows the user to provide a user-allocated scratch buffer.
   *
   * If this routine is not called before compression / decompression is called, the manager
   * allocates the required scratch buffer. If this is called after the manager has allocated a
   * scratch buffer, the manager frees the scratch buffer it allocated then switches to use
   * the new user-provided one.
   *
   * @param new_scratch_buffer The location (GPU accessible) to use for comp/decomp scratch space
   *
   */
  virtual void set_scratch_buffer(uint8_t* new_scratch_buffer) = 0;

  /**
   * @brief Computes the size of the required scratch space
   *
   * This scratch space size is constant and based on the configuration of the manager and the
   * maximum occupancy on the device.
   *
   * \return The required scratch buffer size
   */
  virtual size_t get_required_scratch_buffer_size() = 0;

  /**
   * @brief Computes the compressed output size of a given buffer
   *
   * Synchronously copies the size of the compressed buffer to a stack variable for return.
   *
   * @param comp_buffer The start pointer of the compressed buffer to assess.
   * \return Size of the compressed buffer
   */
  virtual size_t get_compressed_output_size(uint8_t* comp_buffer) = 0;

  virtual ~nvcompManagerBase() = default;
};

/**
 * @brief ManagerBase contains shared functionality amongst the different nvcompManager types
 *
 * - Intended that all Managers will inherit from this class directly or indirectly.
 *
 * - Contains a CPU/GPU-accessible memory pool for result statuses to avoid repeated
 *   allocations when tasked with multiple compressions / decompressions.
 *
 * - Templated on the particular format's FormatSpecHeader so that some operations can be shared here.
 *   This is likely to be inherited by template classes. In this case,
 *   some usage trickery is suggested to get around dependent name lookup issues.
 *   https://en.cppreference.com/w/cpp/language/dependent_name
 *
 */
template <typename FormatSpecHeader>
struct ManagerBase : nvcompManagerBase {

protected: // members
  CommonHeader* common_header_cpu;
  cudaStream_t user_stream;
  uint8_t* scratch_buffer;
  size_t scratch_buffer_size;
  int device_id;
  PinnedPtrPool<nvcompStatus_t> status_pool;
  bool manager_filled_scratch_buffer;

private: // members
  bool scratch_buffer_filled;

protected: // members
  bool finished_init;

public: // API
  /**
   * @brief Construct a ManagerBase
   *
   * @param user_stream The stream to use for all operations. Optional, defaults to the default stream
   * @param device_id The default device ID to use for all operations. Optional, defaults to the default device
   */
  ManagerBase(cudaStream_t user_stream = 0, int device_id = 0)
    : common_header_cpu(),
      user_stream(user_stream),
      scratch_buffer(nullptr),
      scratch_buffer_size(0),
      device_id(device_id),
      status_pool(),
      manager_filled_scratch_buffer(false),
      scratch_buffer_filled(false),
      finished_init(false)
  {
    CudaUtils::check(cudaHostAlloc(&common_header_cpu, sizeof(CommonHeader), cudaHostAllocDefault));
  }

  size_t get_required_scratch_buffer_size() final override {
    return scratch_buffer_size;
  }

  // Disable copying
  ManagerBase(const ManagerBase&) = delete;
  ManagerBase& operator=(const ManagerBase&) = delete;
  ManagerBase() = delete;

  size_t get_compressed_output_size(uint8_t* comp_buffer) final override {
    CommonHeader* common_header = reinterpret_cast<CommonHeader*>(comp_buffer);

    CudaUtils::check(cudaMemcpy(common_header_cpu,
        common_header,
        sizeof(CommonHeader),
        cudaMemcpyDefault));

    return common_header_cpu->comp_data_size + common_header_cpu->comp_data_offset;
  };

  virtual ~ManagerBase() {
    CudaUtils::check(cudaFreeHost(common_header_cpu));
    if (scratch_buffer_filled) {
      if (manager_filled_scratch_buffer) {
        CudaUtils::check(cudaFree(scratch_buffer));
      }
    }
  }

  CompressionConfig configure_compression(const size_t decomp_buffer_size) final override
  {
    const size_t max_comp_size = calculate_max_compressed_output_size(decomp_buffer_size);
    return CompressionConfig{status_pool, max_comp_size};
  }

  virtual DecompressionConfig configure_decompression(const uint8_t* comp_buffer) override
  {
    const CommonHeader* common_header = reinterpret_cast<const CommonHeader*>(comp_buffer);
    DecompressionConfig decomp_config{status_pool};

    CudaUtils::check(cudaMemcpyAsync(&decomp_config.decomp_data_size,
        &common_header->decomp_data_size,
        sizeof(size_t),
        cudaMemcpyDefault,
        user_stream));

    do_configure_decompression(decomp_config, common_header);

    return decomp_config;
}

  void set_scratch_buffer(uint8_t* new_scratch_buffer) final override
  {
    if (scratch_buffer_filled) {
      if (manager_filled_scratch_buffer) {
        #if CUDART_VERSION >= 11020
          CudaUtils::check(cudaFreeAsync(scratch_buffer, user_stream));
        #else
          CudaUtils::check(cudaFree(scratch_buffer));
        #endif
        manager_filled_scratch_buffer = false;
      }
    } else {
      scratch_buffer_filled = true;
    }
    scratch_buffer = new_scratch_buffer;
  }

  virtual void compress(
      const uint8_t* decomp_buffer,
      const size_t decomp_buffer_size,
      uint8_t* comp_buffer,
      const CompressionConfig& comp_config)
  {
    assert(finished_init);

    if (not scratch_buffer_filled) {
      #if CUDART_VERSION >= 11020
        CudaUtils::check(cudaMallocAsync(&scratch_buffer, scratch_buffer_size, user_stream));
      #else
        CudaUtils::check(cudaMalloc(&scratch_buffer, scratch_buffer_size));
      #endif
      scratch_buffer_filled = true;
      manager_filled_scratch_buffer = true;
    }

    CommonHeader* common_header = reinterpret_cast<CommonHeader*>(comp_buffer);
    FormatSpecHeader* comp_format_header = reinterpret_cast<FormatSpecHeader*>(common_header + 1);
    CudaUtils::check(cudaMemcpyAsync(comp_format_header, get_format_header(), sizeof(FormatSpecHeader), cudaMemcpyDefault, user_stream));

    CudaUtils::check(cudaMemsetAsync(&common_header->comp_data_size, 0, sizeof(uint64_t), user_stream));

    uint8_t* new_comp_buffer = comp_buffer + sizeof(CommonHeader) + sizeof(FormatSpecHeader);
    do_compress(common_header, decomp_buffer, decomp_buffer_size, new_comp_buffer, comp_config);
  }

  virtual void decompress(
      uint8_t* decomp_buffer,
      const uint8_t* comp_buffer,
      const DecompressionConfig& config)
  {
    assert(finished_init);

    if (not scratch_buffer_filled) {
      #if CUDART_VERSION >= 11020
        CudaUtils::check(cudaMallocAsync(&scratch_buffer, scratch_buffer_size, user_stream));
      #else
        CudaUtils::check(cudaMalloc(&scratch_buffer, scratch_buffer_size));
      #endif
      scratch_buffer_filled = true;
      manager_filled_scratch_buffer = true;
    }

    const uint8_t* new_comp_buffer = comp_buffer + sizeof(CommonHeader) + sizeof(FormatSpecHeader);

    do_decompress(decomp_buffer, new_comp_buffer, config);
  }

protected: // helpers
  virtual void finish_init() {
    scratch_buffer_size = compute_scratch_buffer_size();
    finished_init = true;
  }

private: // helpers

  /**
   * @brief Required helper that actually does the compression
   *
   * @param common_header header filled in by this routine (GPU accessible)
   * @param decomp_buffer The uncompressed input data (GPU accessible)
   * @param decomp_buffer_size The length of the uncompressed input data
   * @param comp_buffer The location to output the compressed data to (GPU accessible).
   * @param comp_config Resulted from configure_compression given this decomp_buffer_size.
   *
   */
  virtual void do_compress(
      CommonHeader* common_header,
      const uint8_t* decomp_buffer,
      const size_t decomp_buffer_size,
      uint8_t* comp_buffer,
      const CompressionConfig& comp_config) = 0;

  /**
   * @brief Required helper that actually does the decompression
   *
   * @param decomp_buffer The location to output the decompressed data to (GPU accessible).
   * @param comp_buffer The compressed input data (GPU accessible).
   * @param decomp_config Resulted from configure_decompression given this decomp_buffer_size.
   */
  virtual void do_decompress(
      uint8_t* decomp_buffer,
      const uint8_t* comp_buffer,
      const DecompressionConfig& config) = 0;

  /**
   * @brief Optionally does additional decompression configuration
   */
  virtual void do_configure_decompression(
      DecompressionConfig& decomp_config,
      const CommonHeader* common_header) = 0;

  /**
   * @brief Computes the required scratch buffer size
   */
  virtual size_t compute_scratch_buffer_size() = 0;

  /**
   * @brief Computes the maximum compressed output size for a given
   * uncompressed buffer.
   */
  virtual size_t calculate_max_compressed_output_size(size_t decomp_buffer_size) = 0;

  /**
   * @brief Retrieves a CPU-accessible pointer to the FormatSpecHeader
   */
  virtual FormatSpecHeader* get_format_header() = 0;
};

} // namespace nvcomp<|endoftext|>


<commit_before>#include <iostream>

#include "tests.h"
#include "XMLProcessor.h"
#include "EACirc.h"

void compareFilesByLine(string filename1, string filename2) {
    string line1,line2;
    ifstream file1(filename1);
    ifstream file2(filename2);
    if (!file1.is_open() || !file2.is_open()) {
        WARN("Could not open files " << filename1 << " and " << filename2 << ".");
        return;
    }
    int differCount = 0;
    while ((!file1.eof() || !file2.eof()) && differCount <=5 ) {
        getline(file1,line1);
        getline(file2,line2);
        if (line1 != line2) {
            differCount++;
        }
        SCOPED_INFO("Comparing files " << filename1 << " and " << filename2 << ".");
        CHECK(line1 == line2);
    }
    if (differCount > 5) {
        WARN("Given files (" << filename1 << ", " << filename2 << " differ in more than 5 lines!");
    }
    file1.close();
    file2.close();
}

int backupFile(string filename) {
    string backupFilename = filename + BACKUP_SUFFIX;
    remove(backupFilename.c_str());
    if (rename(filename.c_str(),backupFilename.c_str()) != 0) {
        return STAT_FILE_WRITE_FAIL;
    }
    return STAT_OK;
}

void backupResults() {
    CHECK(backupFile(FILE_GALIB_SCORES) == STAT_OK);
    CHECK(backupFile(FILE_FITNESS_PROGRESS) == STAT_OK);
    CHECK(backupFile(FILE_BEST_FITNESS) == STAT_OK);
    CHECK(backupFile(FILE_AVG_FITNESS) == STAT_OK);
    CHECK(backupFile(FILE_STATE) == STAT_OK);
    CHECK(backupFile(FILE_POPULATION) == STAT_OK);
}

void compareResults() {
    compareFilesByLine(FILE_GALIB_SCORES,string(FILE_GALIB_SCORES)+BACKUP_SUFFIX);
    compareFilesByLine(FILE_FITNESS_PROGRESS,string(FILE_FITNESS_PROGRESS)+BACKUP_SUFFIX);
    compareFilesByLine(FILE_BEST_FITNESS,string(FILE_BEST_FITNESS)+BACKUP_SUFFIX);
    compareFilesByLine(FILE_AVG_FITNESS,string(FILE_AVG_FITNESS)+BACKUP_SUFFIX);
    compareFilesByLine(FILE_STATE,string(FILE_STATE)+BACKUP_SUFFIX);
    compareFilesByLine(FILE_POPULATION,string(FILE_POPULATION)+BACKUP_SUFFIX);
}

int runEACirc() {
    WARN("######## Running EACirc ########");
    EACirc eacirc(false);
    eacirc.loadConfiguration(FILE_CONFIG);
    eacirc.initializeState();
    eacirc.prepare();
    eacirc.run();
    WARN("######## Ending EACirc (error: " << eacirc.getStatus() << " ) ########");
    return eacirc.getStatus();
}

TEST_CASE("stupid/number equalities", "different numbers are not equal") {
    int number = 5;
    for (int i=1; i<5; i++) {
        CHECK(i !=number);
    }
}

TEST_CASE("xml/xpath","using simple variation of xpath to get/set element and attribute values in XML") {
    string location = "INFO/VERSION";
    TiXmlNode* pRoot = NULL;
    REQUIRE(loadXMLFile(pRoot,FILE_CONFIG) == STAT_OK);
    CHECK(getXMLElementValue(pRoot,location) == "5.0");

    string newData = "new data here!";
    REQUIRE(setXMLElementValue(pRoot,location,newData) == STAT_OK);
    string attrName = "TEST_ATTR";
    string attrValue = "1234";
    REQUIRE(setXMLElementValue(pRoot,location + "/@" + attrName,attrValue) == STAT_OK);
    REQUIRE(saveXMLFile(pRoot,FILE_CONFIG) == STAT_OK);

    REQUIRE(loadXMLFile(pRoot,FILE_CONFIG) == STAT_OK);
    CHECK(getXMLElementValue(pRoot,location) == newData);
    CHECK(getXMLElementValue(pRoot,location+"/@"+attrName) == attrValue);
    delete pRoot;
}

TEST_CASE("determinism/seed","testing whether run with random seed and second run with the same seed are same") {
    // general preparations
    REQUIRE(basicConfiguration::estream() == STAT_OK);
    TiXmlNode* pRootConfig = NULL;
    // prepare run 1
    REQUIRE(loadXMLFile(pRootConfig,FILE_CONFIG) == STAT_OK);
    REQUIRE(setXMLElementValue(pRootConfig,"MAIN/LOAD_STATE","0") == STAT_OK);
    REQUIRE(setXMLElementValue(pRootConfig,"RANDOM/USE_FIXED_SEED","0") == STAT_OK);
    REQUIRE(saveXMLFile(pRootConfig,FILE_CONFIG) == STAT_OK);
    pRootConfig = NULL;
    // run 1
    REQUIRE(runEACirc() == STAT_OK);
    // rename files to be compared
    backupResults();
    REQUIRE(backupFile(FILE_STATE_INITIAL) == STAT_OK);
    REQUIRE(backupFile(FILE_POPULATION_INITIAL) == STAT_OK);
    // prepare run 2
    REQUIRE(loadXMLFile(pRootConfig,FILE_CONFIG) == STAT_OK);
    TiXmlNode* pRootState = NULL;
    REQUIRE(setXMLElementValue(pRootConfig,"RANDOM/USE_FIXED_SEED","1") == STAT_OK);
    REQUIRE(loadXMLFile(pRootState,string(FILE_STATE_INITIAL)+BACKUP_SUFFIX) == STAT_OK);
    string seed = getXMLElementValue(pRootState,"main_seed");
    REQUIRE(setXMLElementValue(pRootConfig,"RANDOM/SEED",seed) == STAT_OK);
    REQUIRE(saveXMLFile(pRootConfig,FILE_CONFIG) == STAT_OK);
    pRootConfig = NULL;
    delete pRootState;
    // run 2
    REQUIRE(runEACirc() == STAT_OK);
    // compare results
    compareResults();
    compareFilesByLine(FILE_STATE_INITIAL,string(FILE_STATE_INITIAL)+BACKUP_SUFFIX);
    compareFilesByLine(FILE_POPULATION_INITIAL,string(FILE_POPULATION_INITIAL)+BACKUP_SUFFIX);
}

TEST_CASE("determinism/load-state","running and running from loaded state") {
    // general preparations
    basicConfiguration::estream();
    TiXmlNode* pRootConfig = NULL;
    // prepare run 1
    REQUIRE(loadXMLFile(pRootConfig,FILE_CONFIG) == STAT_OK);
    REQUIRE(setXMLElementValue(pRootConfig,"MAIN/LOAD_STATE","0") == STAT_OK);
    REQUIRE(saveXMLFile(pRootConfig,FILE_CONFIG) == STAT_OK);
    pRootConfig = NULL;
    // run 1
    REQUIRE(runEACirc() == STAT_OK);
    // rename files to be compared
    backupResults();
    // copy file header for FILE_FITNESS_PROGRESS
    {
        ofstream fitProg(FILE_FITNESS_PROGRESS);
        ifstream fitProgOrig(string(FILE_FITNESS_PROGRESS)+BACKUP_SUFFIX);
        REQUIRE((fitProg.is_open() && fitProgOrig.is_open()));
        string line;
        getline(fitProgOrig,line);
        fitProg << line << endl;
        fitProg.close();
        fitProgOrig.close();
    }
    // prepare run 2
    REQUIRE(loadXMLFile(pRootConfig,FILE_CONFIG) == STAT_OK);
    REQUIRE(setXMLElementValue(pRootConfig,"MAIN/LOAD_STATE","1") == STAT_OK);
    REQUIRE(saveXMLFile(pRootConfig,FILE_CONFIG) == STAT_OK);
    pRootConfig = NULL;
    REQUIRE(rename(FILE_STATE_INITIAL,FILE_STATE) == STAT_OK);
    REQUIRE(rename(FILE_POPULATION_INITIAL,FILE_POPULATION) == STAT_OK);
    // run 2
    REQUIRE(runEACirc() == STAT_OK);
    // compare results
    compareResults();
}

TEST_CASE("determinism/recommencing","compute 40 generations vs. compute 20+20 generations") {
    // general preparations
    basicConfiguration::estream();
    TiXmlNode* pRootConfig = NULL;
    // prepare run 1
    REQUIRE(loadXMLFile(pRootConfig,FILE_CONFIG) == STAT_OK);
    REQUIRE(setXMLElementValue(pRootConfig,"MAIN/LOAD_STATE","0") == STAT_OK);
    REQUIRE(setXMLElementValue(pRootConfig,"MAIN/NUM_GENERATIONS","40") == STAT_OK);
    REQUIRE(setXMLElementValue(pRootConfig,"MAIN/SAVE_STATE_FREQ","10") == STAT_OK);
    REQUIRE(setXMLElementValue(pRootConfig,"RANDOM/USE_FIXED_SEED","1") == STAT_OK);
    REQUIRE(setXMLElementValue(pRootConfig,"RANDOM/SEED","123456789") == STAT_OK);
    REQUIRE(saveXMLFile(pRootConfig,FILE_CONFIG) == STAT_OK);
    pRootConfig = NULL;
    // run 1
    REQUIRE(runEACirc() == STAT_OK);
    // rename files to be compared
    backupResults();
    // prepare run 2
    REQUIRE(loadXMLFile(pRootConfig,FILE_CONFIG) == STAT_OK);
    REQUIRE(setXMLElementValue(pRootConfig,"MAIN/NUM_GENERATIONS","20") == STAT_OK);
    REQUIRE(saveXMLFile(pRootConfig,FILE_CONFIG) == STAT_OK);
    pRootConfig = NULL;
    // run 2
    REQUIRE(runEACirc() == STAT_OK);
    // prepare run 3
    REQUIRE(loadXMLFile(pRootConfig,FILE_CONFIG) == STAT_OK);
    REQUIRE(setXMLElementValue(pRootConfig,"MAIN/LOAD_STATE","1") == STAT_OK);
    REQUIRE(setXMLElementValue(pRootConfig,"MAIN/NUM_GENERATIONS","20") == STAT_OK);
    REQUIRE(saveXMLFile(pRootConfig,FILE_CONFIG) == STAT_OK);
    pRootConfig = NULL;
    // run 3
    REQUIRE(runEACirc() == STAT_OK);
    // compare results
    compareResults();
}
<commit_msg>minor changes to tests<commit_after>#include <iostream>

#include "tests.h"
#include "XMLProcessor.h"
#include "EACirc.h"

void compareFilesByLine(string filename1, string filename2) {
    string line1,line2;
    ifstream file1(filename1);
    ifstream file2(filename2);
    if (!file1.is_open() || !file2.is_open()) {
        WARN("Could not open files " << filename1 << " and " << filename2 << ".");
        return;
    }
    int differCount = 0;
    while ((!file1.eof() || !file2.eof()) && differCount <=5 ) {
        getline(file1,line1);
        getline(file2,line2);
        if (line1 != line2) {
            differCount++;
        }
        SCOPED_INFO("Comparing files " << filename1 << " and " << filename2 << ".");
        CHECK(line1 == line2);
    }
    if (differCount > 5) {
        WARN("Given files (" << filename1 << ", " << filename2 << " differ in more than 5 lines!");
    }
    file1.close();
    file2.close();
}

int backupFile(string filename) {
    string backupFilename = filename + BACKUP_SUFFIX;
    remove(backupFilename.c_str());
    if (rename(filename.c_str(),backupFilename.c_str()) != 0) {
        return STAT_FILE_WRITE_FAIL;
    }
    return STAT_OK;
}

void backupResults() {
    CHECK(backupFile(FILE_GALIB_SCORES) == STAT_OK);
    CHECK(backupFile(FILE_FITNESS_PROGRESS) == STAT_OK);
    CHECK(backupFile(FILE_BEST_FITNESS) == STAT_OK);
    CHECK(backupFile(FILE_AVG_FITNESS) == STAT_OK);
    CHECK(backupFile(FILE_STATE) == STAT_OK);
    CHECK(backupFile(FILE_POPULATION) == STAT_OK);
}

void compareResults() {
    compareFilesByLine(FILE_GALIB_SCORES,string(FILE_GALIB_SCORES)+BACKUP_SUFFIX);
    compareFilesByLine(FILE_FITNESS_PROGRESS,string(FILE_FITNESS_PROGRESS)+BACKUP_SUFFIX);
    compareFilesByLine(FILE_BEST_FITNESS,string(FILE_BEST_FITNESS)+BACKUP_SUFFIX);
    compareFilesByLine(FILE_AVG_FITNESS,string(FILE_AVG_FITNESS)+BACKUP_SUFFIX);
    compareFilesByLine(FILE_STATE,string(FILE_STATE)+BACKUP_SUFFIX);
    compareFilesByLine(FILE_POPULATION,string(FILE_POPULATION)+BACKUP_SUFFIX);
}

int runEACirc() {
	if (mainLogger.getLogging()) {
		WARN("######## Running EACirc ########");
	}
    EACirc eacirc(false);
    eacirc.loadConfiguration(FILE_CONFIG);
    eacirc.initializeState();
    eacirc.prepare();
    eacirc.run();
	if (mainLogger.getLogging()) {
		WARN("######## Ending EACirc (error: " << eacirc.getStatus() << " ) ########");
	}
    return eacirc.getStatus();
}

TEST_CASE("xml/xpath","using simple variation of xpath to get/set element and attribute values in XML") {
    string location = "INFO/VERSION";
    TiXmlNode* pRoot = NULL;
    REQUIRE(loadXMLFile(pRoot,FILE_CONFIG) == STAT_OK);
    CHECK(getXMLElementValue(pRoot,location) == "5.0");

    string newData = "new data here!";
    REQUIRE(setXMLElementValue(pRoot,location,newData) == STAT_OK);
    string attrName = "TEST_ATTR";
    string attrValue = "1234";
    REQUIRE(setXMLElementValue(pRoot,location + "/@" + attrName,attrValue) == STAT_OK);
    REQUIRE(saveXMLFile(pRoot,FILE_CONFIG) == STAT_OK);

    REQUIRE(loadXMLFile(pRoot,FILE_CONFIG) == STAT_OK);
    CHECK(getXMLElementValue(pRoot,location) == newData);
    CHECK(getXMLElementValue(pRoot,location+"/@"+attrName) == attrValue);
    delete pRoot;
}

TEST_CASE("determinism/seed","testing whether run with random seed and second run with the same seed are same") {
    // general preparations
    REQUIRE(basicConfiguration::estream() == STAT_OK);
    TiXmlNode* pRootConfig = NULL;
    // prepare run 1
    REQUIRE(loadXMLFile(pRootConfig,FILE_CONFIG) == STAT_OK);
    REQUIRE(setXMLElementValue(pRootConfig,"MAIN/LOAD_STATE","0") == STAT_OK);
    REQUIRE(setXMLElementValue(pRootConfig,"RANDOM/USE_FIXED_SEED","0") == STAT_OK);
    REQUIRE(saveXMLFile(pRootConfig,FILE_CONFIG) == STAT_OK);
    pRootConfig = NULL;
    // run 1
    REQUIRE(runEACirc() == STAT_OK);
    // rename files to be compared
    backupResults();
    REQUIRE(backupFile(FILE_STATE_INITIAL) == STAT_OK);
    REQUIRE(backupFile(FILE_POPULATION_INITIAL) == STAT_OK);
    // prepare run 2
    REQUIRE(loadXMLFile(pRootConfig,FILE_CONFIG) == STAT_OK);
    TiXmlNode* pRootState = NULL;
    REQUIRE(setXMLElementValue(pRootConfig,"RANDOM/USE_FIXED_SEED","1") == STAT_OK);
    REQUIRE(loadXMLFile(pRootState,string(FILE_STATE_INITIAL)+BACKUP_SUFFIX) == STAT_OK);
    string seed = getXMLElementValue(pRootState,"main_seed");
    REQUIRE(setXMLElementValue(pRootConfig,"RANDOM/SEED",seed) == STAT_OK);
    REQUIRE(saveXMLFile(pRootConfig,FILE_CONFIG) == STAT_OK);
    pRootConfig = NULL;
    delete pRootState;
    // run 2
    REQUIRE(runEACirc() == STAT_OK);
    // compare results
    compareResults();
    compareFilesByLine(FILE_STATE_INITIAL,string(FILE_STATE_INITIAL)+BACKUP_SUFFIX);
    compareFilesByLine(FILE_POPULATION_INITIAL,string(FILE_POPULATION_INITIAL)+BACKUP_SUFFIX);
}

TEST_CASE("determinism/load-state","running and running from loaded state") {
    // general preparations
    basicConfiguration::estream();
    TiXmlNode* pRootConfig = NULL;
    // prepare run 1
    REQUIRE(loadXMLFile(pRootConfig,FILE_CONFIG) == STAT_OK);
    REQUIRE(setXMLElementValue(pRootConfig,"MAIN/LOAD_STATE","0") == STAT_OK);
    REQUIRE(saveXMLFile(pRootConfig,FILE_CONFIG) == STAT_OK);
    pRootConfig = NULL;
    // run 1
    REQUIRE(runEACirc() == STAT_OK);
    // rename files to be compared
    backupResults();
    // copy file header for FILE_FITNESS_PROGRESS
    {
        ofstream fitProg(FILE_FITNESS_PROGRESS);
        ifstream fitProgOrig(string(FILE_FITNESS_PROGRESS)+BACKUP_SUFFIX);
        REQUIRE((fitProg.is_open() && fitProgOrig.is_open()));
        string line;
        getline(fitProgOrig,line);
        fitProg << line << endl;
        fitProg.close();
        fitProgOrig.close();
    }
    // prepare run 2
    REQUIRE(loadXMLFile(pRootConfig,FILE_CONFIG) == STAT_OK);
    REQUIRE(setXMLElementValue(pRootConfig,"MAIN/LOAD_STATE","1") == STAT_OK);
    REQUIRE(saveXMLFile(pRootConfig,FILE_CONFIG) == STAT_OK);
    pRootConfig = NULL;
    REQUIRE(rename(FILE_STATE_INITIAL,FILE_STATE) == STAT_OK);
    REQUIRE(rename(FILE_POPULATION_INITIAL,FILE_POPULATION) == STAT_OK);
    // run 2
    REQUIRE(runEACirc() == STAT_OK);
    // compare results
    compareResults();
}

TEST_CASE("determinism/recommencing","compute 40 generations vs. compute 20+20 generations") {
    // general preparations
    basicConfiguration::estream();
    TiXmlNode* pRootConfig = NULL;
    // prepare run 1
    REQUIRE(loadXMLFile(pRootConfig,FILE_CONFIG) == STAT_OK);
    REQUIRE(setXMLElementValue(pRootConfig,"MAIN/LOAD_STATE","0") == STAT_OK);
    REQUIRE(setXMLElementValue(pRootConfig,"MAIN/NUM_GENERATIONS","40") == STAT_OK);
    REQUIRE(setXMLElementValue(pRootConfig,"MAIN/SAVE_STATE_FREQ","10") == STAT_OK);
    REQUIRE(setXMLElementValue(pRootConfig,"RANDOM/USE_FIXED_SEED","1") == STAT_OK);
    REQUIRE(setXMLElementValue(pRootConfig,"RANDOM/SEED","123456789") == STAT_OK);
    REQUIRE(saveXMLFile(pRootConfig,FILE_CONFIG) == STAT_OK);
    pRootConfig = NULL;
    // run 1
    REQUIRE(runEACirc() == STAT_OK);
    // rename files to be compared
    backupResults();
    // prepare run 2
    REQUIRE(loadXMLFile(pRootConfig,FILE_CONFIG) == STAT_OK);
    REQUIRE(setXMLElementValue(pRootConfig,"MAIN/NUM_GENERATIONS","20") == STAT_OK);
    REQUIRE(saveXMLFile(pRootConfig,FILE_CONFIG) == STAT_OK);
    pRootConfig = NULL;
    // run 2
    REQUIRE(runEACirc() == STAT_OK);
    // prepare run 3
    REQUIRE(loadXMLFile(pRootConfig,FILE_CONFIG) == STAT_OK);
    REQUIRE(setXMLElementValue(pRootConfig,"MAIN/LOAD_STATE","1") == STAT_OK);
    REQUIRE(setXMLElementValue(pRootConfig,"MAIN/NUM_GENERATIONS","20") == STAT_OK);
    REQUIRE(saveXMLFile(pRootConfig,FILE_CONFIG) == STAT_OK);
    pRootConfig = NULL;
    // run 3
    REQUIRE(runEACirc() == STAT_OK);
    // compare results
    compareResults();
}
<|endoftext|>


<commit_before>/*
 * IBDS - Impulse-Based Dynamic Simulation Library
 * Copyright (c) 2003-2008 Jan Bender http://www.impulse-based.de
 *
 * This software is provided 'as-is', without any express or implied
 * warranty. In no event will the authors be held liable for any damages
 * arising from the use of this software.
 *
 * Permission is granted to anyone to use this software for any purpose,
 * including commercial applications, and to alter it and redistribute it
 * freely, subject to the following restrictions:
 *
 * 1. The origin of this software must not be misrepresented; you must not
 *    claim that you wrote the original software. If you use this software
 *    in a product, an acknowledgment in the product documentation would be
 *    appreciated but is not required.
 * 2. Altered source versions must be plainly marked as such, and must not be
 *    misrepresented as being the original software.
 * 3. This notice may not be removed or altered from any source distribution.
 *
 * Jan Bender - Jan.Bender@impulse-based.de
 */

#include "Common/StringTools.h"
#include "Common/timing.h"
#include "CustomSimulation.h"
#include <GlutRunner/GlutSimulationRunner.h>
#include <Visualization/Renderers/SimulationRunnerRenderer.h>
#include <Visualization/Renderers/TweakBarRenderer.h>
// Enable memory leak detection
#ifdef _DEBUG
  #define new DEBUG_NEW
#endif

using namespace IBDS;
using namespace std;

// main
int main( int argc, char **argv )
	{
	REPORT_MEMORY_LEAKS
	USE_TIMESTEP_TIMING(Timing::m_dontPrintTimes = true;);

  auto simulation = new CustomSimulation();

  GlutSimulationRunner & runner = GlutSimulationRunner::instance();

  IAction * action = new DelegateAction("TogglePause", [&runner](){runner.togglePause();});

  simulation->addSimulationObject(action);

  runner.setCommandLineArguments(argc,argv);

  runner.setSimulation(simulation);

  //add a renderer that shows info for the simulation runner
  simulation->addSimulationObject(new SimulationRunnerRenderer(runner));

  // this order has to be maintaned.  i'll need to fix this.
  simulation->buildModel();
  simulation->buildAlgorithms();

  Real b=9;
  simulation->addSimulationObject(new RealValue("test",b));

  auto integrable = simulation->getIntegrator()->getIntegratable();
  Real* initialState = new Real[integrable->getStateDimension()];
  integrable->getState(initialState);

  action = new DelegateAction("Reset",[initialState, integrable](){
    integrable->setState(initialState);
  });
  simulation->addSimulationObject(action);

  runner.run();

	USE_TIMESTEP_TIMING(printAverageTimes());

	return 0;
	}<commit_msg><commit_after>/*
 * IBDS - Impulse-Based Dynamic Simulation Library
 * Copyright (c) 2003-2008 Jan Bender http://www.impulse-based.de
 *
 * This software is provided 'as-is', without any express or implied
 * warranty. In no event will the authors be held liable for any damages
 * arising from the use of this software.
 *
 * Permission is granted to anyone to use this software for any purpose,
 * including commercial applications, and to alter it and redistribute it
 * freely, subject to the following restrictions:
 *
 * 1. The origin of this software must not be misrepresented; you must not
 *    claim that you wrote the original software. If you use this software
 *    in a product, an acknowledgment in the product documentation would be
 *    appreciated but is not required.
 * 2. Altered source versions must be plainly marked as such, and must not be
 *    misrepresented as being the original software.
 * 3. This notice may not be removed or altered from any source distribution.
 *
 * Jan Bender - Jan.Bender@impulse-based.de
 */

#include "Common/StringTools.h"
#include "Common/timing.h"
#include "CustomSimulation.h"
#include <GlutRunner/GlutSimulationRunner.h>
#include <Visualization/Renderers/SimulationRunnerRenderer.h>
#include <Visualization/Renderers/TweakBarRenderer.h>
// Enable memory leak detection
#ifdef _DEBUG
  #define new DEBUG_NEW
#endif

using namespace IBDS;
using namespace std;

// main
int main( int argc, char **argv )
	{
	REPORT_MEMORY_LEAKS
	USE_TIMESTEP_TIMING(Timing::m_dontPrintTimes = true;);

  auto simulation = new CustomSimulation();

  GlutSimulationRunner & runner = GlutSimulationRunner::instance();

  IAction * action = new DelegateAction("TogglePause", [&runner](){runner.togglePause();});

  simulation->addSimulationObject(action);

  runner.setCommandLineArguments(argc,argv);

  runner.setSimulation(simulation);

  // this order has to be maintaned.  i'll need to fix this.
  simulation->buildModel();
  simulation->buildAlgorithms();

  auto integrable = simulation->getIntegrator()->getIntegratable();
  Real* initialState = new Real[integrable->getStateDimension()];
  integrable->getState(initialState);

  action = new DelegateAction("Reset",[initialState, integrable](){
    integrable->setState(initialState);
  });
  simulation->addSimulationObject(action);

  runner.run();

	USE_TIMESTEP_TIMING(printAverageTimes());

	return 0;
	}<|endoftext|>


<commit_before>#include "FSEObject.h"
#include "../Application.h"

namespace fse
{

	FSEObject::FSEObject(Scene *scene) : position_(sf::Vector2f(0,0))
	{
		scene_ = scene;
		input_ = scene->getApplication()->getInput();
	}

	FSEObject::FSEObject(Scene* scene, const sf::Vector2f spawnPos) : FSEObject(scene)
	{

	}

	FSEObject::~FSEObject()
	{

	}

	void FSEObject::setPosition(const sf::Vector2f position)
	{
		position_ = position;
	}

	sf::Vector2f FSEObject::getPosition()
	{
		return position_;
	}

	void FSEObject::BeginContact(FSEObject* otherObject, b2Contact* contact)
	{
	}

	void FSEObject::EndContact(FSEObject* otherObject, b2Contact* contact)
	{
	}

	void FSEObject::PreSolve(FSEObject* otherObject, b2Contact* contact, const b2Manifold* oldManifold)
	{
	}

	void FSEObject::PostSolve(FSEObject* otherObject, b2Contact* contact, const b2ContactImpulse* impulse)
	{
	}

	int FSEObject::getZOrder() const
	{
		return z_order_;
	}

	bool FSEObject::isPendingKill() const
	{
		if (pending_timed_kill_)
			return true;
		return is_pending_kill_;
	}

	void FSEObject::setTimedKill()
	{
		pending_timed_kill_ = true;
	}

	Scene* FSEObject::getScene()
	{
		return scene_;
	}

	void FSEObject::spawn(int id)
	{
		id_ = id;
		spawned();
		spawned_signal_(this);
		spawned_signal_.disconnectAll();
	}

	bool FSEObject::destroy()
	{
		if (!is_pending_kill_)
		{
			is_pending_kill_ = true;

			scene_->destroyFSEObject(this);

			return true;
		}
		return false;
	}

	int FSEObject::getID()
	{
		return id_;
	}

	void FSEObject::setZOrder(int ZOrder)
	{
		z_order_ = ZOrder;
		scene_->notifyZOrderChanged();
	}

	std::vector<std::unique_ptr<FSEObject>>* FSEObject::getSceneFSEObjects() const
	{
		return scene_->getFSEObjects();
	}

}
<commit_msg>FSEObject: Adjust position from spawnposition by default<commit_after>#include "FSEObject.h"
#include "../Application.h"

namespace fse
{

	FSEObject::FSEObject(Scene *scene) : position_(sf::Vector2f(0,0))
	{
		scene_ = scene;
		input_ = scene->getApplication()->getInput();
	}

	FSEObject::FSEObject(Scene* scene, const sf::Vector2f spawnPos) : FSEObject(scene)
	{
		position_ = spawnPos;
	}

	FSEObject::~FSEObject()
	{

	}

	void FSEObject::setPosition(const sf::Vector2f position)
	{
		position_ = position;
	}

	sf::Vector2f FSEObject::getPosition()
	{
		return position_;
	}

	void FSEObject::BeginContact(FSEObject* otherObject, b2Contact* contact)
	{
	}

	void FSEObject::EndContact(FSEObject* otherObject, b2Contact* contact)
	{
	}

	void FSEObject::PreSolve(FSEObject* otherObject, b2Contact* contact, const b2Manifold* oldManifold)
	{
	}

	void FSEObject::PostSolve(FSEObject* otherObject, b2Contact* contact, const b2ContactImpulse* impulse)
	{
	}

	int FSEObject::getZOrder() const
	{
		return z_order_;
	}

	bool FSEObject::isPendingKill() const
	{
		if (pending_timed_kill_)
			return true;
		return is_pending_kill_;
	}

	void FSEObject::setTimedKill()
	{
		pending_timed_kill_ = true;
	}

	Scene* FSEObject::getScene()
	{
		return scene_;
	}

	void FSEObject::spawn(int id)
	{
		id_ = id;
		spawned();
		spawned_signal_(this);
		spawned_signal_.disconnectAll();
	}

	bool FSEObject::destroy()
	{
		if (!is_pending_kill_)
		{
			is_pending_kill_ = true;

			scene_->destroyFSEObject(this);

			return true;
		}
		return false;
	}

	int FSEObject::getID()
	{
		return id_;
	}

	void FSEObject::setZOrder(int ZOrder)
	{
		z_order_ = ZOrder;
		scene_->notifyZOrderChanged();
	}

	std::vector<std::unique_ptr<FSEObject>>* FSEObject::getSceneFSEObjects() const
	{
		return scene_->getFSEObjects();
	}

}
<|endoftext|>


<commit_before>/*
	This file is part of the E_Util library.
	Copyright (C) 2012 Benjamin Eikel <benjamin@eikel.org>

	This library is subject to the terms of the Mozilla Public License, v. 2.0.
	You should have received a copy of the MPL along with this library; see the
	file LICENSE. If not, you can obtain one at http://mozilla.org/MPL/2.0/.
*/
#include "E_Window.h"

#include <EScript/Basics.h>
#include <EScript/StdObjects.h>
#include <Util/Graphics/Bitmap.h>
#include <Util/IO/FileName.h>
#include <Util/Serialization/Serialization.h>
#include <Util/UI/UI.h>

namespace E_Util {
namespace E_UI {

EScript::Type * E_Window::getTypeObject() {
	// E_Window ---|> E_Object
	static EScript::ERef<EScript::Type> typeObject = new EScript::Type(EScript::Object::getTypeObject());
	return typeObject.get();
}

void E_Window::init(EScript::Namespace & lib) {
	EScript::Type * typeObject = E_Window::getTypeObject();
	EScript::declareConstant(&lib, getClassName(), typeObject);

	static const EScript::StringId ATTR_borderless("borderless");
	static const EScript::StringId ATTR_debug("debug");
	static const EScript::StringId ATTR_compatibilityProfile("compatibilityProfile");
	static const EScript::StringId ATTR_fullscreen("fullscreen");
	static const EScript::StringId ATTR_multisampled("multisampled");
	static const EScript::StringId ATTR_positioned("positioned");
	static const EScript::StringId ATTR_resizable("resizable");
	static const EScript::StringId ATTR_clientAreaWidth("clientAreaWidth");
	static const EScript::StringId ATTR_clientAreaHeight("clientAreaHeight");
	static const EScript::StringId ATTR_posX("posX");
	static const EScript::StringId ATTR_posY("posY");
	static const EScript::StringId ATTR_multisamples("multisamples");
	static const EScript::StringId ATTR_title("title");

	//!(static) [ESM] ExtObject Window.createPropertyObject()
	ES_FUNCTION(typeObject, "createPropertyObject", 0, 0, {
		EScript::ERef<EScript::ExtObject> eProperties = EScript::ExtObject::create();
		const Util::UI::Window::Properties properties; // for default values

		eProperties->setAttribute(ATTR_borderless,EScript::Bool::create(properties.borderless));
		eProperties->setAttribute(ATTR_debug,EScript::Bool::create(properties.debug));
		eProperties->setAttribute(ATTR_compatibilityProfile,EScript::Bool::create(properties.compatibilityProfile));
		eProperties->setAttribute(ATTR_fullscreen,EScript::Bool::create(properties.fullscreen));
		eProperties->setAttribute(ATTR_multisampled,EScript::Bool::create(properties.multisampled));
		eProperties->setAttribute(ATTR_positioned,EScript::Bool::create(properties.positioned));
		eProperties->setAttribute(ATTR_resizable,EScript::Bool::create(properties.resizable));
		eProperties->setAttribute(ATTR_clientAreaWidth,EScript::Number::create(properties.clientAreaWidth));
		eProperties->setAttribute(ATTR_clientAreaHeight,EScript::Number::create(properties.clientAreaHeight));
		eProperties->setAttribute(ATTR_posX,EScript::Number::create(properties.posX));
		eProperties->setAttribute(ATTR_posY,EScript::Number::create(properties.posY));
		eProperties->setAttribute(ATTR_multisamples,EScript::Number::create(properties.multisamples));
		eProperties->setAttribute(ATTR_title,EScript::String::create(properties.title));
		return eProperties.detachAndDecrease();
	})

	//! [ESMF] Window new Window(Properties)
	ES_CONSTRUCTOR(typeObject, 1, 1,{
		Util::UI::Window::Properties properties;
		Object * eProperties = parameter[0].get();

		Object * attr;
		if( (attr = eProperties->getAttribute(ATTR_borderless).getValue()) != nullptr)
			properties.borderless = attr->toBool();
		if( (attr = eProperties->getAttribute(ATTR_debug).getValue()) != nullptr)
			properties.debug = attr->toBool();
		if( (attr = eProperties->getAttribute(ATTR_compatibilityProfile).getValue()) != nullptr)
			properties.compatibilityProfile = attr->toBool();
		if( (attr = eProperties->getAttribute(ATTR_fullscreen).getValue()) != nullptr)
			properties.fullscreen = attr->toBool();
		if( (attr = eProperties->getAttribute(ATTR_multisampled).getValue()) != nullptr)
			properties.multisampled = attr->toBool();
		if( (attr = eProperties->getAttribute(ATTR_positioned).getValue()) != nullptr)
			properties.positioned = attr->toBool();
		if( (attr = eProperties->getAttribute(ATTR_resizable).getValue()) != nullptr)
			properties.resizable = attr->toBool();
		if( (attr = eProperties->getAttribute(ATTR_clientAreaWidth).getValue()) != nullptr)
			properties.clientAreaWidth = attr->toUInt();
		if( (attr = eProperties->getAttribute(ATTR_clientAreaHeight).getValue()) != nullptr)
			properties.clientAreaHeight = attr->toUInt();
		if( (attr = eProperties->getAttribute(ATTR_posX).getValue()) != nullptr)
			properties.posX = attr->toInt();
		if( (attr = eProperties->getAttribute(ATTR_posY).getValue()) != nullptr)
			properties.posY = attr->toInt();
		if( (attr = eProperties->getAttribute(ATTR_multisamples).getValue()) != nullptr)
			properties.multisamples = attr->toUInt();
		if( (attr = eProperties->getAttribute(ATTR_title).getValue()) != nullptr)
			properties.title = attr->toString();
		return new E_Window(properties);
	})

	//! [ESMF] Void Window.destroy()
	ES_MFUN(typeObject, E_Window, "destroy", 0, 0, (thisObj->destroy(),thisEObj))

	//! [ESMF] thisObj Window.swapBuffers()
	ES_MFUN(typeObject, E_Window, "swapBuffers", 0, 0, ((**thisObj)->swapBuffers(), thisObj))

	//! [ESMF] Number Window.getSwapInterval()
	ES_MFUN(typeObject, E_Window, "getSwapInterval", 0, 0, (**thisObj)->getSwapInterval())

	//! [ESMF] self Window.grabInput()
	ES_MFUN(typeObject, E_Window, "grabInput", 0, 0, ((**thisObj)->grabInput(),thisEObj))

	//! [ESMF] thisObj Window.hideCursor()
	ES_MFUN(typeObject, E_Window, "hideCursor", 0, 0, ((**thisObj)->hideCursor(),thisEObj))

	//! [ESMF] thisObj Window.showCursor()
	ES_MFUN(typeObject, E_Window, "showCursor", 0, 0, ((**thisObj)->showCursor(), thisObj))

	//! [ESMF] self Window.ungrabInput()
	ES_MFUN(typeObject, E_Window, "ungrabInput", 0, 0, ((**thisObj)->ungrabInput(),thisEObj))

	//! [ESMF] thisObj Window.warpCursor(Number x, Number y)
	ES_MFUN(typeObject, E_Window, "warpCursor", 2, 2,
				 ((**thisObj)->warpCursor(parameter[0].toInt(), parameter[1].toInt()), thisObj))

	//! [ESMF] thisObj Window.setIcon(String imagePath)
	ES_MFUN(typeObject, E_Window, "setIcon", 1, 1,
				 ((**thisObj)->setIcon(*Util::Serialization::loadBitmap(Util::FileName(parameter[0].toString())).get()), thisObj))
}

E_Window::E_Window(const Util::UI::Window::Properties & properties) :
	ReferenceObject_t(E_Window::getTypeObject(), Util::UI::createWindow(properties)) {
}

E_Window::~E_Window() = default;

void E_Window::destroy() {
	ref().reset();
}

}
}
<commit_msg>Bindings for Window::makeCurrent() & new property 'shareContext'<commit_after>/*
	This file is part of the E_Util library.
	Copyright (C) 2012 Benjamin Eikel <benjamin@eikel.org>

	This library is subject to the terms of the Mozilla Public License, v. 2.0.
	You should have received a copy of the MPL along with this library; see the
	file LICENSE. If not, you can obtain one at http://mozilla.org/MPL/2.0/.
*/
#include "E_Window.h"

#include <EScript/Basics.h>
#include <EScript/StdObjects.h>
#include <Util/Graphics/Bitmap.h>
#include <Util/IO/FileName.h>
#include <Util/Serialization/Serialization.h>
#include <Util/UI/UI.h>

namespace E_Util {
namespace E_UI {

EScript::Type * E_Window::getTypeObject() {
	// E_Window ---|> E_Object
	static EScript::ERef<EScript::Type> typeObject = new EScript::Type(EScript::Object::getTypeObject());
	return typeObject.get();
}

void E_Window::init(EScript::Namespace & lib) {
	EScript::Type * typeObject = E_Window::getTypeObject();
	EScript::declareConstant(&lib, getClassName(), typeObject);

	static const EScript::StringId ATTR_borderless("borderless");
	static const EScript::StringId ATTR_debug("debug");
	static const EScript::StringId ATTR_compatibilityProfile("compatibilityProfile");
	static const EScript::StringId ATTR_fullscreen("fullscreen");
	static const EScript::StringId ATTR_multisampled("multisampled");
	static const EScript::StringId ATTR_positioned("positioned");
	static const EScript::StringId ATTR_resizable("resizable");
	static const EScript::StringId ATTR_clientAreaWidth("clientAreaWidth");
	static const EScript::StringId ATTR_clientAreaHeight("clientAreaHeight");
	static const EScript::StringId ATTR_posX("posX");
	static const EScript::StringId ATTR_posY("posY");
	static const EScript::StringId ATTR_multisamples("multisamples");
	static const EScript::StringId ATTR_title("title");
	static const EScript::StringId ATTR_shareContext("shareContext");

	//!(static) [ESM] ExtObject Window.createPropertyObject()
	ES_FUNCTION(typeObject, "createPropertyObject", 0, 0, {
		EScript::ERef<EScript::ExtObject> eProperties = EScript::ExtObject::create();
		const Util::UI::Window::Properties properties; // for default values

		eProperties->setAttribute(ATTR_borderless,EScript::Bool::create(properties.borderless));
		eProperties->setAttribute(ATTR_debug,EScript::Bool::create(properties.debug));
		eProperties->setAttribute(ATTR_compatibilityProfile,EScript::Bool::create(properties.compatibilityProfile));
		eProperties->setAttribute(ATTR_fullscreen,EScript::Bool::create(properties.fullscreen));
		eProperties->setAttribute(ATTR_multisampled,EScript::Bool::create(properties.multisampled));
		eProperties->setAttribute(ATTR_positioned,EScript::Bool::create(properties.positioned));
		eProperties->setAttribute(ATTR_resizable,EScript::Bool::create(properties.resizable));
		eProperties->setAttribute(ATTR_clientAreaWidth,EScript::Number::create(properties.clientAreaWidth));
		eProperties->setAttribute(ATTR_clientAreaHeight,EScript::Number::create(properties.clientAreaHeight));
		eProperties->setAttribute(ATTR_posX,EScript::Number::create(properties.posX));
		eProperties->setAttribute(ATTR_posY,EScript::Number::create(properties.posY));
		eProperties->setAttribute(ATTR_multisamples,EScript::Number::create(properties.multisamples));
		eProperties->setAttribute(ATTR_title,EScript::String::create(properties.title));
		eProperties->setAttribute(ATTR_shareContext,EScript::Bool::create(properties.shareContext));
		return eProperties.detachAndDecrease();
	})

	//! [ESMF] Window new Window(Properties)
	ES_CONSTRUCTOR(typeObject, 1, 1,{
		Util::UI::Window::Properties properties;
		Object * eProperties = parameter[0].get();

		Object * attr;
		if( (attr = eProperties->getAttribute(ATTR_borderless).getValue()) != nullptr)
			properties.borderless = attr->toBool();
		if( (attr = eProperties->getAttribute(ATTR_debug).getValue()) != nullptr)
			properties.debug = attr->toBool();
		if( (attr = eProperties->getAttribute(ATTR_compatibilityProfile).getValue()) != nullptr)
			properties.compatibilityProfile = attr->toBool();
		if( (attr = eProperties->getAttribute(ATTR_fullscreen).getValue()) != nullptr)
			properties.fullscreen = attr->toBool();
		if( (attr = eProperties->getAttribute(ATTR_multisampled).getValue()) != nullptr)
			properties.multisampled = attr->toBool();
		if( (attr = eProperties->getAttribute(ATTR_positioned).getValue()) != nullptr)
			properties.positioned = attr->toBool();
		if( (attr = eProperties->getAttribute(ATTR_resizable).getValue()) != nullptr)
			properties.resizable = attr->toBool();
		if( (attr = eProperties->getAttribute(ATTR_clientAreaWidth).getValue()) != nullptr)
			properties.clientAreaWidth = attr->toUInt();
		if( (attr = eProperties->getAttribute(ATTR_clientAreaHeight).getValue()) != nullptr)
			properties.clientAreaHeight = attr->toUInt();
		if( (attr = eProperties->getAttribute(ATTR_posX).getValue()) != nullptr)
			properties.posX = attr->toInt();
		if( (attr = eProperties->getAttribute(ATTR_posY).getValue()) != nullptr)
			properties.posY = attr->toInt();
		if( (attr = eProperties->getAttribute(ATTR_multisamples).getValue()) != nullptr)
			properties.multisamples = attr->toUInt();
		if( (attr = eProperties->getAttribute(ATTR_title).getValue()) != nullptr)
			properties.title = attr->toString();
		if( (attr = eProperties->getAttribute(ATTR_shareContext).getValue()) != nullptr)
			properties.shareContext = attr->toBool();
		return new E_Window(properties);
	})

	//! [ESMF] Void Window.destroy()
	ES_MFUN(typeObject, E_Window, "destroy", 0, 0, (thisObj->destroy(),thisEObj))

	//! [ESMF] thisObj Window.swapBuffers()
	ES_MFUN(typeObject, E_Window, "swapBuffers", 0, 0, ((**thisObj)->swapBuffers(), thisObj))

	//! [ESMF] Number Window.getSwapInterval()
	ES_MFUN(typeObject, E_Window, "getSwapInterval", 0, 0, (**thisObj)->getSwapInterval())

	//! [ESMF] self Window.grabInput()
	ES_MFUN(typeObject, E_Window, "grabInput", 0, 0, ((**thisObj)->grabInput(),thisEObj))

	//! [ESMF] thisObj Window.hideCursor()
	ES_MFUN(typeObject, E_Window, "hideCursor", 0, 0, ((**thisObj)->hideCursor(),thisEObj))

	//! [ESMF] thisObj Window.showCursor()
	ES_MFUN(typeObject, E_Window, "showCursor", 0, 0, ((**thisObj)->showCursor(), thisObj))

	//! [ESMF] self Window.ungrabInput()
	ES_MFUN(typeObject, E_Window, "ungrabInput", 0, 0, ((**thisObj)->ungrabInput(),thisEObj))

	//! [ESMF] thisObj Window.warpCursor(Number x, Number y)
	ES_MFUN(typeObject, E_Window, "warpCursor", 2, 2,
				 ((**thisObj)->warpCursor(parameter[0].toInt(), parameter[1].toInt()), thisObj))

	//! [ESMF] thisObj Window.setIcon(String imagePath)
	ES_MFUN(typeObject, E_Window, "setIcon", 1, 1,
				 ((**thisObj)->setIcon(*Util::Serialization::loadBitmap(Util::FileName(parameter[0].toString())).get()), thisObj))

	//! [ESMF] thisObj Window.makeCurrent()
	ES_MFUN(typeObject, E_Window, "makeCurrent", 0, 0, ((**thisObj)->makeCurrent(),thisEObj))
}

E_Window::E_Window(const Util::UI::Window::Properties & properties) :
	ReferenceObject_t(E_Window::getTypeObject(), Util::UI::createWindow(properties)) {
}

E_Window::~E_Window() = default;

void E_Window::destroy() {
	ref().reset();
}

}
}
<|endoftext|>


<commit_before>// Author: Danilo Piparo, Omar Zapata   16/12/2015

#include <unistd.h>
#include <fcntl.h>
#include <string>
#include <iostream>
#include "TInterpreter.h"

bool JupyROOTExecutorImpl(const char *code);
bool JupyROOTDeclarerImpl(const char *code);

class JupyROOTExecutorHandler {
private:
   bool fCapturing = false;
   std::string fStdoutpipe;
   std::string fStderrpipe;
   int fStdout_pipe[2];
   int fStderr_pipe[2];
   int fSaved_stderr;
   int fSaved_stdout;
public:
   JupyROOTExecutorHandler();
   void Poll();
   void InitCapture();
   void EndCapture();
   void Clear();
   std::string &GetStdout();
   std::string &GetStderr();
};

#ifndef F_LINUX_SPECIFIC_BASE
#define F_LINUX_SPECIFIC_BASE       1024
#endif
#ifndef F_SETPIPE_SZ
#define F_SETPIPE_SZ    (F_LINUX_SPECIFIC_BASE + 7)
#endif

constexpr long MAX_PIPE_SIZE = 1048575;

JupyROOTExecutorHandler::JupyROOTExecutorHandler() {}

static void PollImpl(FILE *stdStream, int *pipeHandle, std::string &pipeContent)
{
   int buf_read;
   char ch;
   fflush(stdStream);
   while (true) {
      buf_read = read(pipeHandle[0], &ch, 1);
      if (buf_read == 1) {
         pipeContent += ch;
      } else break;
   }
}

void JupyROOTExecutorHandler::Poll()
{
   PollImpl(stdout, fStdout_pipe, fStdoutpipe);
   PollImpl(stderr, fStderr_pipe, fStderrpipe);
}

static void InitCaptureImpl(int &savedStdStream, int *pipeHandle, int FILENO)
{
   savedStdStream = dup(FILENO);
   if (pipe(pipeHandle) != 0) {
      return;
   }
   long flags_stdout = fcntl(pipeHandle[0], F_GETFL);
   flags_stdout |= O_NONBLOCK;
   fcntl(pipeHandle[0], F_SETFL, flags_stdout);
   fcntl(pipeHandle[0], F_SETPIPE_SZ, MAX_PIPE_SIZE);
   dup2(pipeHandle[1], FILENO);
   close(pipeHandle[1]);
}

void JupyROOTExecutorHandler::InitCapture()
{
   if (!fCapturing)  {
      InitCaptureImpl(fSaved_stdout, fStdout_pipe, STDOUT_FILENO);
      InitCaptureImpl(fSaved_stderr, fStderr_pipe, STDERR_FILENO);
      fCapturing = true;
   }
}

void JupyROOTExecutorHandler::EndCapture()
{
   if (fCapturing)  {
      Poll();
      dup2(fSaved_stdout, STDOUT_FILENO);
      dup2(fSaved_stderr, STDERR_FILENO);
      fCapturing = false;
   }
}

void JupyROOTExecutorHandler::Clear()
{
   fStdoutpipe = "";
   fStderrpipe = "";
}

std::string &JupyROOTExecutorHandler::GetStdout()
{
   return fStdoutpipe;
}

std::string &JupyROOTExecutorHandler::GetStderr()
{
   return fStderrpipe;
}

JupyROOTExecutorHandler *JupyROOTExecutorHandler_ptr = nullptr;

////////////////////////////////////////////////////////////////////////////////
bool JupyROOTExecutorImpl(const char *code)
{
   auto status = false;
   try {
      TInterpreter::EErrorCode err = TInterpreter::kNoError;
      if (gInterpreter->ProcessLine(code, &err)) {
         status = true;
      }

      if (err == TInterpreter::kProcessing) {
         gInterpreter->ProcessLine(".@");
         gInterpreter->ProcessLine("cerr << \"Unbalanced curly braces. This cell was not processed.\" << endl;");
      }
   } catch (...) {
      status = true;
   }

   return status;
}

bool JupyROOTDeclarerImpl(const char *code)
{
   bool status = false;
   try {
      if (gInterpreter->Declare(code)) {
         status = true;
      }
   } catch (...) {
      status = true;
   }
   return status;
}

extern "C" {

   int JupyROOTExecutor(const char *code)
   {
      return JupyROOTExecutorImpl(code);
   }
   int JupyROOTDeclarer(const char *code)
   {
      return JupyROOTDeclarerImpl(code);
   }

   void JupyROOTExecutorHandler_Clear()
   {
      JupyROOTExecutorHandler_ptr->Clear();
   }

   void JupyROOTExecutorHandler_Ctor()
   {
      if (!JupyROOTExecutorHandler_ptr) {
         JupyROOTExecutorHandler_ptr = new JupyROOTExecutorHandler();
      }
   }

   void JupyROOTExecutorHandler_Poll()
   {
      JupyROOTExecutorHandler_ptr->Poll();
   }

   void JupyROOTExecutorHandler_EndCapture()
   {
      JupyROOTExecutorHandler_ptr->EndCapture();
   }

   void JupyROOTExecutorHandler_InitCapture()
   {
      JupyROOTExecutorHandler_ptr->InitCapture();
   }

   const char *JupyROOTExecutorHandler_GetStdout()
   {
      return JupyROOTExecutorHandler_ptr->GetStdout().c_str();
   }

   const char *JupyROOTExecutorHandler_GetStderr()
   {
      return JupyROOTExecutorHandler_ptr->GetStderr().c_str();
   }

   void JupyROOTExecutorHandler_Dtor()
   {
      if (!JupyROOTExecutorHandler_ptr) return;
      delete JupyROOTExecutorHandler_ptr;
      JupyROOTExecutorHandler_ptr = nullptr;
   }

}
<commit_msg>Modernize<commit_after>// Author: Danilo Piparo, Omar Zapata   16/12/2015

#include <unistd.h>
#include <fcntl.h>
#include <string>
#include <iostream>
#include "TInterpreter.h"

bool JupyROOTExecutorImpl(const char *code);
bool JupyROOTDeclarerImpl(const char *code);

class JupyROOTExecutorHandler {
private:
   bool fCapturing = false;
   std::string fStdoutpipe;
   std::string fStderrpipe;
   int fStdout_pipe[2];
   int fStderr_pipe[2];
   int fSaved_stderr;
   int fSaved_stdout;
public:
   JupyROOTExecutorHandler();
   void Poll();
   void InitCapture();
   void EndCapture();
   void Clear();
   std::string &GetStdout();
   std::string &GetStderr();
};

#ifndef F_LINUX_SPECIFIC_BASE
#define F_LINUX_SPECIFIC_BASE       1024
#endif
#ifndef F_SETPIPE_SZ
#define F_SETPIPE_SZ    (F_LINUX_SPECIFIC_BASE + 7)
#endif

constexpr long MAX_PIPE_SIZE = 1048575;

JupyROOTExecutorHandler::JupyROOTExecutorHandler() {}

static void PollImpl(FILE *stdStream, int *pipeHandle, std::string &pipeContent)
{
   int buf_read;
   char ch;
   fflush(stdStream);
   while (true) {
      buf_read = read(pipeHandle[0], &ch, 1);
      if (buf_read == 1) {
         pipeContent += ch;
      } else break;
   }
}

void JupyROOTExecutorHandler::Poll()
{
   PollImpl(stdout, fStdout_pipe, fStdoutpipe);
   PollImpl(stderr, fStderr_pipe, fStderrpipe);
}

static void InitCaptureImpl(int &savedStdStream, int *pipeHandle, int FILENO)
{
   savedStdStream = dup(FILENO);
   if (pipe(pipeHandle) != 0) {
      return;
   }
   long flags_stdout = fcntl(pipeHandle[0], F_GETFL);
   flags_stdout |= O_NONBLOCK;
   fcntl(pipeHandle[0], F_SETFL, flags_stdout);
   fcntl(pipeHandle[0], F_SETPIPE_SZ, MAX_PIPE_SIZE);
   dup2(pipeHandle[1], FILENO);
   close(pipeHandle[1]);
}

void JupyROOTExecutorHandler::InitCapture()
{
   if (!fCapturing)  {
      InitCaptureImpl(fSaved_stdout, fStdout_pipe, STDOUT_FILENO);
      InitCaptureImpl(fSaved_stderr, fStderr_pipe, STDERR_FILENO);
      fCapturing = true;
   }
}

void JupyROOTExecutorHandler::EndCapture()
{
   if (fCapturing)  {
      Poll();
      dup2(fSaved_stdout, STDOUT_FILENO);
      dup2(fSaved_stderr, STDERR_FILENO);
      fCapturing = false;
   }
}

void JupyROOTExecutorHandler::Clear()
{
   fStdoutpipe = "";
   fStderrpipe = "";
}

std::string &JupyROOTExecutorHandler::GetStdout()
{
   return fStdoutpipe;
}

std::string &JupyROOTExecutorHandler::GetStderr()
{
   return fStderrpipe;
}

JupyROOTExecutorHandler *JupyROOTExecutorHandler_ptr = nullptr;

////////////////////////////////////////////////////////////////////////////////
bool JupyROOTExecutorImpl(const char *code)
{
   auto status = false;
   try {
      auto err = TInterpreter::kNoError;
      if (gInterpreter->ProcessLine(code, &err)) {
         status = true;
      }

      if (err == TInterpreter::kProcessing) {
         gInterpreter->ProcessLine(".@");
         gInterpreter->ProcessLine("cerr << \"Unbalanced curly braces. This cell was not processed.\" << endl;");
      }
   } catch (...) {
      status = true;
   }

   return status;
}

bool JupyROOTDeclarerImpl(const char *code)
{
   auto status = false;
   try {
      if (gInterpreter->Declare(code)) {
         status = true;
      }
   } catch (...) {
      status = true;
   }
   return status;
}

extern "C" {

   int JupyROOTExecutor(const char *code)
   {
      return JupyROOTExecutorImpl(code);
   }
   int JupyROOTDeclarer(const char *code)
   {
      return JupyROOTDeclarerImpl(code);
   }

   void JupyROOTExecutorHandler_Clear()
   {
      JupyROOTExecutorHandler_ptr->Clear();
   }

   void JupyROOTExecutorHandler_Ctor()
   {
      if (!JupyROOTExecutorHandler_ptr) {
         JupyROOTExecutorHandler_ptr = new JupyROOTExecutorHandler();
      }
   }

   void JupyROOTExecutorHandler_Poll()
   {
      JupyROOTExecutorHandler_ptr->Poll();
   }

   void JupyROOTExecutorHandler_EndCapture()
   {
      JupyROOTExecutorHandler_ptr->EndCapture();
   }

   void JupyROOTExecutorHandler_InitCapture()
   {
      JupyROOTExecutorHandler_ptr->InitCapture();
   }

   const char *JupyROOTExecutorHandler_GetStdout()
   {
      return JupyROOTExecutorHandler_ptr->GetStdout().c_str();
   }

   const char *JupyROOTExecutorHandler_GetStderr()
   {
      return JupyROOTExecutorHandler_ptr->GetStderr().c_str();
   }

   void JupyROOTExecutorHandler_Dtor()
   {
      if (!JupyROOTExecutorHandler_ptr) return;
      delete JupyROOTExecutorHandler_ptr;
      JupyROOTExecutorHandler_ptr = nullptr;
   }

}
<|endoftext|>


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

  Program:   Monteverdi2
  Language:  C++

  Copyright (c) Centre National d'Etudes Spatiales. All rights reserved.
  See Copyright.txt for details.

  Monteverdi2 is distributed under the CeCILL licence version 2. See
  Licence_CeCILL_V2-en.txt or
  http://www.cecill.info/licences/Licence_CeCILL_V2-en.txt for more 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 notices for more information.

=========================================================================*/
#include "Gui/mvdPixelDescriptionWidget.h"
#include "Gui/ui_mvdPixelDescriptionWidget.h"

/*****************************************************************************/
/* INCLUDE SECTION                                                           */

//
// Qt includes (sorted by alphabetic order)
//// Must be included before system/custom includes.

//
// System includes (sorted by alphabetic order)

//
// ITK includes (sorted by alphabetic order)

//
// OTB includes (sorted by alphabetic order)

//
// Monteverdi includes (sorted by alphabetic order)
#include "Core/mvdAlgorithm.h"

namespace mvd
{
/*
  TRANSLATOR mvd::PixelDescriptionWidget

  Necessary for lupdate to be aware of C++ namespaces.

  Context comment for translator.
*/

/*****************************************************************************/
/* CONSTANTS                                                                 */

/*****************************************************************************/
/* STATIC IMPLEMENTATION SECTION                                             */

/*****************************************************************************/
/* CLASS IMPLEMENTATION SECTION                                              */

/*******************************************************************************/
PixelDescriptionWidget
::PixelDescriptionWidget( QWidget* parent, Qt::WindowFlags flags  ):
  QWidget( parent, flags ),
  m_UI( new mvd::Ui::PixelDescriptionWidget() )
{
  m_UI->setupUi( this );

  SetupUI();
}

/*******************************************************************************/
PixelDescriptionWidget
::~PixelDescriptionWidget()
{
}

/*******************************************************************************/
void
PixelDescriptionWidget
::SetupUI()
{
  //
  // Cartographic coordiantes
  m_CartographicRootItem = new QTreeWidgetItem( GetDescriptionTree() );
  m_CartographicRootItem->setText(0, tr("Cartographic"));
  m_CartographicRootItem->setExpanded(true);

  m_CartographicItem = new QTreeWidgetItem( m_CartographicRootItem );
  m_CartographicItem->setText(0, tr("Coordinates"));

  //
  // Geographic coordiantes
  m_GeographicRootItem = new QTreeWidgetItem( GetDescriptionTree() );
  m_GeographicRootItem->setText(0, tr("Geographic"));
  m_GeographicRootItem->setExpanded(true);

  m_GeographicItem = new QTreeWidgetItem( m_GeographicRootItem );
  m_GeographicItem->setText(0, tr("Coordinates"));

  //
  // Child items will be created + updated in a dedicated slot
  m_PixelValueRootItem = new QTreeWidgetItem( GetDescriptionTree() );
  m_PixelValueRootItem->setText(0, tr("Pixel Values"));
  m_PixelValueRootItem->setExpanded(true);
}

/*******************************************************************************/
QTreeWidget *
PixelDescriptionWidget
::GetDescriptionTree()
{
  return m_UI->m_DescriptionTree;
}

/*******************************************************************************/
/* SLOTS                                                                       */
/*******************************************************************************/
void
PixelDescriptionWidget
::OnCurrentPhysicalUpdated(const QString & currentPhysical)
{
  m_CartographicItem->setText(1, currentPhysical);
}

/*******************************************************************************/
void
PixelDescriptionWidget
::OnCurrentGeographicUpdated(const QString & currentGeo)
{
  m_GeographicItem->setText(1, currentGeo);
}

/*******************************************************************************/
void
PixelDescriptionWidget
::OnCurrentPixelValueUpdated(const VectorImageType::PixelType & currentPixel,
                             const QStringList& bandNames)
{
  //
  assert( bandNames.size()==currentPixel.GetSize() );

  //
  // remove the previous QTreeWidgetItem  of m_PixelValueRootItem
  while( m_PixelValueRootItem->childCount()>0 )
    {
    // Remove QTreeWidgetItem
    QTreeWidgetItem* child = m_PixelValueRootItem->takeChild( 0 );

    // Delete it from memory.
    delete child;
    child = NULL;
    }

  // fill with the new values
  for (unsigned int idx = 0; idx < currentPixel.GetSize(); idx++)
    {
    QTreeWidgetItem * iBandItem = new QTreeWidgetItem( m_PixelValueRootItem );

    // figure out if a band name is available, if not use Band idx
    if ( bandNames[idx].isEmpty() )
      {
      iBandItem->setText(0, QString( tr("Band") )+ QString(" %1").arg(idx) );
      }
    else
      {
      iBandItem->setText(0, bandNames[ idx ] );
      }
    // set the value
    iBandItem->setText(1, QString("%1").arg(currentPixel.GetElement( idx )) );
    }
}

/*******************************************************************************/

} // end namespace 'mvd'
<commit_msg>ENH: handle proprely bandnames<commit_after>/*=========================================================================

  Program:   Monteverdi2
  Language:  C++

  Copyright (c) Centre National d'Etudes Spatiales. All rights reserved.
  See Copyright.txt for details.

  Monteverdi2 is distributed under the CeCILL licence version 2. See
  Licence_CeCILL_V2-en.txt or
  http://www.cecill.info/licences/Licence_CeCILL_V2-en.txt for more 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 notices for more information.

=========================================================================*/
#include "Gui/mvdPixelDescriptionWidget.h"
#include "Gui/ui_mvdPixelDescriptionWidget.h"

/*****************************************************************************/
/* INCLUDE SECTION                                                           */

//
// Qt includes (sorted by alphabetic order)
//// Must be included before system/custom includes.

//
// System includes (sorted by alphabetic order)

//
// ITK includes (sorted by alphabetic order)

//
// OTB includes (sorted by alphabetic order)

//
// Monteverdi includes (sorted by alphabetic order)
#include "Core/mvdAlgorithm.h"

namespace mvd
{
/*
  TRANSLATOR mvd::PixelDescriptionWidget

  Necessary for lupdate to be aware of C++ namespaces.

  Context comment for translator.
*/

/*****************************************************************************/
/* CONSTANTS                                                                 */

/*****************************************************************************/
/* STATIC IMPLEMENTATION SECTION                                             */

/*****************************************************************************/
/* CLASS IMPLEMENTATION SECTION                                              */

/*******************************************************************************/
PixelDescriptionWidget
::PixelDescriptionWidget( QWidget* parent, Qt::WindowFlags flags  ):
  QWidget( parent, flags ),
  m_UI( new mvd::Ui::PixelDescriptionWidget() )
{
  m_UI->setupUi( this );

  SetupUI();
}

/*******************************************************************************/
PixelDescriptionWidget
::~PixelDescriptionWidget()
{
}

/*******************************************************************************/
void
PixelDescriptionWidget
::SetupUI()
{
  //
  // Cartographic coordiantes
  m_CartographicRootItem = new QTreeWidgetItem( GetDescriptionTree() );
  m_CartographicRootItem->setText(0, tr("Cartographic"));
  m_CartographicRootItem->setExpanded(true);

  m_CartographicItem = new QTreeWidgetItem( m_CartographicRootItem );
  m_CartographicItem->setText(0, tr("Coordinates"));

  //
  // Geographic coordiantes
  m_GeographicRootItem = new QTreeWidgetItem( GetDescriptionTree() );
  m_GeographicRootItem->setText(0, tr("Geographic"));
  m_GeographicRootItem->setExpanded(true);

  m_GeographicItem = new QTreeWidgetItem( m_GeographicRootItem );
  m_GeographicItem->setText(0, tr("Coordinates"));

  //
  // Child items will be created + updated in a dedicated slot
  m_PixelValueRootItem = new QTreeWidgetItem( GetDescriptionTree() );
  m_PixelValueRootItem->setText(0, tr("Pixel Values"));
  m_PixelValueRootItem->setExpanded(true);
}

/*******************************************************************************/
QTreeWidget *
PixelDescriptionWidget
::GetDescriptionTree()
{
  return m_UI->m_DescriptionTree;
}

/*******************************************************************************/
/* SLOTS                                                                       */
/*******************************************************************************/
void
PixelDescriptionWidget
::OnCurrentPhysicalUpdated(const QString & currentPhysical)
{
  m_CartographicItem->setText(1, currentPhysical);
}

/*******************************************************************************/
void
PixelDescriptionWidget
::OnCurrentGeographicUpdated(const QString & currentGeo)
{
  m_GeographicItem->setText(1, currentGeo);
}

/*******************************************************************************/
void
PixelDescriptionWidget
::OnCurrentPixelValueUpdated(const VectorImageType::PixelType & currentPixel,
                             const QStringList& bandNames)
{
  //
  // remove the previous QTreeWidgetItem  of m_PixelValueRootItem
  while( m_PixelValueRootItem->childCount()>0 )
    {
    // Remove QTreeWidgetItem
    QTreeWidgetItem* child = m_PixelValueRootItem->takeChild( 0 );

    // Delete it from memory.
    delete child;
    child = NULL;
    }

  // fill with the new values
  for (unsigned int idx = 0; idx < currentPixel.GetSize(); idx++)
    {
    QTreeWidgetItem * iBandItem = new QTreeWidgetItem( m_PixelValueRootItem );

    // figure out if a band name is available, if not use Band idx
    if ( bandNames.size()==currentPixel.GetSize() && !bandNames[idx].isEmpty() )
      {
      iBandItem->setText(0, bandNames[ idx ] );
      }
    else
      {
      iBandItem->setText(0, QString( tr("Band") )+ QString(" %1").arg(idx) );
      }
    // set the value
    iBandItem->setText(1, QString("%1").arg(currentPixel.GetElement( idx )) );
    }
}

/*******************************************************************************/

} // end namespace 'mvd'
<|endoftext|>