<commit_before>/*
 * Distributed under the OSI-approved Apache License, Version 2.0.  See
 * accompanying file Copyright.txt for details.
 *
 * Comm.cpp
 */

#include "adiosComm.h"
#include "adiosComm.tcc"

#include <algorithm>
#include <ios> //std::ios_base::failure
#include <iterator>
#include <utility>

#include "adios2/common/ADIOSMPI.h"
#include "adios2/helper/adiosString.h"

namespace adios2
{
namespace helper
{

Comm::Comm() = default;

Comm::Comm(MPI_Comm mpiComm) : m_MPIComm(mpiComm) {}

Comm::~Comm()
{
    // Handle the case where MPI is finalized before the ADIOS destructor is
    // called, which happens, e.g., with global / static ADIOS objects
    int flag;
    MPI_Finalized(&flag);
    if (!flag)
    {
        if (m_MPIComm != MPI_COMM_NULL && m_MPIComm != MPI_COMM_WORLD &&
            m_MPIComm != MPI_COMM_SELF)
        {
            SMPI_Comm_free(&m_MPIComm);
        }
    }
}

Comm::Comm(Comm &&comm) : m_MPIComm(comm.m_MPIComm)
{
    comm.m_MPIComm = MPI_COMM_NULL;
}

Comm &Comm::operator=(Comm &&comm)
{
    Comm(std::move(comm)).swap(*this);
    return *this;
}

void Comm::swap(Comm &comm) { std::swap(this->m_MPIComm, comm.m_MPIComm); }

Comm Comm::Duplicate(MPI_Comm mpiComm)
{
    MPI_Comm newComm;
    SMPI_Comm_dup(mpiComm, &newComm);
    return Comm(newComm);
}

void Comm::CheckMPIReturn(const int value, const std::string &hint)
{
    if (value == MPI_SUCCESS)
    {
        return;
    }

    std::string error;
    switch (value)
    {
    case MPI_ERR_COMM:
        error = "MPI_ERR_COMM";
        break;
    case MPI_ERR_INTERN:
        error = "MPI_ERR_INTERN";
        break;
    default:
        error = "MPI_ERR number: " + std::to_string(value);
    }

    throw std::runtime_error("ERROR: ADIOS2 detected " + error + ", " + hint);
}

void Comm::Free(const std::string &hint)
{
    if (m_MPIComm != MPI_COMM_NULL && m_MPIComm != MPI_COMM_WORLD &&
        m_MPIComm != MPI_COMM_SELF)
    {
        CheckMPIReturn(SMPI_Comm_free(&m_MPIComm), hint);
    }
}

Comm Comm::Split(int color, int key, const std::string &hint) const
{
    MPI_Comm newComm;
    CheckMPIReturn(MPI_Comm_split(m_MPIComm, color, key, &newComm), hint);
    return Comm(newComm);
}

int Comm::Rank() const
{
    int rank;
    CheckMPIReturn(SMPI_Comm_rank(m_MPIComm, &rank), {});
    return rank;
}

int Comm::Size() const
{
    int size;
    CheckMPIReturn(SMPI_Comm_size(m_MPIComm, &size), {});
    return size;
}

void Comm::Barrier(const std::string &hint) const
{
    CheckMPIReturn(SMPI_Barrier(m_MPIComm), hint);
}

std::string Comm::BroadcastFile(const std::string &fileName,
                                const std::string hint,
                                const int rankSource) const
{
    int rank;
    MPI_Comm_rank(m_MPIComm, &rank);
    std::string fileContents;

    // Read the file on rank 0 and broadcast it to everybody else
    if (rank == rankSource)
    {
        // load file contents
        fileContents = FileToString(fileName, hint);
    }
    fileContents = this->BroadcastValue(fileContents, rankSource);

    return fileContents;
}

void Comm::AllgatherImpl(const void *sendbuf, size_t sendcount,
                         MPI_Datatype sendtype, void *recvbuf, size_t recvcount,
                         MPI_Datatype recvtype, const std::string &hint) const
{
    CheckMPIReturn(
        SMPI_Allgather(sendbuf, static_cast<int>(sendcount), sendtype, recvbuf,
                       static_cast<int>(recvcount), recvtype, m_MPIComm),
        hint);
}

void Comm::AllreduceImpl(const void *sendbuf, void *recvbuf, size_t count,
                         MPI_Datatype datatype, MPI_Op op,
                         const std::string &hint) const
{
    CheckMPIReturn(SMPI_Allreduce(sendbuf, recvbuf, static_cast<int>(count),
                                  datatype, op, m_MPIComm),
                   hint);
}

void Comm::BcastImpl(void *buffer, size_t count, MPI_Datatype datatype,
                     size_t datatypeSize, int root,
                     const std::string &hint) const
{
    size_t inputSize = count;
    const int MAXBCASTSIZE = 1073741824;
    size_t blockSize = (inputSize > MAXBCASTSIZE ? MAXBCASTSIZE : inputSize);
    unsigned char *blockBuf = static_cast<unsigned char *>(buffer);
    while (inputSize > 0)
    {
        CheckMPIReturn(SMPI_Bcast(blockBuf, static_cast<int>(blockSize),
                                  datatype, root, m_MPIComm),
                       hint);
        blockBuf += blockSize * datatypeSize;
        inputSize -= blockSize;
        blockSize = (inputSize > MAXBCASTSIZE ? MAXBCASTSIZE : inputSize);
    }
}

void Comm::GatherImpl(const void *sendbuf, size_t sendcount,
                      MPI_Datatype sendtype, void *recvbuf, size_t recvcount,
                      MPI_Datatype recvtype, int root,
                      const std::string &hint) const
{
    CheckMPIReturn(SMPI_Gather(sendbuf, static_cast<int>(sendcount), sendtype,
                               recvbuf, static_cast<int>(recvcount), recvtype,
                               root, m_MPIComm),
                   hint);
}

void Comm::GathervImpl(const void *sendbuf, size_t sendcount,
                       MPI_Datatype sendtype, void *recvbuf,
                       const size_t *recvcounts, const size_t *displs,
                       MPI_Datatype recvtype, int root,
                       const std::string &hint) const
{
    std::vector<int> countsInt;
    std::vector<int> displsInt;
    if (root == this->Rank())
    {
        auto cast = [](size_t sz) -> int { return int(sz); };
        const int size = this->Size();
        countsInt.reserve(size);
        std::transform(recvcounts, recvcounts + size,
                       std::back_inserter(countsInt), cast);
        displsInt.reserve(size);
        std::transform(displs, displs + size, std::back_inserter(displsInt),
                       cast);
    }
    CheckMPIReturn(SMPI_Gatherv(sendbuf, static_cast<int>(sendcount), sendtype,
                                recvbuf, countsInt.data(), displsInt.data(),
                                recvtype, root, m_MPIComm),
                   hint);
}

void Comm::ReduceImpl(const void *sendbuf, void *recvbuf, size_t count,
                      MPI_Datatype datatype, MPI_Op op, int root,
                      const std::string &hint) const
{
    CheckMPIReturn(SMPI_Reduce(sendbuf, recvbuf, static_cast<int>(count),
                               datatype, op, root, m_MPIComm),
                   hint);
}

void Comm::ReduceInPlaceImpl(void *buf, size_t count, MPI_Datatype datatype,
                             MPI_Op op, int root, const std::string &hint) const
{
    CheckMPIReturn(SMPI_Reduce(MPI_IN_PLACE, buf, static_cast<int>(count),
                               datatype, op, root, m_MPIComm),
                   hint);
}

void Comm::SendImpl(const void *buf, size_t count, MPI_Datatype datatype,
                    int dest, int tag, const std::string &hint) const
{
    CheckMPIReturn(
        MPI_Send(buf, static_cast<int>(count), datatype, dest, tag, m_MPIComm),
        hint);
}

Comm::Status Comm::RecvImpl(void *buf, size_t count, MPI_Datatype datatype,
                            int source, int tag, const std::string &hint) const
{
    MPI_Status mpiStatus;
    CheckMPIReturn(MPI_Recv(buf, static_cast<int>(count), datatype, source, tag,
                            m_MPIComm, &mpiStatus),
                   hint);

    Status status;
#ifdef ADIOS2_HAVE_MPI
    status.Source = mpiStatus.MPI_SOURCE;
    status.Tag = mpiStatus.MPI_TAG;
    {
        int mpiCount = 0;
        CheckMPIReturn(MPI_Get_count(&mpiStatus, datatype, &mpiCount), hint);
        status.Count = mpiCount;
    }
#endif
    return status;
}

void Comm::ScatterImpl(const void *sendbuf, size_t sendcount,
                       MPI_Datatype sendtype, void *recvbuf, size_t recvcount,
                       MPI_Datatype recvtype, int root,
                       const std::string &hint) const
{
    CheckMPIReturn(MPI_Scatter(sendbuf, static_cast<int>(sendcount), sendtype,
                               recvbuf, static_cast<int>(recvcount), recvtype,
                               root, m_MPIComm),
                   hint);
}

Comm::Req Comm::IsendImpl(const void *buffer, size_t count,
                          MPI_Datatype datatype, int dest, int tag,
                          const std::string &hint) const
{
    Comm::Req req(datatype);

    if (count > DefaultMaxFileBatchSize)
    {
        const size_t batches = count / DefaultMaxFileBatchSize;

        size_t position = 0;
        for (size_t b = 0; b < batches; ++b)
        {
            int batchSize = static_cast<int>(DefaultMaxFileBatchSize);
            MPI_Request mpiReq;
            CheckMPIReturn(
                MPI_Isend(static_cast<char *>(const_cast<void *>(buffer)) +
                              position,
                          batchSize, datatype, dest, tag, m_MPIComm, &mpiReq),
                "in call to Isend batch " + std::to_string(b) + " " + hint +
                    "\n");
            req.m_MPIReqs.emplace_back(mpiReq);

            position += DefaultMaxFileBatchSize;
        }
        const size_t remainder = count % DefaultMaxFileBatchSize;
        if (remainder > 0)
        {
            int batchSize = static_cast<int>(remainder);
            MPI_Request mpiReq;
            CheckMPIReturn(
                MPI_Isend(static_cast<char *>(const_cast<void *>(buffer)) +
                              position,
                          batchSize, datatype, dest, tag, m_MPIComm, &mpiReq),
                "in call to Isend remainder batch " + hint + "\n");
            req.m_MPIReqs.emplace_back(mpiReq);
        }
    }
    else
    {
        int batchSize = static_cast<int>(count);
        MPI_Request mpiReq;
        CheckMPIReturn(
            MPI_Isend(static_cast<char *>(const_cast<void *>(buffer)),
                      batchSize, datatype, dest, tag, m_MPIComm, &mpiReq),
            " in call to Isend with single batch " + hint + "\n");
        req.m_MPIReqs.emplace_back(mpiReq);
    }
    return req;
}

Comm::Req Comm::IrecvImpl(void *buffer, size_t count, MPI_Datatype datatype,
                          int source, int tag, const std::string &hint) const
{
    Comm::Req req(datatype);

    if (count > DefaultMaxFileBatchSize)
    {
        const size_t batches = count / DefaultMaxFileBatchSize;
        size_t position = 0;
        for (size_t b = 0; b < batches; ++b)
        {
            int batchSize = static_cast<int>(DefaultMaxFileBatchSize);
            MPI_Request mpiReq;
            CheckMPIReturn(MPI_Irecv(static_cast<char *>(buffer) + position,
                                     batchSize, datatype, source, tag,
                                     m_MPIComm, &mpiReq),
                           "in call to Irecv batch " + std::to_string(b) + " " +
                               hint + "\n");
            req.m_MPIReqs.emplace_back(mpiReq);

            position += DefaultMaxFileBatchSize;
        }

        const size_t remainder = count % DefaultMaxFileBatchSize;
        if (remainder > 0)
        {
            int batchSize = static_cast<int>(remainder);
            MPI_Request mpiReq;
            CheckMPIReturn(MPI_Irecv(static_cast<char *>(buffer) + position,
                                     batchSize, datatype, source, tag,
                                     m_MPIComm, &mpiReq),
                           "in call to Irecv remainder batch " + hint + "\n");
            req.m_MPIReqs.emplace_back(mpiReq);
        }
    }
    else
    {
        int batchSize = static_cast<int>(count);
        MPI_Request mpiReq;
        CheckMPIReturn(MPI_Irecv(buffer, batchSize, datatype, source, tag,
                                 m_MPIComm, &mpiReq),
                       " in call to Isend with single batch " + hint + "\n");
        req.m_MPIReqs.emplace_back(mpiReq);
    }

    return req;
}

Comm::Req::Req() = default;

Comm::Req::Req(MPI_Datatype datatype) : m_MPIDatatype(datatype) {}

Comm::Req::~Req() {}

Comm::Req::Req(Req &&req)
: m_MPIDatatype(req.m_MPIDatatype), m_MPIReqs(std::move(req.m_MPIReqs))
{
}

Comm::Req &Comm::Req::operator=(Req &&req)
{
    Req(std::move(req)).swap(*this);
    return *this;
}

void Comm::Req::swap(Req &req)
{
    std::swap(this->m_MPIDatatype, req.m_MPIDatatype);
    std::swap(this->m_MPIReqs, req.m_MPIReqs);
}

Comm::Status Comm::Req::Wait(const std::string &hint)
{
    Comm::Status status;
    if (m_MPIReqs.empty())
    {
        return status;
    }

#ifdef ADIOS2_HAVE_MPI
    std::vector<MPI_Request> mpiRequests = std::move(m_MPIReqs);
    std::vector<MPI_Status> mpiStatuses(mpiRequests.size());

    if (mpiRequests.size() > 1)
    {
        int mpiReturn = MPI_Waitall(static_cast<int>(mpiRequests.size()),
                                    mpiRequests.data(), mpiStatuses.data());
        if (mpiReturn == MPI_ERR_IN_STATUS)
        {
            for (auto &mpiStatus : mpiStatuses)
            {
                if (mpiStatus.MPI_ERROR != MPI_SUCCESS)
                {
                    mpiReturn = mpiStatus.MPI_ERROR;
                    break;
                }
            }
        }
        CheckMPIReturn(mpiReturn, hint);
    }
    else
    {
        CheckMPIReturn(MPI_Wait(mpiRequests.data(), mpiStatuses.data()), hint);
    }

    // Our batched operation should be from only one source and have one tag.
    status.Source = mpiStatuses.front().MPI_SOURCE;
    status.Tag = mpiStatuses.front().MPI_TAG;

    // Accumulate the total count of our batched operation.
    for (auto &mpiStatus : mpiStatuses)
    {
        int mpiCount = 0;
        CheckMPIReturn(MPI_Get_count(&mpiStatus, m_MPIDatatype, &mpiCount),
                       hint);
        status.Count += mpiCount;
    }

    // Our batched operation was cancelled if any member was cancelled.
    for (auto &mpiStatus : mpiStatuses)
    {
        int mpiCancelled = 0;
        MPI_Test_cancelled(&mpiStatus, &mpiCancelled);
        if (mpiCancelled)
        {
            status.Cancelled = true;
            break;
        }
    }
#endif

    return status;
}

} // end namespace helper
} // end namespace adios2
<commit_msg>helper: Implement Comm::BroadcastFile in terms of our encapsulation<commit_after>/*
 * Distributed under the OSI-approved Apache License, Version 2.0.  See
 * accompanying file Copyright.txt for details.
 *
 * Comm.cpp
 */

