<commit_before>//==============================================================================
// CellML model runtime class
//==============================================================================

#include "cellmlmodelruntime.h"

//==============================================================================

#include <QDebug>

//==============================================================================

#include "CCGSBootstrap.hpp"

//==============================================================================

namespace OpenCOR {
namespace CellMLSupport {

//==============================================================================

CellmlModelRuntime::CellmlModelRuntime()
{
    // Initialise the runtime's properties

    reset();
}

//==============================================================================

bool CellmlModelRuntime::isValid()
{
    // The runtime is valid if no issue was found

    return mIssues.isEmpty();
}

//==============================================================================

CellmlModelRuntime::ModelType CellmlModelRuntime::modelType()
{
    // Return the type of model for the runtime

    return mModelType;
}

//==============================================================================

QList<CellmlModelIssue> CellmlModelRuntime::issues()
{
    // Return the issue(s)

    return mIssues;
}

//==============================================================================

void CellmlModelRuntime::resetOdeCodeInformation()
{
    /*delete mOdeCodeInformation;*/ mOdeCodeInformation = 0;
    //---GRY--- WE CANNOT delete mOdeCodeInformation AT THIS STAGE. FOR THIS, WE
    //          WOULD NEED TO USE THE CLEANED UP C++ INTERFACE (SEE THE MAIN
    //          COMMENT AT THE BEGINNING OF THE cellmlmodel.cpp FILE)
}

//==============================================================================

void CellmlModelRuntime::resetDaeCodeInformation()
{
    /*delete mDaeCodeInformation;*/ mDaeCodeInformation = 0;
    //---GRY--- WE CANNOT delete mDaeCodeInformation AT THIS STAGE. FOR THIS, WE
    //          WOULD NEED TO USE THE CLEANED UP C++ INTERFACE (SEE THE MAIN
    //          COMMENT AT THE BEGINNING OF THE cellmlmodel.cpp FILE)
}

//==============================================================================

void CellmlModelRuntime::reset()
{
    // Reset all of the runtime's properties

//---GRY--- TO BE DONE...

    mModelType = Undefined;

    resetOdeCodeInformation();
    resetDaeCodeInformation();

    mIssues.clear();
}

//==============================================================================

void CellmlModelRuntime::couldNotCompileModelIssue()
{
    mIssues.append(CellmlModelIssue(CellmlModelIssue::Error,
                                    tr("the model could not be compiled")));
}

//==============================================================================

void CellmlModelRuntime::unexpectedProblemDuringModelCompilationIssue()
{
    mIssues.append(CellmlModelIssue(CellmlModelIssue::Error,
                                    tr("an unexpected problem occurred while trying to compile the model")));
}

//==============================================================================

void CellmlModelRuntime::checkCodeInformation(iface::cellml_services::CodeInformation *pCodeInformation)
{
    if (!pCodeInformation)
        // No code information was provided, so...

        return;

    // Retrieve the code information's latest error message

    QString codeGenerationErrorMessage = QString::fromStdWString(pCodeInformation->errorMessage());

    if (codeGenerationErrorMessage.isEmpty()) {
        // The code generation went fine, so check the model's constraint level

        iface::cellml_services::ModelConstraintLevel constraintLevel = pCodeInformation->constraintLevel();

        if (constraintLevel == iface::cellml_services::UNDERCONSTRAINED) {
            mIssues.append(CellmlModelIssue(CellmlModelIssue::Error,
                                            tr("the model is underconstrained (i.e. some variables need to be initialised or computed)")));
        } else if (constraintLevel == iface::cellml_services::UNSUITABLY_CONSTRAINED) {
            mIssues.append(CellmlModelIssue(CellmlModelIssue::Error,
                                            tr("the model is unsuitably constrained (i.e. some variables could not be found and/or some equations could not be used)")));
        } else if (constraintLevel == iface::cellml_services::OVERCONSTRAINED) {
            mIssues.append(CellmlModelIssue(CellmlModelIssue::Error,
                                            tr("the model is overconstrained (i.e. some variables are either both initialised and computed or computed more than once)")));
        }
    } else {
        // The code generation didn't go fine, so...

        mIssues.append(CellmlModelIssue(CellmlModelIssue::Error,
                                        tr("a problem occurred during the compilation of the model: %1").arg(codeGenerationErrorMessage.toLatin1().constData())));
    }
}

//==============================================================================

void CellmlModelRuntime::getOdeCodeInformation(iface::cellml_api::Model *pModel)
{
    // Get a code generator bootstrap and create an ODE code generator

    ObjRef<iface::cellml_services::CodeGeneratorBootstrap> codeGeneratorBootstrap = CreateCodeGeneratorBootstrap();
    ObjRef<iface::cellml_services::CodeGenerator> codeGenerator = codeGeneratorBootstrap->createCodeGenerator();

    // Generate some code for the model (i.e. 'compile' the model)

    try {
        mOdeCodeInformation = codeGenerator->generateCode(pModel);

        // Check that the code generation went fine

        checkCodeInformation(mOdeCodeInformation);
    } catch (iface::cellml_api::CellMLException &) {
        couldNotCompileModelIssue();
    } catch (...) {
        unexpectedProblemDuringModelCompilationIssue();
    }

    // Check the outcome of the ODE code generation

    if (mIssues.count())
        // Something went wrong at some point, so...

        resetOdeCodeInformation();
}

//==============================================================================

void CellmlModelRuntime::getDaeCodeInformation(iface::cellml_api::Model *pModel)
{
    // Get a code generator bootstrap and create a DAE code generator

    ObjRef<iface::cellml_services::CodeGeneratorBootstrap> codeGeneratorBootstrap = CreateCodeGeneratorBootstrap();
    ObjRef<iface::cellml_services::IDACodeGenerator> codeGenerator = codeGeneratorBootstrap->createIDACodeGenerator();

    // Generate some code for the model (i.e. 'compile' the model)

    try {
        mDaeCodeInformation = codeGenerator->generateIDACode(pModel);

        // Check that the code generation went fine

        checkCodeInformation(mDaeCodeInformation);
    } catch (iface::cellml_api::CellMLException &) {
        couldNotCompileModelIssue();
    } catch (...) {
        unexpectedProblemDuringModelCompilationIssue();
    }

    // Check the outcome of the DAE code generation

    if (mIssues.count())
        // Something went wrong at some point, so...

        resetDaeCodeInformation();
}

//==============================================================================

CellmlModelRuntime * CellmlModelRuntime::update(iface::cellml_api::Model *pModel,
                                                const bool &pValidModel)
{
    // Reset the runtime's properties

    reset();

    // Check that the model is valid

    if (pValidModel) {
        // The model is valid, so make sure that it's either a 'simple' ODE
        // model or a DAE model
        // Note #1: in order to do so, we need to get a 'normal' code generator
        //          (as opposed to an IDA, i.e. DAE, code generator) since if
        //          the model is correctly constrained, then we can check
        //          whether some of its equations were flagged as needing a
        //          Newton-Raphson evaluation, in which case we would be dealing
        //          with a DAE model...
        // Note #2: ideally, there would be a more convenient way to determine
        //          the type of a model, but well... there isn't, so...

        getOdeCodeInformation(pModel);

        // Retrieve the model's type
        // Note: this can be done by checking whether some equations were
        //       flagged as needing a Newton-Raphson evaluation...

        if (mOdeCodeInformation) {
            // An ODE code information could be retrieved, so we can determine
            // the model's type

            mModelType = mOdeCodeInformation->flaggedEquations()->length()?Dae:Ode;

            // If the model is of DAE type, then we must get the 'right' code
            // information

            if (mModelType == Dae)
                getDaeCodeInformation(pModel);
        } else {
            // No ODE code information could be retrieved, so...

            mModelType = Undefined;
        }

//        qDebug("---------------------------------------");
//        qDebug("\nRequired functions:");
//        qDebug(QString::fromStdWString(codeInformation->functionsString()).toLatin1().constData());
//        qDebug("---------------------------------------");
//        qDebug("\nInitialisations:");
//        qDebug(QString::fromStdWString(codeInformation->initConstsString()).toLatin1().constData());
//        qDebug("---------------------------------------");
//        qDebug("\nVariable evaluations:");
//        qDebug(QString::fromStdWString(codeInformation->variablesString()).toLatin1().constData());
//        qDebug("---------------------------------------");

        // Just testing the generation of 'C code'...

//qDebug() << QString::fromStdWString(getModelAsCCode(pModel));
    } else {
        // The model is not valid, so...

        mIssues.append(CellmlModelIssue(CellmlModelIssue::Error,
                                        tr("the model is not valid")));
    }

    // We are done, so return ourselves

    return this;
}

//==============================================================================

}   // namespace CellMLSupport
}   // namespace OpenCOR

//==============================================================================
// End of file
//==============================================================================
<commit_msg>Further work on our CellMLModelRuntime class.<commit_after>//==============================================================================
// CellML model runtime class
//==============================================================================

#include "cellmlmodelruntime.h"

//==============================================================================

#include <QDebug>

//==============================================================================

#include "CCGSBootstrap.hpp"

//==============================================================================

