<commit_before>#include "postgres.h"
#include "funcapi.h"

#include "S3ExtWrapper.h"
#include "utils.h"
#include "gps3conf.h"
#include "gps3ext.h"
#include "S3Log.h"

#include <string>
#include <sstream>
using std::stringstream;
using std::string;

S3ExtBase *CreateExtWrapper(const char *url) {
    S3ExtBase *ret = new S3Reader(url);
    return ret;
}

S3ExtBase::S3ExtBase(const char *url) {
    this->url = url;

    // get following from config
    this->cred.secret = s3ext_secret;
    this->cred.keyid = s3ext_accessid;

    this->segid = s3ext_segid;
    this->segnum = s3ext_segnum;

    this->chunksize = s3ext_chunksize;
    this->concurrent_num = s3ext_threadnum;

    S3INFO("Created %d threads for downloading", s3ext_threadnum);
    S3INFO("File is splited to %d each", s3ext_chunksize);
}

S3ExtBase::~S3ExtBase() {}

S3Reader::~S3Reader() {}

S3Reader::S3Reader(const char *url) : S3ExtBase(url) {
    this->contentindex = -1;
    this->filedownloader = NULL;
    this->keylist = NULL;
}

bool S3Reader::Init(int segid, int segnum, int chunksize) {
    // set segment id and num
    this->segid = s3ext_segid;
    this->segnum = s3ext_segnum;
    this->contentindex = this->segid;

    this->chunksize = chunksize;

    // Validate url first
    if (!this->ValidateURL()) {
        S3ERROR("The given URL(%s) is invalid", this->url.c_str());
        ereport(ERROR, (0, errmsg("ERROR: the given URL is invalid")));
        return false;
    }

    // TODO: As separated function for generating url
    stringstream sstr;
    sstr << "s3-" << this->region << ".amazonaws.com";
    S3DEBUG("Host url is %s", sstr.str().c_str());
    int initretry = 3;
    while (initretry--) {
        this->keylist =
            ListBucket(this->schema.c_str(), sstr.str().c_str(),
                       this->bucket.c_str(), this->prefix.c_str(), this->cred);

        if (!this->keylist) {
            S3INFO("Can't get keylist from bucket %s", this->bucket.c_str());
            if (initretry) {
                S3INFO("Retrying");
                continue;
            } else {
                S3ERROR("Quit initialization because ListBucket keeps failing");
                return false;
            }
        }

        if (this->keylist->contents.size() == 0) {
            S3INFO("Keylist of bucket is empty");
            if (initretry) {
                S3INFO("Retry listing bucket");
                continue;
            } else {
                S3ERROR("Quit initialization because keylist is empty");
                ereport(ERROR, (0, errmsg("ERROR: the given bucket is empty")));
                return false;
            }
        }
        break;
    }
    S3INFO("Got %d files to download", this->keylist->contents.size());
    this->getNextDownloader();

    // return this->filedownloader ? true : false;
    return true;
}

void S3Reader::getNextDownloader() {
    if (this->filedownloader) {  // reset old downloader
        filedownloader->destroy();
        delete this->filedownloader;
        this->filedownloader = NULL;
    }

    if (this->contentindex >= this->keylist->contents.size()) {
        S3DEBUG("No more files to download");
        return;
    }
    this->filedownloader = new Downloader(this->concurrent_num);

    if (!this->filedownloader) {
        S3ERROR("Failed to create filedownloader");
        return;
    }
    BucketContent *c = this->keylist->contents[this->contentindex];
    string keyurl = this->getKeyURL(c->Key());
    S3DEBUG("key: %s, size: %llu", keyurl.c_str(), c->Size());

    // XXX don't use strdup()
    if (!filedownloader->init(strdup(keyurl.c_str()), c->Size(),
                              this->chunksize, &this->cred)) {
        delete this->filedownloader;
        this->filedownloader = NULL;
    } else {  // move to next file
        // for now, every segment downloads its assigned files(mod)
        // better to build a workqueue in case not all segments are available
        this->contentindex += this->segnum;
    }
    return;
}

string S3Reader::getKeyURL(const string key) {
    stringstream sstr;
    sstr << this->schema << "://"
         << "s3-" << this->region << ".amazonaws.com/";
    sstr << this->bucket << "/" << key;
    return sstr.str();
}

bool S3Reader::TransferData(char *data, uint64_t &len) {
    if (!this->filedownloader) {
        S3INFO("No files to download, exit");
        // not initialized?
        len = 0;
        return true;
    }
    uint64_t buflen;
RETRY:
    buflen = len;
    // S3DEBUG("getlen is %d", len);
    bool result = filedownloader->get(data, buflen);
    if (!result) {  // read fail
        S3ERROR("Failed to get data from filedownloader");
        return false;
    }
    // S3DEBUG("getlen is %lld", buflen);
    if (buflen == 0) {
        // change to next downloader
        this->getNextDownloader();
        if (this->filedownloader) {  // download next file
            S3INFO("Time to download new file");
            goto RETRY;
        }
    }
    len = buflen;
    return true;
}

bool S3Reader::Destroy() {
    // reset filedownloader
    if (this->filedownloader) {
        this->filedownloader->destroy();
        delete this->filedownloader;
    }

    // Free keylist
    if (this->keylist) {
        delete this->keylist;
    }
    return true;
}

bool S3ExtBase::ValidateURL() {
    const char *awsdomain = ".amazonaws.com";
    int ibegin = 0;
    int iend = url.find("://");
    if (iend == string::npos) {  // -1
        // error
        return false;
    }

    this->schema = url.substr(ibegin, iend);
    if (this->schema == "s3") {
        if (s3ext_encryption)
            this->schema = "https";
        else
            this->schema = "http";
    }

    ibegin = url.find("-");
    iend = url.find(awsdomain);
    if ((iend == string::npos) || (ibegin == string::npos)) {
        return false;
    }
    this->region = url.substr(ibegin + 1, iend - ibegin - 1);

    ibegin = find_Nth(url, 3, "/");
    iend = find_Nth(url, 4, "/");
    if ((iend == string::npos) || (ibegin == string::npos)) {
        return false;
    }
    this->bucket = url.substr(ibegin + 1, iend - ibegin - 1);

    this->prefix = url.substr(iend + 1, url.length() - iend - 1);

    /*
    if (url.back() != '/') {
        return false;
    }
    */
    return true;
}

/*
bool S3Protocol_t::Write(char *data, size_t &len) {
    if (!this->fileuploader) {
        // not initialized?
        return false;
    }

    bool result = fileuploader->write(data, len);
    if (!result) {
        S3DEBUG("Failed to write data via fileuploader");
        return false;
    }

    return true;
}
*/
<commit_msg>remove ereport() outputs since it's not thread-safe<commit_after>#include "S3ExtWrapper.h"
#include "utils.h"
#include "gps3conf.h"
#include "gps3ext.h"
#include "S3Log.h"

#include <string>
#include <sstream>
using std::stringstream;
using std::string;

S3ExtBase *CreateExtWrapper(const char *url) {
    S3ExtBase *ret = new S3Reader(url);
    return ret;
}

S3ExtBase::S3ExtBase(const char *url) {
    this->url = url;

    // get following from config
    this->cred.secret = s3ext_secret;
    this->cred.keyid = s3ext_accessid;

    this->segid = s3ext_segid;
    this->segnum = s3ext_segnum;

    this->chunksize = s3ext_chunksize;
    this->concurrent_num = s3ext_threadnum;

    S3INFO("Created %d threads for downloading", s3ext_threadnum);
    S3INFO("File is splited to %d each", s3ext_chunksize);
}

S3ExtBase::~S3ExtBase() {}

S3Reader::~S3Reader() {}

S3Reader::S3Reader(const char *url) : S3ExtBase(url) {
    this->contentindex = -1;
    this->filedownloader = NULL;
    this->keylist = NULL;
}

bool S3Reader::Init(int segid, int segnum, int chunksize) {
    // set segment id and num
    this->segid = s3ext_segid;
    this->segnum = s3ext_segnum;
    this->contentindex = this->segid;

    this->chunksize = chunksize;

    // Validate url first
    if (!this->ValidateURL()) {
        S3ERROR("The given URL(%s) is invalid", this->url.c_str());
        return false;
    }

    // TODO: As separated function for generating url
    stringstream sstr;
    sstr << "s3-" << this->region << ".amazonaws.com";
    S3DEBUG("Host url is %s", sstr.str().c_str());
    int initretry = 3;
    while (initretry--) {
        this->keylist =
            ListBucket(this->schema.c_str(), sstr.str().c_str(),
                       this->bucket.c_str(), this->prefix.c_str(), this->cred);

        if (!this->keylist) {
            S3INFO("Can't get keylist from bucket %s", this->bucket.c_str());
            if (initretry) {
                S3INFO("Retrying");
                continue;
            } else {
                S3ERROR("Quit initialization because ListBucket keeps failing");
                return false;
            }
        }

        if (this->keylist->contents.size() == 0) {
            S3INFO("Keylist of bucket is empty");
            if (initretry) {
                S3INFO("Retry listing bucket");
                continue;
            } else {
                S3ERROR("Quit initialization because keylist is empty");
                return false;
            }
        }
        break;
    }
    S3INFO("Got %d files to download", this->keylist->contents.size());
    this->getNextDownloader();

    // return this->filedownloader ? true : false;
    return true;
}

void S3Reader::getNextDownloader() {
    if (this->filedownloader) {  // reset old downloader
        filedownloader->destroy();
        delete this->filedownloader;
        this->filedownloader = NULL;
    }

    if (this->contentindex >= this->keylist->contents.size()) {
        S3DEBUG("No more files to download");
        return;
    }
    this->filedownloader = new Downloader(this->concurrent_num);

    if (!this->filedownloader) {
        S3ERROR("Failed to create filedownloader");
        return;
    }
    BucketContent *c = this->keylist->contents[this->contentindex];
    string keyurl = this->getKeyURL(c->Key());
    S3DEBUG("key: %s, size: %llu", keyurl.c_str(), c->Size());

    // XXX don't use strdup()
    if (!filedownloader->init(strdup(keyurl.c_str()), c->Size(),
                              this->chunksize, &this->cred)) {
        delete this->filedownloader;
        this->filedownloader = NULL;
    } else {  // move to next file
        // for now, every segment downloads its assigned files(mod)
        // better to build a workqueue in case not all segments are available
        this->contentindex += this->segnum;
    }
    return;
}

string S3Reader::getKeyURL(const string key) {
    stringstream sstr;
    sstr << this->schema << "://"
         << "s3-" << this->region << ".amazonaws.com/";
    sstr << this->bucket << "/" << key;
    return sstr.str();
}

bool S3Reader::TransferData(char *data, uint64_t &len) {
    if (!this->filedownloader) {
        S3INFO("No files to download, exit");
        // not initialized?
        len = 0;
        return true;
    }
    uint64_t buflen;
RETRY:
    buflen = len;
    // S3DEBUG("getlen is %d", len);
    bool result = filedownloader->get(data, buflen);
    if (!result) {  // read fail
        S3ERROR("Failed to get data from filedownloader");
        return false;
    }
    // S3DEBUG("getlen is %lld", buflen);
    if (buflen == 0) {
        // change to next downloader
        this->getNextDownloader();
        if (this->filedownloader) {  // download next file
            S3INFO("Time to download new file");
            goto RETRY;
        }
    }
    len = buflen;
    return true;
}

bool S3Reader::Destroy() {
    // reset filedownloader
    if (this->filedownloader) {
        this->filedownloader->destroy();
        delete this->filedownloader;
    }

    // Free keylist
    if (this->keylist) {
        delete this->keylist;
    }
    return true;
}

bool S3ExtBase::ValidateURL() {
    const char *awsdomain = ".amazonaws.com";
    int ibegin = 0;
    int iend = url.find("://");
    if (iend == string::npos) {  // -1
        // error
        return false;
    }

    this->schema = url.substr(ibegin, iend);
    if (this->schema == "s3") {
        if (s3ext_encryption)
            this->schema = "https";
        else
            this->schema = "http";
    }

    ibegin = url.find("-");
    iend = url.find(awsdomain);
    if ((iend == string::npos) || (ibegin == string::npos)) {
        return false;
    }
    this->region = url.substr(ibegin + 1, iend - ibegin - 1);

    ibegin = find_Nth(url, 3, "/");
    iend = find_Nth(url, 4, "/");
    if ((iend == string::npos) || (ibegin == string::npos)) {
        return false;
    }
    this->bucket = url.substr(ibegin + 1, iend - ibegin - 1);

    this->prefix = url.substr(iend + 1, url.length() - iend - 1);

    /*
    if (url.back() != '/') {
        return false;
    }
    */
    return true;
}