#include "adiosComm.h"
#include "adiosComm.tcc"

#include <algorithm>
#include <ios> //std::ios_base::failure
#include <iterator>
#include <utility>

#include "adios2/common/ADIOSMPI.h"
#include "adios2/helper/adiosString.h"

namespace adios2
{
namespace helper
{

Comm::Comm() = default;

Comm::Comm(MPI_Comm mpiComm) : m_MPIComm(mpiComm) {}

Comm::~Comm()
{
    // Handle the case where MPI is finalized before the ADIOS destructor is
    // called, which happens, e.g., with global / static ADIOS objects
    int flag;
    MPI_Finalized(&flag);
    if (!flag)
    {
        if (m_MPIComm != MPI_COMM_NULL && m_MPIComm != MPI_COMM_WORLD &&
            m_MPIComm != MPI_COMM_SELF)
        {
            SMPI_Comm_free(&m_MPIComm);
        }
    }
}

Comm::Comm(Comm &&comm) : m_MPIComm(comm.m_MPIComm)
{
    comm.m_MPIComm = MPI_COMM_NULL;
}

Comm &Comm::operator=(Comm &&comm)
{
    Comm(std::move(comm)).swap(*this);
    return *this;
}

void Comm::swap(Comm &comm) { std::swap(this->m_MPIComm, comm.m_MPIComm); }

Comm Comm::Duplicate(MPI_Comm mpiComm)
{
    MPI_Comm newComm;
    SMPI_Comm_dup(mpiComm, &newComm);
    return Comm(newComm);
}

void Comm::CheckMPIReturn(const int value, const std::string &hint)
{
    if (value == MPI_SUCCESS)
    {
        return;
    }

    std::string error;
    switch (value)
    {
    case MPI_ERR_COMM:
        error = "MPI_ERR_COMM";
        break;
    case MPI_ERR_INTERN:
        error = "MPI_ERR_INTERN";
        break;
    default:
        error = "MPI_ERR number: " + std::to_string(value);
    }

    throw std::runtime_error("ERROR: ADIOS2 detected " + error + ", " + hint);
}

void Comm::Free(const std::string &hint)
{
    if (m_MPIComm != MPI_COMM_NULL && m_MPIComm != MPI_COMM_WORLD &&
        m_MPIComm != MPI_COMM_SELF)
    {
        CheckMPIReturn(SMPI_Comm_free(&m_MPIComm), hint);
    }
}

Comm Comm::Split(int color, int key, const std::string &hint) const
{
    MPI_Comm newComm;
    CheckMPIReturn(MPI_Comm_split(m_MPIComm, color, key, &newComm), hint);
    return Comm(newComm);
}

int Comm::Rank() const
{
    int rank;
    CheckMPIReturn(SMPI_Comm_rank(m_MPIComm, &rank), {});
    return rank;
}

int Comm::Size() const
{
    int size;
    CheckMPIReturn(SMPI_Comm_size(m_MPIComm, &size), {});
    return size;
}

void Comm::Barrier(const std::string &hint) const
{
    CheckMPIReturn(SMPI_Barrier(m_MPIComm), hint);
}

std::string Comm::BroadcastFile(const std::string &fileName,
                                const std::string hint,
                                const int rankSource) const
{
    int rank = this->Rank();
    std::string fileContents;

    // Read the file on rank 0 and broadcast it to everybody else
    if (rank == rankSource)
    {
        // load file contents
        fileContents = FileToString(fileName, hint);
    }
    fileContents = this->BroadcastValue(fileContents, rankSource);

    return fileContents;
}

void Comm::AllgatherImpl(const void *sendbuf, size_t sendcount,
                         MPI_Datatype sendtype, void *recvbuf, size_t recvcount,
                         MPI_Datatype recvtype, const std::string &hint) const
{
    CheckMPIReturn(
        SMPI_Allgather(sendbuf, static_cast<int>(sendcount), sendtype, recvbuf,
                       static_cast<int>(recvcount), recvtype, m_MPIComm),
        hint);
}

void Comm::AllreduceImpl(const void *sendbuf, void *recvbuf, size_t count,
                         MPI_Datatype datatype, MPI_Op op,
                         const std::string &hint) const
{
    CheckMPIReturn(SMPI_Allreduce(sendbuf, recvbuf, static_cast<int>(count),
                                  datatype, op, m_MPIComm),
                   hint);
}

void Comm::BcastImpl(void *buffer, size_t count, MPI_Datatype datatype,
                     size_t datatypeSize, int root,
                     const std::string &hint) const
{
    size_t inputSize = count;
    const int MAXBCASTSIZE = 1073741824;
    size_t blockSize = (inputSize > MAXBCASTSIZE ? MAXBCASTSIZE : inputSize);
    unsigned char *blockBuf = static_cast<unsigned char *>(buffer);
    while (inputSize > 0)
    {
        CheckMPIReturn(SMPI_Bcast(blockBuf, static_cast<int>(blockSize),
                                  datatype, root, m_MPIComm),
                       hint);
        blockBuf += blockSize * datatypeSize;
        inputSize -= blockSize;
        blockSize = (inputSize > MAXBCASTSIZE ? MAXBCASTSIZE : inputSize);
    }
}

void Comm::GatherImpl(const void *sendbuf, size_t sendcount,
                      MPI_Datatype sendtype, void *recvbuf, size_t recvcount,
                      MPI_Datatype recvtype, int root,
                      const std::string &hint) const
{
    CheckMPIReturn(SMPI_Gather(sendbuf, static_cast<int>(sendcount), sendtype,
                               recvbuf, static_cast<int>(recvcount), recvtype,
                               root, m_MPIComm),
                   hint);
}

void Comm::GathervImpl(const void *sendbuf, size_t sendcount,
                       MPI_Datatype sendtype, void *recvbuf,
                       const size_t *recvcounts, const size_t *displs,
                       MPI_Datatype recvtype, int root,
                       const std::string &hint) const
{
    std::vector<int> countsInt;
    std::vector<int> displsInt;
    if (root == this->Rank())
    {
        auto cast = [](size_t sz) -> int { return int(sz); };
        const int size = this->Size();
        countsInt.reserve(size);
        std::transform(recvcounts, recvcounts + size,
                       std::back_inserter(countsInt), cast);
        displsInt.reserve(size);
        std::transform(displs, displs + size, std::back_inserter(displsInt),
                       cast);
    }
    CheckMPIReturn(SMPI_Gatherv(sendbuf, static_cast<int>(sendcount), sendtype,
                                recvbuf, countsInt.data(), displsInt.data(),
                                recvtype, root, m_MPIComm),
                   hint);
}

void Comm::ReduceImpl(const void *sendbuf, void *recvbuf, size_t count,
                      MPI_Datatype datatype, MPI_Op op, int root,
                      const std::string &hint) const
{
    CheckMPIReturn(SMPI_Reduce(sendbuf, recvbuf, static_cast<int>(count),
                               datatype, op, root, m_MPIComm),
                   hint);
}

void Comm::ReduceInPlaceImpl(void *buf, size_t count, MPI_Datatype datatype,
                             MPI_Op op, int root, const std::string &hint) const
{
    CheckMPIReturn(SMPI_Reduce(MPI_IN_PLACE, buf, static_cast<int>(count),
                               datatype, op, root, m_MPIComm),
                   hint);
}

void Comm::SendImpl(const void *buf, size_t count, MPI_Datatype datatype,
                    int dest, int tag, const std::string &hint) const
{
    CheckMPIReturn(
        MPI_Send(buf, static_cast<int>(count), datatype, dest, tag, m_MPIComm),
        hint);
}

Comm::Status Comm::RecvImpl(void *buf, size_t count, MPI_Datatype datatype,
                            int source, int tag, const std::string &hint) const
{
    MPI_Status mpiStatus;
    CheckMPIReturn(MPI_Recv(buf, static_cast<int>(count), datatype, source, tag,
                            m_MPIComm, &mpiStatus),
                   hint);

    Status status;
#ifdef ADIOS2_HAVE_MPI
    status.Source = mpiStatus.MPI_SOURCE;
    status.Tag = mpiStatus.MPI_TAG;
    {
        int mpiCount = 0;
        CheckMPIReturn(MPI_Get_count(&mpiStatus, datatype, &mpiCount), hint);
        status.Count = mpiCount;
    }
#endif
    return status;
}

void Comm::ScatterImpl(const void *sendbuf, size_t sendcount,
                       MPI_Datatype sendtype, void *recvbuf, size_t recvcount,
                       MPI_Datatype recvtype, int root,
                       const std::string &hint) const
{
    CheckMPIReturn(MPI_Scatter(sendbuf, static_cast<int>(sendcount), sendtype,
                               recvbuf, static_cast<int>(recvcount), recvtype,
                               root, m_MPIComm),
                   hint);
}

Comm::Req Comm::IsendImpl(const void *buffer, size_t count,
                          MPI_Datatype datatype, int dest, int tag,
                          const std::string &hint) const
{
    Comm::Req req(datatype);

    if (count > DefaultMaxFileBatchSize)
    {
        const size_t batches = count / DefaultMaxFileBatchSize;

        size_t position = 0;
        for (size_t b = 0; b < batches; ++b)
        {
            int batchSize = static_cast<int>(DefaultMaxFileBatchSize);
            MPI_Request mpiReq;
            CheckMPIReturn(
                MPI_Isend(static_cast<char *>(const_cast<void *>(buffer)) +
                              position,
                          batchSize, datatype, dest, tag, m_MPIComm, &mpiReq),
                "in call to Isend batch " + std::to_string(b) + " " + hint +
                    "\n");
            req.m_MPIReqs.emplace_back(mpiReq);

            position += DefaultMaxFileBatchSize;
        }
        const size_t remainder = count % DefaultMaxFileBatchSize;
        if (remainder > 0)
        {
            int batchSize = static_cast<int>(remainder);
            MPI_Request mpiReq;
            CheckMPIReturn(
                MPI_Isend(static_cast<char *>(const_cast<void *>(buffer)) +
                              position,
                          batchSize, datatype, dest, tag, m_MPIComm, &mpiReq),
                "in call to Isend remainder batch " + hint + "\n");
            req.m_MPIReqs.emplace_back(mpiReq);
        }
    }
    else
    {
        int batchSize = static_cast<int>(count);
        MPI_Request mpiReq;
        CheckMPIReturn(
            MPI_Isend(static_cast<char *>(const_cast<void *>(buffer)),
                      batchSize, datatype, dest, tag, m_MPIComm, &mpiReq),
            " in call to Isend with single batch " + hint + "\n");
        req.m_MPIReqs.emplace_back(mpiReq);
    }
    return req;
}

Comm::Req Comm::IrecvImpl(void *buffer, size_t count, MPI_Datatype datatype,
                          int source, int tag, const std::string &hint) const
{
    Comm::Req req(datatype);

    if (count > DefaultMaxFileBatchSize)
    {
        const size_t batches = count / DefaultMaxFileBatchSize;
        size_t position = 0;
        for (size_t b = 0; b < batches; ++b)
        {
            int batchSize = static_cast<int>(DefaultMaxFileBatchSize);
            MPI_Request mpiReq;
            CheckMPIReturn(MPI_Irecv(static_cast<char *>(buffer) + position,
                                     batchSize, datatype, source, tag,
                                     m_MPIComm, &mpiReq),
                           "in call to Irecv batch " + std::to_string(b) + " " +
                               hint + "\n");
            req.m_MPIReqs.emplace_back(mpiReq);

            position += DefaultMaxFileBatchSize;
        }

        const size_t remainder = count % DefaultMaxFileBatchSize;
        if (remainder > 0)
        {
            int batchSize = static_cast<int>(remainder);
            MPI_Request mpiReq;
            CheckMPIReturn(MPI_Irecv(static_cast<char *>(buffer) + position,
                                     batchSize, datatype, source, tag,
                                     m_MPIComm, &mpiReq),
                           "in call to Irecv remainder batch " + hint + "\n");
            req.m_MPIReqs.emplace_back(mpiReq);
        }
    }
    else
    {
        int batchSize = static_cast<int>(count);
        MPI_Request mpiReq;
        CheckMPIReturn(MPI_Irecv(buffer, batchSize, datatype, source, tag,
                                 m_MPIComm, &mpiReq),
                       " in call to Isend with single batch " + hint + "\n");
        req.m_MPIReqs.emplace_back(mpiReq);
    }

    return req;
}

Comm::Req::Req() = default;

Comm::Req::Req(MPI_Datatype datatype) : m_MPIDatatype(datatype) {}

Comm::Req::~Req() {}

Comm::Req::Req(Req &&req)
: m_MPIDatatype(req.m_MPIDatatype), m_MPIReqs(std::move(req.m_MPIReqs))
{
}

Comm::Req &Comm::Req::operator=(Req &&req)
{
    Req(std::move(req)).swap(*this);
    return *this;
}

void Comm::Req::swap(Req &req)
{
    std::swap(this->m_MPIDatatype, req.m_MPIDatatype);
    std::swap(this->m_MPIReqs, req.m_MPIReqs);
}

Comm::Status Comm::Req::Wait(const std::string &hint)
{
    Comm::Status status;
    if (m_MPIReqs.empty())
    {
        return status;
    }

#ifdef ADIOS2_HAVE_MPI
    std::vector<MPI_Request> mpiRequests = std::move(m_MPIReqs);
    std::vector<MPI_Status> mpiStatuses(mpiRequests.size());

    if (mpiRequests.size() > 1)
    {
        int mpiReturn = MPI_Waitall(static_cast<int>(mpiRequests.size()),
                                    mpiRequests.data(), mpiStatuses.data());
        if (mpiReturn == MPI_ERR_IN_STATUS)
        {
            for (auto &mpiStatus : mpiStatuses)
            {
                if (mpiStatus.MPI_ERROR != MPI_SUCCESS)
                {
                    mpiReturn = mpiStatus.MPI_ERROR;
                    break;
                }
            }
        }
        CheckMPIReturn(mpiReturn, hint);
    }
    else
    {
        CheckMPIReturn(MPI_Wait(mpiRequests.data(), mpiStatuses.data()), hint);
    }

    // Our batched operation should be from only one source and have one tag.
    status.Source = mpiStatuses.front().MPI_SOURCE;
    status.Tag = mpiStatuses.front().MPI_TAG;

    // Accumulate the total count of our batched operation.
    for (auto &mpiStatus : mpiStatuses)
    {
        int mpiCount = 0;
        CheckMPIReturn(MPI_Get_count(&mpiStatus, m_MPIDatatype, &mpiCount),
                       hint);
        status.Count += mpiCount;
    }

    // Our batched operation was cancelled if any member was cancelled.
    for (auto &mpiStatus : mpiStatuses)
    {
        int mpiCancelled = 0;
        MPI_Test_cancelled(&mpiStatus, &mpiCancelled);
        if (mpiCancelled)
        {
            status.Cancelled = true;
            break;
        }
    }
#endif

    return status;
}

} // end namespace helper
} // end namespace adios2
<|endoftext|>