namespace OpenCOR {
namespace CellMLSupport {

//==============================================================================

CellmlModelRuntime::CellmlModelRuntime()
{
    // Initialise the runtime's properties

    reset();
}

//==============================================================================

bool CellmlModelRuntime::isValid()
{
    // The runtime is valid if no issue was found

    return mIssues.isEmpty();
}

//==============================================================================

CellmlModelRuntime::ModelType CellmlModelRuntime::modelType()
{
    // Return the type of model for the runtime

    return mModelType;
}

//==============================================================================

QList<CellmlModelIssue> CellmlModelRuntime::issues()
{
    // Return the issue(s)

    return mIssues;
}

//==============================================================================

void CellmlModelRuntime::resetOdeCodeInformation()
{
    /*delete mOdeCodeInformation;*/ mOdeCodeInformation = 0;
    //---GRY--- WE CANNOT delete mOdeCodeInformation AT THIS STAGE. FOR THIS, WE
    //          WOULD NEED TO USE THE CLEANED UP C++ INTERFACE (SEE THE MAIN
    //          COMMENT AT THE BEGINNING OF THE cellmlmodel.cpp FILE)
}

//==============================================================================

void CellmlModelRuntime::resetDaeCodeInformation()
{
    /*delete mDaeCodeInformation;*/ mDaeCodeInformation = 0;
    //---GRY--- WE CANNOT delete mDaeCodeInformation AT THIS STAGE. FOR THIS, WE
    //          WOULD NEED TO USE THE CLEANED UP C++ INTERFACE (SEE THE MAIN
    //          COMMENT AT THE BEGINNING OF THE cellmlmodel.cpp FILE)
}

//==============================================================================

void CellmlModelRuntime::reset()
{
    // Reset all of the runtime's properties

//---GRY--- TO BE DONE...

    mModelType = Undefined;

    resetOdeCodeInformation();
    resetDaeCodeInformation();

    mIssues.clear();
}

//==============================================================================

void CellmlModelRuntime::couldNotCompileModelIssue()
{
    mIssues.append(CellmlModelIssue(CellmlModelIssue::Error,
                                    tr("the model could not be compiled")));
}

//==============================================================================

void CellmlModelRuntime::unexpectedProblemDuringModelCompilationIssue()
{
    mIssues.append(CellmlModelIssue(CellmlModelIssue::Error,
                                    tr("an unexpected problem occurred while trying to compile the model")));
}

//==============================================================================

void CellmlModelRuntime::checkCodeInformation(iface::cellml_services::CodeInformation *pCodeInformation)
{
    if (!pCodeInformation)
        // No code information was provided, so...

        return;

    // Retrieve the code information's latest error message

    QString codeGenerationErrorMessage = QString::fromStdWString(pCodeInformation->errorMessage());

    if (codeGenerationErrorMessage.isEmpty()) {
        // The code generation went fine, so check the model's constraint level

        iface::cellml_services::ModelConstraintLevel constraintLevel = pCodeInformation->constraintLevel();

        if (constraintLevel == iface::cellml_services::UNDERCONSTRAINED) {
            mIssues.append(CellmlModelIssue(CellmlModelIssue::Error,
                                            tr("the model is underconstrained (i.e. some variables need to be initialised or computed)")));
        } else if (constraintLevel == iface::cellml_services::UNSUITABLY_CONSTRAINED) {
            mIssues.append(CellmlModelIssue(CellmlModelIssue::Error,
                                            tr("the model is unsuitably constrained (i.e. some variables could not be found and/or some equations could not be used)")));
        } else if (constraintLevel == iface::cellml_services::OVERCONSTRAINED) {
            mIssues.append(CellmlModelIssue(CellmlModelIssue::Error,
                                            tr("the model is overconstrained (i.e. some variables are either both initialised and computed or computed more than once)")));
        }
    } else {
        // The code generation didn't go fine, so...

        mIssues.append(CellmlModelIssue(CellmlModelIssue::Error,
                                        tr("a problem occurred during the compilation of the model: %1").arg(codeGenerationErrorMessage.toLatin1().constData())));
    }
}

//==============================================================================

void CellmlModelRuntime::getOdeCodeInformation(iface::cellml_api::Model *pModel)
{
    // Get a code generator bootstrap and create an ODE code generator

    ObjRef<iface::cellml_services::CodeGeneratorBootstrap> codeGeneratorBootstrap = CreateCodeGeneratorBootstrap();
    ObjRef<iface::cellml_services::CodeGenerator> codeGenerator = codeGeneratorBootstrap->createCodeGenerator();

    // Generate some code for the model (i.e. 'compile' the model)

    try {
        mOdeCodeInformation = codeGenerator->generateCode(pModel);

        // Check that the code generation went fine

        checkCodeInformation(mOdeCodeInformation);
    } catch (iface::cellml_api::CellMLException &) {
        couldNotCompileModelIssue();
    } catch (...) {
        unexpectedProblemDuringModelCompilationIssue();
    }

    // Check the outcome of the ODE code generation

    if (mIssues.count())
        // Something went wrong at some point, so...

        resetOdeCodeInformation();
}

//==============================================================================

void CellmlModelRuntime::getDaeCodeInformation(iface::cellml_api::Model *pModel)
{
    // Get a code generator bootstrap and create a DAE code generator

    ObjRef<iface::cellml_services::CodeGeneratorBootstrap> codeGeneratorBootstrap = CreateCodeGeneratorBootstrap();
    ObjRef<iface::cellml_services::IDACodeGenerator> codeGenerator = codeGeneratorBootstrap->createIDACodeGenerator();

    // Generate some code for the model (i.e. 'compile' the model)

    try {
        mDaeCodeInformation = codeGenerator->generateIDACode(pModel);

        // Check that the code generation went fine

        checkCodeInformation(mDaeCodeInformation);
    } catch (iface::cellml_api::CellMLException &) {
        couldNotCompileModelIssue();
    } catch (...) {
        unexpectedProblemDuringModelCompilationIssue();
    }

    // Check the outcome of the DAE code generation

    if (mIssues.count())
        // Something went wrong at some point, so...

        resetDaeCodeInformation();
}

//==============================================================================

CellmlModelRuntime * CellmlModelRuntime::update(iface::cellml_api::Model *pModel,
                                                const bool &pValidModel)
{
    // Reset the runtime's properties

    reset();

    // Check that the model is valid

    if (pValidModel) {
        // The model is valid, so make sure that it's either a 'simple' ODE
        // model or a DAE model
        // Note #1: in order to do so, we need to get a 'normal' code generator
        //          (as opposed to an IDA, i.e. DAE, code generator) since if
        //          the model is correctly constrained, then we can check
        //          whether some of its equations were flagged as needing a
        //          Newton-Raphson evaluation, in which case we would be dealing
        //          with a DAE model...
        // Note #2: ideally, there would be a more convenient way to determine
        //          the type of a model, but well... there isn't, so...

        getOdeCodeInformation(pModel);

        // Retrieve the model's type
        // Note: this can be done by checking whether some equations were
        //       flagged as needing a Newton-Raphson evaluation...

        if (mOdeCodeInformation) {
            // An ODE code information could be retrieved, so we can determine
            // the model's type

            mModelType = mOdeCodeInformation->flaggedEquations()->length()?Dae:Ode;

            // If the model is of DAE type, then we must get the 'right' code
            // information

            if (mModelType == Dae)
                getDaeCodeInformation(pModel);

            // Retrieve some code

            if (mModelType ==Ode) {
                qDebug("---------------------------------------");
                qDebug("\ninitConstsString():");
                qDebug(QString::fromStdWString(mOdeCodeInformation->initConstsString()).toLatin1().constData());
                qDebug("---------------------------------------");
                qDebug("\nratesString():");
                qDebug(QString::fromStdWString(mOdeCodeInformation->ratesString()).toLatin1().constData());
                qDebug("---------------------------------------");
                qDebug("\nvariablesString():");
                qDebug(QString::fromStdWString(mOdeCodeInformation->variablesString()).toLatin1().constData());
                qDebug("---------------------------------------");
                qDebug("\nfunctionsString():");
                qDebug(QString::fromStdWString(mOdeCodeInformation->functionsString()).toLatin1().constData());
                qDebug("---------------------------------------");
            } else {
                qDebug("---------------------------------------");
                qDebug("\ninitConstsString():");
                qDebug(QString::fromStdWString(mDaeCodeInformation->initConstsString()).toLatin1().constData());
                qDebug("---------------------------------------");
                qDebug("\nratesString():");
                qDebug(QString::fromStdWString(mDaeCodeInformation->ratesString()).toLatin1().constData());
                qDebug("---------------------------------------");
                qDebug("\nvariablesString():");
                qDebug(QString::fromStdWString(mDaeCodeInformation->variablesString()).toLatin1().constData());
                qDebug("---------------------------------------");
                qDebug("\nfunctionsString():");
                qDebug(QString::fromStdWString(mDaeCodeInformation->functionsString()).toLatin1().constData());
                qDebug("---------------------------------------");
                qDebug("\nessentialVariablesString():");
                qDebug(QString::fromStdWString(mDaeCodeInformation->essentialVariablesString()).toLatin1().constData());
                qDebug("---------------------------------------");
                qDebug("\nstateInformationString():");
                qDebug(QString::fromStdWString(mDaeCodeInformation->stateInformationString()).toLatin1().constData());
                qDebug("---------------------------------------");
                qDebug("\nrootInformationString():");
                qDebug(QString::fromStdWString(mDaeCodeInformation->rootInformationString()).toLatin1().constData());
                qDebug("---------------------------------------");
            }
        } else {
            // No ODE code information could be retrieved, so...

            mModelType = Undefined;
        }
    } else {
        // The model is not valid, so...

        mIssues.append(CellmlModelIssue(CellmlModelIssue::Error,
                                        tr("the model is not valid")));
    }

    // We are done, so return ourselves

    return this;
}

//==============================================================================

}   // namespace CellMLSupport
}   // namespace OpenCOR

//==============================================================================
// End of file
//==============================================================================
<|endoftext|>


<commit_before>/* Copyright (c) 2013 Quanta Research Cambridge, Inc
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the "Software"),
 * to deal in the Software without restriction, including without limitation
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
 * and/or sell copies of the Software, and to permit persons to whom the
 * Software is furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included
 * in all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 * DEALINGS IN THE SOFTWARE.
 */

/*
 * Implementation of:
 *    MP algorithm on pages 7-11 from "Pattern Matching Algorithms" by
 *       Alberto Apostolico, Zvi Galil, 1997
 *
 *    procedure MP(x, t: string; m, n: integer);
 *    begin
 *        i := 1; j := 1;
 *        while j <= n do begin
 *            while (i = m + 1) or (i > 0 and x[i] != t[j]) do j := MP_next[i];
 *            i := i + 1; j := j + 1;
 *            if i = m + 1 then writeln('x occurs in t at position ', j - i + 1);
 *        end;
 *    end;
 *
 *    procedure Compute_borders(x: string; m: integer);
 *    begin
 *        Border[0] := -1;
 *        for i := 1 to m do begin
 *            j := Border[i - 1];
 *            while j >= 0 and x[i] != x[j + 1] do j := Border[j];
 *            Border[i] := j + 1;
 *        end;
 *    end;
 *
 *    procedure Compute_MP_next(x: string; m: integer);
 *    begin
 *        MP_next[i] := 0; j := 0;
 *        for i := 1 to m do begin
 *            { at this point, we have j = MP_next[i] }
 *            while j > 0 and x[i] != x[j] do j := MP_next[j];
 *            j := j + 1;
 *            MP_next[i + 1] := j;
 *        end;
 *    end;
 *
 */

#include <stdio.h>
#include <sys/mman.h>
#include <stdlib.h>
#include <unistd.h>
#include <assert.h>
#include <semaphore.h>
#include <ctime>
#include "StdDmaIndication.h"

#include "StrstrIndicationWrapper.h"
#include "StrstrRequestProxy.h"
#include "GeneratedTypes.h"
#include "DmaConfigProxy.h"

sem_t test_sem;
sem_t setup_sem;
unsigned int sw_match_cnt = 0;
unsigned int hw_match_cnt = 0;

class StrstrIndication : public StrstrIndicationWrapper
{
public:
  StrstrIndication(unsigned int id) : StrstrIndicationWrapper(id){};

  virtual void setupComplete() {
    sem_post(&setup_sem);
  }

  virtual void searchResult (int v){
    fprintf(stderr, "searchResult = %d\n", v);
    if (v == -1)
      sem_post(&test_sem);
    else
      hw_match_cnt++;
  }
};

void compute_borders(const char *x, int *border, int m)
{
  border[0] = -1;
  for(int i = 1; i <=m; i++){
    int j = border[i-1];
    while ((j>=0) && (x[i] != x[j+1]))
      j = border[j];
    border[i] = j+1;
  }
}

void compute_MP_next(const char *x, int *MP_next, int m)
{
  MP_next[1] = 0;
  int j = 0;
  for(int i = 1; i <= m; i++){
    while ((j>0) && (x[i] != x[j]))
      j = MP_next[j];
    j = j+1;
    MP_next[i+1] = j;
  }
}

void MP(const char *x, const char *t, int *MP_next, int m, int n, int iter_cnt)
{
  while(iter_cnt--){
    int i = 1;
    int j = 1;
    fprintf(stderr, "MP starting\n");
    while (j <= n) {
      while ((i==m+1) || ((i>0) && (x[i-1] != t[j-1]))){
	//fprintf(stderr, "char mismatch %d %d MP_next[i]=%d\n", i,j,MP_next[i]);
	i = MP_next[i];
      }
      //fprintf(stderr, "   char match %d %d\n", i, j);
      i = i+1;
      j = j+1;
      if (i==m+1){
	fprintf(stderr, "%s occurs in t at position %d\n", x, j-i);
	i = 1;
	sw_match_cnt++;
      }
    }
  }
  fprintf(stderr, "MP exiting\n");
}