/*
bool S3Protocol_t::Write(char *data, size_t &len) {
    if (!this->fileuploader) {
        // not initialized?
        return false;
    }

    bool result = fileuploader->write(data, len);
    if (!result) {
        S3DEBUG("Failed to write data via fileuploader");
        return false;
    }

    return true;
}
*/
<|endoftext|>


<commit_before>// Copyright (c) 2013-2016 Anton Kozhevnikov, Thomas Schulthess
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without modification, are permitted provided that
// the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the
//    following disclaimer.
// 2. 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.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 HOLDER 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.

/** \file dmatrix.hpp
 *
 *  \brief Contains definition and implementaiton of dmatrix class.
 */

#ifndef __DMATRIX_HPP__
#define __DMATRIX_HPP__

#include "blacs_grid.hpp"
#include "splindex.hpp"

namespace sddk {

/// Distributed matrix.
template <typename T>
class dmatrix : public matrix<T>
{
  private:
    /// Global number of matrix rows.
    int num_rows_{0};

    /// Global number of matrix columns.
    int num_cols_{0};

    int bs_row_{0};

    int bs_col_{0};

    BLACS_grid const* blacs_grid_{nullptr};

    splindex<block_cyclic> spl_row_;

    splindex<block_cyclic> spl_col_;

    /// Matrix descriptor.
    ftn_int descriptor_[9];

    void init()
    {
        #ifdef __SCALAPACK
        linalg_base::descinit(descriptor_, num_rows_, num_cols_, bs_row_, bs_col_, 0, 0, blacs_grid_->context(),
                              spl_row_.local_size());
        #endif
    }

    /* forbid copy constructor */
    dmatrix(dmatrix<T> const& src) = delete;
    /* forbid assigment operator */
    dmatrix<T>& operator=(dmatrix<T> const& src) = delete;

  public:
    // Default constructor
    dmatrix()
    {
    }

    dmatrix(int num_rows__, int num_cols__, BLACS_grid const& blacs_grid__, int bs_row__, int bs_col__,
            memory_t mem_type__ = memory_t::host)
        : matrix<T>(splindex<block_cyclic>(num_rows__, blacs_grid__.num_ranks_row(), blacs_grid__.rank_row(), bs_row__).local_size(),
                    splindex<block_cyclic>(num_cols__, blacs_grid__.num_ranks_col(), blacs_grid__.rank_col(), bs_col__).local_size(),
                    mem_type__)
        , num_rows_(num_rows__)
        , num_cols_(num_cols__)
        , bs_row_(bs_row__)
        , bs_col_(bs_col__)
        , blacs_grid_(&blacs_grid__)
        , spl_row_(num_rows_, blacs_grid__.num_ranks_row(), blacs_grid__.rank_row(), bs_row_)
        , spl_col_(num_cols_, blacs_grid__.num_ranks_col(), blacs_grid__.rank_col(), bs_col_)
    {
        init();
    }

    dmatrix(T* ptr__, int num_rows__, int num_cols__, BLACS_grid const& blacs_grid__, int bs_row__, int bs_col__)
        : matrix<T>(ptr__,
                    splindex<block_cyclic>(num_rows__, blacs_grid__.num_ranks_row(), blacs_grid__.rank_row(), bs_row__).local_size(),
                    splindex<block_cyclic>(num_cols__, blacs_grid__.num_ranks_col(), blacs_grid__.rank_col(), bs_col__).local_size())
        , num_rows_(num_rows__)
        , num_cols_(num_cols__)
        , bs_row_(bs_row__)
        , bs_col_(bs_col__)
        , blacs_grid_(&blacs_grid__)
        , spl_row_(num_rows_, blacs_grid__.num_ranks_row(), blacs_grid__.rank_row(), bs_row_)
        , spl_col_(num_cols_, blacs_grid__.num_ranks_col(), blacs_grid__.rank_col(), bs_col_)
    {
        init();
    }

    dmatrix(dmatrix<T>&& src) = default;

    dmatrix<T>& operator=(dmatrix<T>&& src) = default;

    inline int num_rows() const
    {
        return num_rows_;
    }

    inline int num_rows_local() const
    {
        return spl_row_.local_size();
    }

    inline int num_rows_local(int rank) const
    {
        return spl_row_.local_size(rank);
    }

    inline int irow(int irow_loc) const
    {
        return spl_row_[irow_loc];
    }

    inline int num_cols() const
    {
        return num_cols_;
    }

    /// Local number of columns.
    inline int num_cols_local() const
    {
        return spl_col_.local_size();
    }

    inline int num_cols_local(int rank) const
    {
        return spl_col_.local_size(rank);
    }

    /// Inindex of column in global matrix.
    inline int icol(int icol_loc) const
    {
        return spl_col_[icol_loc];
    }

    inline int const* descriptor() const
    {
        return descriptor_;
    }

    //inline void zero()
    //{
    //    this->zero();
    //}

    //inline void zero(int ir0__, int jc0__, int mr__, int nc__)
    //{
    //    for (int j = 0; j < num_cols_local(); j++) {
    //        int jc = icol(j);
    //        if (jc >= jc0__ && jc < jc0__ + nc__) {
    //            for (int i = 0; i < num_rows_local(); i++) {
    //                int ir = irow(i);
    //                if (ir >= ir0__ && ir < ir0__ + mr__) {
    //                    (*this)(i, j) = 0;
    //                }
    //            }
    //        }
    //    }
    //}

#ifdef __GPU
//== inline void copy_cols_to_device(int icol_fisrt, int icol_last)
//== {
//==     splindex<block_cyclic> s0(icol_fisrt, num_ranks_col_, rank_col_, bs_col_);
//==     splindex<block_cyclic> s1(icol_last,  num_ranks_col_, rank_col_, bs_col_);
//==     int nloc = static_cast<int>(s1.local_size() - s0.local_size());
//==     if (nloc)
//==     {
//==         cuda_copy_to_device(at<GPU>(0, s0.local_size()), at<CPU>(0, s0.local_size()),
//==                             num_rows_local() * nloc * sizeof(double_complex));
//==     }
//== }

//== inline void copy_cols_to_host(int icol_fisrt, int icol_last)
//== {
//==     splindex<block_cyclic> s0(icol_fisrt, num_ranks_col_, rank_col_, bs_col_);
//==     splindex<block_cyclic> s1(icol_last,  num_ranks_col_, rank_col_, bs_col_);
//==     int nloc = static_cast<int>(s1.local_size() - s0.local_size());
//==     if (nloc)
//==     {
//==         cuda_copy_to_host(at<CPU>(0, s0.local_size()), at<GPU>(0, s0.local_size()),
//==                           num_rows_local() * nloc * sizeof(double_complex));
//==     }
//== }
#endif

    inline void set(const int irow_glob, const int icol_glob, T val)
    {
        auto r = spl_row_.location(irow_glob);
        if (blacs_grid_->rank_row() == r.rank) {
            auto c = spl_col_.location(icol_glob);
            if (blacs_grid_->rank_col() == c.rank) {
                (*this)(r.local_index, c.local_index) = val;
            }
        }
    }

    inline void add(const int irow_glob, const int icol_glob, T val)
    {
        auto r = spl_row_.location(irow_glob);
        if (blacs_grid_->rank_row() == r.rank) {
            auto c = spl_col_.location(icol_glob);
            if (blacs_grid_->rank_col() == c.rank) {
                (*this)(r.local_index, c.local_index) += val;
            }
        }
    }

    inline void make_real_diag(int n__)
    {
        for (int i = 0; i < n__; i++) {
            auto r = spl_row_.location(i);
            if (blacs_grid_->rank_row() == r.rank) {
                auto c = spl_col_.location(i);
                if (blacs_grid_->rank_col() == c.rank) {
                    T v = (*this)(r.local_index, c.local_index);
                    (*this)(r.local_index, c.local_index) = sddk_type_wrapper<T>::real(v);
                }
            }
        }
    }

    inline mdarray<T, 1> get_diag(int n__)
    {
        mdarray<T, 1> d(n__);
        d.zero();

        for (int i = 0; i < n__; i++) {
            auto r = spl_row_.location(i);
            if (blacs_grid_->rank_row() == r.rank) {
                auto c = spl_col_.location(i);
                if (blacs_grid_->rank_col() == c.rank) {
                    d(i) = (*this)(r.local_index, c.local_index);
                }
            }
        }
        blacs_grid_->comm().allreduce(d.template at<CPU>(), n__);
        return std::move(d);
    }

    inline splindex<block_cyclic> const& spl_col() const
    {
        return spl_col_;
    }

    inline splindex<block_cyclic> const& spl_row() const
    {
        return spl_row_;
    }

    inline int rank_row() const
    {
        return blacs_grid_->rank_row();
    }

    inline int num_ranks_row() const
    {
        return blacs_grid_->num_ranks_row();
    }

    inline int rank_col() const
    {
        return blacs_grid_->rank_col();
    }

    inline int num_ranks_col() const
    {
        return blacs_grid_->num_ranks_col();
    }

    inline int bs_row() const
    {
        return bs_row_;
    }

    inline int bs_col() const
    {
        return bs_col_;
    }

    inline BLACS_grid const& blacs_grid() const
    {
        assert(blacs_grid_ != nullptr);
        return *blacs_grid_;
    }

    inline void serialize(std::string name__, int n__) const;
};

template <>
inline void dmatrix<double_complex>::serialize(std::string name__, int n__) const
{
    mdarray<double_complex, 2> full_mtrx(num_rows(), num_cols());
    full_mtrx.zero();

    for (int j = 0; j < num_cols_local(); j++) {
        for (int i = 0; i < num_rows_local(); i++) {
            full_mtrx(irow(i), icol(j)) = (*this)(i, j);
        }
    }
    blacs_grid_->comm().allreduce(full_mtrx.at<CPU>(), static_cast<int>(full_mtrx.size()));

    //json dict;
    //dict["mtrx_re"] = json::array();
    //for (int i = 0; i < num_rows(); i++) {
    //    dict["mtrx_re"].push_back(json::array());
    //    for (int j = 0; j < num_cols(); j++) {
    //        dict["mtrx_re"][i].push_back(full_mtrx(i, j).real());
    //    }
    //}

    if (blacs_grid_->comm().rank() == 0) {
        //std::cout << "mtrx: " << name__ << std::endl;
        // std::cout << dict.dump(4);

        printf("{\n");
        for (int i = 0; i < n__; i++) {
            printf("{");
            for (int j = 0; j < n__; j++) {
                printf("%18.12f + I * %18.12f", full_mtrx(i, j).real(), full_mtrx(i, j).imag());
                if (j != n__ - 1) {
                    printf(",");
                }
            }
            if (i != n__ - 1) {
                printf("},\n");
            } else {
                printf("}\n");
            }
        }
        printf("}\n");
    }

    // std::ofstream ofs(aiida_output_file, std::ofstream::out | std::ofstream::trunc);
    // ofs << dict.dump(4);
}

template <>
inline void dmatrix<double>::serialize(std::string name__, int n__) const
{
    mdarray<double, 2> full_mtrx(num_rows(), num_cols());
    full_mtrx.zero();

    for (int j = 0; j < num_cols_local(); j++) {
        for (int i = 0; i < num_rows_local(); i++) {
            full_mtrx(irow(i), icol(j)) = (*this)(i, j);
        }
    }
    blacs_grid_->comm().allreduce(full_mtrx.at<CPU>(), static_cast<int>(full_mtrx.size()));

    //json dict;
    //dict["mtrx"] = json::array();
    //for (int i = 0; i < num_rows(); i++) {
    //    dict["mtrx"].push_back(json::array());
    //    for (int j = 0; j < num_cols(); j++) {
    //        dict["mtrx"][i].push_back(full_mtrx(i, j));
    //    }
    //}

    //if (blacs_grid_->comm().rank() == 0) {
    //    std::cout << "mtrx: " << name__ << std::endl;
    //    std::cout << dict.dump(4);
    //}

    // std::ofstream ofs(aiida_output_file, std::ofstream::out | std::ofstream::trunc);
    // ofs << dict.dump(4);

    if (blacs_grid_->comm().rank() == 0) {
        printf("{\n");
        for (int i = 0; i < n__; i++) {
            printf("{");
            for (int j = 0; j < n__; j++) {
                printf("%18.12f", full_mtrx(i, j));
                if (j != n__ - 1) {
                    printf(",");
                }
            }
            if (i != n__ - 1) {
                printf("},\n");
            } else {
                printf("}\n");
            }
        }
        printf("}\n");
    }
}

} // namespace sddk