<commit_before>#include <iostream>

#include <boost/thread.hpp>

#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>

#include <include/ImageUtils.h>

#include "utils.h"

class ResizeCallback: public ghog::lib::ImageCallback
{
public:
	ResizeCallback(int num_images)
	{
		_finished = 0;
		_total_images = num_images;
	}
	void image_processed(cv::Mat ret_mat)
	{
		_finished++;
	}

	bool is_finished()
	{
		return (_finished == _total_images);
	}

private:
	int _finished;
	int _total_images;
};

int main(int argc,
	char** argv)
{
	std::vector< std::string > file_list = getImagesList("resources/inputs");
	cleanOutputDir("resources/resized");
	ResizeCallback callback(file_list.size());
	ghog::lib::ImageUtils utils(&callback);
	cv::Size new_size(24, 24);

	for(int i = 0; i < file_list.size(); ++i)
	{
		cv::Mat input_img = cv::imread(file_list[i], CV_LOAD_IMAGE_GRAYSCALE);
		utils.resize(input_img, new_size);
	}
	std::cout << "Processing " << file_list.size() << " images..." << std::endl;
	while(!callback.is_finished())
	{
		std::cout << ".";
		std::cout.flush();
		boost::this_thread::sleep(boost::posix_time::milliseconds(1000));
	}
	std::cout << std::endl;
	std::cout << "Images processed." << std::endl;
	return 0;
}

<commit_msg>Remove useless (at the moment) directory cleanup.<commit_after>#include <iostream>

#include <boost/thread.hpp>

#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>

#include <include/ImageUtils.h>

#include "utils.h"

class ResizeCallback: public ghog::lib::ImageCallback
{
public:
	ResizeCallback(int num_images)
	{
		_finished = 0;
		_total_images = num_images;
	}
	void image_processed(cv::Mat ret_mat)
	{
		_finished++;
	}

	bool is_finished()
	{
		return (_finished == _total_images);
	}

private:
	int _finished;
	int _total_images;
};

int main(int argc,
	char** argv)
{
	std::vector< std::string > file_list = getImagesList("resources/inputs");
	ResizeCallback callback(file_list.size());
	ghog::lib::ImageUtils utils(&callback);
	cv::Size new_size(24, 24);

	for(int i = 0; i < file_list.size(); ++i)
	{
		cv::Mat input_img = cv::imread(file_list[i], CV_LOAD_IMAGE_GRAYSCALE);
		utils.resize(input_img, new_size);
	}
	std::cout << "Processing " << file_list.size() << " images..." << std::endl;
	while(!callback.is_finished())
	{
		std::cout << ".";
		std::cout.flush();
		boost::this_thread::sleep(boost::posix_time::milliseconds(1000));
	}
	std::cout << std::endl;
	std::cout << "Images processed." << std::endl;
	return 0;
}

<|endoftext|>