int main(int argc, const char **argv)
{
  StrstrRequestProxy *device = 0;
  DmaConfigProxy *dma = 0;

  StrstrIndication *deviceIndication = 0;
  DmaIndication *dmaIndication = 0;

  fprintf(stderr, "%s %s\n", __DATE__, __TIME__);
  device = new StrstrRequestProxy(IfcNames_StrstrRequest);
  dma = new DmaConfigProxy(IfcNames_DmaConfig);

  deviceIndication = new StrstrIndication(IfcNames_StrstrIndication);
  dmaIndication = new DmaIndication(dma, IfcNames_DmaIndication);

  if(sem_init(&test_sem, 1, 0)){
    fprintf(stderr, "failed to init test_sem\n");
    return -1;
  }

  if(sem_init(&setup_sem, 1, 0)){
    fprintf(stderr, "failed to init setup_sem\n");
    return -1;
  }

  pthread_t tid;
  fprintf(stderr, "creating exec thread\n");
  if(pthread_create(&tid, NULL,  portalExec, NULL)){
   fprintf(stderr, "error creating exec thread\n");
   exit(1);
  }

#ifndef MMAP_HW
  if(1){
    fprintf(stderr, "simple tests\n");
    PortalAlloc *needleAlloc;
    PortalAlloc *haystackAlloc;
    PortalAlloc *mpNextAlloc;
    unsigned int alloc_len = 16 << 2;

    dma->alloc(alloc_len, &needleAlloc);
    dma->alloc(alloc_len, &mpNextAlloc);
    dma->alloc(alloc_len, &haystackAlloc);

    char *needle = (char *)mmap(0, alloc_len, PROT_READ|PROT_WRITE|PROT_EXEC, MAP_SHARED, needleAlloc->header.fd, 0);
    char *haystack = (char *)mmap(0, alloc_len, PROT_READ|PROT_WRITE|PROT_EXEC, MAP_SHARED, haystackAlloc->header.fd, 0);
    int *mpNext = (int *)mmap(0, alloc_len, PROT_READ|PROT_WRITE|PROT_EXEC, MAP_SHARED, mpNextAlloc->header.fd, 0);

    const char *needle_text = "ababab";
    const char *haystack_text = "acabcabacababacababababababcacabcabacababacabababc";

    assert(strlen(haystack_text) < alloc_len);
    assert(strlen(needle_text)*4 < alloc_len);

    strncpy(needle, needle_text, alloc_len);
    strncpy(haystack, haystack_text, alloc_len);

    int needle_len = strlen(needle);
    int haystack_len = strlen(haystack);
    int border[needle_len+1];

    compute_borders(needle, border, needle_len);
    compute_MP_next(needle, mpNext, needle_len);

    assert(mpNext[1] == 0);
    assert(border[1] == 0);
    for(int i = 2; i < needle_len+1; i++)
      assert(mpNext[i] == border[i-1]+1);

    for(int i = 0; i < needle_len; i++)
      fprintf(stderr, "%d %d\n", needle[i], mpNext[i]);

    int iter_cnt = 2;

    start_timer(0);
    MP(needle, haystack, mpNext, needle_len, haystack_len, iter_cnt);
    fprintf(stderr, "elapsed time (hw cycles): %lld\n", lap_timer(0));

    dma->dCacheFlushInval(needleAlloc, needle);
    dma->dCacheFlushInval(mpNextAlloc, mpNext);

    unsigned int ref_needleAlloc = dma->reference(needleAlloc);
    unsigned int ref_mpNextAlloc = dma->reference(mpNextAlloc);
    unsigned int ref_haystackAlloc = dma->reference(haystackAlloc);

    device->setup(ref_needleAlloc, ref_mpNextAlloc, needle_len);
    sem_wait(&setup_sem);
    start_timer(0);
    device->search(ref_haystackAlloc, haystack_len, iter_cnt);
    sem_wait(&test_sem);
    uint64_t cycles = lap_timer(0);
    uint64_t beats = dma->show_mem_stats(ChannelType_Read);
    fprintf(stderr, "memory read utilization (beats/cycle): %f\n", ((float)beats)/((float)cycles));

    close(needleAlloc->header.fd);
    close(haystackAlloc->header.fd);
    close(mpNextAlloc->header.fd);
  }
#endif

#ifdef MMAP_HW
  if(1){
    fprintf(stderr, "benchmarks\n");
    PortalAlloc *needleAlloc;
    PortalAlloc *haystackAlloc;
    PortalAlloc *mpNextAlloc;
    const char *needle_text = "I have control\n";
    unsigned int BENCHMARK_INPUT_SIZE = 16 << 18;
    unsigned int haystack_alloc_len = BENCHMARK_INPUT_SIZE;
    unsigned int needle_alloc_len = strlen(needle_text);
    unsigned int mpNext_alloc_len = needle_alloc_len*4;

    dma->alloc(needle_alloc_len, &needleAlloc);
    dma->alloc(haystack_alloc_len, &haystackAlloc);
    dma->alloc(mpNext_alloc_len, &mpNextAlloc);

    char *needle = (char *)mmap(0, needle_alloc_len, PROT_READ|PROT_WRITE|PROT_EXEC, MAP_SHARED, needleAlloc->header.fd, 0);
    char *haystack = (char *)mmap(0, haystack_alloc_len, PROT_READ|PROT_WRITE|PROT_EXEC, MAP_SHARED, haystackAlloc->header.fd, 0);
    int *mpNext = (int *)mmap(0, mpNext_alloc_len, PROT_READ|PROT_WRITE|PROT_EXEC, MAP_SHARED, mpNextAlloc->header.fd, 0);

    unsigned int ref_needleAlloc = dma->reference(needleAlloc);
    unsigned int ref_haystackAlloc = dma->reference(haystackAlloc);
    unsigned int ref_mpNextAlloc = dma->reference(mpNextAlloc);

    FILE* fp = fopen("/dev/urandom", "r");
    size_t rv = fread(haystack, 1, BENCHMARK_INPUT_SIZE, fp);
    strncpy(needle, needle_text, needle_alloc_len);

    int needle_len = strlen(needle);
    int haystack_len = haystack_alloc_len;
    int border[needle_len+1];

    compute_borders(needle, border, needle_len);
    compute_MP_next(needle, mpNext, needle_len);

    assert(mpNext[1] == 0);
    assert(border[1] == 0);
    for(int i = 2; i < needle_len+1; i++)
      assert(mpNext[i] == border[i-1]+1);

    int iter_cnt = 32;

    start_timer(0);
    MP(needle, haystack, mpNext, needle_len, haystack_len, iter_cnt);
    uint64_t sw_cycles = lap_timer(0);
    fprintf(stderr, "sw_cycles:%zx\n", sw_cycles);

    dma->dCacheFlushInval(needleAlloc, needle);
    dma->dCacheFlushInval(mpNextAlloc, mpNext);

    device->setup(ref_needleAlloc, ref_mpNextAlloc, needle_len);
    sem_wait(&setup_sem);
    start_timer(0);
    device->search(ref_haystackAlloc, haystack_len, iter_cnt);
    sem_wait(&test_sem);
    uint64_t hw_cycles = lap_timer(0);
    uint64_t beats = dma->show_mem_stats(ChannelType_Read);
    fprintf(stderr, "memory read utilization (beats/cycle): %f\n", ((float)beats)/((float)hw_cycles));

    close(needleAlloc->header.fd);
    close(haystackAlloc->header.fd);
    close(mpNextAlloc->header.fd);
  }
#endif

  fprintf(stderr, "sw_match_cnt=%d, hw_match_cnt=%d\n", sw_match_cnt, hw_match_cnt);
  return (sw_match_cnt != hw_match_cnt);
}
<commit_msg>updating strstr test<commit_after>/* Copyright (c) 2013 Quanta Research Cambridge, Inc
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the "Software"),
 * to deal in the Software without restriction, including without limitation
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
 * and/or sell copies of the Software, and to permit persons to whom the
 * Software is furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included
 * in all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 * DEALINGS IN THE SOFTWARE.
 */

/*
 * Implementation of:
 *    MP algorithm on pages 7-11 from "Pattern Matching Algorithms" by
 *       Alberto Apostolico, Zvi Galil, 1997
 *
 *    procedure MP(x, t: string; m, n: integer);
 *    begin
 *        i := 1; j := 1;
 *        while j <= n do begin
 *            while (i = m + 1) or (i > 0 and x[i] != t[j]) do j := MP_next[i];
 *            i := i + 1; j := j + 1;
 *            if i = m + 1 then writeln('x occurs in t at position ', j - i + 1);
 *        end;
 *    end;
 *
 *    procedure Compute_borders(x: string; m: integer);
 *    begin
 *        Border[0] := -1;
 *        for i := 1 to m do begin
 *            j := Border[i - 1];
 *            while j >= 0 and x[i] != x[j + 1] do j := Border[j];
 *            Border[i] := j + 1;
 *        end;
 *    end;
 *
 *    procedure Compute_MP_next(x: string; m: integer);
 *    begin
 *        MP_next[i] := 0; j := 0;
 *        for i := 1 to m do begin
 *            { at this point, we have j = MP_next[i] }
 *            while j > 0 and x[i] != x[j] do j := MP_next[j];
 *            j := j + 1;
 *            MP_next[i + 1] := j;
 *        end;
 *    end;
 *
 */

#include <stdio.h>
#include <sys/mman.h>
#include <stdlib.h>
#include <unistd.h>
#include <assert.h>
#include <semaphore.h>
#include <ctime>
#include "StdDmaIndication.h"

#include "StrstrIndicationWrapper.h"
#include "StrstrRequestProxy.h"
#include "GeneratedTypes.h"
#include "DmaConfigProxy.h"

sem_t test_sem;
sem_t setup_sem;
unsigned int sw_match_cnt = 0;
unsigned int hw_match_cnt = 0;

class StrstrIndication : public StrstrIndicationWrapper
{
public:
  StrstrIndication(unsigned int id) : StrstrIndicationWrapper(id){};

  virtual void setupComplete() {
    sem_post(&setup_sem);
  }

  virtual void searchResult (int v){
    fprintf(stderr, "searchResult = %d\n", v);
    if (v == -1)
      sem_post(&test_sem);
    else
      hw_match_cnt++;
  }
};

void compute_borders(const char *x, int *border, int m)
{
  border[0] = -1;
  for(int i = 1; i <=m; i++){
    int j = border[i-1];
    while ((j>=0) && (x[i] != x[j+1]))
      j = border[j];
    border[i] = j+1;
  }
}

void compute_MP_next(const char *x, int *MP_next, int m)
{
  MP_next[1] = 0;
  int j = 0;
  for(int i = 1; i <= m; i++){
    while ((j>0) && (x[i] != x[j]))
      j = MP_next[j];
    j = j+1;
    MP_next[i+1] = j;
  }
}

void MP(const char *x, const char *t, int *MP_next, int m, int n, int iter_cnt)
{
  while(iter_cnt--){
    int i = 1;
    int j = 1;
    fprintf(stderr, "MP starting\n");
    while (j <= n) {
      while ((i==m+1) || ((i>0) && (x[i-1] != t[j-1]))){
	//fprintf(stderr, "char mismatch %d %d MP_next[i]=%d\n", i,j,MP_next[i]);
	i = MP_next[i];
      }
      //fprintf(stderr, "   char match %d %d\n", i, j);
      i = i+1;
      j = j+1;
      if (i==m+1){
	fprintf(stderr, "%s occurs in t at position %d\n", x, j-i);
	i = 1;
	sw_match_cnt++;
      }
    }
  }
  fprintf(stderr, "MP exiting\n");
}