#endif // __DMATRIX_HPP__
<commit_msg>serialize dmartix<commit_after>// Copyright (c) 2013-2016 Anton Kozhevnikov, Thomas Schulthess
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without modification, are permitted provided that
// the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the
//    following disclaimer.
// 2. 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.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 HOLDER 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.

/** \file dmatrix.hpp
 *
 *  \brief Contains definition and implementaiton of dmatrix class.
 */

#ifndef __DMATRIX_HPP__
#define __DMATRIX_HPP__

#include "blacs_grid.hpp"
#include "splindex.hpp"

namespace sddk {

/// Distributed matrix.
template <typename T>
class dmatrix : public matrix<T>
{
  private:
    /// Global number of matrix rows.
    int num_rows_{0};

    /// Global number of matrix columns.
    int num_cols_{0};

    int bs_row_{0};

    int bs_col_{0};

    BLACS_grid const* blacs_grid_{nullptr};

    splindex<block_cyclic> spl_row_;

    splindex<block_cyclic> spl_col_;

    /// Matrix descriptor.
    ftn_int descriptor_[9];

    void init()
    {
        #ifdef __SCALAPACK
        linalg_base::descinit(descriptor_, num_rows_, num_cols_, bs_row_, bs_col_, 0, 0, blacs_grid_->context(),
                              spl_row_.local_size());
        #endif
    }

    /* forbid copy constructor */
    dmatrix(dmatrix<T> const& src) = delete;
    /* forbid assigment operator */
    dmatrix<T>& operator=(dmatrix<T> const& src) = delete;

  public:
    // Default constructor
    dmatrix()
    {
    }

    dmatrix(int num_rows__, int num_cols__, BLACS_grid const& blacs_grid__, int bs_row__, int bs_col__,
            memory_t mem_type__ = memory_t::host)
        : matrix<T>(splindex<block_cyclic>(num_rows__, blacs_grid__.num_ranks_row(), blacs_grid__.rank_row(), bs_row__).local_size(),
                    splindex<block_cyclic>(num_cols__, blacs_grid__.num_ranks_col(), blacs_grid__.rank_col(), bs_col__).local_size(),
                    mem_type__)
        , num_rows_(num_rows__)
        , num_cols_(num_cols__)
        , bs_row_(bs_row__)
        , bs_col_(bs_col__)
        , blacs_grid_(&blacs_grid__)
        , spl_row_(num_rows_, blacs_grid__.num_ranks_row(), blacs_grid__.rank_row(), bs_row_)
        , spl_col_(num_cols_, blacs_grid__.num_ranks_col(), blacs_grid__.rank_col(), bs_col_)
    {
        init();
    }

    dmatrix(T* ptr__, int num_rows__, int num_cols__, BLACS_grid const& blacs_grid__, int bs_row__, int bs_col__)
        : matrix<T>(ptr__,
                    splindex<block_cyclic>(num_rows__, blacs_grid__.num_ranks_row(), blacs_grid__.rank_row(), bs_row__).local_size(),
                    splindex<block_cyclic>(num_cols__, blacs_grid__.num_ranks_col(), blacs_grid__.rank_col(), bs_col__).local_size())
        , num_rows_(num_rows__)
        , num_cols_(num_cols__)
        , bs_row_(bs_row__)
        , bs_col_(bs_col__)
        , blacs_grid_(&blacs_grid__)
        , spl_row_(num_rows_, blacs_grid__.num_ranks_row(), blacs_grid__.rank_row(), bs_row_)
        , spl_col_(num_cols_, blacs_grid__.num_ranks_col(), blacs_grid__.rank_col(), bs_col_)
    {
        init();
    }

    dmatrix(dmatrix<T>&& src) = default;

    dmatrix<T>& operator=(dmatrix<T>&& src) = default;

    inline int num_rows() const
    {
        return num_rows_;
    }

    inline int num_rows_local() const
    {
        return spl_row_.local_size();
    }

    inline int num_rows_local(int rank) const
    {
        return spl_row_.local_size(rank);
    }

    inline int irow(int irow_loc) const
    {
        return spl_row_[irow_loc];
    }

    inline int num_cols() const
    {
        return num_cols_;
    }

    /// Local number of columns.
    inline int num_cols_local() const
    {
        return spl_col_.local_size();
    }

    inline int num_cols_local(int rank) const
    {
        return spl_col_.local_size(rank);
    }

    /// Inindex of column in global matrix.
    inline int icol(int icol_loc) const
    {
        return spl_col_[icol_loc];
    }

    inline int const* descriptor() const
    {
        return descriptor_;
    }

    //inline void zero()
    //{
    //    this->zero();
    //}

    //inline void zero(int ir0__, int jc0__, int mr__, int nc__)
    //{
    //    for (int j = 0; j < num_cols_local(); j++) {
    //        int jc = icol(j);
    //        if (jc >= jc0__ && jc < jc0__ + nc__) {
    //            for (int i = 0; i < num_rows_local(); i++) {
    //                int ir = irow(i);
    //                if (ir >= ir0__ && ir < ir0__ + mr__) {
    //                    (*this)(i, j) = 0;
    //                }
    //            }
    //        }
    //    }
    //}

#ifdef __GPU
//== inline void copy_cols_to_device(int icol_fisrt, int icol_last)
//== {
//==     splindex<block_cyclic> s0(icol_fisrt, num_ranks_col_, rank_col_, bs_col_);
//==     splindex<block_cyclic> s1(icol_last,  num_ranks_col_, rank_col_, bs_col_);
//==     int nloc = static_cast<int>(s1.local_size() - s0.local_size());
//==     if (nloc)
//==     {
//==         cuda_copy_to_device(at<GPU>(0, s0.local_size()), at<CPU>(0, s0.local_size()),
//==                             num_rows_local() * nloc * sizeof(double_complex));
//==     }
//== }

//== inline void copy_cols_to_host(int icol_fisrt, int icol_last)
//== {
//==     splindex<block_cyclic> s0(icol_fisrt, num_ranks_col_, rank_col_, bs_col_);
//==     splindex<block_cyclic> s1(icol_last,  num_ranks_col_, rank_col_, bs_col_);
//==     int nloc = static_cast<int>(s1.local_size() - s0.local_size());
//==     if (nloc)
//==     {
//==         cuda_copy_to_host(at<CPU>(0, s0.local_size()), at<GPU>(0, s0.local_size()),
//==                           num_rows_local() * nloc * sizeof(double_complex));
//==     }
//== }
#endif

    inline void set(const int irow_glob, const int icol_glob, T val)
    {
        auto r = spl_row_.location(irow_glob);
        if (blacs_grid_->rank_row() == r.rank) {
            auto c = spl_col_.location(icol_glob);
            if (blacs_grid_->rank_col() == c.rank) {
                (*this)(r.local_index, c.local_index) = val;
            }
        }
    }

    inline void add(const int irow_glob, const int icol_glob, T val)
    {
        auto r = spl_row_.location(irow_glob);
        if (blacs_grid_->rank_row() == r.rank) {
            auto c = spl_col_.location(icol_glob);
            if (blacs_grid_->rank_col() == c.rank) {
                (*this)(r.local_index, c.local_index) += val;
            }
        }
    }

    inline void make_real_diag(int n__)
    {
        for (int i = 0; i < n__; i++) {
            auto r = spl_row_.location(i);
            if (blacs_grid_->rank_row() == r.rank) {
                auto c = spl_col_.location(i);
                if (blacs_grid_->rank_col() == c.rank) {
                    T v = (*this)(r.local_index, c.local_index);
                    (*this)(r.local_index, c.local_index) = sddk_type_wrapper<T>::real(v);
                }
            }
        }
    }

    inline mdarray<T, 1> get_diag(int n__)
    {
        mdarray<T, 1> d(n__);
        d.zero();

        for (int i = 0; i < n__; i++) {
            auto r = spl_row_.location(i);
            if (blacs_grid_->rank_row() == r.rank) {
                auto c = spl_col_.location(i);
                if (blacs_grid_->rank_col() == c.rank) {
                    d(i) = (*this)(r.local_index, c.local_index);
                }
            }
        }
        blacs_grid_->comm().allreduce(d.template at<CPU>(), n__);
        return std::move(d);
    }

    inline splindex<block_cyclic> const& spl_col() const
    {
        return spl_col_;
    }

    inline splindex<block_cyclic> const& spl_row() const
    {
        return spl_row_;
    }

    inline int rank_row() const
    {
        return blacs_grid_->rank_row();
    }

    inline int num_ranks_row() const
    {
        return blacs_grid_->num_ranks_row();
    }

    inline int rank_col() const
    {
        return blacs_grid_->rank_col();
    }

    inline int num_ranks_col() const
    {
        return blacs_grid_->num_ranks_col();
    }

    inline int bs_row() const
    {
        return bs_row_;
    }

    inline int bs_col() const
    {
        return bs_col_;
    }

    inline BLACS_grid const& blacs_grid() const
    {
        assert(blacs_grid_ != nullptr);
        return *blacs_grid_;
    }

    inline void serialize(std::string name__, int n__) const;
};

template <>
inline void dmatrix<double_complex>::serialize(std::string name__, int n__) const
{
    mdarray<double_complex, 2> full_mtrx(num_rows(), num_cols());
    full_mtrx.zero();

    for (int j = 0; j < num_cols_local(); j++) {
        for (int i = 0; i < num_rows_local(); i++) {
            full_mtrx(irow(i), icol(j)) = (*this)(i, j);
        }
    }
    blacs_grid_->comm().allreduce(full_mtrx.at<CPU>(), static_cast<int>(full_mtrx.size()));

    //json dict;
    //dict["mtrx_re"] = json::array();
    //for (int i = 0; i < num_rows(); i++) {
    //    dict["mtrx_re"].push_back(json::array());
    //    for (int j = 0; j < num_cols(); j++) {
    //        dict["mtrx_re"][i].push_back(full_mtrx(i, j).real());
    //    }
    //}

    if (blacs_grid_->comm().rank() == 0) {
        //std::cout << "mtrx: " << name__ << std::endl;
        // std::cout << dict.dump(4);

        printf("matrix label: %s\n", name__.c_str());
        printf("{\n");
        for (int i = 0; i < n__; i++) {
            printf("{");
            for (int j = 0; j < n__; j++) {
                printf("%18.13f + I * %18.13f", full_mtrx(i, j).real(), full_mtrx(i, j).imag());
                if (j != n__ - 1) {
                    printf(",");
                }
            }
            if (i != n__ - 1) {
                printf("},\n");
            } else {
                printf("}\n");
            }
        }
        printf("}\n");
    }

    // std::ofstream ofs(aiida_output_file, std::ofstream::out | std::ofstream::trunc);
    // ofs << dict.dump(4);
}

template <>
inline void dmatrix<double>::serialize(std::string name__, int n__) const
{
    mdarray<double, 2> full_mtrx(num_rows(), num_cols());
    full_mtrx.zero();

    for (int j = 0; j < num_cols_local(); j++) {
        for (int i = 0; i < num_rows_local(); i++) {
            full_mtrx(irow(i), icol(j)) = (*this)(i, j);
        }
    }
    blacs_grid_->comm().allreduce(full_mtrx.at<CPU>(), static_cast<int>(full_mtrx.size()));

    //json dict;
    //dict["mtrx"] = json::array();
    //for (int i = 0; i < num_rows(); i++) {
    //    dict["mtrx"].push_back(json::array());
    //    for (int j = 0; j < num_cols(); j++) {
    //        dict["mtrx"][i].push_back(full_mtrx(i, j));
    //    }
    //}

    //if (blacs_grid_->comm().rank() == 0) {
    //    std::cout << "mtrx: " << name__ << std::endl;
    //    std::cout << dict.dump(4);
    //}

    // std::ofstream ofs(aiida_output_file, std::ofstream::out | std::ofstream::trunc);
    // ofs << dict.dump(4);

    if (blacs_grid_->comm().rank() == 0) {
        printf("matrix label: %s\n", name__.c_str());
        printf("{\n");
        for (int i = 0; i < n__; i++) {
            printf("{");
            for (int j = 0; j < n__; j++) {
                printf("%18.13f", full_mtrx(i, j));
                if (j != n__ - 1) {
                    printf(",");
                }
            }
            if (i != n__ - 1) {
                printf("},\n");
            } else {
                printf("}\n");
            }
        }
        printf("}\n");
    }
}

} // namespace sddk