<commit_before>#include	<cstdlib>
#include	<cmath>
#include	<fstream>
#include	<sstream>
#include	<iostream>
#include	<iomanip>
#include	<string>
#include	<vector>
#include	<algorithm>
#include	<exception>
#include	<sys/time.h>
#include	"modules/htmTree.h"
#include	"modules/kdTree.h"
#include        "misc.h"
#include        "feat.h"
#include        "structs.h"
#include        "collision.h"
#include        "global.h"
//reduce redistributes, updates  07/02/15 rnc
int main(int argc, char **argv) {
	//// Initializations ---------------------------------------------
	srand48(1234); // Make sure we have reproducability
	check_args(argc);
	Time t, time; // t for global, time for local
	init_time(t);
	Feat F;

	// Read parameters file //
	F.readInputFile(argv[1]);
	printFile(argv[1]);

	// Read galaxies
	Gals G;
    if(F.Ascii){
        G=read_galaxies_ascii(F);}
    else{
        G = read_galaxies(F);
    }
	F.Ngal = G.size();
	printf("# Read %s galaxies from %s \n",f(F.Ngal).c_str(),F.galFile.c_str());

	// Read fiber center positions and compute related things
	PP pp;
	pp.read_fiber_positions(F);
	F.Nfiber = pp.fp.size()/2;
	F.Npetal = max(pp.spectrom)+1; // spectrometer has to be identified from 0 to F.Npetal-1
	F.Nfbp = (int) (F.Nfiber/F.Npetal);// fibers per petal = 500
	pp.get_neighbors(F); pp.compute_fibsofsp(F);//get neighbors of each fiber;
                                                //for each spectrometer, get list of fibers

	// Read plates in order they are to be observed

	Plates P = read_plate_centers(F);
	F.Nplate = P.size();
	printf("# Read %s plate centers from %s and %d fibers from %s\n",f(F.Nplate).c_str(),F.tileFile.c_str(),F.Nfiber,F.fibFile.c_str());

	// Computes geometries of cb and fh: pieces of positioner - used to determine possible collisions
	F.cb = create_cb(); // cb=central body
	F.fh = create_fh(); // fh=fiber holder

	//// Collect available galaxies <-> tilefibers --------------------
	// HTM Tree of galaxies
	const double MinTreeSize = 0.01;
	init_time_at(time,"# Start building HTM tree",t);
	htmTree<struct galaxy> T(G,MinTreeSize);
	print_time(time,"# ... took :");//T.stats();

	// For plates/fibers, collect available galaxies; done in parallel  P[plate j].av_gal[k]=[g1,g2,..]
	collect_galaxies_for_all(G,T,P,pp,F);

	// For each galaxy, computes available tilefibers  G[i].av_tfs = [(j1,k1),(j2,k2),..]
	collect_available_tilefibers(G,P,F);

	//results_on_inputs("doc/figs/",G,P,F,true);

	//// Assignment |||||||||||||||||||||||||||||||||||||||||||||||||||
    printf("before assignment\n");
	Assignment A(G,F);
	print_time(t,"# Start assignment at : ");

	// Make a plan ----------------------------------------------------
	//new_assign_fibers(G,P,pp,F,A); // Plans whole survey without sky fibers, standard stars
                                   // assumes maximum number of observations needed for QSOs, LRGs
    printf(" Nplate %d  Ngal %d   Nfiber %d \n", F.Nplate, F.Ngal, F.Nfiber);
    simple_assign(G,P,pp,F,A);
    diagnostic(G,F,A);

	print_hist("Unused fibers",5,histogram(A.unused_fbp(pp,F),5),false); // Hist of unused fibs
                                    // Want to have even distribution of unused fibers
                                    // so we can put in sky fibers and standard stars

	// Smooth out distribution of free fibers, and increase the number of assignments
	for (int i=0; i<1; i++) redistribute_tf(G,P,pp,F,A);// more iterations will improve performance slightly
	for (int i=0; i<1; i++) {                           // more iterations will improve performance slightly
		improve(G,P,pp,F,A);
		redistribute_tf(G,P,pp,F,A);
		redistribute_tf(G,P,pp,F,A);
	}
	for (int i=0; i<1; i++) redistribute_tf(G,P,pp,F,A);

	print_hist("Unused fibers",5,histogram(A.unused_fbp(pp,F),5),false);

	// Still not updated, so all QSO targets have multiple observations etc
	// Apply and update the plan --------------------------------------
	init_time_at(time,"# Begin real time assignment",t);
	for (int jj=0; jj<F.Nplate; jj++) {
		int j = A.next_plate;
		//printf(" - Plate %d :",j);
		assign_sf_ss(j,G,P,pp,F,A); // Assign SS and SF just before an observation
		assign_unused(j,G,P,pp,F,A);
		//if (j%2000==0) pyplotTile(j,"doc/figs",G,P,pp,F,A); // Picture of positioners, galaxies

		//printf(" %s not as - ",format(5,f(A.unused_f(j,F))).c_str()); fl();
		// Update corrects all future occurrences of wrong QSOs etc and tries to observe something else
		if (0<=j-F.Analysis) update_plan_from_one_obs(G,P,pp,F,A,F.Nplate-1); else printf("\n");
		A.next_plate++;
		// Redistribute and improve on various occasions  add more times if desired

		if ( j==2000 || j==4000) {
			redistribute_tf(G,P,pp,F,A);
			redistribute_tf(G,P,pp,F,A);
			improve(G,P,pp,F,A);
            redistribute_tf(G,P,pp,F,A);
		}
	}
	print_time(time,"# ... took :");

	init_time_at(time,"# Begin FITS writing",t);
	// Results -------------------------------------------------------
    if (F.Output) for (int j=0; j<F.Nplate; j++){
        fa_write(j,F.outDir,G,P,pp,F,A); // Write output
    }
	display_results("doc/figs/",G,P,pp,F,A,true);
	if (F.Verif) A.verif(P,G,pp,F); // Verification that the assignment is sane
	print_time(time,"# ... took :");

	print_time(t,"# Finished !... in");

	return(0);
}
<commit_msg>diagnostic<commit_after>#include	<cstdlib>
#include	<cmath>
#include	<fstream>
#include	<sstream>
#include	<iostream>
#include	<iomanip>
#include	<string>
#include	<vector>
#include	<algorithm>
#include	<exception>
#include	<sys/time.h>
#include	"modules/htmTree.h"
#include	"modules/kdTree.h"
#include        "misc.h"
#include        "feat.h"
#include        "structs.h"
#include        "collision.h"
#include        "global.h"
//reduce redistributes, updates  07/02/15 rnc
int main(int argc, char **argv) {
	//// Initializations ---------------------------------------------
	srand48(1234); // Make sure we have reproducability
	check_args(argc);
	Time t, time; // t for global, time for local
	init_time(t);
	Feat F;

	// Read parameters file //
	F.readInputFile(argv[1]);
	printFile(argv[1]);

	// Read galaxies
	Gals G;
    if(F.Ascii){
        G=read_galaxies_ascii(F);}
    else{
        G = read_galaxies(F);
    }
	F.Ngal = G.size();
	printf("# Read %s galaxies from %s \n",f(F.Ngal).c_str(),F.galFile.c_str());

	// Read fiber center positions and compute related things
	PP pp;
	pp.read_fiber_positions(F);
	F.Nfiber = pp.fp.size()/2;
	F.Npetal = max(pp.spectrom)+1; // spectrometer has to be identified from 0 to F.Npetal-1
	F.Nfbp = (int) (F.Nfiber/F.Npetal);// fibers per petal = 500
	pp.get_neighbors(F); pp.compute_fibsofsp(F);//get neighbors of each fiber;
                                                //for each spectrometer, get list of fibers

	// Read plates in order they are to be observed

	Plates P = read_plate_centers(F);
	F.Nplate = P.size();
	printf("# Read %s plate centers from %s and %d fibers from %s\n",f(F.Nplate).c_str(),F.tileFile.c_str(),F.Nfiber,F.fibFile.c_str());

	// Computes geometries of cb and fh: pieces of positioner - used to determine possible collisions
	F.cb = create_cb(); // cb=central body
	F.fh = create_fh(); // fh=fiber holder

	//// Collect available galaxies <-> tilefibers --------------------
	// HTM Tree of galaxies
	const double MinTreeSize = 0.01;
	init_time_at(time,"# Start building HTM tree",t);
	htmTree<struct galaxy> T(G,MinTreeSize);
	print_time(time,"# ... took :");//T.stats();

	// For plates/fibers, collect available galaxies; done in parallel  P[plate j].av_gal[k]=[g1,g2,..]
	collect_galaxies_for_all(G,T,P,pp,F);

	// For each galaxy, computes available tilefibers  G[i].av_tfs = [(j1,k1),(j2,k2),..]
	collect_available_tilefibers(G,P,F);

	//results_on_inputs("doc/figs/",G,P,F,true);

	//// Assignment |||||||||||||||||||||||||||||||||||||||||||||||||||
    printf("before assignment\n");
	Assignment A(G,F);
	print_time(t,"# Start assignment at : ");

	// Make a plan ----------------------------------------------------
	//new_assign_fibers(G,P,pp,F,A); // Plans whole survey without sky fibers, standard stars
                                   // assumes maximum number of observations needed for QSOs, LRGs
    printf(" Nplate %d  Ngal %d   Nfiber %d \n", F.Nplate, F.Ngal, F.Nfiber);
    simple_assign(G,P,pp,F,A);
    //diagnostic 11/7/15
    int count_total=0;
    for(int j=0;j<F.Nplate;++j){

        int count_assigned=0;
        for (int k=0;k<F.Nfiber;++k){
            if(A.TF[j][k]!=-1)count_assigned++;
        }
        printf("  %d  %d \n",j, count_assigned);
	count_total+=count_assigned;
    }
    printf(" total = %d \n",count_total);

    diagnostic(G,F,A);

	print_hist("Unused fibers",5,histogram(A.unused_fbp(pp,F),5),false); // Hist of unused fibs
                                    // Want to have even distribution of unused fibers
                                    // so we can put in sky fibers and standard stars

	// Smooth out distribution of free fibers, and increase the number of assignments
	for (int i=0; i<1; i++) redistribute_tf(G,P,pp,F,A);// more iterations will improve performance slightly
	for (int i=0; i<1; i++) {                           // more iterations will improve performance slightly
		improve(G,P,pp,F,A);
		redistribute_tf(G,P,pp,F,A);
		redistribute_tf(G,P,pp,F,A);
	}
	for (int i=0; i<1; i++) redistribute_tf(G,P,pp,F,A);

	print_hist("Unused fibers",5,histogram(A.unused_fbp(pp,F),5),false);

	// Still not updated, so all QSO targets have multiple observations etc
	// Apply and update the plan --------------------------------------
	init_time_at(time,"# Begin real time assignment",t);
	for (int jj=0; jj<F.Nplate; jj++) {
		int j = A.next_plate;
		//printf(" - Plate %d :",j);
		assign_sf_ss(j,G,P,pp,F,A); // Assign SS and SF just before an observation
		assign_unused(j,G,P,pp,F,A);
		//if (j%2000==0) pyplotTile(j,"doc/figs",G,P,pp,F,A); // Picture of positioners, galaxies

		//printf(" %s not as - ",format(5,f(A.unused_f(j,F))).c_str()); fl();
		// Update corrects all future occurrences of wrong QSOs etc and tries to observe something else
		if (0<=j-F.Analysis) update_plan_from_one_obs(G,P,pp,F,A,F.Nplate-1); else printf("\n");
		A.next_plate++;
		// Redistribute and improve on various occasions  add more times if desired

		if ( j==2000 || j==4000) {
			redistribute_tf(G,P,pp,F,A);
			redistribute_tf(G,P,pp,F,A);
			improve(G,P,pp,F,A);
            redistribute_tf(G,P,pp,F,A);
		}
	}
	print_time(time,"# ... took :");

	init_time_at(time,"# Begin FITS writing",t);
	// Results -------------------------------------------------------
    if (F.Output) for (int j=0; j<F.Nplate; j++){
        fa_write(j,F.outDir,G,P,pp,F,A); // Write output
    }
	display_results("doc/figs/",G,P,pp,F,A,true);
	if (F.Verif) A.verif(P,G,pp,F); // Verification that the assignment is sane
	print_time(time,"# ... took :");

	print_time(t,"# Finished !... in");

	return(0);
}
<|endoftext|>


<commit_before>/*!
    \file phase_metrics.cpp
    \brief Benchmark phase metrics implementation
    \author Ivan Shynkarenka
    \date 03.07.2015
    \copyright MIT License
*/

#include "benchmark/phase_metrics.h"

#include "benchmark/system.h"