int main(int argc, const char **argv)
{
  StrstrRequestProxy *device = 0;
  DmaConfigProxy *dma = 0;

  StrstrIndication *deviceIndication = 0;
  DmaIndication *dmaIndication = 0;

  fprintf(stderr, "%s %s\n", __DATE__, __TIME__);
  device = new StrstrRequestProxy(IfcNames_StrstrRequest);
  dma = new DmaConfigProxy(IfcNames_DmaConfig);

  deviceIndication = new StrstrIndication(IfcNames_StrstrIndication);
  dmaIndication = new DmaIndication(dma, IfcNames_DmaIndication);

  if(sem_init(&test_sem, 1, 0)){
    fprintf(stderr, "failed to init test_sem\n");
    return -1;
  }

  if(sem_init(&setup_sem, 1, 0)){
    fprintf(stderr, "failed to init setup_sem\n");
    return -1;
  }

  pthread_t tid;
  fprintf(stderr, "creating exec thread\n");
  if(pthread_create(&tid, NULL,  portalExec, NULL)){
   fprintf(stderr, "error creating exec thread\n");
   exit(1);
  }

  if(1){
    fprintf(stderr, "simple tests\n");
    PortalAlloc *needleAlloc;
    PortalAlloc *haystackAlloc;
    PortalAlloc *mpNextAlloc;
    unsigned int alloc_len = 16 << 2;

    dma->alloc(alloc_len, &needleAlloc);
    dma->alloc(alloc_len, &mpNextAlloc);
    dma->alloc(alloc_len, &haystackAlloc);

    char *needle = (char *)mmap(0, alloc_len, PROT_READ|PROT_WRITE|PROT_EXEC, MAP_SHARED, needleAlloc->header.fd, 0);
    char *haystack = (char *)mmap(0, alloc_len, PROT_READ|PROT_WRITE|PROT_EXEC, MAP_SHARED, haystackAlloc->header.fd, 0);
    int *mpNext = (int *)mmap(0, alloc_len, PROT_READ|PROT_WRITE|PROT_EXEC, MAP_SHARED, mpNextAlloc->header.fd, 0);

    const char *needle_text = "ababab";
    const char *haystack_text = "acabcabacababacababababababcacabcabacababacabababc";

    assert(strlen(haystack_text) < alloc_len);
    assert(strlen(needle_text)*4 < alloc_len);

    strncpy(needle, needle_text, alloc_len);
    strncpy(haystack, haystack_text, alloc_len);

    int needle_len = strlen(needle);
    int haystack_len = strlen(haystack);
    int border[needle_len+1];

    compute_borders(needle, border, needle_len);
    compute_MP_next(needle, mpNext, needle_len);

    assert(mpNext[1] == 0);
    assert(border[1] == 0);
    for(int i = 2; i < needle_len+1; i++)
      assert(mpNext[i] == border[i-1]+1);

    for(int i = 0; i < needle_len; i++)
      fprintf(stderr, "%d %d\n", needle[i], mpNext[i]);

    int iter_cnt = 2;

    start_timer(0);
    MP(needle, haystack, mpNext, needle_len, haystack_len, iter_cnt);
    fprintf(stderr, "elapsed time (hw cycles): %lld\n", lap_timer(0));

    dma->dCacheFlushInval(needleAlloc, needle);
    dma->dCacheFlushInval(mpNextAlloc, mpNext);

    unsigned int ref_needleAlloc = dma->reference(needleAlloc);
    unsigned int ref_mpNextAlloc = dma->reference(mpNextAlloc);
    unsigned int ref_haystackAlloc = dma->reference(haystackAlloc);

    device->setup(ref_needleAlloc, ref_mpNextAlloc, needle_len);
    sem_wait(&setup_sem);
    start_timer(0);
    device->search(ref_haystackAlloc, haystack_len, iter_cnt);
    sem_wait(&test_sem);
    uint64_t cycles = lap_timer(0);
    uint64_t beats = dma->show_mem_stats(ChannelType_Read);
    fprintf(stderr, "memory read utilization (beats/cycle): %f\n", ((float)beats)/((float)cycles));

    close(needleAlloc->header.fd);
    close(haystackAlloc->header.fd);
    close(mpNextAlloc->header.fd);
  }

#ifdef MMAP_HW
  if(1){
    fprintf(stderr, "benchmarks\n");
    PortalAlloc *needleAlloc;
    PortalAlloc *haystackAlloc;
    PortalAlloc *mpNextAlloc;
    const char *needle_text = "I have control\n";
    unsigned int BENCHMARK_INPUT_SIZE = 16 << 18;
    unsigned int haystack_alloc_len = BENCHMARK_INPUT_SIZE;
    unsigned int needle_alloc_len = strlen(needle_text);
    unsigned int mpNext_alloc_len = needle_alloc_len*4;

    dma->alloc(needle_alloc_len, &needleAlloc);
    dma->alloc(haystack_alloc_len, &haystackAlloc);
    dma->alloc(mpNext_alloc_len, &mpNextAlloc);

    char *needle = (char *)mmap(0, needle_alloc_len, PROT_READ|PROT_WRITE|PROT_EXEC, MAP_SHARED, needleAlloc->header.fd, 0);
    char *haystack = (char *)mmap(0, haystack_alloc_len, PROT_READ|PROT_WRITE|PROT_EXEC, MAP_SHARED, haystackAlloc->header.fd, 0);
    int *mpNext = (int *)mmap(0, mpNext_alloc_len, PROT_READ|PROT_WRITE|PROT_EXEC, MAP_SHARED, mpNextAlloc->header.fd, 0);

    unsigned int ref_needleAlloc = dma->reference(needleAlloc);
    unsigned int ref_haystackAlloc = dma->reference(haystackAlloc);
    unsigned int ref_mpNextAlloc = dma->reference(mpNextAlloc);

    FILE* fp = fopen("/dev/urandom", "r");
    size_t rv = fread(haystack, 1, BENCHMARK_INPUT_SIZE, fp);
    strncpy(needle, needle_text, needle_alloc_len);

    int needle_len = strlen(needle);
    int haystack_len = haystack_alloc_len;
    int border[needle_len+1];

    compute_borders(needle, border, needle_len);
    compute_MP_next(needle, mpNext, needle_len);

    assert(mpNext[1] == 0);
    assert(border[1] == 0);
    for(int i = 2; i < needle_len+1; i++)
      assert(mpNext[i] == border[i-1]+1);

    int iter_cnt = 8;

    start_timer(0);
    MP(needle, haystack, mpNext, needle_len, haystack_len, iter_cnt);
    uint64_t sw_cycles = lap_timer(0);
    fprintf(stderr, "sw_cycles:%zx\n", sw_cycles);

    dma->dCacheFlushInval(needleAlloc, needle);
    dma->dCacheFlushInval(mpNextAlloc, mpNext);

    device->setup(ref_needleAlloc, ref_mpNextAlloc, needle_len);
    sem_wait(&setup_sem);
    start_timer(0);
    device->search(ref_haystackAlloc, haystack_len, iter_cnt);
    sem_wait(&test_sem);
    uint64_t hw_cycles = lap_timer(0);
    uint64_t beats = dma->show_mem_stats(ChannelType_Read);
    fprintf(stderr, "memory read utilization (beats/cycle): %f\n", ((float)beats)/((float)hw_cycles));

    close(needleAlloc->header.fd);
    close(haystackAlloc->header.fd);
    close(mpNextAlloc->header.fd);
  }
#endif

  fprintf(stderr, "sw_match_cnt=%d, hw_match_cnt=%d\n", sw_match_cnt, hw_match_cnt);
  return (sw_match_cnt != hw_match_cnt);
}
<|endoftext|>


<commit_before>#include "UniformRand.h"

UniformRand::UniformRand(double minValue, double maxValue)
{
    setBoundaries(minValue, maxValue);
}

std::string UniformRand::name()
{
    return "Uniform(" + toStringWithPrecision(getMinValue()) + ", " + toStringWithPrecision(getMaxValue()) + ")";
}

void UniformRand::setBoundaries(double minValue, double maxValue)
{
    a = minValue;
    b = maxValue;

    /// Sanity check
    if (b < a)
        SWAP(a, b);
    if (a == b)
        b = a + 1.0;

    c = 1.0 / (b - a);
}

double UniformRand::f(double x) const
{
    return (x >= a && x <= b) ? c : 0;
}

double UniformRand::F(double x) const
{
    if (x < a)
        return 0;
    if (x > b)
        return 1;
    return c * (x - a);
}

double UniformRand::variate() const
{
    return a + standardVariate() * (b - a);
}

double UniformRand::variate(double minValue, double maxValue)
{
    return minValue + standardVariate() * (maxValue - minValue);
}

double UniformRand::standardVariate()
{
    double x;
    unsigned long long a = RandGenerator::variate();
    a = (a >> 12) | 0x3FF0000000000000ULL; /// Take upper 52 bits
    *((unsigned long long *)&x) = a; /// Make a double from bits
    return x - 1.0;
}

double UniformRand::Mean() const
{
    return .5 * (b + a);
}

double UniformRand::Variance() const
{
    return (b - a) * (b - a) / 12;
}

std::complex<double> UniformRand::CF(double t) const
{
    std::complex<double> x(0, -t * a), y(0, -t * b);
    std::complex<double> numerator = std::exp(x) - std::exp(y);
    std::complex<double> denominator(0, t * (b - a));
    return numerator / denominator;
}

double UniformRand::Quantile(double p) const
{
    if (p < 0 || p > 1)
        return NAN;
    if (p == 0)
        return -INFINITY;
    return a + (b - a) * p;
}

double UniformRand::Median() const
{
    return .5 * (b + a);
}

double UniformRand::Mode() const
{
    /// this can be any value in [a, b]
    return variate();
}

double UniformRand::Skewness() const
{
    return 0.0;
}

double UniformRand::ExcessKurtosis() const
{
    return -1.2;
}

double UniformRand::Entropy() const
{
    return (b == a) ? -INFINITY : std::log(b - a);
}

bool UniformRand::fitMax_MLE(const QVector<double> &sample)
{
    int n = sample.size();
    if (n <= 0)
        return false;
    double maxVar = sample.at(0);
    for (double var : sample) {
        if (var < a)
            return false;
        maxVar = std::max(var, maxVar);
    }
    setBoundaries(a, maxVar);
    return true;
}

bool UniformRand::fitMin_MLE(const QVector<double> &sample)
{
    int n = sample.size();
    if (n <= 0)
        return false;
    double minVar = sample.at(0);
    for (double var : sample) {
        if (var > b)
            return false;
        minVar = std::min(var, minVar);
    }
    setBoundaries(minVar, b);
    return true;
}

bool UniformRand::fit_MLE(const QVector<double> &sample)
{
    int n = sample.size();
    if (n <= 0)
        return false;
    double maxVar = sample.at(0), minVar = maxVar;
    for (double var : sample) {
        maxVar = std::max(var, maxVar);
        minVar = std::min(var, minVar);
    }
    setBoundaries(minVar, maxVar);
    return true;
}

bool UniformRand::fitToData(const QVector<double> &sample)
{
    int n = sample.size();
    if (n == 0)
        return false;
    double maxVar = sample.at(0), minVar = maxVar;
    for (double var : sample) {
        maxVar = std::max(var, maxVar);
        minVar = std::min(var, minVar);
    }

    /// E[min] = b - n / (n + 1) * (b - a)
    /// E[max] = (b - a) * n / (n + 1) + a

    minVar = (minVar * n - maxVar) / (n - 1.0);
    maxVar = (maxVar * (n + 1) - minVar) / n;

    setBoundaries(minVar, maxVar);
    return true;
}
<commit_msg>Update UniformRand.cpp<commit_after>#include "UniformRand.h"

UniformRand::UniformRand(double minValue, double maxValue)
{
    setBoundaries(minValue, maxValue);
}

std::string UniformRand::name()
{
    return "Uniform(" + toStringWithPrecision(getMinValue()) + ", " + toStringWithPrecision(getMaxValue()) + ")";
}

void UniformRand::setBoundaries(double minValue, double maxValue)
{
    a = minValue;
    b = maxValue;

    /// Sanity check
    if (b < a)
        SWAP(a, b);
    if (a == b)
        b = a + 1.0;

    c = 1.0 / (b - a);
}

double UniformRand::f(double x) const
{
    return (x >= a && x <= b) ? c : 0;
}

double UniformRand::F(double x) const
{
    if (x < a)
        return 0;
    if (x > b)
        return 1;
    return c * (x - a);
}

double UniformRand::variate() const
{
    return a + standardVariate() * (b - a);
}

double UniformRand::variate(double minValue, double maxValue)
{
    return minValue + standardVariate() * (maxValue - minValue);
}

double UniformRand::standardVariate()
{
    double x;
    unsigned long long a = RandGenerator::variate();
    a = (a >> 12) | 0x3FF0000000000000ULL; /// Take upper 52 bits
    *((unsigned long long *)&x) = a; /// Make a double from bits
    return x - 1.0;
}

double UniformRand::Mean() const
{
    return .5 * (b + a);
}

double UniformRand::Variance() const
{
    return (b - a) * (b - a) / 12;
}

std::complex<double> UniformRand::CF(double t) const
{
    std::complex<double> x(0, -t * a), y(0, -t * b);
    std::complex<double> numerator = std::exp(x) - std::exp(y);
    std::complex<double> denominator(0, t * (b - a));
    return numerator / denominator;
}

double UniformRand::Quantile(double p) const
{
    if (p < 0 || p > 1)
        return NAN;
    if (p == 0)
        return -INFINITY;
    return a + (b - a) * p;
}

double UniformRand::Median() const
{
    return .5 * (b + a);
}

double UniformRand::Mode() const
{
    /// this can be any value in [a, b]
    return variate();
}

double UniformRand::Skewness() const
{
    return 0.0;
}

double UniformRand::ExcessKurtosis() const
{
    return -1.2;
}

double UniformRand::Entropy() const
{
    return (b == a) ? -INFINITY : std::log(b - a);
}

bool UniformRand::fitMax_MLE(const QVector<double> &sample)
{
    int n = sample.size();
    if (n <= 0)
        return false;
    double maxVar = sample.at(0);
    for (double var : sample) {
        if (var < a)
            return false;
        maxVar = std::max(var, maxVar);
    }
    setBoundaries(a, maxVar);
    return true;
}

bool UniformRand::fitMin_MLE(const QVector<double> &sample)
{
    int n = sample.size();
    if (n <= 0)
        return false;
    double minVar = sample.at(0);
    for (double var : sample) {
        if (var > b)
            return false;
        minVar = std::min(var, minVar);
    }
    setBoundaries(minVar, b);
    return true;
}

bool UniformRand::fit_MLE(const QVector<double> &sample)
{
    int n = sample.size();
    if (n <= 0)
        return false;
    double maxVar = sample.at(0), minVar = maxVar;
    for (double var : sample) {
        maxVar = std::max(var, maxVar);
        minVar = std::min(var, minVar);
    }
    setBoundaries(minVar, maxVar);
    return true;
}

bool UniformRand::fitMin_UMVU(const QVector<double> &sample)
{
    int n = sample.size();
    if (n <= 0)
        return false;
    double minVar = sample.at(0);
    for (double var : sample) {
        if (var < a)
            return false;
        minVar = std::min(var, minVar);
    }

    /// E[min] = b - n / (n + 1) * (b - a)
    minVar = (minVar * (n + 1) - b) / n;
    setBoundaries(minVar, b);
    return true;
}

bool UniformRand::fitMax_UMVU(const QVector<double> &sample)
{
    int n = sample.size();
    if (n <= 0)
        return false;
    double maxVar = sample.at(0);
    for (double var : sample) {
        if (var < a)
            return false;
        maxVar = std::max(var, maxVar);
    }

    /// E[max] = (b - a) * n / (n + 1) + a
    maxVar = (maxVar * (n + 1) - a) / n;
    setBoundaries(a, maxVar);
    return true;
}