#endif // __DMATRIX_HPP__
<|endoftext|>


<commit_before>#pragma once

#include <vector>

#include "CommonConfig.hpp"
#include "GradingConfig.hpp"
#include "MultipleTestCasesConfig.hpp"
#include "SeedSetter.hpp"
#include "Spec.hpp"
#include "StyleConfig.hpp"
#include "tcframe/spec/random.hpp"
#include "tcframe/util.hpp"

using std::vector;

namespace tcframe {

template<typename TProblemSpec /* extends BaseProblemSpec */>
class BaseTestSpec : public TProblemSpec, protected TestSuiteBuilder {
private:
    vector<void(BaseTestSpec::*)()> sampleTestCases_ = {
            &BaseTestSpec::SampleTestCase1,
            &BaseTestSpec::SampleTestCase2,
            &BaseTestSpec::SampleTestCase3,
            &BaseTestSpec::SampleTestCase4,
            &BaseTestSpec::SampleTestCase5,
            &BaseTestSpec::SampleTestCase6,
            &BaseTestSpec::SampleTestCase7,
            &BaseTestSpec::SampleTestCase8,
            &BaseTestSpec::SampleTestCase9,
            &BaseTestSpec::SampleTestCase10,
            &BaseTestSpec::SampleTestCase11,
            &BaseTestSpec::SampleTestCase12,
            &BaseTestSpec::SampleTestCase13,
            &BaseTestSpec::SampleTestCase14,
            &BaseTestSpec::SampleTestCase15,
            &BaseTestSpec::SampleTestCase16,
            &BaseTestSpec::SampleTestCase17,
            &BaseTestSpec::SampleTestCase18,
            &BaseTestSpec::SampleTestCase19,
            &BaseTestSpec::SampleTestCase20,
            &BaseTestSpec::SampleTestCase21,
            &BaseTestSpec::SampleTestCase22,
            &BaseTestSpec::SampleTestCase23,
            &BaseTestSpec::SampleTestCase24,
            &BaseTestSpec::SampleTestCase25};

    vector<void(BaseTestSpec::*)()> testGroups_ = {
            &BaseTestSpec::TestGroup1,
            &BaseTestSpec::TestGroup2,
            &BaseTestSpec::TestGroup3,
            &BaseTestSpec::TestGroup4,
            &BaseTestSpec::TestGroup5,
            &BaseTestSpec::TestGroup6,
            &BaseTestSpec::TestGroup7,
            &BaseTestSpec::TestGroup8,
            &BaseTestSpec::TestGroup9,
            &BaseTestSpec::TestGroup10,
            &BaseTestSpec::TestGroup11,
            &BaseTestSpec::TestGroup12,
            &BaseTestSpec::TestGroup13,
            &BaseTestSpec::TestGroup14,
            &BaseTestSpec::TestGroup15,
            &BaseTestSpec::TestGroup16,
            &BaseTestSpec::TestGroup17,
            &BaseTestSpec::TestGroup18,
            &BaseTestSpec::TestGroup19,
            &BaseTestSpec::TestGroup20,
            &BaseTestSpec::TestGroup21,
            &BaseTestSpec::TestGroup22,
            &BaseTestSpec::TestGroup23,
            &BaseTestSpec::TestGroup24,
            &BaseTestSpec::TestGroup25};

public:
    virtual ~BaseTestSpec() {}

    TestSuite buildTestSuite(const string& slug, const set<int>& definedSubtaskIds) {
        TestSuiteBuilder::setSlug(slug);
        TestSuiteBuilder::setDefinedSubtaskIds(definedSubtaskIds);
        TestSuiteBuilder::setBeforeClosure([this] {
            BeforeTestCase();
        });
        TestSuiteBuilder::setAfterClosure([this] {
            AfterTestCase();
        });

        for (auto sampleTestCase : sampleTestCases_) {
            try {
                TestSuiteBuilder::newSampleTestCase();
                (this->*sampleTestCase)();
            } catch (NotImplementedException&) {
                break;
            }
        }

        try {
            TestCases();
        } catch (NotImplementedException&) {
            for (auto testGroup : testGroups_) {
                try {
                    TestSuiteBuilder::newTestGroup();
                    (this->*testGroup)();
                } catch (NotImplementedException&) {
                    break;
                }
            }
        }
        return TestSuiteBuilder::build();
    }

    virtual Spec buildSpec(const string& slug) {
        SeedSetter* seedSetter = new SeedSetter([=] (unsigned seed) {rnd.setSeed(seed);});
        IOFormat ioFormat = TProblemSpec::buildIOFormat();
        StyleConfig styleConfig = TProblemSpec::buildStyleConfig();
        GradingConfig gradingConfig = TProblemSpec::buildGradingConfig();
        MultipleTestCasesConfig multipleTestCasesConfig = TProblemSpec::buildMultipleTestCasesConfig();
        ConstraintSuite constraintSuite = TProblemSpec::buildConstraintSuite();
        TestSuite testSuite = buildTestSuite(slug, constraintSuite.getDefinedSubtaskIds());
        return Spec(
                seedSetter,
                ioFormat,
                styleConfig,
                gradingConfig,
                multipleTestCasesConfig,
                constraintSuite,
                testSuite);
    }

protected:
    Random rnd;

    virtual void BeforeTestCase() {}
    virtual void AfterTestCase() {}
    virtual void SampleTestCase1() {throw NotImplementedException();}
    virtual void SampleTestCase2() {throw NotImplementedException();}
    virtual void SampleTestCase3() {throw NotImplementedException();}
    virtual void SampleTestCase4() {throw NotImplementedException();}
    virtual void SampleTestCase5() {throw NotImplementedException();}
    virtual void SampleTestCase6() {throw NotImplementedException();}
    virtual void SampleTestCase7() {throw NotImplementedException();}
    virtual void SampleTestCase8() {throw NotImplementedException();}
    virtual void SampleTestCase9() {throw NotImplementedException();}
    virtual void SampleTestCase10() {throw NotImplementedException();}
    virtual void SampleTestCase11() {throw NotImplementedException();}
    virtual void SampleTestCase12() {throw NotImplementedException();}
    virtual void SampleTestCase13() {throw NotImplementedException();}
    virtual void SampleTestCase14() {throw NotImplementedException();}
    virtual void SampleTestCase15() {throw NotImplementedException();}
    virtual void SampleTestCase16() {throw NotImplementedException();}
    virtual void SampleTestCase17() {throw NotImplementedException();}
    virtual void SampleTestCase18() {throw NotImplementedException();}
    virtual void SampleTestCase19() {throw NotImplementedException();}
    virtual void SampleTestCase20() {throw NotImplementedException();}
    virtual void SampleTestCase21() {throw NotImplementedException();}
    virtual void SampleTestCase22() {throw NotImplementedException();}
    virtual void SampleTestCase23() {throw NotImplementedException();}
    virtual void SampleTestCase24() {throw NotImplementedException();}
    virtual void SampleTestCase25() {throw NotImplementedException();}
    virtual void TestCases() {throw NotImplementedException();}
    virtual void TestGroup1() {throw NotImplementedException();}
    virtual void TestGroup2() {throw NotImplementedException();}
    virtual void TestGroup3() {throw NotImplementedException();}
    virtual void TestGroup4() {throw NotImplementedException();}
    virtual void TestGroup5() {throw NotImplementedException();}
    virtual void TestGroup6() {throw NotImplementedException();}
    virtual void TestGroup7() {throw NotImplementedException();}
    virtual void TestGroup8() {throw NotImplementedException();}
    virtual void TestGroup9() {throw NotImplementedException();}
    virtual void TestGroup10() {throw NotImplementedException();}
    virtual void TestGroup11() {throw NotImplementedException();}
    virtual void TestGroup12() {throw NotImplementedException();}
    virtual void TestGroup13() {throw NotImplementedException();}
    virtual void TestGroup14() {throw NotImplementedException();}
    virtual void TestGroup15() {throw NotImplementedException();}
    virtual void TestGroup16() {throw NotImplementedException();}
    virtual void TestGroup17() {throw NotImplementedException();}
    virtual void TestGroup18() {throw NotImplementedException();}
    virtual void TestGroup19() {throw NotImplementedException();}
    virtual void TestGroup20() {throw NotImplementedException();}
    virtual void TestGroup21() {throw NotImplementedException();}
    virtual void TestGroup22() {throw NotImplementedException();}
    virtual void TestGroup23() {throw NotImplementedException();}
    virtual void TestGroup24() {throw NotImplementedException();}
    virtual void TestGroup25() {throw NotImplementedException();}
};

}
<commit_msg>Add missing includes in BaseTestSpec<commit_after>#pragma once

#include <set>
#include <string>
#include <vector>

#include "CommonConfig.hpp"
#include "GradingConfig.hpp"
#include "MultipleTestCasesConfig.hpp"
#include "SeedSetter.hpp"
#include "Spec.hpp"
#include "StyleConfig.hpp"
#include "tcframe/spec/random.hpp"
#include "tcframe/util.hpp"

using std::set;
using std::string;
using std::vector;

namespace tcframe {

template<typename TProblemSpec /* extends BaseProblemSpec */>
class BaseTestSpec : public TProblemSpec, protected TestSuiteBuilder {
private:
    vector<void(BaseTestSpec::*)()> sampleTestCases_ = {
            &BaseTestSpec::SampleTestCase1,
            &BaseTestSpec::SampleTestCase2,
            &BaseTestSpec::SampleTestCase3,
            &BaseTestSpec::SampleTestCase4,
            &BaseTestSpec::SampleTestCase5,
            &BaseTestSpec::SampleTestCase6,
            &BaseTestSpec::SampleTestCase7,
            &BaseTestSpec::SampleTestCase8,
            &BaseTestSpec::SampleTestCase9,
            &BaseTestSpec::SampleTestCase10,
            &BaseTestSpec::SampleTestCase11,
            &BaseTestSpec::SampleTestCase12,
            &BaseTestSpec::SampleTestCase13,
            &BaseTestSpec::SampleTestCase14,
            &BaseTestSpec::SampleTestCase15,
            &BaseTestSpec::SampleTestCase16,
            &BaseTestSpec::SampleTestCase17,
            &BaseTestSpec::SampleTestCase18,
            &BaseTestSpec::SampleTestCase19,
            &BaseTestSpec::SampleTestCase20,
            &BaseTestSpec::SampleTestCase21,
            &BaseTestSpec::SampleTestCase22,
            &BaseTestSpec::SampleTestCase23,
            &BaseTestSpec::SampleTestCase24,
            &BaseTestSpec::SampleTestCase25};

    vector<void(BaseTestSpec::*)()> testGroups_ = {
            &BaseTestSpec::TestGroup1,
            &BaseTestSpec::TestGroup2,
            &BaseTestSpec::TestGroup3,
            &BaseTestSpec::TestGroup4,
            &BaseTestSpec::TestGroup5,
            &BaseTestSpec::TestGroup6,
            &BaseTestSpec::TestGroup7,
            &BaseTestSpec::TestGroup8,
            &BaseTestSpec::TestGroup9,
            &BaseTestSpec::TestGroup10,
            &BaseTestSpec::TestGroup11,
            &BaseTestSpec::TestGroup12,
            &BaseTestSpec::TestGroup13,
            &BaseTestSpec::TestGroup14,
            &BaseTestSpec::TestGroup15,
            &BaseTestSpec::TestGroup16,
            &BaseTestSpec::TestGroup17,
            &BaseTestSpec::TestGroup18,
            &BaseTestSpec::TestGroup19,
            &BaseTestSpec::TestGroup20,
            &BaseTestSpec::TestGroup21,
            &BaseTestSpec::TestGroup22,
            &BaseTestSpec::TestGroup23,
            &BaseTestSpec::TestGroup24,
            &BaseTestSpec::TestGroup25};

public:
    virtual ~BaseTestSpec() {}