namespace CppBenchmark {

int64_t PhaseMetrics::avg_time() const noexcept
{
    return (_total_iterations > 0) ? (_total_time / _total_iterations) : 0;
}

int64_t PhaseMetrics::min_time() const noexcept
{
    return (_total_iterations > 0) ? (_min_time / _total_iterations) : _min_time;
}

int64_t PhaseMetrics::max_time() const noexcept
{
    return (_total_iterations > 0) ? (_max_time / _total_iterations) : _max_time;
}

int64_t PhaseMetrics::iterations_per_second() const noexcept
{
    if (_total_time <= 0)
        return 0;

    return MulDiv64(_total_iterations, 1000000000, _total_time);
}

int64_t PhaseMetrics::items_per_second() const noexcept
{
    if (_total_time <= 0)
        return 0;

    return MulDiv64(_total_items, 1000000000, _total_time);
}

int64_t PhaseMetrics::bytes_per_second() const noexcept
{
    if (_total_time <= 0)
        return 0;

    return MulDiv64(_total_bytes, 1000000000, _total_time);
}

void PhaseMetrics::StartCollecting() noexcept
{
    _iterstamp = _total_iterations;
    _timestamp = System::Timestamp();
}

void PhaseMetrics::StopCollecting() noexcept
{
    // Get iterations count & duration
    int64_t total_duration = System::Timestamp() - _timestamp;

    // Update time counters
    if (total_duration < _min_time)
        _min_time = total_duration;
    if (total_duration > _max_time)
        _max_time = total_duration;
    _total_time += total_duration;
}

void PhaseMetrics::MergeMetrics(const PhaseMetrics& metrics)
{
    // Choose best min time
    if (metrics._min_time < _min_time)
        _min_time = metrics._min_time;

    // Choose best max time
    if (metrics._max_time > _max_time)
        _max_time = metrics._max_time;

    // Merge custom hash tables
    _custom_int.insert(metrics._custom_int.begin(), metrics._custom_int.end());
    _custom_uint.insert(metrics._custom_uint.begin(), metrics._custom_uint.end());
    _custom_int64.insert(metrics._custom_int64.begin(), metrics._custom_int64.end());
    _custom_uint64.insert(metrics._custom_uint64.begin(), metrics._custom_uint64.end());
    _custom_flt.insert(metrics._custom_flt.begin(), metrics._custom_flt.end());
    _custom_dbl.insert(metrics._custom_dbl.begin(), metrics._custom_dbl.end());
    _custom_str.insert(metrics._custom_str.begin(), metrics._custom_str.end());

    // Choose best total time with iterations, items and bytes
    if (metrics._total_time < _total_time)
    {
        _total_time = metrics._total_time;
        _total_iterations = metrics._total_iterations;
        _total_items = metrics._total_items;
        _total_bytes = metrics._total_bytes;
        // Overwrite metrics custom tables
        for (auto& it : metrics._custom_int)
            _custom_int[it.first] = it.second;
        for (auto& it : metrics._custom_uint)
            _custom_uint[it.first] = it.second;
        for (auto& it : metrics._custom_int64)
            _custom_int64[it.first] = it.second;
        for (auto& it : metrics._custom_uint64)
            _custom_uint64[it.first] = it.second;
        for (auto& it : metrics._custom_flt)
            _custom_flt[it.first] = it.second;
        for (auto& it : metrics._custom_dbl)
            _custom_dbl[it.first] = it.second;
        for (auto& it : metrics._custom_str)
            _custom_str[it.first] = it.second;
    }
}

uint64_t PhaseMetrics::MulDiv64(uint64_t operant, uint64_t multiplier, uint64_t divider)
{
#if defined(_MSC_VER)
#if defined(_M_IX86)
    // Declare 128bit storage
    struct
    {
        unsigned long DW[4];
    } var128, quotient;

    // Change semantics for intermediate results for Full Div
    // by renaming the vars
    #define REMAINDER quotient
    #define QUOTIENT edi

    // Save combined sign on stack
    _asm
    {
        mov     eax, dword ptr[operant+4]
        xor     eax, dword ptr[multiplier+4]
        xor     eax, dword ptr[divider+4]
        pushfd
    }

    _asm
    {
        // First check divider for 0
        mov     eax, dword ptr[divider+4]
        or      eax, dword ptr[divider]
        jnz     dividerOK
        div     eax
dividerOK:
        lea     edi,[var128]                    // edi = &var128
        // Check multiplier for 1 or 0
        xor     eax, eax
        cmp     eax, dword ptr[multiplier+4]
        jnz     startMUL
        cmp     eax, dword ptr[multiplier]
        jnz     multiNotNUL
        xor     edx, edx
        popfd                                   // cleanup stack
        jmp     done
multiNotNUL:
        // Set result HI part to 0
        xor     eax,eax
        mov     dword ptr[edi+12], eax
        mov     dword ptr[edi+8], eax
        mov     eax, 1
        cmp     eax, dword ptr[multiplier]
        jnz     smallMUL
        // Multiplier is 1 so just copy operant to result
        mov     eax, dword ptr[operant+4]
        mov     dword ptr[edi+4], eax
        mov     eax, dword ptr[operant]
        mov     dword ptr[edi], eax
        jmp     startDIV
smallMUL:
        // Test for 32/32 bit multiplication
        xor     eax, eax
        mov     ecx, dword ptr[operant+4]
        or      ecx, eax         ;test for both hiwords zero.
        jnz     startMUL
        // Do 32/32 bit multiplication
        mov     ecx, dword ptr[multiplier]
        mov     eax, dword ptr[operant]
        mul     ecx
        mov     dword ptr[edi+4], edx
        mov     dword ptr[edi], eax
        jmp     startDIV
startMUL:
        // Check signs
        // Multiply: var128 = operant * multiplier
        mov     eax, dword ptr[multiplier]      // eax = LO(multiplier)
        mul     dword ptr[operant]              // edx:eax = eax * LO(operant)
        mov     dword ptr[edi], eax             // var128.DW0 = eax
        mov     ecx, edx                        // ecx = edx

        mov     eax, dword ptr[multiplier]      // eax = LO(multiplier)
        mul     dword ptr[operant+4]            // edx:eax = eax * HI(operant)
        add     eax, ecx                        // eax = eax + ecx
        adc     edx, 0                          // edx = edx + 0 + carry
        mov     ebx, eax
        mov     ecx, edx

        mov     eax, dword ptr[multiplier+4]
        mul     dword ptr[operant]
        add     eax, ebx
        mov     dword ptr[edi+4], eax
        adc     ecx, edx
        pushfd

        mov     eax, dword ptr[multiplier+4]
        mul     dword ptr[operant+4]
        popfd
        adc     eax, ecx
        adc     edx, 0
        mov     dword ptr[edi+8], eax
        mov     dword ptr[edi+12], edx
startDIV:
        // Divide: var128 = var128 / divider
        //
        // Test divider = 32bit value
        mov     eax, dword ptr[divider+4]
        cmp     eax, 0
        jnz     fullDIV
        mov     ecx, dword ptr[divider]
        cmp     ecx, 1
        jz      applySign

        // Start 128/32 bit division
        mov     eax, dword ptr[edi+12]
        xor     edx, edx
        div     ecx
        mov     dword ptr[quotient+12], eax

        mov     eax, dword ptr[edi+8]
        div     ecx
        mov     dword ptr[quotient+8], eax

        mov     eax, dword ptr[edi+4]
        div     ecx
        mov     dword ptr[quotient+4], eax

        mov     eax, dword ptr[edi]
        div     ecx
        mov     dword ptr[quotient], eax

        // Copy the quotient to the result storage (var128)
        mov     eax, dword ptr[quotient+12]
        mov     dword ptr[edi+12], eax
        mov     eax, dword ptr[quotient+8]
        mov     dword ptr[edi+8], eax
        mov     eax, dword ptr[quotient+4]
        mov     dword ptr[edi+4], eax
        mov     eax, dword ptr[quotient]
        mov     dword ptr[edi], eax
        // To sign correction and return
        jmp     applySign

fullDIV:
        // Full 128/64 bit division
        xor     eax, eax
        mov     dword ptr[REMAINDER+12], eax
        mov     dword ptr[REMAINDER+8], eax
        mov     dword ptr[REMAINDER+4], eax
        mov     dword ptr[REMAINDER], eax

        mov     ecx, 128
loop1:
        // Compute REMAINDER:QUOTIENT = REMAINDER:QUOTIENT shl 1
        shl     dword ptr[QUOTIENT], 1
        rcl     dword ptr[QUOTIENT+4], 1
        rcl     dword ptr[QUOTIENT+8], 1
        rcl     dword ptr[QUOTIENT+12], 1
        rcl     dword ptr[REMAINDER], 1
        rcl     dword ptr[REMAINDER+4], 1
        rcl     dword ptr[REMAINDER+8], 1
        rcl     dword ptr[REMAINDER+12], 1

        // Test (REMAINDER >= Divider)
        xor     eax, eax
        cmp     dword ptr[REMAINDER+12], eax
        ja      iftrue
        jb      iffalse

        cmp     dword ptr[REMAINDER+8], eax
        ja      iftrue
        jb      iffalse

        mov     eax, dword ptr[REMAINDER+4]
        cmp     eax, dword ptr[divider+4]
        ja      iftrue
        jb      iffalse

        mov     eax, dword ptr[REMAINDER]
        cmp     eax, dword ptr[divider]
        jb      iffalse
iftrue:
        // Remainder = remainder - divider
        mov     eax, dword ptr[divider]
        sub     dword ptr[REMAINDER], eax
        mov     eax, dword ptr[divider+4]
        sbb     dword ptr[REMAINDER+4], eax
        xor     eax, eax
        sbb     dword ptr[REMAINDER+8], eax
        sbb     dword ptr[REMAINDER+12], eax
        // Quotient = quotient +1
        add     dword ptr[QUOTIENT], 1
        adc     dword ptr[QUOTIENT+4], 0
        adc     dword ptr[QUOTIENT+8], 0
        adc     dword ptr[QUOTIENT+12], 0
iffalse:
        // Loop size = 101 bytes, is less than 127 so loop is possible
        loop    loop1

applySign:
        // Correct the sign of the result based on the stored combined sign
        popfd
        jns     storeRes
        not     dword ptr[edi+12]
        not     dword ptr[edi+ 8]
        not     dword ptr[edi+ 4]
        not     dword ptr[edi]
        add     dword ptr[edi], 1
        adc     dword ptr[edi+ 4], 0
        adc     dword ptr[edi+ 8], 0
        adc     dword ptr[edi+12], 0

storeRES:
        // Get low order qword from var128
        mov     edx, dword ptr[edi+4]
        mov     eax, dword ptr[edi]
done:
    }
    // result is returned in edx:eax
#elif defined (_M_X64 )
#pragma warning(push)
#pragma warning(disable: 4018)
#pragma warning(disable: 4244)
#pragma warning(disable: 4389)
    uint64_t a = operant;
    uint64_t b = multiplier;
    uint64_t c = divider;

    //  Normalize divisor
    unsigned long shift;
    _BitScanReverse64(&shift, c);
    shift = 63 - shift;

    c <<= shift;

    // Multiply
    a = _umul128(a, b, &b);
    if (((b << shift) >> shift) != b)
    {
        // Overflow
        return 0xFFFFFFFFFFFFFFFF;
    }
    b = __shiftleft128(a, b, shift);
    a <<= shift;

    uint32_t div;
    uint32_t q0, q1;
    uint64_t t0, t1;

    // 1st Reduction
    div = (uint32_t)(c >> 32);
    t0 = b / div;
    if (t0 > 0xFFFFFFFF)
        t0 = 0xFFFFFFFF;
    q1 = (uint32_t)t0;
    while (1)
    {
        t0 = _umul128(c, (uint64_t)q1 << 32, &t1);
        if (t1 < b || (t1 == b && t0 <= a))
            break;
        q1--;
    }
    b -= t1;
    if (t0 > a)
        b--;
    a -= t0;

    if (b > 0xFFFFFFFF)
    {
        // Overflow
        return 0xFFFFFFFFFFFFFFFF;
    }

    // 2nd reduction
    t0 = ((b << 32) | (a >> 32)) / div;
    if (t0 > 0xFFFFFFFF)
        t0 = 0xFFFFFFFF;
    q0 = (uint32_t)t0;

    while (1)
    {
        t0 = _umul128(c, q0, &t1);
        if (t1 < b || (t1 == b && t0 <= a))
            break;
        q0--;
    }

    return ((uint64_t)q1 << 32) | q0;
#pragma warning(pop)
#endif
#elif defined(__GNUC__)
    __uint128_t a = operant;
    __uint128_t b = multiplier;
    __uint128_t c = divider;

    return (uint64_t)(a * b / c);
#else
    #error MulDiv64 is no supported!
#endif
}

} // namespace CppBenchmark
<commit_msg>Fix 32bit cygwin build<commit_after>/*!
    \file phase_metrics.cpp
    \brief Benchmark phase metrics implementation
    \author Ivan Shynkarenka
    \date 03.07.2015
    \copyright MIT License
*/