bool UniformRand::fit_UMVU(const QVector<double> &sample)
{
    int n = sample.size();
    if (n <= 0)
        return false;
    double maxVar = sample.at(0), minVar = maxVar;
    for (double var : sample) {
        maxVar = std::max(var, maxVar);
        minVar = std::min(var, minVar);
    }

    /// E[min] = b - n / (n + 1) * (b - a)
    /// E[max] = (b - a) * n / (n + 1) + a

    minVar = (minVar * n - maxVar) / (n - 1);
    maxVar = (maxVar * (n + 1) - minVar) / n;

    setBoundaries(minVar, maxVar);
    return true;
}
<|endoftext|>


<commit_before>#include "cexio.h"
#include "parameters.h"
#include "utils/restapi.h"
#include "utils/base64.h"
#include "unique_json.hpp"
#include "hex_str.hpp"

#include "openssl/sha.h"
#include "openssl/hmac.h"
#include <vector>
#include <iomanip>
#include <array>
#include <chrono>
#include <cmath>
#include <algorithm>

namespace Cexio {

static json_t* authRequest(Parameters &, std::string, std::string);

static RestApi& queryHandle(Parameters &params)
{
  static RestApi query ("https://cex.io/api",
                        params.cacert.c_str(), *params.logFile);
  return query;
}

static json_t* checkResponse(std::ostream &logFile, json_t *root)
{
  auto errstatus = json_object_get(root, "error");

  if (errstatus)
  {
    auto errmsg = json_dumps(errstatus, JSON_ENCODE_ANY);
    logFile << "<Cexio> Error with response: "
            << errmsg << '\n';
    free(errmsg);
  }

  return root;
}

quote_t getQuote(Parameters &params)
{
  auto &exchange = queryHandle(params);
  unique_json root { exchange.getRequest("/ticker/BTC/USD") };

  double bidValue = json_number_value(json_object_get(root.get(), "bid"));
  double askValue = json_number_value(json_object_get(root.get(), "ask"));

  return std::make_pair(bidValue, askValue);
}

double getAvail(Parameters& params, std::string currency)
{
  double available = 0.0;
  std::transform(currency.begin(), currency.end(), currency.begin(), ::toupper);
  const char * curr_ = currency.c_str();

  unique_json root { authRequest(params, "/balance/","") };

  const char * avail_str = json_string_value(json_object_get(json_object_get(root.get(), curr_), "available"));
  available = avail_str ? atof(avail_str) : 0.0;

  return available;
}

std::string sendLongOrder(Parameters& params, std::string direction, double quantity, double price)
{
  return sendOrder(params, direction, quantity, price);
}

std::string sendShortOrder(Parameters& params, std::string direction, double quantity, double price)
{
  return sendOrder(params, direction, quantity, price);
}

std::string sendOrder(Parameters& params, std::string direction, double quantity, double price)
{
  using namespace std;
  string pair = "btc_usd";
  string orderId = "";
  *params.logFile << "<Cexio> Trying to send a " << pair << " " << direction << " limit order: " << quantity << "@" << price << endl;

  ostringstream oss;
  oss << "type=" << direction << "&amount=" << quantity << "&price=" << fixed << setprecision(2) << price;
  string options = oss.str();

  unique_json root { authRequest(params, "/place_order/BTC/USD/", options) };
  auto error = json_string_value(json_object_get(root.get(), "error"));
  if (error){
    // auto dump = json_dumps(root.get(), 0);
    // *params.logFile << "<Cexio> Error placing order: " << dump << ")\n" << endl;
    // free(dump);
    orderId = "0";
  } else {
    orderId = json_string_value(json_object_get(root.get(), "id"));
    *params.logFile << "<Cexio> Done (order ID): " << orderId << ")\n" << endl;
  }
  return orderId;
}

bool isOrderComplete(Parameters& params, std::string orderId)
{
  using namespace std;

  bool tmp = true;
  unique_json root { authRequest(params, "/open_orders/","") };
  size_t arraySize = json_array_size(root.get());
  for (size_t i = 0; i < arraySize; ++i){
    string tmpid = json_string_value(json_object_get(json_array_get(root.get(),i),"id"));
    if (tmpid.compare(orderId.c_str())==0){
      *params.logFile << "<Cexio> Order Still open (ID: " << orderId << " )" << " Remaining: "
      << json_string_value(json_object_get(json_array_get(root.get(),i),"pending"))
      << endl;
      return tmp = false;
    }
  }
  if (tmp == true){ *params.logFile << "<Cexio> Order Complete (ID: " << orderId << " )" << endl;}
  return tmp;
}

double getActivePos(Parameters& params) { return getAvail(params, "btc"); }

double getLimitPrice(Parameters &params, double volume, bool isBid)
{
  auto &exchange = queryHandle(params);
  auto root = unique_json(exchange.getRequest("/order_book/BTC/USD/"));
  auto branch = json_object_get(root.get(), isBid ? "bids" : "asks");

  // loop on volume
  double totVol = 0.0;
  double currPrice = 0.0;
  double currVol = 0.0;
  unsigned int i = 0;
  // // [[<price>, <volume>], [<price>, <volume>], ...]
  for(i = 0; i < (json_array_size(branch)); i++)
  {
    // volumes are added up until the requested volume is reached
    currVol = json_number_value(json_array_get(json_array_get(branch, i), 1));
    currPrice = json_number_value(json_array_get(json_array_get(branch, i), 0));
    totVol += currVol;
    if(totVol >= volume * params.orderBookFactor){
        break;
    }
  }

  return currPrice;
}

json_t* authRequest(Parameters &params, std::string request, std::string options)
{
  using namespace std;
  static uint64_t nonce = time(nullptr) * 4;
  auto msg = to_string(++nonce) + params.cexioClientId + params.cexioApi;
  uint8_t *digest = HMAC (EVP_sha256(),
                          params.cexioSecret.c_str(), params.cexioSecret.size(),
                          reinterpret_cast<const uint8_t *>(msg.data()), msg.size(),
                          nullptr, nullptr);

  string postParams = "key=" + params.cexioApi +
                           "&signature=" + hex_str<upperhex>(digest, digest + SHA256_DIGEST_LENGTH) +
                           "&nonce=" + to_string(nonce);

  if (!options.empty())
  {
    postParams += "&";
    postParams += options;
  }

  auto &exchange = queryHandle(params);
  return checkResponse(*params.logFile, exchange.postRequest(request, postParams));
}

void testCexio() {
  using namespace std;
  Parameters params("blackbird.conf");
  params.logFile = new ofstream("./test.log" , ofstream::trunc);

  string orderId;

  cout << "Current value BTC_USD bid: " << getQuote(params).bid() << endl;
  cout << "Current value BTC_USD ask: " << getQuote(params).ask() << endl;
  cout << "Current balance BTC: " << getAvail(params, "BTC") << endl;
  cout << "Current balance BCH: " << getAvail(params, "BCH") << endl;
  cout << "Current balance ETH: " << getAvail(params, "ETH") << endl;
  cout << "Current balance LTC: " << getAvail(params, "LTC") << endl;
  cout << "Current balance DASH: " << getAvail(params, "DASH") << endl;
  cout << "Current balance ZEC: " << getAvail(params, "ZEC") << endl;
  cout << "Current balance USD: " << getAvail(params, "USD") << endl;
  cout << "Current balance EUR: " << getAvail(params, "EUR")<< endl;
  cout << "Current balance GBP: " << getAvail(params, "GBP") << endl;
  cout << "Current balance RUB: " << getAvail(params, "RUB") << endl;
  cout << "Current balance GHS: " << getAvail(params, "GHS") << endl;
  cout << "Current bid limit price for 10 units: " << getLimitPrice(params, 10.0, true) << endl;
  cout << "Current ask limit price for 10 units: " << getLimitPrice(params, 10.0, false) << endl;

  // cout << "Sending buy order - TXID: " ;
  // orderId = sendLongOrder(params, "buy", 0.002, 9510);
  // cout << orderId << endl;
  // cout << "Buy order is complete: " << isOrderComplete(params, orderId) << endl;
  // cout << "Active positions (BTC): " << getActivePos(params) << endl;

  // cout << "Sending sell order - TXID: " ;
  // orderId = sendLongOrder(params, "sell", 0.002, 8800);
  // cout << orderId << endl;
  // cout << "Sell order is complete: " << isOrderComplete(params, orderId) << endl;

  // cout << "Active positions (BTC): " << getActivePos(params) << endl;

  // cout << "Sending short order - TXID: " ;
  // orderId = sendShortOrder(params, "sell", 0.002, 8800);
  // cout << orderId << endl;
  // cout << "Sell order is complete: " << isOrderComplete(params, orderId) << endl;

  // cout << "Active positions: " << getActivePos(params) << endl;

  /******* Cancel order functionality - for testing *******/
  // long oId = 0; //Add orderId here
  // ostringstream oss;
  // oss << "id=" << oId;
  // string options = oss.str();

  // unique_json root { authRequest(params, "/cancel_order/", options) };
  // auto dump = json_dumps(root.get(), 0);
  // *params.logFile << "<Cexio> Error canceling order: " << dump << ")\n" << endl;
  // free(dump);
  /*********************************************************/
  }

}
<commit_msg>cex.io<commit_after>#include "cexio.h"
#include "parameters.h"
#include "utils/restapi.h"
#include "utils/base64.h"
#include "unique_json.hpp"
#include "hex_str.hpp"

#include "openssl/sha.h"
#include "openssl/hmac.h"
#include <vector>
#include <iomanip>
#include <array>
#include <chrono>
#include <cmath>
#include <algorithm>