    TestSuite buildTestSuite(const string& slug, const set<int>& definedSubtaskIds) {
        TestSuiteBuilder::setSlug(slug);
        TestSuiteBuilder::setDefinedSubtaskIds(definedSubtaskIds);
        TestSuiteBuilder::setBeforeClosure([this] {
            BeforeTestCase();
        });
        TestSuiteBuilder::setAfterClosure([this] {
            AfterTestCase();
        });

        for (auto sampleTestCase : sampleTestCases_) {
            try {
                TestSuiteBuilder::newSampleTestCase();
                (this->*sampleTestCase)();
            } catch (NotImplementedException&) {
                break;
            }
        }

        try {
            TestCases();
        } catch (NotImplementedException&) {
            for (auto testGroup : testGroups_) {
                try {
                    TestSuiteBuilder::newTestGroup();
                    (this->*testGroup)();
                } catch (NotImplementedException&) {
                    break;
                }
            }
        }
        return TestSuiteBuilder::build();
    }

    virtual Spec buildSpec(const string& slug) {
        SeedSetter* seedSetter = new SeedSetter([=] (unsigned seed) {rnd.setSeed(seed);});
        IOFormat ioFormat = TProblemSpec::buildIOFormat();
        StyleConfig styleConfig = TProblemSpec::buildStyleConfig();
        GradingConfig gradingConfig = TProblemSpec::buildGradingConfig();
        MultipleTestCasesConfig multipleTestCasesConfig = TProblemSpec::buildMultipleTestCasesConfig();
        ConstraintSuite constraintSuite = TProblemSpec::buildConstraintSuite();
        TestSuite testSuite = buildTestSuite(slug, constraintSuite.getDefinedSubtaskIds());
        return Spec(
                seedSetter,
                ioFormat,
                styleConfig,
                gradingConfig,
                multipleTestCasesConfig,
                constraintSuite,
                testSuite);
    }

protected:
    Random rnd;

    virtual void BeforeTestCase() {}
    virtual void AfterTestCase() {}
    virtual void SampleTestCase1() {throw NotImplementedException();}
    virtual void SampleTestCase2() {throw NotImplementedException();}
    virtual void SampleTestCase3() {throw NotImplementedException();}
    virtual void SampleTestCase4() {throw NotImplementedException();}
    virtual void SampleTestCase5() {throw NotImplementedException();}
    virtual void SampleTestCase6() {throw NotImplementedException();}
    virtual void SampleTestCase7() {throw NotImplementedException();}
    virtual void SampleTestCase8() {throw NotImplementedException();}
    virtual void SampleTestCase9() {throw NotImplementedException();}
    virtual void SampleTestCase10() {throw NotImplementedException();}
    virtual void SampleTestCase11() {throw NotImplementedException();}
    virtual void SampleTestCase12() {throw NotImplementedException();}
    virtual void SampleTestCase13() {throw NotImplementedException();}
    virtual void SampleTestCase14() {throw NotImplementedException();}
    virtual void SampleTestCase15() {throw NotImplementedException();}
    virtual void SampleTestCase16() {throw NotImplementedException();}
    virtual void SampleTestCase17() {throw NotImplementedException();}
    virtual void SampleTestCase18() {throw NotImplementedException();}
    virtual void SampleTestCase19() {throw NotImplementedException();}
    virtual void SampleTestCase20() {throw NotImplementedException();}
    virtual void SampleTestCase21() {throw NotImplementedException();}
    virtual void SampleTestCase22() {throw NotImplementedException();}
    virtual void SampleTestCase23() {throw NotImplementedException();}
    virtual void SampleTestCase24() {throw NotImplementedException();}
    virtual void SampleTestCase25() {throw NotImplementedException();}
    virtual void TestCases() {throw NotImplementedException();}
    virtual void TestGroup1() {throw NotImplementedException();}
    virtual void TestGroup2() {throw NotImplementedException();}
    virtual void TestGroup3() {throw NotImplementedException();}
    virtual void TestGroup4() {throw NotImplementedException();}
    virtual void TestGroup5() {throw NotImplementedException();}
    virtual void TestGroup6() {throw NotImplementedException();}
    virtual void TestGroup7() {throw NotImplementedException();}
    virtual void TestGroup8() {throw NotImplementedException();}
    virtual void TestGroup9() {throw NotImplementedException();}
    virtual void TestGroup10() {throw NotImplementedException();}
    virtual void TestGroup11() {throw NotImplementedException();}
    virtual void TestGroup12() {throw NotImplementedException();}
    virtual void TestGroup13() {throw NotImplementedException();}
    virtual void TestGroup14() {throw NotImplementedException();}
    virtual void TestGroup15() {throw NotImplementedException();}
    virtual void TestGroup16() {throw NotImplementedException();}
    virtual void TestGroup17() {throw NotImplementedException();}
    virtual void TestGroup18() {throw NotImplementedException();}
    virtual void TestGroup19() {throw NotImplementedException();}
    virtual void TestGroup20() {throw NotImplementedException();}
    virtual void TestGroup21() {throw NotImplementedException();}
    virtual void TestGroup22() {throw NotImplementedException();}
    virtual void TestGroup23() {throw NotImplementedException();}
    virtual void TestGroup24() {throw NotImplementedException();}
    virtual void TestGroup25() {throw NotImplementedException();}
};

}
<|endoftext|>


<commit_before>#include "taichi_grid.h"
#include <taichi/visual/texture.h>
#include <taichi/system/threading.h>
#include <taichi/util.h>
#include <taichi/math/svd.h>

TC_NAMESPACE_BEGIN

struct Node {
  real channels[16];
  real &operator[](int i) {
    return channels[i];
  }
};

using Block = TBlock<Node, char, TSize3D<8>, 0>;

class MGPCGTest {
 public:
  static constexpr auto dim = Block::dim;
  using Vector = TVector<real, dim>;
  using VectorP = TVector<real, dim + 1>;
  using Matrix = TMatrix<real, dim>;
  using Grid = TaichiGrid<Block>;

  Grid grid;

  using VectorI = Vector3i;
  using Vectori = VectorI;
  using GridScratchPad = TGridScratchPad<Block>;

  enum { CHANNEL_R, CHANNEL_Z, CHANNEL_X, CHANNEL_B, CHANNEL_TMP, CHANNEL_P };

  MGPCGTest() {
    // Span a region in
    constexpr int n = 32;
    Region3D active_region(VectorI(-n, -n, -n * 2), VectorI(n, n, n * 2));
    for (auto &ind : active_region) {
      grid.touch(ind.get_ipos());
      if (ind.get_ipos() == VectorI(0)) {
        TC_TAG;
        grid.node(ind.get_ipos())[CHANNEL_B] = 1;
      }
    }
  }

  void multiply(int channel_out, int channel_in) {
    grid.advance(
        [&](Block &b, Grid::Ancestors &an) {
          GridScratchPad scratch(an);
          std::memcpy(&b.nodes[0], &an[VectorI(0)]->nodes[0], sizeof(b.nodes));
          // 6 neighbours
          for (int i = 0; i < Block::size[0]; i++) {
            for (int j = 0; j < Block::size[1]; j++) {
              for (int k = 0; k < Block::size[2]; k++) {
#define V(ii, jj, kk) scratch.data[i + (ii)][j + (jj)][k + (kk)][channel_in]
                auto &o = b.get_node_volume()[i][j][k][channel_out];
                o = 6 * V(0, 0, 0) - V(0, 0, 1) - V(0, 0, -1) - V(0, 1, 0) -
                    V(0, -1, 0) - V(1, 0, 0) - V(-1, 0, 0);
                if (o != o) {
                  TC_P(b.base_coord);
                  TC_P(V(0, 0, 0));
                  TC_P(V(0, 0, 1));
                  TC_P(V(0, 1, 0));
                  TC_P(V(1, 0, 0));
                  TC_P(V(0, 0, -1));
                  TC_P(V(0, -1, 0));
                  TC_P(V(-1, 0, 0));
                  TC_P(o);
                  TC_P(i);
                  TC_P(j);
                  TC_P(k);
                  Time::sleep(0.01);
                }
#undef V
              }
            }
          }
        },
        false);
  }

  // out += a + scale * b
  void saxpy(int channel_out, int channel_a, int channel_b, real scale) {
    TC_ASSERT(!with_mpi());
    grid.map([&](Block &b) {
      for (auto &n : b.nodes) {
        n[channel_out] = n[channel_a] + scale * n[channel_b];
      }
    });
  }

  // out += a + scale * b
  void copy(int channel_out, int channel_a) {
    grid.map([&](Block &b) {
      for (auto &n : b.nodes) {
        n[channel_out] = n[channel_a];
      }
    });
  }

  float64 dot_product(int channel_a, int channel_b) {
    return grid.reduce([&](Block &b) -> float64 {
      float64 sum = 0;
      for (auto &n : b.nodes) {
        sum += n[channel_a] * n[channel_b];
      }
      return sum;
    });
  }

  void smoothing() {
    grid.advance(
        [&](Grid::Block &b, Grid::Ancestors &an) {

        },
        true);
  }

  real norm(int channel) {
    return std::sqrt(dot_product(channel, channel));
  }

  // https://en.wikipedia.org/wiki/Conjugate_gradient_method
  void run() {
    TC_P(norm(CHANNEL_B));
    // r = b - Ax
    multiply(CHANNEL_TMP, CHANNEL_X);
    TC_P(norm(CHANNEL_TMP));
    saxpy(CHANNEL_R, CHANNEL_B, CHANNEL_TMP, -1);
    // z = M^-1 r
    saxpy(CHANNEL_Z, CHANNEL_R, CHANNEL_R, 0);
    // p = z
    copy(CHANNEL_P, CHANNEL_Z);
    while (1) {
      multiply(CHANNEL_TMP, CHANNEL_P);
      real alpha = dot_product(CHANNEL_R, CHANNEL_Z) /
                   dot_product(CHANNEL_P, CHANNEL_TMP);

      auto old_zr = dot_product(CHANNEL_Z, CHANNEL_R);

      saxpy(CHANNEL_X, CHANNEL_X, CHANNEL_P, alpha);

      saxpy(CHANNEL_R, CHANNEL_R, CHANNEL_TMP, -alpha);

      auto l2 = norm(CHANNEL_R);
      TC_P(l2);
      if (l2 < 1e-7) {
        break;
      }

      copy(CHANNEL_Z, CHANNEL_R);

      auto beta = dot_product(CHANNEL_Z, CHANNEL_R) / old_zr;

      saxpy(CHANNEL_P, CHANNEL_Z, CHANNEL_P, beta);
    }
  }
};

auto mgpcg = [](const std::vector<std::string> &params) {
  // ThreadedTaskManager::TbbParallelismControl _(1);
  std::unique_ptr<MGPCGTest> mgpcg;
  mgpcg = std::make_unique<MGPCGTest>();
  mgpcg->run();
};

TC_REGISTER_TASK(mgpcg);

TC_NAMESPACE_END
<commit_msg>simplfy, allocate MG hierarchy<commit_after>#include "taichi_grid.h"
#include <taichi/visual/texture.h>
#include <taichi/system/threading.h>
#include <taichi/util.h>
#include <taichi/math/svd.h>

TC_NAMESPACE_BEGIN

struct Node {
  real channels[16];
  real &operator[](int i) {
    return channels[i];
  }
};

using Block = TBlock<Node, char, TSize3D<8>, 0>;

class MGPCGTest {
 public:
  static constexpr auto dim = Block::dim;
  using Vector = TVector<real, dim>;
  using VectorP = TVector<real, dim + 1>;
  using Matrix = TMatrix<real, dim>;
  using Grid = TaichiGrid<Block>;