#include "benchmark/phase_metrics.h"

#include "benchmark/system.h"

namespace CppBenchmark {

int64_t PhaseMetrics::avg_time() const noexcept
{
    return (_total_iterations > 0) ? (_total_time / _total_iterations) : 0;
}

int64_t PhaseMetrics::min_time() const noexcept
{
    return (_total_iterations > 0) ? (_min_time / _total_iterations) : _min_time;
}

int64_t PhaseMetrics::max_time() const noexcept
{
    return (_total_iterations > 0) ? (_max_time / _total_iterations) : _max_time;
}

int64_t PhaseMetrics::iterations_per_second() const noexcept
{
    if (_total_time <= 0)
        return 0;

    return MulDiv64(_total_iterations, 1000000000, _total_time);
}

int64_t PhaseMetrics::items_per_second() const noexcept
{
    if (_total_time <= 0)
        return 0;

    return MulDiv64(_total_items, 1000000000, _total_time);
}

int64_t PhaseMetrics::bytes_per_second() const noexcept
{
    if (_total_time <= 0)
        return 0;

    return MulDiv64(_total_bytes, 1000000000, _total_time);
}

void PhaseMetrics::StartCollecting() noexcept
{
    _iterstamp = _total_iterations;
    _timestamp = System::Timestamp();
}

void PhaseMetrics::StopCollecting() noexcept
{
    // Get iterations count & duration
    int64_t total_duration = System::Timestamp() - _timestamp;

    // Update time counters
    if (total_duration < _min_time)
        _min_time = total_duration;
    if (total_duration > _max_time)
        _max_time = total_duration;
    _total_time += total_duration;
}

void PhaseMetrics::MergeMetrics(const PhaseMetrics& metrics)
{
    // Choose best min time
    if (metrics._min_time < _min_time)
        _min_time = metrics._min_time;

    // Choose best max time
    if (metrics._max_time > _max_time)
        _max_time = metrics._max_time;

    // Merge custom hash tables
    _custom_int.insert(metrics._custom_int.begin(), metrics._custom_int.end());
    _custom_uint.insert(metrics._custom_uint.begin(), metrics._custom_uint.end());
    _custom_int64.insert(metrics._custom_int64.begin(), metrics._custom_int64.end());
    _custom_uint64.insert(metrics._custom_uint64.begin(), metrics._custom_uint64.end());
    _custom_flt.insert(metrics._custom_flt.begin(), metrics._custom_flt.end());
    _custom_dbl.insert(metrics._custom_dbl.begin(), metrics._custom_dbl.end());
    _custom_str.insert(metrics._custom_str.begin(), metrics._custom_str.end());

    // Choose best total time with iterations, items and bytes
    if (metrics._total_time < _total_time)
    {
        _total_time = metrics._total_time;
        _total_iterations = metrics._total_iterations;
        _total_items = metrics._total_items;
        _total_bytes = metrics._total_bytes;
        // Overwrite metrics custom tables
        for (auto& it : metrics._custom_int)
            _custom_int[it.first] = it.second;
        for (auto& it : metrics._custom_uint)
            _custom_uint[it.first] = it.second;
        for (auto& it : metrics._custom_int64)
            _custom_int64[it.first] = it.second;
        for (auto& it : metrics._custom_uint64)
            _custom_uint64[it.first] = it.second;
        for (auto& it : metrics._custom_flt)
            _custom_flt[it.first] = it.second;
        for (auto& it : metrics._custom_dbl)
            _custom_dbl[it.first] = it.second;
        for (auto& it : metrics._custom_str)
            _custom_str[it.first] = it.second;
    }
}

uint64_t PhaseMetrics::MulDiv64(uint64_t operant, uint64_t multiplier, uint64_t divider)
{
#if defined(_MSC_VER)
#if defined(_M_IX86)
    // Declare 128bit storage
    struct
    {
        unsigned long DW[4];
    } var128, quotient;

    // Change semantics for intermediate results for Full Div
    // by renaming the vars
    #define REMAINDER quotient
    #define QUOTIENT edi

    // Save combined sign on stack
    _asm
    {
        mov     eax, dword ptr[operant+4]
        xor     eax, dword ptr[multiplier+4]
        xor     eax, dword ptr[divider+4]
        pushfd
    }

    _asm
    {
        // First check divider for 0
        mov     eax, dword ptr[divider+4]
        or      eax, dword ptr[divider]
        jnz     dividerOK
        div     eax
dividerOK:
        lea     edi,[var128]                    // edi = &var128
        // Check multiplier for 1 or 0
        xor     eax, eax
        cmp     eax, dword ptr[multiplier+4]
        jnz     startMUL
        cmp     eax, dword ptr[multiplier]
        jnz     multiNotNUL
        xor     edx, edx
        popfd                                   // cleanup stack
        jmp     done
multiNotNUL:
        // Set result HI part to 0
        xor     eax,eax
        mov     dword ptr[edi+12], eax
        mov     dword ptr[edi+8], eax
        mov     eax, 1
        cmp     eax, dword ptr[multiplier]
        jnz     smallMUL
        // Multiplier is 1 so just copy operant to result
        mov     eax, dword ptr[operant+4]
        mov     dword ptr[edi+4], eax
        mov     eax, dword ptr[operant]
        mov     dword ptr[edi], eax
        jmp     startDIV
smallMUL:
        // Test for 32/32 bit multiplication
        xor     eax, eax
        mov     ecx, dword ptr[operant+4]
        or      ecx, eax         ;test for both hiwords zero.
        jnz     startMUL
        // Do 32/32 bit multiplication
        mov     ecx, dword ptr[multiplier]
        mov     eax, dword ptr[operant]
        mul     ecx
        mov     dword ptr[edi+4], edx
        mov     dword ptr[edi], eax
        jmp     startDIV
startMUL:
        // Check signs
        // Multiply: var128 = operant * multiplier
        mov     eax, dword ptr[multiplier]      // eax = LO(multiplier)
        mul     dword ptr[operant]              // edx:eax = eax * LO(operant)
        mov     dword ptr[edi], eax             // var128.DW0 = eax
        mov     ecx, edx                        // ecx = edx

        mov     eax, dword ptr[multiplier]      // eax = LO(multiplier)
        mul     dword ptr[operant+4]            // edx:eax = eax * HI(operant)
        add     eax, ecx                        // eax = eax + ecx
        adc     edx, 0                          // edx = edx + 0 + carry
        mov     ebx, eax
        mov     ecx, edx

        mov     eax, dword ptr[multiplier+4]
        mul     dword ptr[operant]
        add     eax, ebx
        mov     dword ptr[edi+4], eax
        adc     ecx, edx
        pushfd

        mov     eax, dword ptr[multiplier+4]
        mul     dword ptr[operant+4]
        popfd
        adc     eax, ecx
        adc     edx, 0
        mov     dword ptr[edi+8], eax
        mov     dword ptr[edi+12], edx
startDIV:
        // Divide: var128 = var128 / divider
        //
        // Test divider = 32bit value
        mov     eax, dword ptr[divider+4]
        cmp     eax, 0
        jnz     fullDIV
        mov     ecx, dword ptr[divider]
        cmp     ecx, 1
        jz      applySign

        // Start 128/32 bit division
        mov     eax, dword ptr[edi+12]
        xor     edx, edx
        div     ecx
        mov     dword ptr[quotient+12], eax

        mov     eax, dword ptr[edi+8]
        div     ecx
        mov     dword ptr[quotient+8], eax

        mov     eax, dword ptr[edi+4]
        div     ecx
        mov     dword ptr[quotient+4], eax

        mov     eax, dword ptr[edi]
        div     ecx
        mov     dword ptr[quotient], eax

        // Copy the quotient to the result storage (var128)
        mov     eax, dword ptr[quotient+12]
        mov     dword ptr[edi+12], eax
        mov     eax, dword ptr[quotient+8]
        mov     dword ptr[edi+8], eax
        mov     eax, dword ptr[quotient+4]
        mov     dword ptr[edi+4], eax
        mov     eax, dword ptr[quotient]
        mov     dword ptr[edi], eax
        // To sign correction and return
        jmp     applySign

fullDIV:
        // Full 128/64 bit division
        xor     eax, eax
        mov     dword ptr[REMAINDER+12], eax
        mov     dword ptr[REMAINDER+8], eax
        mov     dword ptr[REMAINDER+4], eax
        mov     dword ptr[REMAINDER], eax

        mov     ecx, 128
loop1:
        // Compute REMAINDER:QUOTIENT = REMAINDER:QUOTIENT shl 1
        shl     dword ptr[QUOTIENT], 1
        rcl     dword ptr[QUOTIENT+4], 1
        rcl     dword ptr[QUOTIENT+8], 1
        rcl     dword ptr[QUOTIENT+12], 1
        rcl     dword ptr[REMAINDER], 1
        rcl     dword ptr[REMAINDER+4], 1
        rcl     dword ptr[REMAINDER+8], 1
        rcl     dword ptr[REMAINDER+12], 1

        // Test (REMAINDER >= Divider)
        xor     eax, eax
        cmp     dword ptr[REMAINDER+12], eax
        ja      iftrue
        jb      iffalse

        cmp     dword ptr[REMAINDER+8], eax
        ja      iftrue
        jb      iffalse

        mov     eax, dword ptr[REMAINDER+4]
        cmp     eax, dword ptr[divider+4]
        ja      iftrue
        jb      iffalse

        mov     eax, dword ptr[REMAINDER]
        cmp     eax, dword ptr[divider]
        jb      iffalse
iftrue:
        // Remainder = remainder - divider
        mov     eax, dword ptr[divider]
        sub     dword ptr[REMAINDER], eax
        mov     eax, dword ptr[divider+4]
        sbb     dword ptr[REMAINDER+4], eax
        xor     eax, eax
        sbb     dword ptr[REMAINDER+8], eax
        sbb     dword ptr[REMAINDER+12], eax
        // Quotient = quotient +1
        add     dword ptr[QUOTIENT], 1
        adc     dword ptr[QUOTIENT+4], 0
        adc     dword ptr[QUOTIENT+8], 0
        adc     dword ptr[QUOTIENT+12], 0
iffalse:
        // Loop size = 101 bytes, is less than 127 so loop is possible
        loop    loop1

applySign:
        // Correct the sign of the result based on the stored combined sign
        popfd
        jns     storeRes
        not     dword ptr[edi+12]
        not     dword ptr[edi+ 8]
        not     dword ptr[edi+ 4]
        not     dword ptr[edi]
        add     dword ptr[edi], 1
        adc     dword ptr[edi+ 4], 0
        adc     dword ptr[edi+ 8], 0
        adc     dword ptr[edi+12], 0

storeRES:
        // Get low order qword from var128
        mov     edx, dword ptr[edi+4]
        mov     eax, dword ptr[edi]
done:
    }
    // result is returned in edx:eax
#elif defined (_M_X64 )
#pragma warning(push)
#pragma warning(disable: 4018)
#pragma warning(disable: 4244)
#pragma warning(disable: 4389)
    uint64_t a = operant;
    uint64_t b = multiplier;
    uint64_t c = divider;

    //  Normalize divisor
    unsigned long shift;
    _BitScanReverse64(&shift, c);
    shift = 63 - shift;

    c <<= shift;

    // Multiply
    a = _umul128(a, b, &b);
    if (((b << shift) >> shift) != b)
    {
        // Overflow
        return 0xFFFFFFFFFFFFFFFF;
    }
    b = __shiftleft128(a, b, shift);
    a <<= shift;

    uint32_t div;
    uint32_t q0, q1;
    uint64_t t0, t1;

    // 1st Reduction
    div = (uint32_t)(c >> 32);
    t0 = b / div;
    if (t0 > 0xFFFFFFFF)
        t0 = 0xFFFFFFFF;
    q1 = (uint32_t)t0;
    while (1)
    {
        t0 = _umul128(c, (uint64_t)q1 << 32, &t1);
        if (t1 < b || (t1 == b && t0 <= a))
            break;
        q1--;
    }
    b -= t1;
    if (t0 > a)
        b--;
    a -= t0;

    if (b > 0xFFFFFFFF)
    {
        // Overflow
        return 0xFFFFFFFFFFFFFFFF;
    }

    // 2nd reduction
    t0 = ((b << 32) | (a >> 32)) / div;
    if (t0 > 0xFFFFFFFF)
        t0 = 0xFFFFFFFF;
    q0 = (uint32_t)t0;

    while (1)
    {
        t0 = _umul128(c, q0, &t1);
        if (t1 < b || (t1 == b && t0 <= a))
            break;
        q0--;
    }

    return ((uint64_t)q1 << 32) | q0;
#pragma warning(pop)
#endif
#elif defined(__GNUC__)
#if defined(__x86_64__) || defined(__amd64__) || defined(__aarch64__) || defined(__ia64__) || defined(__ppc64__)
    __uint128_t a = operant;
    __uint128_t b = multiplier;
    __uint128_t c = divider;

    return (uint64_t)(a * b / c);
#else
    uint64_t a = operant;
    uint64_t b = multiplier;
    uint64_t c = divider;

    return (uint64_t)(a * b / c);
#endif
#else
    #error MulDiv64 is no supported!
#endif
}

} // namespace CppBenchmark
<|endoftext|>