namespace Cexio {

static json_t* authRequest(Parameters &, std::string, std::string);

static bool g_bShort= false;

static RestApi& queryHandle(Parameters &params)
{
  static RestApi query ("https://cex.io/api",
                        params.cacert.c_str(), *params.logFile);
  return query;
}

static json_t* checkResponse(std::ostream &logFile, json_t *root)
{
  auto errstatus = json_object_get(root, "error");

  if (errstatus)
  {
    auto errmsg = json_dumps(errstatus, JSON_ENCODE_ANY);
    logFile << "<Cexio> Error with response: "
            << errmsg << '\n';
    free(errmsg);
  }

  return root;
}

quote_t getQuote(Parameters &params)
{
  auto &exchange = queryHandle(params);
  unique_json root { exchange.getRequest("/ticker/BTC/USD") };

  double bidValue = json_number_value(json_object_get(root.get(), "bid"));
  double askValue = json_number_value(json_object_get(root.get(), "ask"));

  return std::make_pair(bidValue, askValue);
}

double getAvail(Parameters& params, std::string currency)
{
  double available = 0.0;
  std::transform(currency.begin(), currency.end(), currency.begin(), ::toupper);
  const char * curr_ = currency.c_str();

  unique_json root { authRequest(params, "/balance/","") };

  const char * avail_str = json_string_value(json_object_get(json_object_get(root.get(), curr_), "available"));
  available = avail_str ? atof(avail_str) : 0.0;

  return available;
}

std::string sendLongOrder(Parameters& params, std::string direction, double quantity, double price)
{
    g_bShort = false;
    return sendOrder(params, direction, quantity, price);

}

std::string sendShortOrder(Parameters& params, std::string direction, double quantity, double price)
{
  //return sendOrder(params, direction, quantity, price);

  g_bShort = true;

  if(direction.compare("sell") == 0)
  {
     return openPosition(params, direction, quantity, price);

  }else if(direction.compare("buy")== 0){

    return closePosition(params);

  }

   return "0";
}

std::string openPosition(Parameters& params, std::string direction, double quantity, double price)
{
   using namespace std;
   string pair = "btc_usd";
   string orderId = "";
   *params.logFile << "<Cexio> Trying to open a " << pair << " " << direction << " position: " << quantity << "@" << price << endl;

   ostringstream oss;
   string ptype = "";

   if(direction.compare("sell") == 0)
   {
      ptype = "short";

   }else if(direction.compare("buy")== 0){
     ptype = "long";
   }

   oss << "symbol=" << "BTC" << "&amount=" <<  setprecision(8) << quantity << "&msymbol=" << "USD" << "&leverage="
    << "3" << "&ptype=" << ptype << "&anySlipppage=" << "true" << "&eoprice=" <<  setprecision(8) << price << "&stopLossPrice=" << "35000";

   string options = oss.str();

   unique_json root {authRequest(params,"open_position/BTC/USD/",options)};
   auto error = json_string_value(json_object_get(root.get(),"error"));
   if(error){

        orderId = "0";

    }else{

        orderId = json_string_value(json_object_get(root.get(),"id"));
        *params.logFile << "<Cexio>Open Position Done (positon ID): " << orderId << ")\n" << endl;

    }

    return orderId;
}

std::string closePosition(Parameters& params)
{

 using namespace std;
 string orderId = "";
 unique_json root {authRequest(params,"/open_positions/BTC/USD/","")};
 size_t arraySize = json_array_size(json_object_get(root.get(),"data"));
 auto data = json_object_get(root.get(),"data");
 for(size_t i=0; i< arraySize;i++){

     std::string tmpId = json_string_value(json_object_get(json_array_get(data,i),"id"));
     ostringstream oss;
     oss << "id=" << tmpId;
     string options = oss.str();

     unique_json root1 {authRequest(params,"close_position/BTC/USD/",options)};
     auto error = json_string_value(json_object_get(root1.get(),"error"));
     if(error){
           orderId ="0";

     }else{

         orderId = json_string_value(json_object_get(root1.get(),"id"));

     }

 }

return orderId;

}

std::string sendOrder(Parameters& params, std::string direction, double quantity, double price)
{
  using namespace std;
  string pair = "btc_usd";
  string orderId = "";
  *params.logFile << "<Cexio> Trying to send a " << pair << " " << direction << " limit order: " << quantity << "@" << price << endl;

  ostringstream oss;
  oss << "type=" << direction << "&amount=" << quantity << "&price=" << fixed << setprecision(2) << price;
  string options = oss.str();

  unique_json root { authRequest(params, "/place_order/BTC/USD/", options) };
  auto error = json_string_value(json_object_get(root.get(), "error"));
  if (error){
    // auto dump = json_dumps(root.get(), 0);
    // *params.logFile << "<Cexio> Error placing order: " << dump << ")\n" << endl;
    // free(dump);
    orderId = "0";
  } else {
    orderId = json_string_value(json_object_get(root.get(), "id"));
    *params.logFile << "<Cexio> Done (order ID): " << orderId << ")\n" << endl;
  }
  return orderId;
}

bool isOrderComplete(Parameters& params, std::string orderId)
{

  using namespace std;
  if (orderId == "0") return false;

  auto oId = stol(orderId);
  ostringstream oss;
  oss << "id=" << oId;
  string options = oss.str();

 if(g_bShort)
 {
   unique_json root { authRequest(params, "/get_position/", options) };
   auto slremains = atof(json_string_value(json_object_get(root.get(), "slremains")));
  if (slremains==0){
    return true;
  } else {
    auto dump = json_dumps(root.get(), 0);
    *params.logFile << "<Cexio> Position Order Not Complete: " << dump << ")\n" << endl;
    free(dump);
    // cout << "REMAINS:" << remains << endl;
    return false;
  }

 }else{

  unique_json root { authRequest(params, "/get_order/", options) };
  auto remains = atof(json_string_value(json_object_get(root.get(), "remains")));
  if (remains==0){
    return true;
  } else {
    auto dump = json_dumps(root.get(), 0);
    *params.logFile << "<Cexio> Order Not Complete: " << dump << ")\n" << endl;
    free(dump);
    // cout << "REMAINS:" << remains << endl;
    return false;
  }

 }

}

double getActivePos(Parameters& params) { return getAvail(params, "btc"); }

double getLimitPrice(Parameters &params, double volume, bool isBid)
{
  auto &exchange = queryHandle(params);
  auto root = unique_json(exchange.getRequest("/order_book/BTC/USD/"));
  auto branch = json_object_get(root.get(), isBid ? "bids" : "asks");

  // loop on volume
  double totVol = 0.0;
  double currPrice = 0.0;
  double currVol = 0.0;
  unsigned int i = 0;
  // // [[<price>, <volume>], [<price>, <volume>], ...]
  for(i = 0; i < (json_array_size(branch)); i++)
  {
    // volumes are added up until the requested volume is reached
    currVol = json_number_value(json_array_get(json_array_get(branch, i), 1));
    currPrice = json_number_value(json_array_get(json_array_get(branch, i), 0));
    totVol += currVol;
    if(totVol >= volume * params.orderBookFactor){
        break;
    }
  }

  return currPrice;
}

json_t* authRequest(Parameters &params, std::string request, std::string options)
{
  using namespace std;
  static uint64_t nonce = time(nullptr) * 4;
  auto msg = to_string(++nonce) + params.cexioClientId + params.cexioApi;
  uint8_t *digest = HMAC (EVP_sha256(),
                          params.cexioSecret.c_str(), params.cexioSecret.size(),
                          reinterpret_cast<const uint8_t *>(msg.data()), msg.size(),
                          nullptr, nullptr);

  string postParams = "key=" + params.cexioApi +
                           "&signature=" + hex_str<upperhex>(digest, digest + SHA256_DIGEST_LENGTH) +
                           "&nonce=" + to_string(nonce);

  if (!options.empty())
  {
    postParams += "&";
    postParams += options;
  }

  auto &exchange = queryHandle(params);
  return checkResponse(*params.logFile, exchange.postRequest(request, postParams));
}

void testCexio() {
  using namespace std;
  Parameters params("blackbird.conf");
  params.logFile = new ofstream("./test.log" , ofstream::trunc);

  string orderId;

  cout << "Current value BTC_USD bid: " << getQuote(params).bid() << endl;
  cout << "Current value BTC_USD ask: " << getQuote(params).ask() << endl;
  cout << "Current balance BTC: " << getAvail(params, "BTC") << endl;
  cout << "Current balance BCH: " << getAvail(params, "BCH") << endl;
  cout << "Current balance ETH: " << getAvail(params, "ETH") << endl;
  cout << "Current balance LTC: " << getAvail(params, "LTC") << endl;
  cout << "Current balance DASH: " << getAvail(params, "DASH") << endl;
  cout << "Current balance ZEC: " << getAvail(params, "ZEC") << endl;
  cout << "Current balance USD: " << getAvail(params, "USD") << endl;
  cout << "Current balance EUR: " << getAvail(params, "EUR")<< endl;
  cout << "Current balance GBP: " << getAvail(params, "GBP") << endl;
  cout << "Current balance RUB: " << getAvail(params, "RUB") << endl;
  cout << "Current balance GHS: " << getAvail(params, "GHS") << endl;
  cout << "Current bid limit price for 10 units: " << getLimitPrice(params, 10.0, true) << endl;
  cout << "Current ask limit price for 10 units: " << getLimitPrice(params, 10.0, false) << endl;

  // cout << "Sending buy order - TXID: " ;
  // orderId = sendLongOrder(params, "buy", 0.002, 9510);
  // cout << orderId << endl;
  // cout << "Buy order is complete: " << isOrderComplete(params, orderId) << endl;
  // cout << "Active positions (BTC): " << getActivePos(params) << endl;

  // cout << "Sending sell order - TXID: " ;
  // orderId = sendLongOrder(params, "sell", 0.002, 8800);
  // cout << orderId << endl;
  // cout << "Sell order is complete: " << isOrderComplete(params, orderId) << endl;

  // cout << "Active positions (BTC): " << getActivePos(params) << endl;

  // cout << "Sending short order - TXID: " ;
  // orderId = sendShortOrder(params, "sell", 0.002, 8800);
  // cout << orderId << endl;
  // cout << "Sell order is complete: " << isOrderComplete(params, orderId) << endl;

  // cout << "Active positions: " << getActivePos(params) << endl;

  /******* Cancel order functionality - for testing *******/
  // long oId = 0; //Add orderId here
  // ostringstream oss;
  // oss << "id=" << oId;
  // string options = oss.str();

  // unique_json root { authRequest(params, "/cancel_order/", options) };
  // auto dump = json_dumps(root.get(), 0);
  // *params.logFile << "<Cexio> Error canceling order: " << dump << ")\n" << endl;
  // free(dump);
  /*********************************************************/
  }

}
<|endoftext|>


<commit_before>/**
 * Run SDC for the van der Pol oscillator.
 *
 */

#include<pfasst.hpp>
#include<pfasst/sdc.hpp>
#include<pfasst/encap/vector.hpp>

#include "vdp_sweeper.hpp"

double run_vdp_sdc(const size_t nsteps, const double dt, const size_t nnodes,
                   const size_t niters, const double nu, const double x0,
                   const double y0, const pfasst::quadrature::QuadratureType nodetype)
{
  pfasst::SDC<> sdc;

  auto quad = pfasst::quadrature::quadrature_factory(nnodes, nodetype);

  // van der Pol oscillator (as first order system) has two components
  auto factory = make_shared<pfasst::encap::VectorFactory<double>>(2);
  // input is parameter nu and initial values for position and velocity
  auto sweeper = make_shared<VdpSweeper<>>(nu, x0, y0);

  sweeper->set_quadrature(quad);
  sweeper->set_factory(factory);

  sdc.add_level(sweeper);

  // Final time Tend = dt*nsteps
  sdc.set_duration(0.0, dt*nsteps, dt, niters);
  sdc.setup();

  auto q0 = sweeper->get_state(0);
  sweeper->exact(q0, 0.0);

  sdc.run();

  return sweeper->get_errors();
}

#ifndef PFASST_UNIT_TESTING
/**
 * Main routine running the scalar example with a preset parameters
 */
int main(int /*argc*/, char** /*argv*/)
{
  const double x0 = 2.0,
               y0 = 0.0;
  const size_t nsteps = 1000;
  const double dt     = 50.0/( (double) nsteps);
  const size_t nnodes = 3;
  const size_t niters = 1;
  const double nu     = 5.0;
  const pfasst::quadrature::QuadratureType nodetype = pfasst::quadrature::QuadratureType::GaussLegendre;

  std::cout << "Used timestep: " << dt << std::endl;

  run_vdp_sdc(nsteps, dt, nnodes, niters, nu, x0, y0, nodetype);
}
#endif
<commit_msg>vdp: Fix initial condition.<commit_after>/**
 * Run SDC for the van der Pol oscillator.
 *
 */

#include<pfasst.hpp>
#include<pfasst/sdc.hpp>
#include<pfasst/encap/vector.hpp>

#include "vdp_sweeper.hpp"

double run_vdp_sdc(const size_t nsteps, const double dt, const size_t nnodes,
                   const size_t niters, const double nu, const double x0,
                   const double y0, const pfasst::quadrature::QuadratureType nodetype)
{
  pfasst::SDC<> sdc;

  auto quad = pfasst::quadrature::quadrature_factory(nnodes, nodetype);

  // van der Pol oscillator (as first order system) has two components
  auto factory = make_shared<pfasst::encap::VectorFactory<double>>(2);
  // input is parameter nu and initial values for position and velocity
  auto sweeper = make_shared<VdpSweeper<>>(nu, x0, y0);

  sweeper->set_quadrature(quad);
  sweeper->set_factory(factory);

  sdc.add_level(sweeper);

  // Final time Tend = dt*nsteps
  sdc.set_duration(0.0, dt*nsteps, dt, niters);
  sdc.setup();

  auto q0 = sweeper->get_start_state();
  sweeper->exact(q0, 0.0);

  sdc.run();

  return sweeper->get_errors();
}

#ifndef PFASST_UNIT_TESTING
/**
 * Main routine running the scalar example with a preset parameters
 */
int main(int /*argc*/, char** /*argv*/)
{
  const double x0 = 2.0,
               y0 = 0.0;
  const size_t nsteps = 1000;
  const double dt     = 50.0/( (double) nsteps);
  const size_t nnodes = 3;
  const size_t niters = 1;
  const double nu     = 5.0;
  const pfasst::quadrature::QuadratureType nodetype = pfasst::quadrature::QuadratureType::GaussLegendre;

  std::cout << "Used timestep: " << dt << std::endl;

  run_vdp_sdc(nsteps, dt, nnodes, niters, nu, x0, y0, nodetype);
}
#endif
<|endoftext|>


<commit_before>// File: gaussian.hh
// Date: Sat May 04 01:33:12 2013 +0800
// Author: Yuxin Wu <ppwwyyxxc@gmail.com>

#pragma once
#include <memory>
#include <vector>
#include "lib/mat.h"
#include "lib/utils.hh"
#include "lib/timer.hh"
#include "common/common.hh"
namespace pano {

class GaussCache {
	public:
		std::unique_ptr<float, std::default_delete<float[]>> kernel_buf;
		float* kernel;
		int kw;
		GaussCache(float sigma);
};

class GaussianBlur {
	float sigma;
	GaussCache gcache;
	public:
		GaussianBlur(float sigma): sigma(sigma), gcache(sigma) {}