  std::vector<std::unique_ptr<Grid>> grids;
  int mg_lv = 4;

  using VectorI = Vector3i;
  using Vectori = VectorI;
  using GridScratchPad = TGridScratchPad<Block>;

  enum { CH_R, CH_Z, CH_X, CH_B, CH_TMP, CH_P };

  MGPCGTest() {
    // Span a region in
    grids.resize(mg_lv);
    for (int i = 0; i < mg_lv; i++) {
      grids[i] = std::make_unique<Grid>();
    }
    TC_ASSERT(mg_lv >= 1);
    constexpr int n = 32;
    Region3D active_region(VectorI(-n, -n, -n * 2), VectorI(n, n, n * 2));
    for (auto &ind : active_region) {
      grids[0]->touch(ind.get_ipos());
      if (ind.get_ipos() == VectorI(0)) {
        TC_TAG;
        grids[0]->node(ind.get_ipos())[CH_B] = 1;
      }
    }
  }

  void multiply(int channel_out, int channel_in) {
    grids[0]->advance(
        [&](Block &b, Grid::Ancestors &an) {
          GridScratchPad scratch(an);
          std::memcpy(&b.nodes[0], &an[VectorI(0)]->nodes[0], sizeof(b.nodes));
          // 6 neighbours
          for (int i = 0; i < Block::size[0]; i++) {
            for (int j = 0; j < Block::size[1]; j++) {
              for (int k = 0; k < Block::size[2]; k++) {
#define V(ii, jj, kk) scratch.data[i + (ii)][j + (jj)][k + (kk)][channel_in]
                auto &o = b.get_node_volume()[i][j][k][channel_out];
                o = 6 * V(0, 0, 0) - V(0, 0, 1) - V(0, 0, -1) - V(0, 1, 0) -
                    V(0, -1, 0) - V(1, 0, 0) - V(-1, 0, 0);
                if (o != o) {
                  TC_P(b.base_coord);
                  TC_P(V(0, 0, 0));
                  TC_P(V(0, 0, 1));
                  TC_P(V(0, 1, 0));
                  TC_P(V(1, 0, 0));
                  TC_P(V(0, 0, -1));
                  TC_P(V(0, -1, 0));
                  TC_P(V(-1, 0, 0));
                  TC_P(o);
                  TC_P(i);
                  TC_P(j);
                  TC_P(k);
                  Time::sleep(0.01);
                }
#undef V
              }
            }
          }
        },
        false);
  }

  // out += a + scale * b
  void saxpy(int channel_out, int channel_a, int channel_b, real scale) {
    TC_ASSERT(!with_mpi());
    grids[0]->map([&](Block &b) {
      for (auto &n : b.nodes) {
        n[channel_out] = n[channel_a] + scale * n[channel_b];
      }
    });
  }

  // out += a + scale * b
  void copy(int channel_out, int channel_a) {
    grids[0]->map([&](Block &b) {
      for (auto &n : b.nodes) {
        n[channel_out] = n[channel_a];
      }
    });
  }

  float64 dot_product(int channel_a, int channel_b) {
    return grids[0]->reduce([&](Block &b) -> float64 {
      float64 sum = 0;
      for (auto &n : b.nodes) {
        sum += n[channel_a] * n[channel_b];
      }
      return sum;
    });
  }

  void smoothing() {
    grids[0]->advance(
        [&](Grid::Block &b, Grid::Ancestors &an) {

        },
        true);
  }

  real norm(int channel) {
    return std::sqrt(dot_product(channel, channel));
  }

  // https://en.wikipedia.org/wiki/Conjugate_gradient_method
  void run() {
    TC_P(norm(CH_B));
    // r = b - Ax
    multiply(CH_TMP, CH_X);
    TC_P(norm(CH_TMP));
    saxpy(CH_R, CH_B, CH_TMP, -1);
    // z = M^-1 r
    saxpy(CH_Z, CH_R, CH_R, 0);
    // p = z
    copy(CH_P, CH_Z);
    while (1) {
      multiply(CH_TMP, CH_P);
      real alpha = dot_product(CH_R, CH_Z) / dot_product(CH_P, CH_TMP);

      auto old_zr = dot_product(CH_Z, CH_R);

      saxpy(CH_X, CH_X, CH_P, alpha);

      saxpy(CH_R, CH_R, CH_TMP, -alpha);

      auto l2 = norm(CH_R);
      TC_P(l2);
      if (l2 < 1e-7) {
        break;
      }

      copy(CH_Z, CH_R);

      auto beta = dot_product(CH_Z, CH_R) / old_zr;

      saxpy(CH_P, CH_Z, CH_P, beta);
    }
  }
};

auto mgpcg = [](const std::vector<std::string> &params) {
  // ThreadedTaskManager::TbbParallelismControl _(1);
  std::unique_ptr<MGPCGTest> mgpcg;
  mgpcg = std::make_unique<MGPCGTest>();
  mgpcg->run();
};

TC_REGISTER_TASK(mgpcg);

TC_NAMESPACE_END
<|endoftext|>


<commit_before>/****************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of PySide2.
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 3 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL3 included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 3 requirements
** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 2.0 or (at your option) the GNU General
** Public license version 3 or any later version approved by the KDE Free
** Qt Foundation. The licenses are as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-2.0.html and
** https://www.gnu.org/licenses/gpl-3.0.html.
**
** $QT_END_LICENSE$
**
****************************************************************************/

#include "pyside.h"
#include "signalmanager.h"
#include "pysideclassinfo_p.h"
#include "pysideproperty_p.h"
#include "pysideproperty.h"
#include "pysidesignal.h"
#include "pysidesignal_p.h"
#include "pysideslot_p.h"
#include "pysidemetafunction_p.h"
#include "pysidemetafunction.h"
#include "dynamicqmetaobject.h"
#include "destroylistener.h"

#include <basewrapper.h>
#include <conversions.h>
#include <sbkconverter.h>
#include <gilstate.h>
#include <typeresolver.h>
#include <bindingmanager.h>
#include <algorithm>
#include <cstring>
#include <cctype>
#include <QStack>
#include <QCoreApplication>
#include <QDebug>
#include <QSharedPointer>

static QStack<PySide::CleanupFunction> cleanupFunctionList;
static void* qobjectNextAddr;

namespace PySide
{

void init(PyObject *module)
{
    qobjectNextAddr = 0;
    ClassInfo::init(module);
    Signal::init(module);
    Slot::init(module);
    Property::init(module);
    MetaFunction::init(module);
    // Init signal manager, so it will register some meta types used by QVariant.
    SignalManager::instance();
}

bool fillQtProperties(PyObject* qObj, const QMetaObject* metaObj, PyObject* kwds, const char** blackList, unsigned int blackListSize)
{

    PyObject *key, *value;
    Py_ssize_t pos = 0;

    while (PyDict_Next(kwds, &pos, &key, &value)) {
        if (!blackListSize || !std::binary_search(blackList, blackList + blackListSize, std::string(Shiboken::String::toCString(key)))) {
            QByteArray propName(Shiboken::String::toCString(key));
            if (metaObj->indexOfProperty(propName) != -1) {
                propName[0] = std::toupper(propName[0]);
                propName.prepend("set");

                Shiboken::AutoDecRef propSetter(PyObject_GetAttrString(qObj, propName.constData()));
                if (!propSetter.isNull()) {
                    Shiboken::AutoDecRef args(PyTuple_Pack(1, value));
                    Shiboken::AutoDecRef retval(PyObject_CallObject(propSetter, args));
                } else {
                    PyObject* attr = PyObject_GenericGetAttr(qObj, key);
                    if (PySide::Property::checkType(attr))
                        PySide::Property::setValue(reinterpret_cast<PySideProperty*>(attr), qObj, value);
                }
            } else {
                propName.append("()");
                if (metaObj->indexOfSignal(propName) != -1) {
                    propName.prepend('2');
                    PySide::Signal::connect(qObj, propName, value);
                } else {
                    PyErr_Format(PyExc_AttributeError, "'%s' is not a Qt property or a signal", propName.constData());
                    return false;
                };
            }
        }
    }
    return true;
}

void registerCleanupFunction(CleanupFunction func)
{
    cleanupFunctionList.push(func);
}

void runCleanupFunctions()
{
    //PySide::DestroyListener::instance()->destroy();
    while (!cleanupFunctionList.isEmpty()) {
        CleanupFunction f = cleanupFunctionList.pop();
        f();
    }
    PySide::DestroyListener::destroy();
}

static void destructionVisitor(SbkObject* pyObj, void* data)
{
    void** realData = reinterpret_cast<void**>(data);
    SbkObject* pyQApp = reinterpret_cast<SbkObject*>(realData[0]);
    PyTypeObject* pyQObjectType = reinterpret_cast<PyTypeObject*>(realData[1]);

    if (pyObj != pyQApp && PyObject_TypeCheck(pyObj, pyQObjectType)) {
        if (Shiboken::Object::hasOwnership(pyObj) && Shiboken::Object::isValid(pyObj, false)) {
            Shiboken::Object::setValidCpp(pyObj, false);

            Py_BEGIN_ALLOW_THREADS
            Shiboken::callCppDestructor<QObject>(Shiboken::Object::cppPointer(pyObj, pyQObjectType));
            Py_END_ALLOW_THREADS
        }
    }

};

void destroyQCoreApplication()
{
    SignalManager::instance().clear();
    QCoreApplication* app = QCoreApplication::instance();
    if (!app)
        return;

    Shiboken::BindingManager& bm = Shiboken::BindingManager::instance();
    SbkObject* pyQApp = bm.retrieveWrapper(app);
    PyTypeObject* pyQObjectType = Shiboken::Conversions::getPythonTypeObject("QObject*");
    assert(pyQObjectType);

    void* data[2] = {pyQApp, pyQObjectType};
    bm.visitAllPyObjects(&destructionVisitor, &data);

    // in the end destroy app
    // Allow threads because the destructor calls
    // QThreadPool::globalInstance().waitForDone() which may deadlock on the GIL
    // if there is a worker working with python objects.
    Py_BEGIN_ALLOW_THREADS
    delete app;
    Py_END_ALLOW_THREADS
}

struct TypeUserData {
    TypeUserData(PyTypeObject* type, const QMetaObject* metaobject) : mo(type, metaobject) {}
    DynamicQMetaObject mo;
    std::size_t cppObjSize;
};

std::size_t getSizeOfQObject(SbkObjectType* type)
{
    using namespace Shiboken::ObjectType;
    TypeUserData* userData = reinterpret_cast<TypeUserData*>(getTypeUserData(reinterpret_cast<SbkObjectType*>(type)));
    return userData->cppObjSize;
}

void initDynamicMetaObject(SbkObjectType* type, const QMetaObject* base, const std::size_t& cppObjSize)
{
    //create DynamicMetaObject based on python type
    TypeUserData* userData = new TypeUserData(reinterpret_cast<PyTypeObject*>(type), base);
    userData->cppObjSize = cppObjSize;
    userData->mo.update();
    Shiboken::ObjectType::setTypeUserData(type, userData, Shiboken::callCppDestructor<TypeUserData>);

    //initialize staticQMetaObject property
    void* metaObjectPtr = &userData->mo;
    static SbkConverter* converter = Shiboken::Conversions::getConverter("QMetaObject");
    if (!converter)
        return;
    Shiboken::AutoDecRef pyMetaObject(Shiboken::Conversions::pointerToPython(converter, metaObjectPtr));
    PyObject_SetAttrString(reinterpret_cast<PyObject*>(type), "staticMetaObject", pyMetaObject);
}

void initDynamicMetaObject(SbkObjectType* type, const QMetaObject* base)
{
    initDynamicMetaObject(type, base, 0);
}

void initQObjectSubType(SbkObjectType *type, PyObject *args, PyObject * /* kwds */)
{
    PyTypeObject* qObjType = Shiboken::Conversions::getPythonTypeObject("QObject*");
    QByteArray className(Shiboken::String::toCString(PyTuple_GET_ITEM(args, 0)));

    PyObject* bases = PyTuple_GET_ITEM(args, 1);
    int numBases = PyTuple_GET_SIZE(bases);
    QMetaObject* baseMo = 0;
    SbkObjectType* qobjBase = 0;

    for (int i = 0; i < numBases; ++i) {
        PyTypeObject* base = reinterpret_cast<PyTypeObject*>(PyTuple_GET_ITEM(bases, i));
        if (PyType_IsSubtype(base, qObjType)) {
            baseMo = reinterpret_cast<QMetaObject*>(Shiboken::ObjectType::getTypeUserData(reinterpret_cast<SbkObjectType*>(base)));
            qobjBase = reinterpret_cast<SbkObjectType*>(base);
            reinterpret_cast<DynamicQMetaObject*>(baseMo)->update();
            break;
        }
    }
    if (!baseMo) {
        qWarning("Sub class of QObject not inheriting QObject!? Crash will happen when using %s.", className.constData());
        return;
    }

    TypeUserData* userData = reinterpret_cast<TypeUserData*>(Shiboken::ObjectType::getTypeUserData(qobjBase));
    initDynamicMetaObject(type, baseMo, userData->cppObjSize);
}

PyObject* getMetaDataFromQObject(QObject* cppSelf, PyObject* self, PyObject* name)
{
    PyObject* attr = PyObject_GenericGetAttr(self, name);
    if (!Shiboken::Object::isValid(reinterpret_cast<SbkObject*>(self), false))
        return attr;

    if (attr && Property::checkType(attr)) {
        PyObject *value = Property::getValue(reinterpret_cast<PySideProperty*>(attr), self);
        Py_DECREF(attr);
        if (!value)
            return 0;
        Py_INCREF(value);
        attr = value;
    }

    //mutate native signals to signal instance type
    if (attr && PyObject_TypeCheck(attr, &PySideSignalType)) {
        PyObject* signal = reinterpret_cast<PyObject*>(Signal::initialize(reinterpret_cast<PySideSignal*>(attr), name, self));
        PyObject_SetAttr(self, name, reinterpret_cast<PyObject*>(signal));
        return signal;
    }

    //search on metaobject (avoid internal attributes started with '__')
    if (!attr) {
        const char* cname = Shiboken::String::toCString(name);
        uint cnameLen = qstrlen(cname);
        if (std::strncmp("__", cname, 2)) {
            const QMetaObject* metaObject = cppSelf->metaObject();
            //signal
            QList<QMetaMethod> signalList;
            for(int i=0, i_max = metaObject->methodCount(); i < i_max; i++) {
                QMetaMethod method = metaObject->method(i);
                const char* methSig = method.methodSignature();
                bool methMacth = !std::strncmp(cname, methSig, cnameLen) && methSig[cnameLen] == '(';
                if (methMacth) {
                    if (method.methodType() == QMetaMethod::Signal) {
                        signalList.append(method);
                    } else {
                        PySideMetaFunction* func = MetaFunction::newObject(cppSelf, i);
                        if (func) {
                            PyObject *result = reinterpret_cast<PyObject *>(func);
                            PyObject_SetAttr(self, name, result);
                            return result;
                        }
                    }
                }
            }
            if (signalList.size() > 0) {
                PyObject* pySignal = reinterpret_cast<PyObject*>(Signal::newObjectFromMethod(self, signalList));
                PyObject_SetAttr(self, name, pySignal);
                return pySignal;
            }
        }
    }
    return attr;
}

bool inherits(PyTypeObject* objType, const char* class_name)
{
    if (strcmp(objType->tp_name, class_name) == 0)
        return true;

    PyTypeObject* base = (objType)->tp_base;
    if (base == 0)
        return false;

    return inherits(base, class_name);
}

void* nextQObjectMemoryAddr()
{
    return qobjectNextAddr;
}

void setNextQObjectMemoryAddr(void* addr)
{
    qobjectNextAddr = addr;
}

} // namespace PySide