<commit_before>/* main.cpp */<commit_msg>basic cgi app<commit_after>#include <iostream>
#include <cstdlib>
int main(){
  std::cout<<"Content-type: text/html\r\n\r\n";

  std::cout<<"QUERY STRING IS:  ";
  std::cout<<std::getenv("QUERY_STRING"); // get enviroment variable
}
<|endoftext|>


<commit_before>/*
 * main.cpp
 *
 * main file for derelict app
 *
 * starts GLUT and runs callbacks
 */

#include <iostream>
#include <GL/glfw.h>

#include "Key.h"
#include "Cam.h"

void Init() {
	glClearColor(1, 1, 1, 0);
}

void Cube() {
	glBegin(GL_QUADS);
		glVertex3f(-0.25, -0.25, -0.25);
		glVertex3f( 0.25, -0.25, -0.25);
		glVertex3f( 0.25,  0.25, -0.25);
		glVertex3f(-0.25,  0.25, -0.25);

		glVertex3f(-0.25, -0.25,  0.25);
		glVertex3f( 0.25, -0.25,  0.25);
		glVertex3f( 0.25,  0.25,  0.25);
		glVertex3f(-0.25,  0.25,  0.25);

		glVertex3f(-0.25, -0.25, -0.25);
		glVertex3f(-0.25,  0.25, -0.25);
		glVertex3f(-0.25,  0.25,  0.25);
		glVertex3f(-0.25, -0.25,  0.25);

		glVertex3f( 0.25, -0.25, -0.25);
		glVertex3f( 0.25,  0.25, -0.25);
		glVertex3f( 0.25,  0.25,  0.25);
		glVertex3f( 0.25, -0.25,  0.25);

		glVertex3f(-0.25, -0.25, -0.25);
		glVertex3f(-0.25, -0.25,  0.25);
		glVertex3f( 0.25, -0.25,  0.25);
		glVertex3f( 0.25, -0.25, -0.25);

		glVertex3f(-0.25,  0.25, -0.25);
		glVertex3f(-0.25,  0.25,  0.25);
		glVertex3f( 0.25,  0.25,  0.25);
		glVertex3f( 0.25,  0.25, -0.25);
	glEnd();

	glColor3f(1, 1, 1);

	glBegin(GL_LINE_LOOP);
		glVertex3f(-0.25, -0.25, -0.25);
		glVertex3f( 0.25, -0.25, -0.25);
		glVertex3f( 0.25,  0.25, -0.25);
		glVertex3f(-0.25,  0.25, -0.25);
	glEnd();

	glBegin(GL_LINE_LOOP);
		glVertex3f(-0.25, -0.25,  0.25);
		glVertex3f( 0.25, -0.25,  0.25);
		glVertex3f( 0.25,  0.25,  0.25);
		glVertex3f(-0.25,  0.25,  0.25);
	glEnd();

	glBegin(GL_LINES);
		glVertex3f(-0.25, -0.25, -0.25);
		glVertex3f(-0.25, -0.25,  0.25);

		glVertex3f( 0.25, -0.25, -0.25);
		glVertex3f( 0.25, -0.25,  0.25);

		glVertex3f( 0.25,  0.25, -0.25);
		glVertex3f( 0.25,  0.25,  0.25);

		glVertex3f(-0.25,  0.25, -0.25);
		glVertex3f(-0.25,  0.25,  0.25);
	glEnd();
}

void Pyramid() {
	glBegin(GL_TRIANGLE_FAN);
		glVertex3f(0, 0.5, 0);

		glVertex3f(0, -.25, -.433);
		glVertex3f(-.375, -.25, .2165);
		glVertex3f( .375, -.25, .2165);
		glVertex3f(0, -.25, -.433);
	glEnd();

	glColor3f(1, 1, 1);

	glBegin(GL_LINES);
		glVertex3f(0, 0.5, 0);
		glVertex3f(0, -.25, -.433);

		glVertex3f(0, 0.5, 0);
		glVertex3f(-.375, -.25, .2165);

		glVertex3f(0, 0.5, 0);
		glVertex3f( .375, -.25, .2165);
	glEnd();
}

void Display() {
	glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);

	glColor3f(0, 0, 0);

	Cube();

	glPushMatrix();

	glTranslatef(0, 0, 5.0);

	glColor3f(1, 0, 0);

	Pyramid();

	glTranslatef(0, 0, 5.0);

	glColor3f(0, 1, 0);

	Cube();

	glPopMatrix();

	//glBegin(GL_TRIANGLE_STRIP);
		//glVertex2f( 0,  0);
		//glVertex2f(1,  0);
		//glVertex2f( 0, 1);
	//glEnd();

	//glColor3f(1, 0, 0);

	//glBegin(GL_TRIANGLE_STRIP);
		//glVertex3f( 0, 0, 1);
		//glVertex3f( 1, 0, 1);
		//glVertex3f( 0, 1, 1);
	//glEnd();

	//glColor3f(0, 1, 0);

	//glBegin(GL_TRIANGLE_STRIP);
		//glVertex3f( 0, 0, 2);
		//glVertex3f( 1, 0, 2);
		//glVertex3f( 0, 1, 2);
	//glEnd();
}

void Update() {
	if(Key::I().Pressed('D')) {
		Vector pos = Cam::I().GetPos();
		pos.i -= 0.1;
		Cam::I().SetPos(pos);
	} else if(Key::I().Pressed('A')) {
		Vector pos = Cam::I().GetPos();
		pos.i += 0.1;
		Cam::I().SetPos(pos);
	}
}

int main(int argc, char ** argv) {
	glfwInit();

	glfwOpenWindow(800, 600, 0, 0, 0, 0, 16, 0, GLFW_WINDOW);

	glEnable(GL_DEPTH_TEST);
	glDepthFunc(GL_LEQUAL);

	Init();

	glfwSetKeyCallback(Key::KeyEvent);
	glfwSetWindowSizeCallback(Cam::ResizeCallback);

	bool running = true;

	while(running) {
		Display();

		Update();
		Key::I().Update();

		glfwSwapBuffers();

		running = !glfwGetKey(GLFW_KEY_ESC) &&
		          glfwGetWindowParam(GLFW_OPENED);

		glfwSleep(0.01);
	}

	glfwCloseWindow();

	glfwTerminate();
}
<commit_msg>Added bottom face to pyramids<commit_after>/*
 * main.cpp
 *
 * main file for derelict app
 *
 * starts GLUT and runs callbacks
 */

#include <iostream>
#include <GL/glfw.h>

#include "Key.h"
#include "Cam.h"

void Init() {
	glClearColor(1, 1, 1, 0);
}

void Cube() {
	glBegin(GL_QUADS);
		glVertex3f(-0.25, -0.25, -0.25);
		glVertex3f( 0.25, -0.25, -0.25);
		glVertex3f( 0.25,  0.25, -0.25);
		glVertex3f(-0.25,  0.25, -0.25);

		glVertex3f(-0.25, -0.25,  0.25);
		glVertex3f( 0.25, -0.25,  0.25);
		glVertex3f( 0.25,  0.25,  0.25);
		glVertex3f(-0.25,  0.25,  0.25);

		glVertex3f(-0.25, -0.25, -0.25);
		glVertex3f(-0.25,  0.25, -0.25);
		glVertex3f(-0.25,  0.25,  0.25);
		glVertex3f(-0.25, -0.25,  0.25);

		glVertex3f( 0.25, -0.25, -0.25);
		glVertex3f( 0.25,  0.25, -0.25);
		glVertex3f( 0.25,  0.25,  0.25);
		glVertex3f( 0.25, -0.25,  0.25);

		glVertex3f(-0.25, -0.25, -0.25);
		glVertex3f(-0.25, -0.25,  0.25);
		glVertex3f( 0.25, -0.25,  0.25);
		glVertex3f( 0.25, -0.25, -0.25);

		glVertex3f(-0.25,  0.25, -0.25);
		glVertex3f(-0.25,  0.25,  0.25);
		glVertex3f( 0.25,  0.25,  0.25);
		glVertex3f( 0.25,  0.25, -0.25);
	glEnd();

	glColor3f(1, 1, 1);

	glBegin(GL_LINE_LOOP);
		glVertex3f(-0.25, -0.25, -0.25);
		glVertex3f( 0.25, -0.25, -0.25);
		glVertex3f( 0.25,  0.25, -0.25);
		glVertex3f(-0.25,  0.25, -0.25);
	glEnd();

	glBegin(GL_LINE_LOOP);
		glVertex3f(-0.25, -0.25,  0.25);
		glVertex3f( 0.25, -0.25,  0.25);
		glVertex3f( 0.25,  0.25,  0.25);
		glVertex3f(-0.25,  0.25,  0.25);
	glEnd();

	glBegin(GL_LINES);
		glVertex3f(-0.25, -0.25, -0.25);
		glVertex3f(-0.25, -0.25,  0.25);

		glVertex3f( 0.25, -0.25, -0.25);
		glVertex3f( 0.25, -0.25,  0.25);

		glVertex3f( 0.25,  0.25, -0.25);
		glVertex3f( 0.25,  0.25,  0.25);

		glVertex3f(-0.25,  0.25, -0.25);
		glVertex3f(-0.25,  0.25,  0.25);
	glEnd();
}