		// TODO faster convolution
		template <typename T>
		Mat<T> blur(const Mat<T>& img) const {
			m_assert(img.channels() == 1);
			TotalTimer tm("gaussianblur");
			const int w = img.width(), h = img.height();
			Mat<T> ret(h, w, img.channels());

			const int kw = gcache.kw;
			const int center = kw / 2;
			float * kernel = gcache.kernel;

			std::vector<T> cur_line_mem(center * 2 + std::max(w, h), 0);
			T *cur_line = cur_line_mem.data() + center;

			// apply to columns
			REP(j, w){
				const T* src = img.ptr(0, j);
				// copy a column of src
				REP(i, h) {
					cur_line[i] = *src;
					src += w;
				}

				// pad the border with border value
				T v0 = cur_line[0];
				for (int i = 1; i <= center; i ++)
					cur_line[-i] = v0;
				v0 = cur_line[h - 1];
				for (int i = 0; i < center; i ++)
					cur_line[h + i] = v0;

				T *dest = ret.ptr(0, j);
				REP(i, h) {
					T tmp{0};
					for (int k = -center; k <= center; k ++)
						tmp += cur_line[i + k] * kernel[k];
					*dest = tmp;
					dest += w;
				}
			}

			// apply to rows
			REP(i, h) {
				T *dest = ret.ptr(i);
				memcpy(cur_line, dest, sizeof(T) * w);
				{	// pad the border
					T v0 = cur_line[0];
					for (int j = 1; j <= center; j ++)
						cur_line[-j] = v0;
					v0 = cur_line[w - 1];
					for (int j = 0; j < center; j ++)
						cur_line[center + j] = v0;
				}
				REP(j, w) {
					T tmp{0};
					for (int k = -center; k <= center; k ++)
						tmp += cur_line[j + k] * kernel[k];
					*(dest ++) = tmp;
				}
			}
			return ret;
		}
};

class MultiScaleGaussianBlur {
	std::vector<GaussianBlur> gauss;		// size = nscale - 1
	public:
	MultiScaleGaussianBlur(
			int nscale, float gauss_sigma,
			float scale_factor) {
		REP(k, nscale - 1) {
			gauss.emplace_back(gauss_sigma);
			gauss_sigma *= scale_factor;
		}
	}