// A QSharedPointer is used with a deletion function to invalidate a pointer
// when the property value is cleared.  This should be a QSharedPointer with
// a void* pointer, but that isn't allowed
typedef char any_t;
Q_DECLARE_METATYPE(QSharedPointer<any_t>);

namespace PySide
{

static void invalidatePtr(any_t* object)
{
    Shiboken::GilState state;

    SbkObject* wrapper = Shiboken::BindingManager::instance().retrieveWrapper(object);
    if (wrapper != NULL)
        Shiboken::BindingManager::instance().releaseWrapper(wrapper);
}

static const char invalidatePropertyName[] = "_PySideInvalidatePtr";

PyObject* getWrapperForQObject(QObject* cppSelf, SbkObjectType* sbk_type)
{
    PyObject* pyOut = reinterpret_cast<PyObject *>(Shiboken::BindingManager::instance().retrieveWrapper(cppSelf));
    if (pyOut) {
        Py_INCREF(pyOut);
        return pyOut;
    }

    // Setting the property will trigger an QEvent notification, which may call into
    // code that creates the wrapper so only set the property if it isn't already
    // set and check if it's created after the set call
    QVariant existing = cppSelf->property(invalidatePropertyName);
    if (!existing.isValid()) {
        QSharedPointer<any_t> shared_with_del((any_t*)cppSelf, invalidatePtr);
        cppSelf->setProperty(invalidatePropertyName, QVariant::fromValue(shared_with_del));
        pyOut = reinterpret_cast<PyObject *>(Shiboken::BindingManager::instance().retrieveWrapper(cppSelf));
        if (pyOut) {
            Py_INCREF(pyOut);
            return pyOut;
        }
    }

    const char* typeName = typeid(*cppSelf).name();
    pyOut = Shiboken::Object::newObject(sbk_type, cppSelf, false, false, typeName);

    return pyOut;
}

#ifdef PYSIDE_QML_SUPPORT
static QuickRegisterItemFunction quickRegisterItem;

QuickRegisterItemFunction getQuickRegisterItemFunction()
{
    return quickRegisterItem;
}

void setQuickRegisterItemFunction(QuickRegisterItemFunction function)
{
    quickRegisterItem = function;
}
#endif // PYSIDE_QML_SUPPORT

} //namespace PySide

<commit_msg>Fix pointer to temporary memory in PySide::getMetaDataFromQObject<commit_after>/****************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of PySide2.
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 3 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL3 included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 3 requirements
** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 2.0 or (at your option) the GNU General
** Public license version 3 or any later version approved by the KDE Free
** Qt Foundation. The licenses are as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-2.0.html and
** https://www.gnu.org/licenses/gpl-3.0.html.
**
** $QT_END_LICENSE$
**
****************************************************************************/

#include "pyside.h"
#include "signalmanager.h"
#include "pysideclassinfo_p.h"
#include "pysideproperty_p.h"
#include "pysideproperty.h"
#include "pysidesignal.h"
#include "pysidesignal_p.h"
#include "pysideslot_p.h"
#include "pysidemetafunction_p.h"
#include "pysidemetafunction.h"
#include "dynamicqmetaobject.h"
#include "destroylistener.h"

#include <basewrapper.h>
#include <conversions.h>
#include <sbkconverter.h>
#include <gilstate.h>
#include <typeresolver.h>
#include <bindingmanager.h>
#include <algorithm>
#include <cstring>
#include <cctype>
#include <QStack>
#include <QCoreApplication>
#include <QDebug>
#include <QSharedPointer>

static QStack<PySide::CleanupFunction> cleanupFunctionList;
static void* qobjectNextAddr;

namespace PySide
{

void init(PyObject *module)
{
    qobjectNextAddr = 0;
    ClassInfo::init(module);
    Signal::init(module);
    Slot::init(module);
    Property::init(module);
    MetaFunction::init(module);
    // Init signal manager, so it will register some meta types used by QVariant.
    SignalManager::instance();
}

bool fillQtProperties(PyObject* qObj, const QMetaObject* metaObj, PyObject* kwds, const char** blackList, unsigned int blackListSize)
{

    PyObject *key, *value;
    Py_ssize_t pos = 0;

    while (PyDict_Next(kwds, &pos, &key, &value)) {
        if (!blackListSize || !std::binary_search(blackList, blackList + blackListSize, std::string(Shiboken::String::toCString(key)))) {
            QByteArray propName(Shiboken::String::toCString(key));
            if (metaObj->indexOfProperty(propName) != -1) {
                propName[0] = std::toupper(propName[0]);
                propName.prepend("set");

                Shiboken::AutoDecRef propSetter(PyObject_GetAttrString(qObj, propName.constData()));
                if (!propSetter.isNull()) {
                    Shiboken::AutoDecRef args(PyTuple_Pack(1, value));
                    Shiboken::AutoDecRef retval(PyObject_CallObject(propSetter, args));
                } else {
                    PyObject* attr = PyObject_GenericGetAttr(qObj, key);
                    if (PySide::Property::checkType(attr))
                        PySide::Property::setValue(reinterpret_cast<PySideProperty*>(attr), qObj, value);
                }
            } else {
                propName.append("()");
                if (metaObj->indexOfSignal(propName) != -1) {
                    propName.prepend('2');
                    PySide::Signal::connect(qObj, propName, value);
                } else {
                    PyErr_Format(PyExc_AttributeError, "'%s' is not a Qt property or a signal", propName.constData());
                    return false;
                };
            }
        }
    }
    return true;
}

void registerCleanupFunction(CleanupFunction func)
{
    cleanupFunctionList.push(func);
}

void runCleanupFunctions()
{
    //PySide::DestroyListener::instance()->destroy();
    while (!cleanupFunctionList.isEmpty()) {
        CleanupFunction f = cleanupFunctionList.pop();
        f();
    }
    PySide::DestroyListener::destroy();
}

static void destructionVisitor(SbkObject* pyObj, void* data)
{
    void** realData = reinterpret_cast<void**>(data);
    SbkObject* pyQApp = reinterpret_cast<SbkObject*>(realData[0]);
    PyTypeObject* pyQObjectType = reinterpret_cast<PyTypeObject*>(realData[1]);

    if (pyObj != pyQApp && PyObject_TypeCheck(pyObj, pyQObjectType)) {
        if (Shiboken::Object::hasOwnership(pyObj) && Shiboken::Object::isValid(pyObj, false)) {
            Shiboken::Object::setValidCpp(pyObj, false);

            Py_BEGIN_ALLOW_THREADS
            Shiboken::callCppDestructor<QObject>(Shiboken::Object::cppPointer(pyObj, pyQObjectType));
            Py_END_ALLOW_THREADS
        }
    }

};

void destroyQCoreApplication()
{
    SignalManager::instance().clear();
    QCoreApplication* app = QCoreApplication::instance();
    if (!app)
        return;

    Shiboken::BindingManager& bm = Shiboken::BindingManager::instance();
    SbkObject* pyQApp = bm.retrieveWrapper(app);
    PyTypeObject* pyQObjectType = Shiboken::Conversions::getPythonTypeObject("QObject*");
    assert(pyQObjectType);

    void* data[2] = {pyQApp, pyQObjectType};
    bm.visitAllPyObjects(&destructionVisitor, &data);

    // in the end destroy app
    // Allow threads because the destructor calls
    // QThreadPool::globalInstance().waitForDone() which may deadlock on the GIL
    // if there is a worker working with python objects.
    Py_BEGIN_ALLOW_THREADS
    delete app;
    Py_END_ALLOW_THREADS
}

struct TypeUserData {
    TypeUserData(PyTypeObject* type, const QMetaObject* metaobject) : mo(type, metaobject) {}
    DynamicQMetaObject mo;
    std::size_t cppObjSize;
};

std::size_t getSizeOfQObject(SbkObjectType* type)
{
    using namespace Shiboken::ObjectType;
    TypeUserData* userData = reinterpret_cast<TypeUserData*>(getTypeUserData(reinterpret_cast<SbkObjectType*>(type)));
    return userData->cppObjSize;
}

void initDynamicMetaObject(SbkObjectType* type, const QMetaObject* base, const std::size_t& cppObjSize)
{
    //create DynamicMetaObject based on python type
    TypeUserData* userData = new TypeUserData(reinterpret_cast<PyTypeObject*>(type), base);
    userData->cppObjSize = cppObjSize;
    userData->mo.update();
    Shiboken::ObjectType::setTypeUserData(type, userData, Shiboken::callCppDestructor<TypeUserData>);

    //initialize staticQMetaObject property
    void* metaObjectPtr = &userData->mo;
    static SbkConverter* converter = Shiboken::Conversions::getConverter("QMetaObject");
    if (!converter)
        return;
    Shiboken::AutoDecRef pyMetaObject(Shiboken::Conversions::pointerToPython(converter, metaObjectPtr));
    PyObject_SetAttrString(reinterpret_cast<PyObject*>(type), "staticMetaObject", pyMetaObject);
}

void initDynamicMetaObject(SbkObjectType* type, const QMetaObject* base)
{
    initDynamicMetaObject(type, base, 0);
}

void initQObjectSubType(SbkObjectType *type, PyObject *args, PyObject * /* kwds */)
{
    PyTypeObject* qObjType = Shiboken::Conversions::getPythonTypeObject("QObject*");
    QByteArray className(Shiboken::String::toCString(PyTuple_GET_ITEM(args, 0)));

    PyObject* bases = PyTuple_GET_ITEM(args, 1);
    int numBases = PyTuple_GET_SIZE(bases);
    QMetaObject* baseMo = 0;
    SbkObjectType* qobjBase = 0;

    for (int i = 0; i < numBases; ++i) {
        PyTypeObject* base = reinterpret_cast<PyTypeObject*>(PyTuple_GET_ITEM(bases, i));
        if (PyType_IsSubtype(base, qObjType)) {
            baseMo = reinterpret_cast<QMetaObject*>(Shiboken::ObjectType::getTypeUserData(reinterpret_cast<SbkObjectType*>(base)));
            qobjBase = reinterpret_cast<SbkObjectType*>(base);
            reinterpret_cast<DynamicQMetaObject*>(baseMo)->update();
            break;
        }
    }
    if (!baseMo) {
        qWarning("Sub class of QObject not inheriting QObject!? Crash will happen when using %s.", className.constData());
        return;
    }

    TypeUserData* userData = reinterpret_cast<TypeUserData*>(Shiboken::ObjectType::getTypeUserData(qobjBase));
    initDynamicMetaObject(type, baseMo, userData->cppObjSize);
}

PyObject* getMetaDataFromQObject(QObject* cppSelf, PyObject* self, PyObject* name)
{
    PyObject* attr = PyObject_GenericGetAttr(self, name);
    if (!Shiboken::Object::isValid(reinterpret_cast<SbkObject*>(self), false))
        return attr;

    if (attr && Property::checkType(attr)) {
        PyObject *value = Property::getValue(reinterpret_cast<PySideProperty*>(attr), self);
        Py_DECREF(attr);
        if (!value)
            return 0;
        Py_INCREF(value);
        attr = value;
    }

    //mutate native signals to signal instance type
    if (attr && PyObject_TypeCheck(attr, &PySideSignalType)) {
        PyObject* signal = reinterpret_cast<PyObject*>(Signal::initialize(reinterpret_cast<PySideSignal*>(attr), name, self));
        PyObject_SetAttr(self, name, reinterpret_cast<PyObject*>(signal));
        return signal;
    }

    //search on metaobject (avoid internal attributes started with '__')
    if (!attr) {
        const char* cname = Shiboken::String::toCString(name);
        uint cnameLen = qstrlen(cname);
        if (std::strncmp("__", cname, 2)) {
            const QMetaObject* metaObject = cppSelf->metaObject();
            //signal
            QList<QMetaMethod> signalList;
            for(int i=0, i_max = metaObject->methodCount(); i < i_max; i++) {
                QMetaMethod method = metaObject->method(i);
                const QByteArray methSig_ = method.methodSignature();
                const char *methSig = methSig_.constData();
                bool methMacth = !std::strncmp(cname, methSig, cnameLen) && methSig[cnameLen] == '(';
                if (methMacth) {
                    if (method.methodType() == QMetaMethod::Signal) {
                        signalList.append(method);
                    } else {
                        PySideMetaFunction* func = MetaFunction::newObject(cppSelf, i);
                        if (func) {
                            PyObject *result = reinterpret_cast<PyObject *>(func);
                            PyObject_SetAttr(self, name, result);
                            return result;
                        }
                    }
                }
            }
            if (signalList.size() > 0) {
                PyObject* pySignal = reinterpret_cast<PyObject*>(Signal::newObjectFromMethod(self, signalList));
                PyObject_SetAttr(self, name, pySignal);
                return pySignal;
            }
        }
    }
    return attr;
}

bool inherits(PyTypeObject* objType, const char* class_name)
{
    if (strcmp(objType->tp_name, class_name) == 0)
        return true;

    PyTypeObject* base = (objType)->tp_base;
    if (base == 0)
        return false;

    return inherits(base, class_name);
}

void* nextQObjectMemoryAddr()
{
    return qobjectNextAddr;
}

void setNextQObjectMemoryAddr(void* addr)
{
    qobjectNextAddr = addr;
}

} // namespace PySide