void Pyramid() {
	glBegin(GL_TRIANGLE_FAN);
		glVertex3f(0, 0.5, 0);

		glVertex3f(0, -.25, -.433);
		glVertex3f(-.375, -.25, .2165);
		glVertex3f( .375, -.25, .2165);
		glVertex3f(0, -.25, -.433);
	glEnd();

	glBegin(GL_TRIANGLES);
		glVertex3f(0, -.25, -.433);
		glVertex3f(-.375, -.25, .2165);
		glVertex3f( .375, -.25, .2165);
	glEnd();

	glColor3f(1, 1, 1);

	glBegin(GL_LINES);
		glVertex3f(0, 0.5, 0);
		glVertex3f(0, -.25, -.433);

		glVertex3f(0, 0.5, 0);
		glVertex3f(-.375, -.25, .2165);

		glVertex3f(0, 0.5, 0);
		glVertex3f( .375, -.25, .2165);
	glEnd();

	glBegin(GL_LINE_LOOP);
		glVertex3f(0, -.25, -.433);
		glVertex3f(-.375, -.25, .2165);
		glVertex3f( .375, -.25, .2165);
	glEnd();
}

void Display() {
	glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);

	glColor3f(0, 0, 0);

	Cube();

	glPushMatrix();

	glTranslatef(0, 0, 5.0);

	glColor3f(1, 0, 0);

	Pyramid();

	glTranslatef(0, 0, 5.0);

	glColor3f(0, 1, 0);

	Cube();

	glPopMatrix();

	//glBegin(GL_TRIANGLE_STRIP);
		//glVertex2f( 0,  0);
		//glVertex2f(1,  0);
		//glVertex2f( 0, 1);
	//glEnd();

	//glColor3f(1, 0, 0);

	//glBegin(GL_TRIANGLE_STRIP);
		//glVertex3f( 0, 0, 1);
		//glVertex3f( 1, 0, 1);
		//glVertex3f( 0, 1, 1);
	//glEnd();

	//glColor3f(0, 1, 0);

	//glBegin(GL_TRIANGLE_STRIP);
		//glVertex3f( 0, 0, 2);
		//glVertex3f( 1, 0, 2);
		//glVertex3f( 0, 1, 2);
	//glEnd();
}

void Update() {
	if(Key::I().Pressed('D')) {
		Vector pos = Cam::I().GetPos();
		pos.i -= 0.1;
		Cam::I().SetPos(pos);
	} else if(Key::I().Pressed('A')) {
		Vector pos = Cam::I().GetPos();
		pos.i += 0.1;
		Cam::I().SetPos(pos);
	}
}

int main(int argc, char ** argv) {
	glfwInit();

	glfwOpenWindow(800, 600, 0, 0, 0, 0, 16, 0, GLFW_WINDOW);

	glEnable(GL_DEPTH_TEST);
	glDepthFunc(GL_LEQUAL);

	Init();

	glfwSetKeyCallback(Key::KeyEvent);
	glfwSetWindowSizeCallback(Cam::ResizeCallback);

	bool running = true;

	while(running) {
		Display();

		Update();
		Key::I().Update();

		glfwSwapBuffers();

		running = !glfwGetKey(GLFW_KEY_ESC) &&
		          glfwGetWindowParam(GLFW_OPENED);

		glfwSleep(0.01);
	}

	glfwCloseWindow();

	glfwTerminate();
}
<|endoftext|>


<commit_before>/* main.cpp */
//-----------------------------------------------------------------------
//include files
//-----------------------------------------------------------------------
#include <iostream>
#include <oauth.h>
#include <thread>
#include <mutex>
#include <chrono>
#include <unistd.h>

#include <opencv2/opencv.hpp>
#include <opencv2/superres/optical_flow.hpp>

#include "sequentialCaptCurrBuffer.h"
#include "sequentialCalcDiffImg.h"
#include "sequentialCalcOptFlow.h"
#include "optFlow2RGB.h"
#include "detectMotionObject.h"

#include "tweet.h"
#include "webclient.h"
// #include "mykey.h"
#include "jphacks_key.h"

//-----------------------------------------------------------------------
// using namespace
//-----------------------------------------------------------------------
using namespace std;

//-----------------------------------------------------------------------

//***********************************************************************
// Function : main |
//***********************************************************************
int main(void)
{
    // buffering off for debug on pty
    setvbuf( stdout, NULL, _IONBF, BUFSIZ );

    WebClient::initialize();
    TwitterClient tc(c_key, c_sec, t_key, t_sec);
    std::string filename("../../skeleton.png");
    cv::Mat src = cv::imread(filename);

    // current frame の連続取得(別スレッド)
    cv::Mat curr_tmp;
    bool break_flag = false;
    cv::VideoCapture cap(0);
		cap.set(CV_CAP_PROP_FRAME_WIDTH, 640);
		cap.set(CV_CAP_PROP_FRAME_HEIGHT, 480);
    thread cap_th( sequentialCaptCurrBuffer, ref(cap), ref(curr_tmp), ref(break_flag));
    while( curr_tmp.empty() ){
        std::chrono::milliseconds ms(250);
        std::this_thread::sleep_for(ms);
    }

    // 画像差分の連続算出(別スレッド)
    cv::Mat diff_tmp;
    thread diff_th( sequentialCalcDiffImg, ref(curr_tmp), ref(diff_tmp), ref(break_flag));
    while( diff_tmp.empty() ){
        std::chrono::milliseconds ms(250);
        std::this_thread::sleep_for(ms);
    }

    // // optical flow の連続算出(別スレッド)
    // cv::Mat flow_tmp;
    // thread optflow_th( sequentialCalcOptFlow, ref(curr_tmp), ref(flow_tmp), ref(break_flag));
    // while( flow_tmp.empty() ){
    //     sleep(0);
    // }

    while( cv::waitKey(1) != '\x1b' ) {
        cap_mtx.lock();
        cv::Mat curr = curr_tmp.clone();
        cap_mtx.unlock();

        diff_mtx.lock();
        cv::Mat diff = diff_tmp.clone();
        diff_mtx.unlock();
        cv::imshow("diff", diff);

        // opt_flow_mtx.lock();
        // cv::Mat flow = flow_tmp.clone();
        // opt_flow_mtx.unlock();

        // // optical flow to RGB
        // cv::Mat flow_rgb;
        // optFlow2RGB( flow, flow_rgb );

        // // 表示
        // cv::imshow("optical flow", flow_rgb);

        // // グレースケール
        // cv::Mat gray;
        // cv::cvtColor( flow_rgb, gray, CV_BGR2GRAY);

        vector<cv::Rect> detected_obj_diff, detected_obj_optflow;
        detectMotionObject(curr, diff, detected_obj_diff);
        // detectMotionObject(curr, gray, detected_obj_optflow);

        for(auto i: detected_obj_diff){
            cv::rectangle(curr, i.tl(), i.br(), cv::Scalar(255, 0, 0), 2, CV_AA);
        }
        // for(auto i: detected_obj_optflow){
        //     cv::rectangle(curr, i.tl(), i.br(), cv::Scalar(0, 255, 0), 2, CV_AA);
        // }
        cv::imshow("dist", curr);
    }

    // スレッドの終了
    break_flag = true;
    cap_th.join();
    diff_th.join();
    // optflow_th.join();

    //return ( tc.tweet(message, src) ) ? 0 : 1;
    return 0;
}
<commit_msg>std::chrono::milliseconds の定義が冗長だったため修正<commit_after>/* main.cpp */
//-----------------------------------------------------------------------
//include files
//-----------------------------------------------------------------------
#include <iostream>
#include <oauth.h>
#include <thread>
#include <mutex>
#include <chrono>
#include <unistd.h>

#include <opencv2/opencv.hpp>
#include <opencv2/superres/optical_flow.hpp>

#include "sequentialCaptCurrBuffer.h"
#include "sequentialCalcDiffImg.h"
#include "sequentialCalcOptFlow.h"
#include "optFlow2RGB.h"
#include "detectMotionObject.h"

#include "tweet.h"
#include "webclient.h"
// #include "mykey.h"
#include "jphacks_key.h"

//-----------------------------------------------------------------------
// using namespace
//-----------------------------------------------------------------------
using namespace std;

//-----------------------------------------------------------------------

//***********************************************************************
// Function : main |
//***********************************************************************
int main(void)
{
    // buffering off for debug on pty
    setvbuf( stdout, NULL, _IONBF, BUFSIZ );

    WebClient::initialize();
    TwitterClient tc(c_key, c_sec, t_key, t_sec);
    std::string filename("../../skeleton.png");
    cv::Mat src = cv::imread(filename);

    // current frame の連続取得(別スレッド)
    cv::Mat curr_tmp;
    bool break_flag = false;
    std::chrono::milliseconds ms(250);
    cv::VideoCapture cap(0);
    cap.set(CV_CAP_PROP_FRAME_WIDTH, 640);
    cap.set(CV_CAP_PROP_FRAME_HEIGHT, 480);
    thread cap_th( sequentialCaptCurrBuffer, ref(cap), ref(curr_tmp), ref(break_flag));
    while( curr_tmp.empty() ){
        std::this_thread::sleep_for(ms);
    }

    // 画像差分の連続算出(別スレッド)
    cv::Mat diff_tmp;
    thread diff_th( sequentialCalcDiffImg, ref(curr_tmp), ref(diff_tmp), ref(break_flag));
    while( diff_tmp.empty() ){
        std::this_thread::sleep_for(ms);
    }

    // // optical flow の連続算出(別スレッド)
    // cv::Mat flow_tmp;
    // thread optflow_th( sequentialCalcOptFlow, ref(curr_tmp), ref(flow_tmp), ref(break_flag));
    // while( flow_tmp.empty() ){
    //     std::this_thread::sleep_for(ms);
    // }

    while( cv::waitKey(1) != '\x1b' ) {
        cap_mtx.lock();
        cv::Mat curr = curr_tmp.clone();
        cap_mtx.unlock();

        diff_mtx.lock();
        cv::Mat diff = diff_tmp.clone();
        diff_mtx.unlock();
        cv::imshow("diff", diff);

        // opt_flow_mtx.lock();
        // cv::Mat flow = flow_tmp.clone();
        // opt_flow_mtx.unlock();

        // // optical flow to RGB
        // cv::Mat flow_rgb;
        // optFlow2RGB( flow, flow_rgb );

        // // 表示
        // cv::imshow("optical flow", flow_rgb);

        // // グレースケール
        // cv::Mat gray;
        // cv::cvtColor( flow_rgb, gray, CV_BGR2GRAY);

        vector<cv::Rect> detected_obj_diff, detected_obj_optflow;
        detectMotionObject(curr, diff, detected_obj_diff);
        // detectMotionObject(curr, gray, detected_obj_optflow);

        for(auto i: detected_obj_diff){
            cv::rectangle(curr, i.tl(), i.br(), cv::Scalar(255, 0, 0), 2, CV_AA);
        }
        // for(auto i: detected_obj_optflow){
        //     cv::rectangle(curr, i.tl(), i.br(), cv::Scalar(0, 255, 0), 2, CV_AA);
        // }
        cv::imshow("dist", curr);
    }

    // スレッドの終了
    break_flag = true;
    cap_th.join();
    diff_th.join();
    // optflow_th.join();

    //return ( tc.tweet(message, src) ) ? 0 : 1;
    return 0;
}
<|endoftext|>