	Mat32f blur(const Mat32f& img, int n) const
	{ return gauss[n - 1].blur(img); }
};

}
<commit_msg>fix padding in gaussian blur (fix #52)<commit_after>// File: gaussian.hh
// Date: Wed Nov 22 14:38:30 2017 +0800
// Author: Yuxin Wu <ppwwyyxxc@gmail.com>

#pragma once
#include <memory>
#include <vector>
#include "lib/mat.h"
#include "lib/utils.hh"
#include "lib/timer.hh"
#include "common/common.hh"
namespace pano {

class GaussCache {
	public:
		std::unique_ptr<float, std::default_delete<float[]>> kernel_buf;
		float* kernel;
		int kw;
		GaussCache(float sigma);
};

class GaussianBlur {
	float sigma;
	GaussCache gcache;
	public:
		GaussianBlur(float sigma): sigma(sigma), gcache(sigma) {}

		// TODO faster convolution
		template <typename T>
		Mat<T> blur(const Mat<T>& img) const {
			m_assert(img.channels() == 1);
			TotalTimer tm("gaussianblur");
			const int w = img.width(), h = img.height();
			Mat<T> ret(h, w, img.channels());

			const int kw = gcache.kw;
			const int center = kw / 2;
			float * kernel = gcache.kernel;

			std::vector<T> cur_line_mem(center * 2 + std::max(w, h), 0);
			T *cur_line = cur_line_mem.data() + center;

			// apply to columns
			REP(j, w){
				const T* src = img.ptr(0, j);
				// copy a column of src
				REP(i, h) {
					cur_line[i] = *src;
					src += w;
				}

				// pad the border with border value
				T v0 = cur_line[0];
				for (int i = 1; i <= center; i ++)
					cur_line[-i] = v0;
				v0 = cur_line[h - 1];
				for (int i = 0; i < center; i ++)
					cur_line[h + i] = v0;

				T *dest = ret.ptr(0, j);
				REP(i, h) {
					T tmp{0};
					for (int k = -center; k <= center; k ++)
						tmp += cur_line[i + k] * kernel[k];
					*dest = tmp;
					dest += w;
				}
			}

			// apply to rows
			REP(i, h) {
				T *dest = ret.ptr(i);
				memcpy(cur_line, dest, sizeof(T) * w);
				{	// pad the border
					T v0 = cur_line[0];
					for (int j = 1; j <= center; j ++)
						cur_line[-j] = v0;
					v0 = cur_line[w - 1];
					for (int j = 0; j < center; j ++)
						cur_line[w + j] = v0;
				}
				REP(j, w) {
					T tmp{0};
					for (int k = -center; k <= center; k ++)
						tmp += cur_line[j + k] * kernel[k];
					*(dest ++) = tmp;
				}
			}
			return ret;
		}
};

class MultiScaleGaussianBlur {
	std::vector<GaussianBlur> gauss;		// size = nscale - 1
	public:
	MultiScaleGaussianBlur(
			int nscale, float gauss_sigma,
			float scale_factor) {
		REP(k, nscale - 1) {
			gauss.emplace_back(gauss_sigma);
			gauss_sigma *= scale_factor;
		}
	}

	Mat32f blur(const Mat32f& img, int n) const
	{ return gauss[n - 1].blur(img); }
};

}
<|endoftext|>


<commit_before>#include "shape/solid.h"

VALUE sr_cSolid;

SR_SHAPE_GET(Solid, solid)
SR_SHAPE_CHECK(Solid, solid)

bool siren_solid_install()
{
  SR_SHAPE_INIT(Solid)
  rb_define_method(sr_cSolid, "initialize", RUBY_METHOD_FUNC(siren_solid_init), -1);
  rb_define_singleton_method(sr_cSolid, "box",        RUBY_METHOD_FUNC(siren_solid_box),        -1);
  rb_define_singleton_method(sr_cSolid, "box2p",      RUBY_METHOD_FUNC(siren_solid_box2p),      -1);
  rb_define_singleton_method(sr_cSolid, "boxax",      RUBY_METHOD_FUNC(siren_solid_boxax),      -1);
  rb_define_singleton_method(sr_cSolid, "sphere",     RUBY_METHOD_FUNC(siren_solid_sphere),     -1);
  rb_define_singleton_method(sr_cSolid, "cylinder",   RUBY_METHOD_FUNC(siren_solid_cylinder),   -1);
  rb_define_singleton_method(sr_cSolid, "cone",       RUBY_METHOD_FUNC(siren_solid_cone),       -1);
  rb_define_singleton_method(sr_cSolid, "torus",      RUBY_METHOD_FUNC(siren_solid_torus),      -1);
  rb_define_singleton_method(sr_cSolid, "halfspace",  RUBY_METHOD_FUNC(siren_solid_halfspace),  -1);
  rb_define_singleton_method(sr_cSolid, "prism",      RUBY_METHOD_FUNC(siren_solid_prism),      -1);
  rb_define_singleton_method(sr_cSolid, "revol",      RUBY_METHOD_FUNC(siren_solid_revol),      -1);
  rb_define_singleton_method(sr_cSolid, "revolution", RUBY_METHOD_FUNC(siren_solid_revolution), -1);
  rb_define_singleton_method(sr_cSolid, "wedge",      RUBY_METHOD_FUNC(siren_solid_wedge),      -1);
  return true;
}

VALUE siren_solid_init(int argc, VALUE* argv, VALUE self)
{
  VALUE* a;
  rb_scan_args(argc, argv, "1", &a);
  int len = RARRAY_LEN(a);
  if (argc == 0 || len == 0) {
    rb_raise(Qnil, "No shapes specified.");
  }
  BRepBuilderAPI_MakeSolid solid_maker;
  for (int i = 0; i < len; i++) {
    TopoDS_Shell shell = siren_shell_get(a[i]);
    solid_maker.Add(shell);
  }
  if (!solid_maker.IsDone()) {
    rb_raise(Qnil, "Failed to make a Solid.");
  }
  TopoDS_Shape shape = solid_maker.Shape();
  if (shape.IsNull()) {
    rb_raise(Qnil, "Failed to make a Solid.");
  }
  auto p = siren_shape_get(self);
  *p = shape;
  return self;
}

VALUE siren_solid_box(int argc, VALUE* argv, VALUE self)
{
  VALUE size, pos;
  rb_scan_args(argc, argv, "02", &size, &pos);

  Standard_Real sx, sy, sz;
  if (argc >= 1) {
    siren_ary_to_xyz(size, sx, sy, sz);
  }
  else {
    sx = 1.0; sy = 1.0; sz = 1.0;
  }

  gp_Pnt op;
  if (argc >= 2) {
    Standard_Real px, py, pz;
    siren_ary_to_xyz(pos, px, py, pz);
    op = gp_Pnt(px, py, pz);
  }
  else {
    op = gp_Pnt(0., 0., 0.);
  }
  if (std::fabs(sx * sy * sz) == 0.0) {
    rb_raise(Qnil,
      "Failed to make solid. Incorrect size specified.");
  }
  BRepPrimAPI_MakeBox api(op, sx, sy, sz);
  return siren_shape_new(api.Shape());
}

VALUE siren_solid_box2p(int argc, VALUE* argv, VALUE self)
{
  VALUE p1, p2;
  rb_scan_args(argc, argv, "02", &p1, &p2);

  Standard_Real x1 = 0.0, y1 = 0.0, z1 = 0.0;
  Standard_Real x2 = 1.0, y2 = 1.0, z2 = 1.0;

  if (argc >= 1) {
    siren_ary_to_xyz(p1, x1, y1, z1);
  }
  if (argc >= 2) {
    siren_ary_to_xyz(p2, x2, y2, z2);
  }

  gp_Pnt point1(x1, x1, x1);
  gp_Pnt point2(x2, x2, x2);

  BRepPrimAPI_MakeBox api(point1, point2);
  return siren_shape_new(api.Shape());
}

VALUE siren_solid_boxax(int argc, VALUE* argv, VALUE self)
{
  VALUE size, pos, dir;
  rb_scan_args(argc, argv, "3", &size, &pos, &dir);

  Standard_Real sx, sy, sz;
  siren_ary_to_xyz(size, sx, sy, sz);

  Standard_Real px, py, pz;
  siren_ary_to_xyz(pos, px, py, pz);

  Standard_Real dx, dy, dz;
  siren_ary_to_xyz(dir, dx, dy, dz);

  gp_Ax2 ax(gp_Pnt(px, py, pz), gp_Dir(dx, dy, dz));

  BRepPrimAPI_MakeBox api(ax, sx, sy, sz);
  return siren_shape_new(api.Shape());
}

VALUE siren_solid_sphere(int argc, VALUE* argv, VALUE self)
{
  VALUE r = 1.0;
  VALUE pos;
  rb_scan_args(argc, argv, "02", &r, &pos);

  siren_numeric_check(r);

  gp_Pnt op;
  if (argc == 2) {
    Standard_Real px, py, pz;
    siren_ary_to_xyz(pos, px, py, pz);
    op = gp_Pnt(px, py, pz);
  }
  else {
    op = gp_Pnt(0., 0., 0.);
  }

  if (NUM2DBL(r) < 0) {
    rb_raise(Qnil, "Failed to make solid."
      " Specified radius value below 0.");
  }

  BRepPrimAPI_MakeSphere api(op, NUM2DBL(r));
  return siren_shape_new(api.Shape());
}

VALUE siren_solid_cylinder(int argc, VALUE* argv, VALUE self)
{
  VALUE pos, norm;
  VALUE r, h, a;
  rb_scan_args(argc, argv, "5", &pos, &norm, &r, &h, &a);

  siren_numeric_check(r);
  siren_numeric_check(h);
  siren_numeric_check(a);

  gp_Ax2 ax = siren_ary_to_ax2(pos, norm);

  BRepPrimAPI_MakeCylinder api(ax, NUM2DBL(r), NUM2DBL(h), NUM2DBL(a));

  return siren_shape_new(api.Shape());
}

VALUE siren_solid_cone(int argc, VALUE* argv, VALUE self)
{
  VALUE pos, norm;
  VALUE r1, r2, h, ang;
  rb_scan_args(argc, argv, "6", &pos, &norm, &r1, &r2, &h, &ang);

  siren_numeric_check(r1);
  siren_numeric_check(r2);
  siren_numeric_check(h);
  siren_numeric_check(ang);

  gp_Ax2 ax = siren_ary_to_ax2(pos, norm);

  BRepPrimAPI_MakeCone api(ax, NUM2DBL(r1), NUM2DBL(r2), NUM2DBL(h), NUM2DBL(ang));
  return siren_shape_new(api.Shape());
}

VALUE siren_solid_torus(int argc, VALUE* argv, VALUE self)
{
  VALUE r1, r2, ang;
  VALUE pos, norm;
  rb_scan_args(argc, argv, "5", &pos, &norm, &r1, &r2, &ang);

  siren_numeric_check(r1);
  siren_numeric_check(r2);
  siren_numeric_check(ang);

  gp_Ax2 ax = siren_ary_to_ax2(pos, norm);

  BRepPrimAPI_MakeTorus api(ax, NUM2DBL(r1), NUM2DBL(r2), NUM2DBL(ang));
  return siren_shape_new(api.Shape());
}

VALUE siren_solid_halfspace(int argc, VALUE* argv, VALUE self)
{
  VALUE surf, refpnt;
  rb_scan_args(argc, argv, "2", &surf, &refpnt);

  siren_shape_check(surf);

  TopoDS_Shape* shape = siren_shape_get(surf);
  TopoDS_Solid solid;
  gp_Pnt pnt = siren_ary_to_pnt(refpnt);
  if (shape->ShapeType() == TopAbs_FACE) {
    solid = BRepPrimAPI_MakeHalfSpace(TopoDS::Face(*shape), pnt);
  }
  else if (shape->ShapeType() == TopAbs_SHELL) {
    solid = BRepPrimAPI_MakeHalfSpace(TopoDS::Shell(*shape), pnt);
  }
  else {
    rb_raise(Qnil, "Specified shape type is not FACE or SHELL.");
  }
  return siren_shape_new(solid);
}

VALUE siren_solid_prism(int argc, VALUE* argv, VALUE self)
{
  rb_raise(Qnil, "Not implemented.");
  return Qnil;
}

VALUE siren_solid_revol(int argc, VALUE* argv, VALUE self)
{
  rb_raise(Qnil, "Not implemented.");
  return Qnil;
}

VALUE siren_solid_revolution(int argc, VALUE* argv, VALUE self)
{
  rb_raise(Qnil, "Not implemented.");
  return Qnil;
}

VALUE siren_solid_wedge(int argc, VALUE* argv, VALUE self)
{
  VALUE dx = DBL2NUM(1.0), dy = DBL2NUM(1.0), dz = DBL2NUM(1.0),
        x = DBL2NUM(0.5), z = DBL2NUM(0.5), X = DBL2NUM(0.5), Z = DBL2NUM(0.5);
  rb_scan_args(argc, argv, "07", &dx, &dy, &dz, &x, &z, &X, &Z);
  try {
    BRepPrimAPI_MakeWedge api(NUM2DBL(dx), NUM2DBL(dy), NUM2DBL(dz),
        NUM2DBL(x), NUM2DBL(z), NUM2DBL(X), NUM2DBL(Z));
    TopoDS_Shape s = api.Shape();
    return siren_shape_new(s);
  }
  catch (...) {
    rb_raise(Qnil, "Failed to make a wedge.");
  }
  return Qnil;
}
<commit_msg>Update Siren::Solid.initialize method.<commit_after>#include "shape/solid.h"

VALUE sr_cSolid;

SR_SHAPE_GET(Solid, solid)
SR_SHAPE_CHECK(Solid, solid)

bool siren_solid_install()
{
  SR_SHAPE_INIT(Solid)
  rb_define_method(sr_cSolid, "initialize", RUBY_METHOD_FUNC(siren_solid_init), -1);
  rb_define_singleton_method(sr_cSolid, "box",        RUBY_METHOD_FUNC(siren_solid_box),        -1);
  rb_define_singleton_method(sr_cSolid, "box2p",      RUBY_METHOD_FUNC(siren_solid_box2p),      -1);
  rb_define_singleton_method(sr_cSolid, "boxax",      RUBY_METHOD_FUNC(siren_solid_boxax),      -1);
  rb_define_singleton_method(sr_cSolid, "sphere",     RUBY_METHOD_FUNC(siren_solid_sphere),     -1);
  rb_define_singleton_method(sr_cSolid, "cylinder",   RUBY_METHOD_FUNC(siren_solid_cylinder),   -1);
  rb_define_singleton_method(sr_cSolid, "cone",       RUBY_METHOD_FUNC(siren_solid_cone),       -1);
  rb_define_singleton_method(sr_cSolid, "torus",      RUBY_METHOD_FUNC(siren_solid_torus),      -1);
  rb_define_singleton_method(sr_cSolid, "halfspace",  RUBY_METHOD_FUNC(siren_solid_halfspace),  -1);
  rb_define_singleton_method(sr_cSolid, "prism",      RUBY_METHOD_FUNC(siren_solid_prism),      -1);
  rb_define_singleton_method(sr_cSolid, "revol",      RUBY_METHOD_FUNC(siren_solid_revol),      -1);
  rb_define_singleton_method(sr_cSolid, "revolution", RUBY_METHOD_FUNC(siren_solid_revolution), -1);
  rb_define_singleton_method(sr_cSolid, "wedge",      RUBY_METHOD_FUNC(siren_solid_wedge),      -1);
  return true;
}

VALUE siren_solid_init(int argc, VALUE* argv, VALUE self)
{
  VALUE a;
  rb_scan_args(argc, argv, "*", &a);
  auto b = rb_funcall(a, rb_intern("flatten"), 0);
  BRepBuilderAPI_MakeSolid solid_maker;
  for (int i = 0; i < RARRAY_LEN(b); i++) {
    auto item = RARRAY_AREF(b, i);
    if (siren_shell_p(item)) {
      TopoDS_Shell shell = siren_shell_get(item);
      solid_maker.Add(shell);
    }
  }
  if (!solid_maker.IsDone()) {
    rb_raise(Qnil, "Failed to make a Solid.");
  }
  TopoDS_Shape shape = solid_maker.Shape();
  if (shape.IsNull()) {
    rb_raise(Qnil, "Failed to make a Solid.");
  }
  auto p = siren_shape_get(self);
  *p = shape;
  return self;
}

VALUE siren_solid_box(int argc, VALUE* argv, VALUE self)
{
  VALUE size, pos;
  rb_scan_args(argc, argv, "02", &size, &pos);

  Standard_Real sx, sy, sz;
  if (argc >= 1) {
    siren_ary_to_xyz(size, sx, sy, sz);
  }
  else {
    sx = 1.0; sy = 1.0; sz = 1.0;
  }

  gp_Pnt op;
  if (argc >= 2) {
    Standard_Real px, py, pz;
    siren_ary_to_xyz(pos, px, py, pz);
    op = gp_Pnt(px, py, pz);
  }
  else {
    op = gp_Pnt(0., 0., 0.);
  }
  if (std::fabs(sx * sy * sz) == 0.0) {
    rb_raise(Qnil,
      "Failed to make solid. Incorrect size specified.");
  }
  BRepPrimAPI_MakeBox api(op, sx, sy, sz);
  return siren_shape_new(api.Shape());
}

VALUE siren_solid_box2p(int argc, VALUE* argv, VALUE self)
{
  VALUE p1, p2;
  rb_scan_args(argc, argv, "02", &p1, &p2);

  Standard_Real x1 = 0.0, y1 = 0.0, z1 = 0.0;
  Standard_Real x2 = 1.0, y2 = 1.0, z2 = 1.0;

  if (argc >= 1) {
    siren_ary_to_xyz(p1, x1, y1, z1);
  }
  if (argc >= 2) {
    siren_ary_to_xyz(p2, x2, y2, z2);
  }

  gp_Pnt point1(x1, x1, x1);
  gp_Pnt point2(x2, x2, x2);

  BRepPrimAPI_MakeBox api(point1, point2);
  return siren_shape_new(api.Shape());
}

VALUE siren_solid_boxax(int argc, VALUE* argv, VALUE self)
{
  VALUE size, pos, dir;
  rb_scan_args(argc, argv, "3", &size, &pos, &dir);

  Standard_Real sx, sy, sz;
  siren_ary_to_xyz(size, sx, sy, sz);

  Standard_Real px, py, pz;
  siren_ary_to_xyz(pos, px, py, pz);

  Standard_Real dx, dy, dz;
  siren_ary_to_xyz(dir, dx, dy, dz);

  gp_Ax2 ax(gp_Pnt(px, py, pz), gp_Dir(dx, dy, dz));

  BRepPrimAPI_MakeBox api(ax, sx, sy, sz);
  return siren_shape_new(api.Shape());
}

VALUE siren_solid_sphere(int argc, VALUE* argv, VALUE self)
{
  VALUE r = 1.0;
  VALUE pos;
  rb_scan_args(argc, argv, "02", &r, &pos);

  siren_numeric_check(r);

  gp_Pnt op;
  if (argc == 2) {
    Standard_Real px, py, pz;
    siren_ary_to_xyz(pos, px, py, pz);
    op = gp_Pnt(px, py, pz);
  }
  else {
    op = gp_Pnt(0., 0., 0.);
  }

  if (NUM2DBL(r) < 0) {
    rb_raise(Qnil, "Failed to make solid."
      " Specified radius value below 0.");
  }

  BRepPrimAPI_MakeSphere api(op, NUM2DBL(r));
  return siren_shape_new(api.Shape());
}

VALUE siren_solid_cylinder(int argc, VALUE* argv, VALUE self)
{
  VALUE pos, norm;
  VALUE r, h, a;
  rb_scan_args(argc, argv, "5", &pos, &norm, &r, &h, &a);

  siren_numeric_check(r);
  siren_numeric_check(h);
  siren_numeric_check(a);

  gp_Ax2 ax = siren_ary_to_ax2(pos, norm);

  BRepPrimAPI_MakeCylinder api(ax, NUM2DBL(r), NUM2DBL(h), NUM2DBL(a));

  return siren_shape_new(api.Shape());
}

VALUE siren_solid_cone(int argc, VALUE* argv, VALUE self)
{
  VALUE pos, norm;
  VALUE r1, r2, h, ang;
  rb_scan_args(argc, argv, "6", &pos, &norm, &r1, &r2, &h, &ang);

  siren_numeric_check(r1);
  siren_numeric_check(r2);
  siren_numeric_check(h);
  siren_numeric_check(ang);

  gp_Ax2 ax = siren_ary_to_ax2(pos, norm);

  BRepPrimAPI_MakeCone api(ax, NUM2DBL(r1), NUM2DBL(r2), NUM2DBL(h), NUM2DBL(ang));
  return siren_shape_new(api.Shape());
}

VALUE siren_solid_torus(int argc, VALUE* argv, VALUE self)
{
  VALUE r1, r2, ang;
  VALUE pos, norm;
  rb_scan_args(argc, argv, "5", &pos, &norm, &r1, &r2, &ang);

  siren_numeric_check(r1);
  siren_numeric_check(r2);
  siren_numeric_check(ang);

  gp_Ax2 ax = siren_ary_to_ax2(pos, norm);

  BRepPrimAPI_MakeTorus api(ax, NUM2DBL(r1), NUM2DBL(r2), NUM2DBL(ang));
  return siren_shape_new(api.Shape());
}

VALUE siren_solid_halfspace(int argc, VALUE* argv, VALUE self)
{
  VALUE surf, refpnt;
  rb_scan_args(argc, argv, "2", &surf, &refpnt);

  siren_shape_check(surf);

  TopoDS_Shape* shape = siren_shape_get(surf);
  TopoDS_Solid solid;
  gp_Pnt pnt = siren_ary_to_pnt(refpnt);
  if (shape->ShapeType() == TopAbs_FACE) {
    solid = BRepPrimAPI_MakeHalfSpace(TopoDS::Face(*shape), pnt);
  }
  else if (shape->ShapeType() == TopAbs_SHELL) {
    solid = BRepPrimAPI_MakeHalfSpace(TopoDS::Shell(*shape), pnt);
  }
  else {
    rb_raise(Qnil, "Specified shape type is not FACE or SHELL.");
  }
  return siren_shape_new(solid);
}

VALUE siren_solid_prism(int argc, VALUE* argv, VALUE self)
{
  rb_raise(Qnil, "Not implemented.");
  return Qnil;
}

VALUE siren_solid_revol(int argc, VALUE* argv, VALUE self)
{
  rb_raise(Qnil, "Not implemented.");
  return Qnil;
}

VALUE siren_solid_revolution(int argc, VALUE* argv, VALUE self)
{
  rb_raise(Qnil, "Not implemented.");
  return Qnil;
}

VALUE siren_solid_wedge(int argc, VALUE* argv, VALUE self)
{
  VALUE dx = DBL2NUM(1.0), dy = DBL2NUM(1.0), dz = DBL2NUM(1.0),
        x = DBL2NUM(0.5), z = DBL2NUM(0.5), X = DBL2NUM(0.5), Z = DBL2NUM(0.5);
  rb_scan_args(argc, argv, "07", &dx, &dy, &dz, &x, &z, &X, &Z);
  try {
    BRepPrimAPI_MakeWedge api(NUM2DBL(dx), NUM2DBL(dy), NUM2DBL(dz),
        NUM2DBL(x), NUM2DBL(z), NUM2DBL(X), NUM2DBL(Z));
    TopoDS_Shape s = api.Shape();
    return siren_shape_new(s);
  }
  catch (...) {
    rb_raise(Qnil, "Failed to make a wedge.");
  }
  return Qnil;
}
<|endoftext|>