// A QSharedPointer is used with a deletion function to invalidate a pointer
// when the property value is cleared.  This should be a QSharedPointer with
// a void* pointer, but that isn't allowed
typedef char any_t;
Q_DECLARE_METATYPE(QSharedPointer<any_t>);

namespace PySide
{

static void invalidatePtr(any_t* object)
{
    Shiboken::GilState state;

    SbkObject* wrapper = Shiboken::BindingManager::instance().retrieveWrapper(object);
    if (wrapper != NULL)
        Shiboken::BindingManager::instance().releaseWrapper(wrapper);
}

static const char invalidatePropertyName[] = "_PySideInvalidatePtr";

PyObject* getWrapperForQObject(QObject* cppSelf, SbkObjectType* sbk_type)
{
    PyObject* pyOut = reinterpret_cast<PyObject *>(Shiboken::BindingManager::instance().retrieveWrapper(cppSelf));
    if (pyOut) {
        Py_INCREF(pyOut);
        return pyOut;
    }

    // Setting the property will trigger an QEvent notification, which may call into
    // code that creates the wrapper so only set the property if it isn't already
    // set and check if it's created after the set call
    QVariant existing = cppSelf->property(invalidatePropertyName);
    if (!existing.isValid()) {
        QSharedPointer<any_t> shared_with_del((any_t*)cppSelf, invalidatePtr);
        cppSelf->setProperty(invalidatePropertyName, QVariant::fromValue(shared_with_del));
        pyOut = reinterpret_cast<PyObject *>(Shiboken::BindingManager::instance().retrieveWrapper(cppSelf));
        if (pyOut) {
            Py_INCREF(pyOut);
            return pyOut;
        }
    }

    const char* typeName = typeid(*cppSelf).name();
    pyOut = Shiboken::Object::newObject(sbk_type, cppSelf, false, false, typeName);

    return pyOut;
}

#ifdef PYSIDE_QML_SUPPORT
static QuickRegisterItemFunction quickRegisterItem;

QuickRegisterItemFunction getQuickRegisterItemFunction()
{
    return quickRegisterItem;
}

void setQuickRegisterItemFunction(QuickRegisterItemFunction function)
{
    quickRegisterItem = function;
}
#endif // PYSIDE_QML_SUPPORT

} //namespace PySide

<|endoftext|>


<commit_before>// This file is distributed under the MIT license.
// See the LICENSE file for details.

#include <visionaray/random_sampler.h>

#include "sched_common.h"

namespace visionaray
{

//-------------------------------------------------------------------------------------------------
// Simple sched
//

template <typename R>
template <typename K, typename SP>
void simple_sched<R>::frame(K kernel, SP sched_params, unsigned frame_num)
{
    sched_params.cam.begin_frame();

    sched_params.rt.begin_frame();

    // TODO: support any sampler
    random_sampler<typename R::scalar_type> samp(detail::tic(typename R::scalar_type{}));

    auto scissor_box = sched_params.scissor_box;

    for (int y = 0; y < sched_params.rt.height(); ++y)
    {
        for (int x = 0; x < sched_params.rt.width(); ++x)
        {
            if (x < scissor_box.x || y < scissor_box.y || x >= scissor_box.w || y >= scissor_box.h)
            {
                continue;
            }

            auto r = detail::make_primary_rays(
                    R{},
                    typename SP::pixel_sampler_type{},
                    samp,
                    x,
                    y,
                    sched_params.rt.width(),
                    sched_params.rt.height(),
                    sched_params.cam
                    );

            sample_pixel(
                    kernel,
                    typename SP::pixel_sampler_type{},
                    r,
                    samp,
                    frame_num,
                    sched_params.rt.ref(),
                    x,
                    y,
                    sched_params.rt.width(),
                    sched_params.rt.height(),
                    sched_params.cam
                    );
        }
    }

    sched_params.rt.end_frame();

    sched_params.cam.end_frame();
}

} // visionaray
<commit_msg>Have one random sampler per ray packet<commit_after>// This file is distributed under the MIT license.
// See the LICENSE file for details.

#include <visionaray/random_sampler.h>

#include "sched_common.h"

namespace visionaray
{

//-------------------------------------------------------------------------------------------------
// Simple sched
//

template <typename R>
template <typename K, typename SP>
void simple_sched<R>::frame(K kernel, SP sched_params, unsigned frame_num)
{
    sched_params.cam.begin_frame();

    sched_params.rt.begin_frame();

    auto scissor_box = sched_params.scissor_box;

    for (int y = 0; y < sched_params.rt.height(); ++y)
    {
        for (int x = 0; x < sched_params.rt.width(); ++x)
        {
            if (x < scissor_box.x || y < scissor_box.y || x >= scissor_box.w || y >= scissor_box.h)
            {
                continue;
            }

            // TODO: support any sampler
            random_sampler<typename R::scalar_type> samp(detail::tic(typename R::scalar_type{}));

            auto r = detail::make_primary_rays(
                    R{},
                    typename SP::pixel_sampler_type{},
                    samp,
                    x,
                    y,
                    sched_params.rt.width(),
                    sched_params.rt.height(),
                    sched_params.cam
                    );

            sample_pixel(
                    kernel,
                    typename SP::pixel_sampler_type{},
                    r,
                    samp,
                    frame_num,
                    sched_params.rt.ref(),
                    x,
                    y,
                    sched_params.rt.width(),
                    sched_params.rt.height(),
                    sched_params.cam
                    );
        }
    }

    sched_params.rt.end_frame();

    sched_params.cam.end_frame();
}

} // visionaray
<|endoftext|>


<commit_before>#include "platform.hpp"

#ifndef WIN32

#include "../collector.hpp"
#include <signal.h>
#include <unistd.h>

namespace Mirb
{
	namespace Platform
	{
		std::string BenchmarkResult::format()
		{
			std::stringstream result;

			result << ((double)time / 1000) << " ms";

			return result.str();
		}

		void *allocate_region(size_t bytes)
		{
			void *result = mmap(0, bytes, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);

			mirb_runtime_assert(result != 0);

			return result;
		}

		void free_region(void *region, size_t bytes)
		{
			munmap(region, bytes);
		}

		CharArray cwd()
		{
			char *result = getcwd(nullptr, 0);

			CharArray str((const char_t *)result, std::strlen(result));

			std::free(result);

			return str;
		}

		void signal_handler(int)
		{
			Collector::signal();
		}

		void initialize()
		{
			signal(SIGINT, signal_handler);
		}
	};
};

#endif
<commit_msg>Added file_exists for POSIX.<commit_after>#include "platform.hpp"

#ifndef WIN32

#include "../collector.hpp"
#include <signal.h>
#include <unistd.h>

namespace Mirb
{
	namespace Platform
	{
		std::string BenchmarkResult::format()
		{
			std::stringstream result;

			result << ((double)time / 1000) << " ms";

			return result.str();
		}

		void *allocate_region(size_t bytes)
		{
			void *result = mmap(0, bytes, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);

			mirb_runtime_assert(result != 0);

			return result;
		}

		void free_region(void *region, size_t bytes)
		{
			munmap(region, bytes);
		}

		CharArray cwd()
		{
			char *result = getcwd(nullptr, 0);

			CharArray str((const char_t *)result, std::strlen(result));

			std::free(result);

			return str;
		}

		bool file_exists(const CharArray &file)
		{
			CharArray file_cstr = file.c_str();

			struct stat buf;

			if(stat(file_cstr.c_str_ref(), &buf) == 0)
				return true;
			else
				return false;
		}

		void signal_handler(int)
		{
			Collector::signal();
		}

		void initialize()
		{
			signal(SIGINT, signal_handler);
		}
	};
};

#endif
<|endoftext|>