<commit_before>/*
 * Copyright 2014 Google Inc.
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#include "GrRRectEffect.h"

#include "gl/GrGLEffect.h"
#include "gl/GrGLSL.h"
#include "GrTBackendEffectFactory.h"

#include "SkPath.h"

// This effect only supports circular corner rrects where all corners have the same radius
// which must be <= kRadiusMin.
static const SkScalar kRadiusMin = 0.5;

//////////////////////////////////////////////////////////////////////////////
class GrGLRRectEffect : public GrGLEffect {
public:
    GrGLRRectEffect(const GrBackendEffectFactory&, const GrDrawEffect&);

    virtual void emitCode(GrGLShaderBuilder* builder,
                          const GrDrawEffect& drawEffect,
                          EffectKey key,
                          const char* outputColor,
                          const char* inputColor,
                          const TransformedCoordsArray&,
                          const TextureSamplerArray&) SK_OVERRIDE;

    static inline EffectKey GenKey(const GrDrawEffect&, const GrGLCaps&) { return 0; }

    virtual void setData(const GrGLUniformManager&, const GrDrawEffect&) SK_OVERRIDE;

private:
    GrGLUniformManager::UniformHandle   fInnerRectUniform;
    GrGLUniformManager::UniformHandle   fRadiusPlusHalfUniform;
    SkRRect                             fPrevRRect;
    typedef GrGLEffect INHERITED;
};

GrGLRRectEffect::GrGLRRectEffect(const GrBackendEffectFactory& factory,
                                 const GrDrawEffect& drawEffect)
    : INHERITED (factory) {
    fPrevRRect.setEmpty();
}

void GrGLRRectEffect::emitCode(GrGLShaderBuilder* builder,
                               const GrDrawEffect& drawEffect,
                               EffectKey key,
                               const char* outputColor,
                               const char* inputColor,
                               const TransformedCoordsArray&,
                               const TextureSamplerArray& samplers) {
    const char *rectName;
    const char *radiusPlusHalfName;
    // The inner rect is the rrect bounds inset by the radius. Its top, left, right, and bottom
    // edges correspond to components x, y, z, and w, respectively.
    fInnerRectUniform = builder->addUniform(GrGLShaderBuilder::kFragment_Visibility,
                                            kVec4f_GrSLType,
                                            "innerRect",
                                            &rectName);
    fRadiusPlusHalfUniform = builder->addUniform(GrGLShaderBuilder::kFragment_Visibility,
                                                 kFloat_GrSLType,
                                                 "radiusPlusHalf",
                                                 &radiusPlusHalfName);
    const char* fragmentPos = builder->fragmentPosition();
    // At each quarter-circle corner we compute a vector that is the offset of the fragment position
    // from the circle center. The vector is pinned in x and y to be in the quarter-plane relevant
    // to that corner. This means that points near the interior near the rrect top edge will have
    // a vector that points straight up for both the TL left and TR corners. Computing an
    // alpha from this vector at either the TR or TL corner will give the correct result. Similarly,
    // fragments near the other three edges will get the correct AA. Fragments in the interior of
    // the rrect will have a (0,0) vector at all four corners. So long as the radius > 0.5 they will
    // correctly produce an alpha value of 1 at all four corners. We take the min of all the alphas.
    // The code below is a simplified version of the above that performs maxs on the vector
    // components before computing distances and alpha values so that only one distance computation
    // need be computed to determine the min alpha.
    builder->fsCodeAppendf("\t\tvec2 dxy0 = %s.xy - %s.xy;\n", rectName, fragmentPos);
    builder->fsCodeAppendf("\t\tvec2 dxy1 = %s.xy - %s.zw;\n", fragmentPos, rectName);
    builder->fsCodeAppend("\t\tvec2 dxy = max(max(dxy0, dxy1), 0.0);\n");
    builder->fsCodeAppendf("\t\tfloat alpha = clamp(%s - length(dxy), 0.0, 1.0);\n",
                           radiusPlusHalfName);

    builder->fsCodeAppendf("\t\t%s = %s;\n", outputColor,
                           (GrGLSLExpr4(inputColor) * GrGLSLExpr1("alpha")).c_str());
}

void GrGLRRectEffect::setData(const GrGLUniformManager& uman, const GrDrawEffect& drawEffect) {
    const GrRRectEffect& rre = drawEffect.castEffect<GrRRectEffect>();
    const SkRRect& rrect = rre.getRRect();
    if (rrect != fPrevRRect) {
        SkASSERT(rrect.isSimpleCircular());
        SkRect rect = rrect.getBounds();
        SkScalar radius = rrect.getSimpleRadii().fX;
        SkASSERT(radius >= kRadiusMin);
        rect.inset(radius, radius);
        uman.set4f(fInnerRectUniform, rect.fLeft, rect.fTop, rect.fRight, rect.fBottom);
        uman.set1f(fRadiusPlusHalfUniform, radius + 0.5f);
        fPrevRRect = rrect;
    }
}

//////////////////////////////////////////////////////////////////////////////

GrEffectRef* GrRRectEffect::Create(const SkRRect& rrect) {
    if (!rrect.isSimpleCircular()) {
        return NULL;
    }
    if (rrect.getSimpleRadii().fX < kRadiusMin) {
        return NULL;
    }
    return CreateEffectRef(AutoEffectUnref(SkNEW_ARGS(GrRRectEffect, (rrect))));
}

GrRRectEffect::~GrRRectEffect() {}

void GrRRectEffect::getConstantColorComponents(GrColor* color, uint32_t* validFlags) const {
    *validFlags = 0;
}

const GrBackendEffectFactory& GrRRectEffect::getFactory() const {
    return GrTBackendEffectFactory<GrRRectEffect>::getInstance();
}

GrRRectEffect::GrRRectEffect(const SkRRect& rrect)
    : fRRect(rrect) {
    SkASSERT(rrect.isSimpleCircular());
    SkASSERT(rrect.getSimpleRadii().fX >= kRadiusMin);
    this->setWillReadFragmentPosition();
}

bool GrRRectEffect::onIsEqual(const GrEffect& other) const {
    const GrRRectEffect& rre = CastEffect<GrRRectEffect>(other);
    return fRRect == rre.fRRect;
}

//////////////////////////////////////////////////////////////////////////////

GR_DEFINE_EFFECT_TEST(GrRRectEffect);

GrEffectRef* GrRRectEffect::TestCreate(SkRandom* random,
                                       GrContext*,
                                       const GrDrawTargetCaps& caps,
                                       GrTexture*[]) {
    SkScalar w = random->nextRangeScalar(20.f, 1000.f);
    SkScalar h = random->nextRangeScalar(20.f, 1000.f);
    SkScalar r = random->nextRangeF(kRadiusMin, 9.f);
    SkRRect rrect;
    rrect.setRectXY(SkRect::MakeWH(w, h), r, r);

    return GrRRectEffect::Create(rrect);
}
<commit_msg>Add f suffix to 0.5 to fix mac 10.6 warning<commit_after>/*
 * Copyright 2014 Google Inc.
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#include "GrRRectEffect.h"

#include "gl/GrGLEffect.h"
#include "gl/GrGLSL.h"
#include "GrTBackendEffectFactory.h"

#include "SkPath.h"

// This effect only supports circular corner rrects where all corners have the same radius
// which must be <= kRadiusMin.
static const SkScalar kRadiusMin = 0.5f;

//////////////////////////////////////////////////////////////////////////////
class GrGLRRectEffect : public GrGLEffect {
public:
    GrGLRRectEffect(const GrBackendEffectFactory&, const GrDrawEffect&);

    virtual void emitCode(GrGLShaderBuilder* builder,
                          const GrDrawEffect& drawEffect,
                          EffectKey key,
                          const char* outputColor,
                          const char* inputColor,
                          const TransformedCoordsArray&,
                          const TextureSamplerArray&) SK_OVERRIDE;

    static inline EffectKey GenKey(const GrDrawEffect&, const GrGLCaps&) { return 0; }

    virtual void setData(const GrGLUniformManager&, const GrDrawEffect&) SK_OVERRIDE;

private:
    GrGLUniformManager::UniformHandle   fInnerRectUniform;
    GrGLUniformManager::UniformHandle   fRadiusPlusHalfUniform;
    SkRRect                             fPrevRRect;
    typedef GrGLEffect INHERITED;
};

GrGLRRectEffect::GrGLRRectEffect(const GrBackendEffectFactory& factory,
                                 const GrDrawEffect& drawEffect)
    : INHERITED (factory) {
    fPrevRRect.setEmpty();
}

void GrGLRRectEffect::emitCode(GrGLShaderBuilder* builder,
                               const GrDrawEffect& drawEffect,
                               EffectKey key,
                               const char* outputColor,
                               const char* inputColor,
                               const TransformedCoordsArray&,
                               const TextureSamplerArray& samplers) {
    const char *rectName;
    const char *radiusPlusHalfName;
    // The inner rect is the rrect bounds inset by the radius. Its top, left, right, and bottom
    // edges correspond to components x, y, z, and w, respectively.
    fInnerRectUniform = builder->addUniform(GrGLShaderBuilder::kFragment_Visibility,
                                            kVec4f_GrSLType,
                                            "innerRect",
                                            &rectName);
    fRadiusPlusHalfUniform = builder->addUniform(GrGLShaderBuilder::kFragment_Visibility,
                                                 kFloat_GrSLType,
                                                 "radiusPlusHalf",
                                                 &radiusPlusHalfName);
    const char* fragmentPos = builder->fragmentPosition();
    // At each quarter-circle corner we compute a vector that is the offset of the fragment position
    // from the circle center. The vector is pinned in x and y to be in the quarter-plane relevant
    // to that corner. This means that points near the interior near the rrect top edge will have
    // a vector that points straight up for both the TL left and TR corners. Computing an
    // alpha from this vector at either the TR or TL corner will give the correct result. Similarly,
    // fragments near the other three edges will get the correct AA. Fragments in the interior of
    // the rrect will have a (0,0) vector at all four corners. So long as the radius > 0.5 they will
    // correctly produce an alpha value of 1 at all four corners. We take the min of all the alphas.
    // The code below is a simplified version of the above that performs maxs on the vector
    // components before computing distances and alpha values so that only one distance computation
    // need be computed to determine the min alpha.
    builder->fsCodeAppendf("\t\tvec2 dxy0 = %s.xy - %s.xy;\n", rectName, fragmentPos);
    builder->fsCodeAppendf("\t\tvec2 dxy1 = %s.xy - %s.zw;\n", fragmentPos, rectName);
    builder->fsCodeAppend("\t\tvec2 dxy = max(max(dxy0, dxy1), 0.0);\n");
    builder->fsCodeAppendf("\t\tfloat alpha = clamp(%s - length(dxy), 0.0, 1.0);\n",
                           radiusPlusHalfName);

    builder->fsCodeAppendf("\t\t%s = %s;\n", outputColor,
                           (GrGLSLExpr4(inputColor) * GrGLSLExpr1("alpha")).c_str());
}

void GrGLRRectEffect::setData(const GrGLUniformManager& uman, const GrDrawEffect& drawEffect) {
    const GrRRectEffect& rre = drawEffect.castEffect<GrRRectEffect>();
    const SkRRect& rrect = rre.getRRect();
    if (rrect != fPrevRRect) {
        SkASSERT(rrect.isSimpleCircular());
        SkRect rect = rrect.getBounds();
        SkScalar radius = rrect.getSimpleRadii().fX;
        SkASSERT(radius >= kRadiusMin);
        rect.inset(radius, radius);
        uman.set4f(fInnerRectUniform, rect.fLeft, rect.fTop, rect.fRight, rect.fBottom);
        uman.set1f(fRadiusPlusHalfUniform, radius + 0.5f);
        fPrevRRect = rrect;
    }
}

//////////////////////////////////////////////////////////////////////////////

GrEffectRef* GrRRectEffect::Create(const SkRRect& rrect) {
    if (!rrect.isSimpleCircular()) {
        return NULL;
    }
    if (rrect.getSimpleRadii().fX < kRadiusMin) {
        return NULL;
    }
    return CreateEffectRef(AutoEffectUnref(SkNEW_ARGS(GrRRectEffect, (rrect))));
}

GrRRectEffect::~GrRRectEffect() {}

void GrRRectEffect::getConstantColorComponents(GrColor* color, uint32_t* validFlags) const {
    *validFlags = 0;
}

const GrBackendEffectFactory& GrRRectEffect::getFactory() const {
    return GrTBackendEffectFactory<GrRRectEffect>::getInstance();
}

GrRRectEffect::GrRRectEffect(const SkRRect& rrect)
    : fRRect(rrect) {
    SkASSERT(rrect.isSimpleCircular());
    SkASSERT(rrect.getSimpleRadii().fX >= kRadiusMin);
    this->setWillReadFragmentPosition();
}

bool GrRRectEffect::onIsEqual(const GrEffect& other) const {
    const GrRRectEffect& rre = CastEffect<GrRRectEffect>(other);
    return fRRect == rre.fRRect;
}

//////////////////////////////////////////////////////////////////////////////

GR_DEFINE_EFFECT_TEST(GrRRectEffect);

GrEffectRef* GrRRectEffect::TestCreate(SkRandom* random,
                                       GrContext*,
                                       const GrDrawTargetCaps& caps,
                                       GrTexture*[]) {
    SkScalar w = random->nextRangeScalar(20.f, 1000.f);
    SkScalar h = random->nextRangeScalar(20.f, 1000.f);
    SkScalar r = random->nextRangeF(kRadiusMin, 9.f);
    SkRRect rrect;
    rrect.setRectXY(SkRect::MakeWH(w, h), r, r);

    return GrRRectEffect::Create(rrect);
}
<|endoftext|>


<commit_before>#include <os>

#include <syscalls.hpp>
#include <string.h>
#include <signal.h>
//#include <vga.hpp>

char *__env[1] = { 0 };
char **environ = __env;

static const int syscall_fd=999;
static bool debug_syscalls=true;
caddr_t heap_end;

//Syscall logger
void syswrite(const char* name, const char* str)
{
  static const char* hdr  = "\tSYSCALL ";
  static const char* term = "\n";
  write(syscall_fd, (char*) hdr,  strlen(hdr));
  write(syscall_fd, (char*) name, strlen(name));
  write(syscall_fd, (char*) ": ", 2);
  write(syscall_fd, (char*) str,  strlen(str));
  write(syscall_fd, (char*) term, strlen(term));
};

void _exit(int status)
{
  printf("EXIT: status == %d\n", status);
  panic("EXIT: Not implemented");
}

int close(int UNUSED(file)){
  syswrite("CLOSE","Dummy, returning -1");
  return -1;
};

#undef errno
int errno=0; //Is this right?
//Not like in http://wiki.osdev.org/Porting_Newlib

int execve(const char* UNUSED(name),
           char* const* UNUSED(argv),
           char* const* UNUSED(env))
{
  syswrite((char*) "EXECVE", "NOT SUPPORTED");
  errno = ENOMEM;
  return -1;
};

int fork(){
  syswrite("FORK","NOT SUPPORTED");
  errno=ENOMEM;
  return -1;
};

int fstat(int UNUSED(file), struct stat *st){
  syswrite("FSTAT","Returning OK 0");
  st->st_mode = S_IFCHR;
  return 0;
};
int getpid(){
  syswrite("GETPID", "RETURNING 1");
  return 1;
};

int isatty(int UNUSED(file))
{
  syswrite("ISATTY","RETURNING 1");
  return 1;
}

int link(const char* UNUSED(old), const char* UNUSED(_new))
{
  syswrite("LINK","CAN'T DO THAT!");
  kill(1,9);
  return -1;
};
int unlink(const char* UNUSED(name)){
  syswrite((char*)"UNLINK","DUMMY, RETURNING -1");
  return -1;
};

off_t lseek(int UNUSED(file), off_t UNUSED(ptr), int UNUSED(dir))
{
  syswrite("LSEEK","RETURNING 0");
  return 0;
}
int open(const char* UNUSED(name), int UNUSED(flags), ...){

  syswrite("OPEN","NOT SUPPORTED - RETURNING -1");
  return -1;
};

int read(int UNUSED(file), void* UNUSED(ptr), size_t UNUSED(len))
{
  syswrite("READ","CAN'T DO THAT - RETURNING 0");
  return 0;
}
int write(int file, const void* ptr, size_t len)
{
	if (file == syscall_fd and not debug_syscalls)
		return len;

	// VGA console output
	//consoleVGA.write(ptr, len);

	// serial output
	for(size_t i = 0; i < len; i++)
		OS::rswrite( ((char*) ptr)[i] );

	return len;
}

void* sbrk(ptrdiff_t incr)
{
  void* prev_heap_end = heap_end;
  heap_end += incr;
  return (caddr_t) prev_heap_end;
}

int stat(const char* UNUSED(file), struct stat *st){
  syswrite((char*)"STAT","DUMMY");
  st->st_mode = S_IFCHR;
  return 0;
};

clock_t times(struct tms* UNUSED(buf))
{
  printf("Syscall: times(tms) returning -1\n");
  syswrite((char*)"TIMES","DUMMY, RETURNING -1");
  //__asm__("rdtsc");
  return -1;
};

int wait(int* UNUSED(status)){
  syswrite((char*)"UNLINK","DUMMY, RETURNING -1");
  return -1;
};

int gettimeofday(struct timeval* p, void* UNUSED(z)){
  float seconds = OS::uptime();
  p->tv_sec = int(seconds);
  p->tv_usec = (seconds - p->tv_sec) * 1000000;
  return 5;
}

int kill(pid_t pid, int sig)
{
  if (pid == 1)
  {
    syswrite("KILL", "HALTING");
    __asm__("cli; hlt;");
    _exit(sig);
  }
  return -1;
}

void panic(const char* why)
{
  printf("\n\t **** PANIC: **** %s\n",why);
  printf("\tHeap end: %p \n",heap_end);
  kill(1, 1);
}
<commit_msg>Added __errno_location<commit_after>#include <os>

#include <syscalls.hpp>
#include <string.h>
#include <signal.h>
//#include <vga.hpp>

char *__env[1] = { 0 };
char **environ = __env;

static const int syscall_fd=999;
static bool debug_syscalls=true;
caddr_t heap_end;

//Syscall logger
void syswrite(const char* name, const char* str)
{
  static const char* hdr  = "\tSYSCALL ";
  static const char* term = "\n";
  write(syscall_fd, (char*) hdr,  strlen(hdr));
  write(syscall_fd, (char*) name, strlen(name));
  write(syscall_fd, (char*) ": ", 2);
  write(syscall_fd, (char*) str,  strlen(str));
  write(syscall_fd, (char*) term, strlen(term));
};

void _exit(int status)
{
  printf("EXIT: status == %d\n", status);
  panic("EXIT: Not implemented");
}

int close(int UNUSED(file)){
  syswrite("CLOSE","Dummy, returning -1");
  return -1;
};

#undef errno
int errno=0; //Is this right?
//Not like in http://wiki.osdev.org/Porting_Newlib

int execve(const char* UNUSED(name),
           char* const* UNUSED(argv),
           char* const* UNUSED(env))
{
  syswrite((char*) "EXECVE", "NOT SUPPORTED");
  errno = ENOMEM;
  return -1;
};

int fork(){
  syswrite("FORK","NOT SUPPORTED");
  errno=ENOMEM;
  return -1;
};

int fstat(int UNUSED(file), struct stat *st){
  syswrite("FSTAT","Returning OK 0");
  st->st_mode = S_IFCHR;
  return 0;
};
int getpid(){
  syswrite("GETPID", "RETURNING 1");
  return 1;
};

int isatty(int UNUSED(file))
{
  syswrite("ISATTY","RETURNING 1");
  return 1;
}

int link(const char* UNUSED(old), const char* UNUSED(_new))
{
  syswrite("LINK","CAN'T DO THAT!");
  kill(1,9);
  return -1;
};
int unlink(const char* UNUSED(name)){
  syswrite((char*)"UNLINK","DUMMY, RETURNING -1");
  return -1;
};

off_t lseek(int UNUSED(file), off_t UNUSED(ptr), int UNUSED(dir))
{
  syswrite("LSEEK","RETURNING 0");
  return 0;
}
int open(const char* UNUSED(name), int UNUSED(flags), ...){

  syswrite("OPEN","NOT SUPPORTED - RETURNING -1");
  return -1;
};

int read(int UNUSED(file), void* UNUSED(ptr), size_t UNUSED(len))
{
  syswrite("READ","CAN'T DO THAT - RETURNING 0");
  return 0;
}
int write(int file, const void* ptr, size_t len)
{
	if (file == syscall_fd and not debug_syscalls)
		return len;

	// VGA console output
	//consoleVGA.write(ptr, len);

	// serial output
	for(size_t i = 0; i < len; i++)
		OS::rswrite( ((char*) ptr)[i] );

	return len;
}

void* sbrk(ptrdiff_t incr)
{
  void* prev_heap_end = heap_end;
  heap_end += incr;
  return (caddr_t) prev_heap_end;
}

int stat(const char* UNUSED(file), struct stat *st){
  syswrite((char*)"STAT","DUMMY");
  st->st_mode = S_IFCHR;
  return 0;
};

clock_t times(struct tms* UNUSED(buf))
{
  printf("Syscall: times(tms) returning -1\n");
  syswrite((char*)"TIMES","DUMMY, RETURNING -1");
  //__asm__("rdtsc");
  return -1;
};

int wait(int* UNUSED(status)){
  syswrite((char*)"UNLINK","DUMMY, RETURNING -1");
  return -1;
};

int gettimeofday(struct timeval* p, void* UNUSED(z)){
  float seconds = OS::uptime();
  p->tv_sec = int(seconds);
  p->tv_usec = (seconds - p->tv_sec) * 1000000;
  return 5;
}

int kill(pid_t pid, int sig)
{
  if (pid == 1)
  {
    syswrite("KILL", "HALTING");
    __asm__("cli; hlt;");
    _exit(sig);
  }
  return -1;
}

void panic(const char* why)
{
  printf("\n\t **** PANIC: **** %s\n",why);
  printf("\tHeap end: %p \n",heap_end);
  kill(1, 1);
}

static int __errno__;

extern "C" {
  int * __errno_location(void){ return &__errno__; }
}
<|endoftext|>


<commit_before>/* Copyright 2014 CyberTech Labs Ltd.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License. */

#include "src/cameraLineDetectorSensorWorker.h"

#include <QtCore/QDebug>
#include <QtCore/QFileInfo>
#include <QtCore/QWaitCondition>
#include <QtCore/QMutex>

#include <unistd.h>
#include <fcntl.h>
#include <errno.h>

using namespace trikControl;

CameraLineDetectorSensorWorker::CameraLineDetectorSensorWorker(
		QString const &roverCvBinary
		, QString const &inputFile
		, QString const &outputFile)
	: mReading(0)
	, mRoverCvBinary(roverCvBinary)
	, mOutputFileDescriptor(0)
	, mInputFile(inputFile)
	, mOutputFile(outputFile)
	, mReady(false)
{
	qDebug() << "CameraLineDetectorSensorWorker::CameraLineDetectorSensorWorker";

	qRegisterMetaType<QProcess::ProcessError>("QProcess::ProcessError");
}

CameraLineDetectorSensorWorker::~CameraLineDetectorSensorWorker()
{
	deinitialize();
}

void CameraLineDetectorSensorWorker::moveChildrenToCorrectThread()
{
	mRoverCvProcess.moveToThread(this->thread());

	connect(&mRoverCvProcess, SIGNAL(error(QProcess::ProcessError))
			, this, SLOT(onRoverCvError(QProcess::ProcessError)), Qt::QueuedConnection);

	connect(&mRoverCvProcess, SIGNAL(readyReadStandardError())
			, this, SLOT(onRoverCvReadyReadStandardError()), Qt::QueuedConnection);

	connect(&mRoverCvProcess, SIGNAL(readyReadStandardOutput())
			, this, SLOT(onRoverCvReadyReadStandardOutput()), Qt::QueuedConnection);
}

void CameraLineDetectorSensorWorker::init()
{
	qDebug() << "CameraLineDetectorSensorWorker::init()";
	if (!mReady) {
		initDetector();
	}
}

void CameraLineDetectorSensorWorker::detect()
{
	qDebug() << "CameraLineDetectorSensorWorker::detect()";
	if (!mReady) {
		init();
	}

	mCommandQueue << "detect";
	tryToExecute();
}

int CameraLineDetectorSensorWorker::read()
{
	return mReading;
}

void CameraLineDetectorSensorWorker::initDetector()
{
	qDebug() << "initDetector()";

	if (!mInputFile.exists() || !mOutputFile.exists()) {
		startRoverCv();
	} else {
		openFifos();
	}
}

void CameraLineDetectorSensorWorker::onRoverCvError(QProcess::ProcessError error)
{
	qDebug() << "rover-cv error: " << error;

	mReady = false;
	deinitialize();
}

void CameraLineDetectorSensorWorker::onRoverCvReadyReadStandardOutput()
{
	qDebug() << "onRoverCvReadyReadStandardOutput";

	QString const data = mRoverCvProcess.readAllStandardOutput();
	QStringList const lines = data.split("\n");
	foreach (QString const line, lines) {
		qDebug() << "From rover-cv:" << line;
		if (line == "Entering video thread loop") {
			openFifos();
		}
	}
}

void CameraLineDetectorSensorWorker::onRoverCvReadyReadStandardError()
{
	QString const data = mRoverCvProcess.readAllStandardError();
	QStringList const lines = data.split("\n");
	foreach (QString const line, lines) {
		qDebug() << "From rover-cv standard error:" << line;
	}
}

void CameraLineDetectorSensorWorker::readFile()
{
	char data[4000] = {0};
	int size = 0;

	mSocketNotifier->setEnabled(false);

	if ((size = ::read(mOutputFileDescriptor, data, 4000)) < 0) {
		qDebug() << mOutputFile.fileName() << ": fifo read failed: " << errno;
		return;
	}

	QString const linesRead(data);
	QStringList const lines = linesRead.split('\n', QString::SkipEmptyParts);

	foreach (QString const line, lines) {
		QStringList const parsedLine = line.split(" ", QString::SkipEmptyParts);

		qDebug() << "parsed: " << parsedLine;

		if (parsedLine[0] == "loc:") {
			int const x = parsedLine[1].toInt();
			int const angle = parsedLine[2].toInt();
			int const mass = parsedLine[3].toInt();

			mReading = x;

			// These values are not needed in current implementation, but are left here for reference.
			Q_UNUSED(angle)
			Q_UNUSED(mass)
		}

		if (parsedLine[0] == "hsv:") {
			int const hue = parsedLine[1].toInt();
			int const hueTolerance = parsedLine[2].toInt();
			int const saturation = parsedLine[3].toInt();
			int const saturationTolerance = parsedLine[4].toInt();
			int const value = parsedLine[5].toInt();
			int const valueTolerance = parsedLine[6].toInt();

			// These values are not needed in current implementation, but are left here for reference too.
			Q_UNUSED(hue)
			Q_UNUSED(hueTolerance)
			Q_UNUSED(saturation)
			Q_UNUSED(saturationTolerance)
			Q_UNUSED(value)
			Q_UNUSED(valueTolerance)

			mInputStream << QString(line).remove(":") << "\n";
			mInputStream.flush();
		}
	}

	mSocketNotifier->setEnabled(true);
}

void CameraLineDetectorSensorWorker::startRoverCv()
{
	QFileInfo roverCvBinaryFileInfo(mRoverCvBinary);

	qDebug() << "Starting rover-cv";

	mRoverCvProcess.setWorkingDirectory(roverCvBinaryFileInfo.absolutePath());
	mRoverCvProcess.start(roverCvBinaryFileInfo.filePath());

	mRoverCvProcess.waitForStarted();

	if (mRoverCvProcess.state() != QProcess::Running)
	{
		qDebug() << "Cannot launch detector application " << roverCvBinaryFileInfo.filePath() << " in "
				<< roverCvBinaryFileInfo.absolutePath();
		return;
	}

	qDebug() << "rover-cv started, waiting for it to initialize...";

	/// @todo Remove this hack! QProcess does not deliver messages from rover-cv during startup.
	QMutex mutex;
	QWaitCondition wait;
	wait.wait(&mutex, 1000);

	openFifos();
}

void CameraLineDetectorSensorWorker::openFifos()
{
	qDebug() << "opening" << mOutputFile.fileName();

	if (!mOutputFileDescriptor) {
		mOutputFileDescriptor = open(mOutputFile.fileName().toStdString().c_str(), O_SYNC | O_NONBLOCK, O_RDONLY);
	}

	if (mOutputFileDescriptor == -1) {
		qDebug() << "Cannot open sensor output file " << mOutputFile.fileName();
		return;
	}

	qDebug() << mOutputFileDescriptor;

	mSocketNotifier.reset(new QSocketNotifier(mOutputFileDescriptor, QSocketNotifier::Read));

	connect(mSocketNotifier.data(), SIGNAL(activated(int)), this, SLOT(readFile()));
	mSocketNotifier->setEnabled(true);

	qDebug() << "opening" << mInputFile.fileName();

	if (!mInputFile.open(QIODevice::WriteOnly | QIODevice::Text)) {
		qDebug() << "Sensor input file" << mInputFile.fileName() << " failed to open";
		return;
	}

	mInputStream.setDevice(&mInputFile);

	mReady = true;

	qDebug() << "initialization completed";

	tryToExecute();
}

void CameraLineDetectorSensorWorker::tryToExecute()
{
	if (mReady) {
		foreach (QString const &command, mCommandQueue) {
			mInputStream << command + "\n";
			mInputStream.flush();
		}

		mCommandQueue.clear();
	}
}

void CameraLineDetectorSensorWorker::deinitialize()
{
	disconnect(mSocketNotifier.data(), SIGNAL(activated(int)), this, SLOT(readFifo()));
	mSocketNotifier->setEnabled(false);
	if (::close(mOutputFileDescriptor) != 0) {
		qDebug() << mOutputFile.fileName() << ": fifo close failed: " << errno;
	}
}
<commit_msg>fixed restart of the rover-cv<commit_after>/* Copyright 2014 CyberTech Labs Ltd.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License. */

#include "src/cameraLineDetectorSensorWorker.h"

#include <QtCore/QDebug>
#include <QtCore/QFileInfo>
#include <QtCore/QWaitCondition>
#include <QtCore/QMutex>

#include <unistd.h>
#include <fcntl.h>
#include <errno.h>

using namespace trikControl;

CameraLineDetectorSensorWorker::CameraLineDetectorSensorWorker(
		QString const &roverCvBinary
		, QString const &inputFile
		, QString const &outputFile)
	: mReading(0)
	, mRoverCvBinary(roverCvBinary)
	, mOutputFileDescriptor(0)
	, mInputFile(inputFile)
	, mOutputFile(outputFile)
	, mReady(false)
{
	qRegisterMetaType<QProcess::ProcessError>("QProcess::ProcessError");

	connect(&mRoverCvProcess, SIGNAL(error(QProcess::ProcessError))
			, this, SLOT(onRoverCvError(QProcess::ProcessError)), Qt::QueuedConnection);

	connect(&mRoverCvProcess, SIGNAL(readyReadStandardError())
			, this, SLOT(onRoverCvReadyReadStandardError()), Qt::QueuedConnection);

	connect(&mRoverCvProcess, SIGNAL(readyReadStandardOutput())
			, this, SLOT(onRoverCvReadyReadStandardOutput()), Qt::QueuedConnection);
}

CameraLineDetectorSensorWorker::~CameraLineDetectorSensorWorker()
{
	deinitialize();
}

void CameraLineDetectorSensorWorker::moveChildrenToCorrectThread()
{
	mRoverCvProcess.moveToThread(this->thread());
}

void CameraLineDetectorSensorWorker::init()
{
	if (!mReady || !mInputFile.exists() || !mOutputFile.exists()) {
		initDetector();
	}
}

void CameraLineDetectorSensorWorker::detect()
{
	if (!mReady || !mInputFile.exists() || !mOutputFile.exists()) {
		init();
	}

	mCommandQueue << "detect";
	tryToExecute();
}

int CameraLineDetectorSensorWorker::read()
{
	return mReading;
}

void CameraLineDetectorSensorWorker::initDetector()
{
	if (!mInputFile.exists() || !mOutputFile.exists()) {
		startRoverCv();
	} else {
		openFifos();
	}
}

void CameraLineDetectorSensorWorker::onRoverCvError(QProcess::ProcessError error)
{
	qDebug() << "rover-cv error: " << error;

	mReady = false;
	deinitialize();
}

void CameraLineDetectorSensorWorker::onRoverCvReadyReadStandardOutput()
{
	QString const data = mRoverCvProcess.readAllStandardOutput();
	QStringList const lines = data.split("\n");
	foreach (QString const line, lines) {
		qDebug() << "From rover-cv:" << line;
		if (line == "Entering video thread loop") {
			openFifos();
		}
		if (line == "Terminating") {
			mReady = false;
			deinitialize();
		}
	}
}

void CameraLineDetectorSensorWorker::onRoverCvReadyReadStandardError()
{
	QString const data = mRoverCvProcess.readAllStandardError();
	QStringList const lines = data.split("\n");
	foreach (QString const line, lines) {
		qDebug() << "From rover-cv standard error:" << line;
	}
}

void CameraLineDetectorSensorWorker::readFile()
{
	char data[4000] = {0};
	int size = 0;

	mSocketNotifier->setEnabled(false);

	if ((size = ::read(mOutputFileDescriptor, data, 4000)) < 0) {
		qDebug() << mOutputFile.fileName() << ": fifo read failed: " << errno;
		return;
	}

	QString const linesRead(data);
	QStringList const lines = linesRead.split('\n', QString::SkipEmptyParts);

	foreach (QString const line, lines) {
		QStringList const parsedLine = line.split(" ", QString::SkipEmptyParts);

		qDebug() << "parsed: " << parsedLine;

		if (parsedLine[0] == "loc:") {
			int const x = parsedLine[1].toInt();
			int const angle = parsedLine[2].toInt();
			int const mass = parsedLine[3].toInt();

			mReading = x;

			// These values are not needed in current implementation, but are left here for reference.
			Q_UNUSED(angle)
			Q_UNUSED(mass)
		}

		if (parsedLine[0] == "hsv:") {
			int const hue = parsedLine[1].toInt();
			int const hueTolerance = parsedLine[2].toInt();
			int const saturation = parsedLine[3].toInt();
			int const saturationTolerance = parsedLine[4].toInt();
			int const value = parsedLine[5].toInt();
			int const valueTolerance = parsedLine[6].toInt();

			// These values are not needed in current implementation, but are left here for reference too.
			Q_UNUSED(hue)
			Q_UNUSED(hueTolerance)
			Q_UNUSED(saturation)
			Q_UNUSED(saturationTolerance)
			Q_UNUSED(value)
			Q_UNUSED(valueTolerance)

			mInputStream << QString(line).remove(":") << "\n";
			mInputStream.flush();
		}
	}

	mSocketNotifier->setEnabled(true);
}

void CameraLineDetectorSensorWorker::startRoverCv()
{
	QFileInfo roverCvBinaryFileInfo(mRoverCvBinary);

	qDebug() << "Starting rover-cv";

	if (mRoverCvProcess.state() == QProcess::Running) {
		mRoverCvProcess.close();
	}

	mRoverCvProcess.setWorkingDirectory(roverCvBinaryFileInfo.absolutePath());
	mRoverCvProcess.start(roverCvBinaryFileInfo.filePath(), QIODevice::ReadOnly | QIODevice::Unbuffered);

	mRoverCvProcess.waitForStarted();

	if (mRoverCvProcess.state() != QProcess::Running)
	{
		qDebug() << "Cannot launch detector application " << roverCvBinaryFileInfo.filePath() << " in "
				<< roverCvBinaryFileInfo.absolutePath();
		return;
	}

	qDebug() << "rover-cv started, waiting for it to initialize...";

	/// @todo Remove this hack! QProcess does not deliver messages from rover-cv during startup.
	QMutex mutex;
	QWaitCondition wait;
	wait.wait(&mutex, 1000);

	openFifos();
}

void CameraLineDetectorSensorWorker::openFifos()
{
	qDebug() << "opening" << mOutputFile.fileName();

	if (!mOutputFileDescriptor) {
		mOutputFileDescriptor = open(mOutputFile.fileName().toStdString().c_str(), O_SYNC | O_NONBLOCK, O_RDONLY);
	}

	if (mOutputFileDescriptor == -1) {
		qDebug() << "Cannot open sensor output file " << mOutputFile.fileName();
		return;
	}

	qDebug() << mOutputFileDescriptor;

	mSocketNotifier.reset(new QSocketNotifier(mOutputFileDescriptor, QSocketNotifier::Read));

	connect(mSocketNotifier.data(), SIGNAL(activated(int)), this, SLOT(readFile()));
	mSocketNotifier->setEnabled(false);

	qDebug() << "opening" << mInputFile.fileName();

	if (!mInputFile.open(QIODevice::WriteOnly | QIODevice::Text)) {
		qDebug() << "Sensor input file" << mInputFile.fileName() << " failed to open";
		return;
	}

	mInputStream.setDevice(&mInputFile);

	mReady = true;

	qDebug() << "initialization completed";

	tryToExecute();
}

void CameraLineDetectorSensorWorker::tryToExecute()
{
	if (mReady) {
		foreach (QString const &command, mCommandQueue) {
			mInputStream << command + "\n";
			mInputStream.flush();
		}

		mCommandQueue.clear();
	}
}

void CameraLineDetectorSensorWorker::deinitialize()
{
	disconnect(mSocketNotifier.data(), SIGNAL(activated(int)), this, SLOT(readFile()));
	mSocketNotifier->setEnabled(false);
	if (::close(mOutputFileDescriptor) != 0) {
		qDebug() << mOutputFile.fileName() << ": fifo close failed: " << errno;
	}
}
<|endoftext|>


<commit_before>// Copyright 2020 The Pigweed Authors
//
// Licensed under the Apache License, Version 2.0 (the "License"); you may not
// use this file except in compliance with the License. You may obtain a copy of
// the License at
//
//     https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
// License for the specific language governing permissions and limitations under
// the License.

#include "pw_kvs/internal/sectors.h"

#include "gtest/gtest.h"
#include "pw_kvs/fake_flash_memory.h"

namespace pw::kvs::internal {
namespace {

class SectorsTest : public ::testing::Test {
 protected:
  SectorsTest()
      : partition_(&flash_),
        sectors_(sector_descriptors_, partition_, nullptr) {}

  FakeFlashMemoryBuffer<128, 16> flash_;
  FlashPartition partition_;
  Vector<SectorDescriptor, 32> sector_descriptors_;
  Sectors sectors_;
};

TEST_F(SectorsTest, Reset) {
  EXPECT_EQ(0u, sectors_.size());

  sectors_.Reset();

  EXPECT_EQ(partition_.sector_count(), sectors_.size());
  EXPECT_EQ(32u, sectors_.max_size());
  EXPECT_EQ(sectors_.begin(), sectors_.last_new());
}

TEST_F(SectorsTest, LastNew) {
  sectors_.set_last_new_sector(130);
  EXPECT_EQ(128u, sectors_.BaseAddress(*sectors_.last_new()));
}

TEST_F(SectorsTest, AddressInSector) {
  SectorDescriptor& sector = sectors_.FromAddress(128);

  EXPECT_FALSE(sectors_.AddressInSector(sector, 127));
  for (size_t address = 128; address < 256; ++address) {
    EXPECT_TRUE(sectors_.AddressInSector(sector, address));
  }
  EXPECT_FALSE(sectors_.AddressInSector(sector, 256));
  EXPECT_FALSE(sectors_.AddressInSector(sector, 1025));
}

TEST_F(SectorsTest, BaseAddressAndFromAddress) {
  for (size_t address = 0; address < 128; ++address) {
    EXPECT_EQ(0u, sectors_.BaseAddress(sectors_.FromAddress(address)));
  }
  for (size_t address = 128; address < 256; ++address) {
    EXPECT_EQ(128u, sectors_.BaseAddress(sectors_.FromAddress(address)));
  }
  for (size_t address = 256; address < 384; ++address) {
    EXPECT_EQ(256u, sectors_.BaseAddress(sectors_.FromAddress(address)));
  }
}

TEST_F(SectorsTest, NextWritableAddress_EmptySector) {
  EXPECT_EQ(0u, sectors_.NextWritableAddress(*sectors_.begin()));
}

TEST_F(SectorsTest, NextWritableAddress_PartiallyWrittenSector) {
  sectors_.begin()->RemoveWritableBytes(123);
  EXPECT_EQ(123u, sectors_.NextWritableAddress(*sectors_.begin()));
}

// TODO: Add tests for FindSpace, FindSpaceDuringGarbageCollection, and
// FindSectorToGarbageCollect.

}  // namespace
}  // namespace pw::kvs::internal
<commit_msg>pw_kvs: Fix sectors test<commit_after>// Copyright 2020 The Pigweed Authors
//
// Licensed under the Apache License, Version 2.0 (the "License"); you may not
// use this file except in compliance with the License. You may obtain a copy of
// the License at
//
//     https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
// License for the specific language governing permissions and limitations under
// the License.

#include "pw_kvs/internal/sectors.h"

#include "gtest/gtest.h"
#include "pw_kvs/fake_flash_memory.h"

namespace pw::kvs::internal {
namespace {

class SectorsTest : public ::testing::Test {
 protected:
  SectorsTest()
      : partition_(&flash_),
        sectors_(sector_descriptors_, partition_, nullptr) {
    EXPECT_EQ(0u, sectors_.size());
    sectors_.Reset();
  }

  FakeFlashMemoryBuffer<128, 16> flash_;
  FlashPartition partition_;
  Vector<SectorDescriptor, 32> sector_descriptors_;
  Sectors sectors_;
};

TEST_F(SectorsTest, Reset) {
  // Reset is done by the fixture.
  EXPECT_EQ(partition_.sector_count(), sectors_.size());
  EXPECT_EQ(32u, sectors_.max_size());
  EXPECT_EQ(sectors_.begin(), sectors_.last_new());
}

TEST_F(SectorsTest, LastNew) {
  sectors_.set_last_new_sector(130);
  EXPECT_EQ(128u, sectors_.BaseAddress(*sectors_.last_new()));
}

TEST_F(SectorsTest, AddressInSector) {
  SectorDescriptor& sector = sectors_.FromAddress(128);

  EXPECT_FALSE(sectors_.AddressInSector(sector, 127));
  for (size_t address = 128; address < 256; ++address) {
    EXPECT_TRUE(sectors_.AddressInSector(sector, address));
  }
  EXPECT_FALSE(sectors_.AddressInSector(sector, 256));
  EXPECT_FALSE(sectors_.AddressInSector(sector, 1025));
}

TEST_F(SectorsTest, BaseAddressAndFromAddress) {
  for (size_t address = 0; address < 128; ++address) {
    EXPECT_EQ(0u, sectors_.BaseAddress(sectors_.FromAddress(address)));
  }
  for (size_t address = 128; address < 256; ++address) {
    EXPECT_EQ(128u, sectors_.BaseAddress(sectors_.FromAddress(address)));
  }
  for (size_t address = 256; address < 384; ++address) {
    EXPECT_EQ(256u, sectors_.BaseAddress(sectors_.FromAddress(address)));
  }
}

TEST_F(SectorsTest, NextWritableAddress_EmptySector) {
  EXPECT_EQ(0u, sectors_.NextWritableAddress(*sectors_.begin()));
}

TEST_F(SectorsTest, NextWritableAddress_PartiallyWrittenSector) {
  sectors_.begin()->RemoveWritableBytes(123);
  EXPECT_EQ(123u, sectors_.NextWritableAddress(*sectors_.begin()));
}

// TODO: Add tests for FindSpace, FindSpaceDuringGarbageCollection, and
// FindSectorToGarbageCollect.

}  // namespace
}  // namespace pw::kvs::internal
<|endoftext|>


<commit_before>//vbSort.cpp
//Copyright (c) 2015 mmYYmmdd
#include "stdafx.h"
#include <algorithm>
#include "VBA_NestFunc.hpp"

//比較関数
class compareByVBAfunc   {
    VARIANT*    begin;
    std::shared_ptr<functionExpr> comp;
public:
    compareByVBAfunc(VARIANT* pA, VARIANT* f) : begin(pA), comp(std::make_shared<functionExpr>(f))
    {    }
    bool valid() const  { return static_cast<bool>(comp);  }
    bool operator ()(__int32 i, __int32 j) const
    {
        return comp->eval(begin + i, begin + j)->lVal ? true: false;
    }
};

//1次元昇順
class compFunctor  {
    VARIANT*    begin;
public:
    compFunctor(VARIANT* pA) : begin(pA) { }
    bool operator ()(__int32 i, __int32 j) const
    {
        return VARCMP_LT == VarCmp(begin + i, begin + j, LANG_JAPANESE, 0);
    }
};

//2次元昇順
class compDictionaryFunctor  {
    VARIANT*    begin;
public:
    compDictionaryFunctor(VARIANT* pA) : begin(pA) { }
    bool operator ()(__int32 i, __int32 j) const
    {
        safearrayRef arr1(begin + i);
        safearrayRef arr2(begin + j);
        if ( arr1.getDim() == 1 || arr2.getDim() == 1 )     return false;
        for ( ULONG k = 0; k < arr1.getSize(1) && k < arr2.getSize(1); ++k )
        {
            if ( VARCMP_LT == VarCmp(&arr1(k), &arr2(k), LANG_JAPANESE, 0) )
                return true;
            if ( VARCMP_LT == VarCmp(&arr2(k), &arr1(k), LANG_JAPANESE, 0) )
                return false;
        }
        return false;
    }
};

VARIANT __stdcall stdsort(VARIANT* array, __int32 defaultFlag, VARIANT* pComp)
{
    VARIANT      ret;
    ::VariantInit(&ret);
    safearrayRef arrIn(array);
    if ( 1 != arrIn.getDim() )          return ret;
    auto index = std::make_unique<__int32[]>(arrIn.getSize(1));
    auto VArray = std::make_unique<VARIANT[]>(arrIn.getSize(1));
    for (std::size_t i = 0; i < arrIn.getSize(1); ++i)
    {
        index[i] = static_cast<__int32>(i);
        ::VariantInit(&VArray[i]);
        ::VariantCopyInd(&VArray[i], &arrIn(i));
    }
    if ( defaultFlag == 1 ) //1次元昇順
    {
        compFunctor   functor(VArray.get());
        std::sort(index.get(), index.get() + arrIn.getSize(1), functor);
    }
    else if ( defaultFlag == 2 ) //2次元昇順
    {
        compDictionaryFunctor   functor(VArray.get());
        std::sort(index.get(), index.get() + arrIn.getSize(1), functor);
    }
    else if ( pComp )
    {
        compareByVBAfunc functor(VArray.get(), pComp);
        if ( functor.valid() )
            std::sort(index.get(), index.get() + arrIn.getSize(1), functor);
    }
    //-------------------------------------------------------
    SAFEARRAYBOUND boundRet = { static_cast<ULONG>(arrIn.getSize(1)), 0};   //要素数、LBound
    ret.vt = VT_ARRAY | VT_VARIANT;
    ret.parray = ::SafeArrayCreate(VT_VARIANT, 1, &boundRet);
    safearrayRef arrOut(&ret);
    VARIANT elem;
    ::VariantInit(&elem);
    elem.vt = VT_I4;
    for ( std::size_t i = 0; i < arrIn.getSize(1); ++i )
    {
        elem.lVal = static_cast<LONG>(index[i] + arrIn.getOriginalLBound(1));
        ::VariantCopy(&arrOut(i), &elem);
    }
    return      ret;
}
<commit_msg>リファクタリング ： コピーコンストラクタ = default; など<commit_after>//vbSort.cpp
//Copyright (c) 2015 mmYYmmdd
#include "stdafx.h"
#include <algorithm>
#include "VBA_NestFunc.hpp"

//比較関数
class compareByVBAfunc   {
    VARIANT*    begin;
    std::shared_ptr<functionExpr> comp;
public:
    compareByVBAfunc(VARIANT* pA, VARIANT* f) : begin(pA), comp(std::make_shared<functionExpr>(f))
    {    }
    compareByVBAfunc(compareByVBAfunc const&) = default;
    compareByVBAfunc(compareByVBAfunc&&) = delete;
    ~compareByVBAfunc() = default;
    bool valid() const  { return static_cast<bool>(comp);  }
    bool operator ()(__int32 i, __int32 j) const
    {
        return comp->eval(begin + i, begin + j)->lVal ? true: false;
    }
};

//1次元昇順
class compFunctor  {
    VARIANT*    begin;
public:
    explicit compFunctor(VARIANT* pA) : begin(pA) { }
    compFunctor(compFunctor const&) = default;
    compFunctor(compFunctor&&) = delete;
    ~compFunctor() = default;
    bool operator ()(__int32 i, __int32 j) const
    {
        return VARCMP_LT == VarCmp(begin + i, begin + j, LANG_JAPANESE, 0);
    }
};

//2次元昇順
class compDictionaryFunctor  {
    VARIANT*    begin;
public:
    explicit compDictionaryFunctor(VARIANT* pA) : begin(pA) { }
    compDictionaryFunctor(compDictionaryFunctor const&) = default;
    compDictionaryFunctor(compDictionaryFunctor&&) = delete;
    ~compDictionaryFunctor() = default;
    bool operator ()(__int32 i, __int32 j) const
    {
        safearrayRef arr1(begin + i);
        safearrayRef arr2(begin + j);
        if ( arr1.getDim() == 1 || arr2.getDim() == 1 )     return false;
        for ( ULONG k = 0; k < arr1.getSize(1) && k < arr2.getSize(1); ++k )
        {
            if ( VARCMP_LT == VarCmp(&arr1(k), &arr2(k), LANG_JAPANESE, 0) )
                return true;
            if ( VARCMP_LT == VarCmp(&arr2(k), &arr1(k), LANG_JAPANESE, 0) )
                return false;
        }
        return false;
    }
};

VARIANT __stdcall stdsort(VARIANT* array, __int32 defaultFlag, VARIANT* pComp)
{
    VARIANT      ret;
    ::VariantInit(&ret);
    safearrayRef arrIn(array);
    if ( 1 != arrIn.getDim() )          return ret;
    auto index = std::make_unique<__int32[]>(arrIn.getSize(1));
    auto VArray = std::make_unique<VARIANT[]>(arrIn.getSize(1));
    for (std::size_t i = 0; i < arrIn.getSize(1); ++i)
    {
        index[i] = static_cast<__int32>(i);
        ::VariantInit(&VArray[i]);
        ::VariantCopyInd(&VArray[i], &arrIn(i));
    }
    if ( defaultFlag == 1 ) //1次元昇順
    {
        compFunctor   functor(VArray.get());
        std::sort(index.get(), index.get() + arrIn.getSize(1), functor);
    }
    else if ( defaultFlag == 2 ) //2次元昇順
    {
        compDictionaryFunctor   functor(VArray.get());
        std::sort(index.get(), index.get() + arrIn.getSize(1), functor);
    }
    else if ( pComp )
    {
        compareByVBAfunc functor(VArray.get(), pComp);
        if ( functor.valid() )
            std::sort(index.get(), index.get() + arrIn.getSize(1), functor);
    }
    //-------------------------------------------------------
    SAFEARRAYBOUND boundRet = { static_cast<ULONG>(arrIn.getSize(1)), 0};   //要素数、LBound
    ret.vt = VT_ARRAY | VT_VARIANT;
    ret.parray = ::SafeArrayCreate(VT_VARIANT, 1, &boundRet);
    safearrayRef arrOut(&ret);
    VARIANT elem;
    ::VariantInit(&elem);
    elem.vt = VT_I4;
    for ( std::size_t i = 0; i < arrIn.getSize(1); ++i )
    {
        elem.lVal = static_cast<LONG>(index[i] + arrIn.getOriginalLBound(1));
        ::VariantCopy(&arrOut(i), &elem);
    }
    return      ret;
}
<|endoftext|>


<commit_before>/* symtable.cc
 * Hash table representing the symbol table.
 * the symbol table.
 * UIdaho CS445 120++ Compiler
 * author: Chris Waltrip <walt2178@vandals.uidaho.edu>
 */
#include <iostream>
#include <sstream>
#include <string>

#include "symtable.hh"
#include "exception.hh"

/*
AbstractSymbol::AbstractSymbol(std::string n, TypenameEntry t)
			: name(n), type(t) { }
*/
AbstractSymbol::AbstractSymbol(std::string n, std::string t)
			: name(n), type(t) { }
std::string AbstractSymbol::to_string(std::size_t depth) {
	std::string spaces = std::string(depth, '>');
	return(spaces + this->type + " " + this->name);
}

/*
 * The only time that SymbolTable's parent will be NULL is the Global Symbol
 * Table.  Given this and the n-ary tree (represented using std::deque),
 * resolving scope should be relatively simple.
 */
SymbolTable::SymbolTable(SymbolTable *p) {
	this->parent = p;
}

/*
 * Just a wrapper function for nesting scopes.
 */
void SymbolTable::add_sub_table(SymbolTable *k) {
	this->kids.push_back(k);
}
/*
 * This hashing method is identical to the Typename Table hash method.
 */
std::size_t SymbolTable::hash(std::string name) {
	std::size_t hash = 0;
	const char* s = name.c_str();
	while(*s) {
		hash = hash * 101 + *s++;
	}
	return hash % this->HASHTABLE_SIZE;
}

bool SymbolTable::insert(std::string n, AbstractSymbol *s) {
	if(!this->symbol_exists(n)) {
		std::size_t h = this->hash(n);
		this->bucket[h].push_back(s);
		return true;
	}
	throw EDuplicateSymbol();
	return false; /* Remove after refactor */
}

bool SymbolTable::empty() {
	for(std::size_t i = 0; i < this->HASHTABLE_SIZE; ++i) {
		if(!this->bucket[i].empty())
			return false;
	}
	return true;
}

AbstractSymbol* SymbolTable::get_symbol(std::string name) {
	std::size_t h = this->hash(name);
	std::deque<AbstractSymbol*> b = this->bucket[h];
	std::deque<AbstractSymbol*>::iterator it;
	for(it = b.begin(); it != b.end(); ++it) {
		std::size_t i = it - b.begin();
		if(*(b[i]) == name) {
			return b[i];
		}
	}
	throw ENoSymbolEntry();
}

/*
 * Tries to get the symbol from the current scope.  If get_symbol throws an
 * ENoSymbolEntry, then the current scope doesn't have the symbol that is
 * being search for.  If the parent symbol table is NULL then we have reached
 * the global symbol table and the symbol doesn't exist so throw
 * ENoSymbolEntry again and let the calling function handle the exception. If
 * the symbol is found, it's returned.
 */
AbstractSymbol* SymbolTable::get_scoped_symbol(std::string name) {
	AbstractSymbol *symb;
	try {
		symb = this->get_symbol(name);
		return symb;
	} catch(ENoSymbolEntry e) {
		if(this->parent == NULL) {
			throw ENoSymbolEntry();
		} else {
			/* Will never be NULL because exception is thrown */
			return this->parent->get_scoped_symbol(name);
		}
	}
}

/*
 * Will return true if a symbol is found.  If get_symbol throws
 * an ENoSymbolEntry exception, then the symbol isn't in the symbol
 * table.  This only checks for the existance in the local symbol table.
 */
bool SymbolTable::symbol_exists(std::string name) {
	try {
		this->get_symbol(name);
	} catch(ENoSymbolEntry e) {
		return false;
	}
	return true;
}

void SymbolTable::print_table(std::size_t depth) {
	std::clog << this->to_string(depth) << std::endl;
}

std::string SymbolTable::to_string(std::size_t depth) {
	std::stringstream ss;
	for(std::size_t i = 0; i < this->HASHTABLE_SIZE; ++i) {
		std::deque<AbstractSymbol*> b = this->bucket[i];
		std::deque<AbstractSymbol*>::iterator it;
		for(it = b.begin(); it != b.end(); ++it) {\
			std::size_t index = it - b.begin();
			ss << (*(b[i]))->to_string(depth) << std::endl;
			//ss << (*it)->to_string(depth) << std::endl;
		}
	}
	return ss.str();
}

/* Basic Symbol constructor */
BasicSymbol::BasicSymbol(std::string n, std::string t, bool p)
				: AbstractSymbol(n,t), pointer(p) { }

/* Function symbol constructor */
FunctionSymbol::FunctionSymbol(std::string n, std::string t, bool p, bool d)
				: AbstractSymbol(n,t), pointer(p),
				def_needed(d) { }

std::string FunctionSymbol::to_string(std::size_t depth) {
	std::stringstream ss;
	ss << AbstractSymbol::to_string(depth) << std::endl;
	ss << this->params.to_string(depth+1) << std::endl;
	ss << this->locals.to_string(depth+1) << std::endl;
	return ss.str();
}<commit_msg>Fixing segfault when referencing iterator<commit_after>/* symtable.cc
 * Hash table representing the symbol table.
 * the symbol table.
 * UIdaho CS445 120++ Compiler
 * author: Chris Waltrip <walt2178@vandals.uidaho.edu>
 */
#include <iostream>
#include <sstream>
#include <string>

#include "symtable.hh"
#include "exception.hh"

/*
AbstractSymbol::AbstractSymbol(std::string n, TypenameEntry t)
			: name(n), type(t) { }
*/
AbstractSymbol::AbstractSymbol(std::string n, std::string t)
			: name(n), type(t) { }
std::string AbstractSymbol::to_string(std::size_t depth) {
	std::string spaces = std::string(depth, '>');
	return(spaces + this->type + " " + this->name);
}

/*
 * The only time that SymbolTable's parent will be NULL is the Global Symbol
 * Table.  Given this and the n-ary tree (represented using std::deque),
 * resolving scope should be relatively simple.
 */
SymbolTable::SymbolTable(SymbolTable *p) {
	this->parent = p;
}

/*
 * Just a wrapper function for nesting scopes.
 */
void SymbolTable::add_sub_table(SymbolTable *k) {
	this->kids.push_back(k);
}
/*
 * This hashing method is identical to the Typename Table hash method.
 */
std::size_t SymbolTable::hash(std::string name) {
	std::size_t hash = 0;
	const char* s = name.c_str();
	while(*s) {
		hash = hash * 101 + *s++;
	}
	return hash % this->HASHTABLE_SIZE;
}

bool SymbolTable::insert(std::string n, AbstractSymbol *s) {
	if(!this->symbol_exists(n)) {
		std::size_t h = this->hash(n);
		this->bucket[h].push_back(s);
		return true;
	}
	throw EDuplicateSymbol();
	return false; /* Remove after refactor */
}

bool SymbolTable::empty() {
	for(std::size_t i = 0; i < this->HASHTABLE_SIZE; ++i) {
		if(!this->bucket[i].empty())
			return false;
	}
	return true;
}

AbstractSymbol* SymbolTable::get_symbol(std::string name) {
	std::size_t h = this->hash(name);
	std::deque<AbstractSymbol*> b = this->bucket[h];
	std::deque<AbstractSymbol*>::iterator it;
	for(it = b.begin(); it != b.end(); ++it) {
		std::size_t i = it - b.begin();
		if(*(b[i]) == name) {
			return b[i];
		}
	}
	throw ENoSymbolEntry();
}

/*
 * Tries to get the symbol from the current scope.  If get_symbol throws an
 * ENoSymbolEntry, then the current scope doesn't have the symbol that is
 * being search for.  If the parent symbol table is NULL then we have reached
 * the global symbol table and the symbol doesn't exist so throw
 * ENoSymbolEntry again and let the calling function handle the exception. If
 * the symbol is found, it's returned.
 */
AbstractSymbol* SymbolTable::get_scoped_symbol(std::string name) {
	AbstractSymbol *symb;
	try {
		symb = this->get_symbol(name);
		return symb;
	} catch(ENoSymbolEntry e) {
		if(this->parent == NULL) {
			throw ENoSymbolEntry();
		} else {
			/* Will never be NULL because exception is thrown */
			return this->parent->get_scoped_symbol(name);
		}
	}
}

/*
 * Will return true if a symbol is found.  If get_symbol throws
 * an ENoSymbolEntry exception, then the symbol isn't in the symbol
 * table.  This only checks for the existance in the local symbol table.
 */
bool SymbolTable::symbol_exists(std::string name) {
	try {
		this->get_symbol(name);
	} catch(ENoSymbolEntry e) {
		return false;
	}
	return true;
}

void SymbolTable::print_table(std::size_t depth) {
	std::clog << this->to_string(depth) << std::endl;
}

std::string SymbolTable::to_string(std::size_t depth) {
	std::stringstream ss;
	for(std::size_t i = 0; i < this->HASHTABLE_SIZE; ++i) {
		std::deque<AbstractSymbol*> b = this->bucket[i];
		std::deque<AbstractSymbol*>::iterator it;
		for(it = b.begin(); it != b.end(); ++it) {\
			std::size_t index = it - b.begin();
			ss << (*(b[i])).to_string(depth) << std::endl;
			//ss << (*it)->to_string(depth) << std::endl;
		}
	}
	return ss.str();
}

/* Basic Symbol constructor */
BasicSymbol::BasicSymbol(std::string n, std::string t, bool p)
				: AbstractSymbol(n,t), pointer(p) { }

/* Function symbol constructor */
FunctionSymbol::FunctionSymbol(std::string n, std::string t, bool p, bool d)
				: AbstractSymbol(n,t), pointer(p),
				def_needed(d) { }

std::string FunctionSymbol::to_string(std::size_t depth) {
	std::stringstream ss;
	ss << AbstractSymbol::to_string(depth) << std::endl;
	ss << this->params.to_string(depth+1) << std::endl;
	ss << this->locals.to_string(depth+1) << std::endl;
	return ss.str();
}<|endoftext|>


<commit_before>#include "google/protobuf/descriptor.h"
#include "boost/system/error_code.hpp"

#include "vtrc-exception.h"
#include "vtrc-errors.pb.h"

namespace vtrc { namespace common {

    namespace gpb = google::protobuf;

    namespace {

        const std::string unknown_error("Unknown error");

        const std::string &get_internal_error( unsigned code )
        {
            const gpb::EnumValueDescriptor *ev =
                vtrc_errors::errors_numbers_descriptor( )
                                ->FindValueByNumber( code );
            if( ev ) {
                return ev->options( ).GetExtension( vtrc_errors::description );
            }
            return unknown_error;
        }

        std::string get_error_code_string( unsigned code, unsigned category )
        {
            if( category == vtrc_errors::CATEGORY_INTERNAL ) {
                return get_internal_error( code );
            } else if( category == vtrc_errors::CATEGORY_SYSTEM ) {
                try {
                    boost::system::error_code ec(code,
                                             boost::system::system_category( ));
                    return ec.message( );
                } catch( const std::exception &ex ) {
                    return ex.what( );
                }
            }
            return unknown_error;
        }

        std::string get_error_code_string( unsigned code )
        {
            return get_error_code_string(code, vtrc_errors::CATEGORY_INTERNAL);
        }

    }

    exception::exception( unsigned code, unsigned code_category )
        :std::runtime_error(get_error_code_string(code, code_category))
        ,code_(code)
        ,category_(code_category)
    {

    }

    exception::exception(unsigned code,
                         unsigned code_category,
                         const std::string &additional)
        :std::runtime_error(get_error_code_string(code, code_category))
        ,code_(code)
        ,category_(code_category)
        ,additional_(additional)
    {

    }

    exception::exception( unsigned code )
        :std::runtime_error(get_error_code_string(code))
        ,code_(code)
        ,category_(vtrc_errors::CATEGORY_INTERNAL)
    { }

    exception::exception( unsigned code, const std::string &additional )
        :std::runtime_error(get_error_code_string(code))
        ,code_(code)
        ,category_(vtrc_errors::CATEGORY_INTERNAL)
        ,additional_(additional)
    { }

    exception::~exception( ) throw ( )
    { }

    const char *exception::additional( ) const
    {
        return additional_.c_str( );
    }

    unsigned exception::code( ) const
    {
        return code_;
    }

    unsigned exception::category( ) const
    {
        return category_;
    }

}}
<commit_msg>exceptions<commit_after>#include "google/protobuf/descriptor.h"
#include "boost/system/error_code.hpp"

#include "vtrc-exception.h"
#include "vtrc-errors.pb.h"

namespace vtrc { namespace common {

    namespace gpb = google::protobuf;

    namespace {

        const std::string unknown_error("Unknown error");
        const unsigned default_category = vtrc_errors::CATEGORY_INTERNAL;

        const std::string &get_internal_error( unsigned code )
        {
            const gpb::EnumValueDescriptor *ev =
                vtrc_errors::errors_numbers_descriptor( )
                                ->FindValueByNumber( code );
            if( ev ) {
                return ev->options( ).GetExtension( vtrc_errors::description );
            }
            return unknown_error;
        }

        std::string get_error_code_string( unsigned code, unsigned category )
        {
            if( category == vtrc_errors::CATEGORY_INTERNAL ) {
                return get_internal_error( code );
            } else if( category == vtrc_errors::CATEGORY_SYSTEM ) {
                try {
                    boost::system::error_code ec(code,
                                             boost::system::system_category( ));
                    return ec.message( );
                } catch( const std::exception &ex ) {
                    return ex.what( );
                }
            }
            return unknown_error;
        }

        std::string get_error_code_string( unsigned code )
        {
            return get_error_code_string( code, default_category );
        }

    }

    exception::exception( unsigned code, unsigned code_category )
        :std::runtime_error(get_error_code_string(code, code_category))
        ,code_(code)
        ,category_(code_category)
    {

    }

    exception::exception(unsigned code,
                         unsigned code_category,
                         const std::string &additional)
        :std::runtime_error(get_error_code_string(code, code_category))
        ,code_(code)
        ,category_(code_category)
        ,additional_(additional)
    { }

    exception::exception( unsigned code )
        :std::runtime_error(get_error_code_string(code))
        ,code_(code)
        ,category_(default_category)
    { }

    exception::exception( unsigned code, const std::string &additional )
        :std::runtime_error(get_error_code_string(code))
        ,code_(code)
        ,category_(default_category)
        ,additional_(additional)
    { }

    exception::~exception( ) throw ( )
    { }

    const char *exception::additional( ) const
    {
        return additional_.c_str( );
    }

    unsigned exception::code( ) const
    {
        return code_;
    }

    unsigned exception::category( ) const
    {
        return category_;
    }

}}
<|endoftext|>


<commit_before>#include <vector>
#include <utility>
#include <algorithm>
#include <functional>
#include <unordered_set>
#include "tokenizer.h"
#include "shl_exception.h"

using std::stack;
using std::function;
using std::unordered_set;

namespace shl {

vector<pair<Range, Scope> > Tokenizer::tokenize(const Grammar& grammar, const string& text) {
    vector<pair<Range, Scope> > tokens;
    vector<const Pattern*> pattern_stack;

    tokens.push_back(std::make_pair(Range(0, text.size()), Scope(grammar.name)));
    tokenize(text, grammar, Match::make_dummy(0,0), pattern_stack, tokens);

    return tokens;
}

void for_all_subrules(const vector<Pattern>& root, function<void(const Pattern&)> callback, int max_depth) {
    if (max_depth <= 0) return;

    for (const auto& pattern : root) {
        const Pattern& pat = (pattern.include != nullptr)? *pattern.include : pattern;
        if (pattern.begin.empty()) {
            for_all_subrules(root, callback, max_depth - 1);
        } else {
            callback(pat);
        }
    }
}
void for_all_subrules(const vector<Pattern>& patterns, function<void(const Pattern&)> callback) {
    // Define containing pattern to be below
    // { patterns: [ {}, {} ] }
    // it have no match/begin but only patterns
    // There can't be 2 containing patterns as parent and child
    // so we set the max_depth to be 2
    for_all_subrules(patterns, callback, 2);
}

/**
 * Find the next lexeme iteratively
 *
 * This method find the next lexeme by matching all begin field of the sub-patterns
 * of current rule, and its own end field, whichever comes first will be seleteced
 *
 * When true returned, found will contain the selected next pattern, and match will hold
 * the results. When false returned, there are 3 scenarios:
 * 1. end field is matched, found & match contains results
 * 2. current pattern is toplevel rule, so no end field, found is nullptr
 * 3. When nothing can be matched(either source text or syntax definition is invalid),
 *    and user specified OPTION_TOLERATE_ERROR, found will be nullptr, otherwise exception
 *    will be thrown
 */
bool Tokenizer::next_lexeme(const string& text, const Match& begin_lexeme, const Pattern& pattern, const Pattern** found, Match& match) {
    int pos = begin_lexeme[0].end();
    const Pattern* found_pattern = nullptr;
    Match first_match;
    bool is_close = false;

    // first find pattern or end pattern, whichever comes first
    for_all_subrules(pattern.patterns, [&found_pattern, &first_match, pos, &text](const Pattern& pattern) {
        const Pattern& sub_pattern = (pattern.include == nullptr)? pattern : *pattern.include;

        Match tmp = sub_pattern.begin.match(text, pos);
        if (tmp != Match::NOT_MATCHED) {
            if( found_pattern == nullptr || tmp[0].position < first_match[0].position) {
                first_match = std::move(tmp);
                found_pattern = &sub_pattern;
            }
        }
    });
    if (!pattern.end.empty()) {
        Match tmp = pattern.end.match(text, pos);
        if (tmp != Match::NOT_MATCHED) {
            if( found_pattern == nullptr || tmp[0].position < first_match[0].position) {
                first_match = std::move(tmp);
                found_pattern = &pattern;
                is_close = true;
            }
        }
    }
    if ( found_pattern != nullptr) {
        *found = found_pattern;
        match = first_match;
        return !is_close;
    }

    // special handle for toplevel rule
    if (pattern.end.empty()) {
        // all rule with begin will has an end, which is enforced by grammar loader
        // so only toplevel rules can be here
        *found = nullptr;
        is_close = true;
        return false;
    }

    // When no lexeme found
    if (_option & OPTION_TOLERATE_ERROR) {
        *found = nullptr;
        return false;
    } else {
       throw InvalidSourceException("scope not properly closed");
    }
}

vector<string> get_name(vector<const Pattern*>& stack, const string& name) {
    vector<string> names;

    for(auto pattern : stack) {
        names.push_back(pattern->name);
    }
    names.push_back(name);

    return names;
}

void Tokenizer::add_scope(vector<pair<Range, Scope> >& tokens, const Range& range, vector<const Pattern*>& stack, const string& name) {
    if (name.empty()) return;

    Scope scope(get_name(stack, name));
    tokens.push_back(std::make_pair(range, scope));
}

inline void append_back(vector<pair<Range, Scope> >& target, const vector<pair<Range, Scope> >& source ) {
    std::move(source.begin(), source.end(), std::back_inserter(target));
}

void Tokenizer::process_capture(vector<pair<Range, Scope> >& tokens, const Match& match, vector<const Pattern*>& stack, const map<int, string>& capture) {
    for (auto& pair : capture) {
        unsigned int capture_num = pair.first;
        const string& name = pair.second;
        if (match.size() > capture_num) {
            add_scope(tokens, match[capture_num], stack, name);
        } else {
            if ((_option & OPTION_TOLERATE_ERROR) == 0) {
                throw InvalidSourceException("capture number out of range");
            }
        }
    }
}

Match Tokenizer::tokenize(const string& text, const Pattern& pattern, const Match& begin_lexeme, vector<const Pattern*>& stack, vector<pair<Range, Scope> >& tokens) {
    stack.push_back(&pattern);

    const Pattern* found_pattern = nullptr;
    Match last_lexeme, match;
    last_lexeme = begin_lexeme;
    while(next_lexeme(text, last_lexeme, pattern, &found_pattern, match)) {
        if (found_pattern->is_match_rule) {
            add_scope(tokens, match[0], stack, found_pattern->name);
            process_capture(tokens, match, stack, found_pattern->captures);
            last_lexeme = match;

        } else {
            vector<pair<Range, Scope> > child_tokens;

            Match end_match = tokenize(text, *found_pattern, match, stack, child_tokens);

            Range name_range = Range(match[0].position, end_match[0].end() - match[0].position);
            add_scope(tokens, name_range, stack, "");
            process_capture(tokens, match, stack, found_pattern->begin_captures);

            Range content_range = Range(match[0].end(), end_match[0].position - match[0].end());
            add_scope(tokens, content_range, stack, found_pattern->content_name);

            append_back(tokens, child_tokens);
            process_capture(tokens, match, stack, found_pattern->end_captures);
            last_lexeme = end_match;
        }
    }

    stack.pop_back();

    if ( found_pattern == nullptr) { //see comments for next_lexeme
        return last_lexeme;
    } else {
        return match;
    }

}

}
<commit_msg>bug fix 2<commit_after>#include <vector>
#include <utility>
#include <algorithm>
#include <functional>
#include <unordered_set>
#include "tokenizer.h"
#include "shl_exception.h"

using std::stack;
using std::function;
using std::unordered_set;

namespace shl {

vector<pair<Range, Scope> > Tokenizer::tokenize(const Grammar& grammar, const string& text) {
    vector<pair<Range, Scope> > tokens;
    vector<const Pattern*> pattern_stack;

    tokens.push_back(std::make_pair(Range(0, text.size()), Scope(grammar.name)));
    tokenize(text, grammar, Match::make_dummy(0,0), pattern_stack, tokens);

    return tokens;
}

void for_all_subrules(const vector<Pattern>& root, function<void(const Pattern&)> callback, int max_depth) {
    if (max_depth <= 0) return;

    for (const auto& pattern : root) {
        const Pattern& pat = (pattern.include != nullptr)? *pattern.include : pattern;
        if (pat.begin.empty()) {
            for_all_subrules(pat.patterns, callback, max_depth - 1);
        } else {
            callback(pat);
        }
    }
}
void for_all_subrules(const vector<Pattern>& patterns, function<void(const Pattern&)> callback) {
    // Define containing pattern to be below
    // { patterns: [ {}, {} ] }
    // it have no match/begin but only patterns
    // There can't be 2 containing patterns as parent and child
    // so we set the max_depth to be 2
    for_all_subrules(patterns, callback, 2);
}

/**
 * Find the next lexeme iteratively
 *
 * This method find the next lexeme by matching all begin field of the sub-patterns
 * of current rule, and its own end field, whichever comes first will be seleteced
 *
 * When true returned, found will contain the selected next pattern, and match will hold
 * the results. When false returned, there are 3 scenarios:
 * 1. end field is matched, found & match contains results
 * 2. current pattern is toplevel rule, so no end field, found is nullptr
 * 3. When nothing can be matched(either source text or syntax definition is invalid),
 *    and user specified OPTION_TOLERATE_ERROR, found will be nullptr, otherwise exception
 *    will be thrown
 */
bool Tokenizer::next_lexeme(const string& text, const Match& begin_lexeme, const Pattern& pattern, const Pattern** found, Match& match) {
    int pos = begin_lexeme[0].end();
    const Pattern* found_pattern = nullptr;
    Match first_match;
    bool is_close = false;

    // first find pattern or end pattern, whichever comes first
    for_all_subrules(pattern.patterns, [&found_pattern, &first_match, pos, &text](const Pattern& sub_pattern) {
        Match tmp = sub_pattern.begin.match(text, pos);
        if (tmp != Match::NOT_MATCHED) {
            if( found_pattern == nullptr || tmp[0].position < first_match[0].position) {
                first_match = std::move(tmp);
                found_pattern = &sub_pattern;
            }
        }
    });
    if (!pattern.end.empty()) {
        Match tmp = pattern.end.match(text, pos);
        if (tmp != Match::NOT_MATCHED) {
            if( found_pattern == nullptr || tmp[0].position < first_match[0].position) {
                first_match = std::move(tmp);
                found_pattern = &pattern;
                is_close = true;
            }
        }
    }
    if ( found_pattern != nullptr) {
        *found = found_pattern;
        match = first_match;
        return !is_close;
    }

    // special handle for toplevel rule
    if (pattern.end.empty()) {
        // all rule with begin will has an end, which is enforced by grammar loader
        // so only toplevel rules can be here
        *found = nullptr;
        is_close = true;
        return false;
    }

    // When no lexeme found
    if (_option & OPTION_TOLERATE_ERROR) {
        *found = nullptr;
        return false;
    } else {
       throw InvalidSourceException("scope not properly closed");
    }
}

vector<string> get_name(vector<const Pattern*>& stack, const string& name) {
    vector<string> names;

    for(auto pattern : stack) {
        names.push_back(pattern->name);
    }
    names.push_back(name);

    return names;
}

void Tokenizer::add_scope(vector<pair<Range, Scope> >& tokens, const Range& range, vector<const Pattern*>& stack, const string& name) {
    if (name.empty()) return;

    Scope scope(get_name(stack, name));
    tokens.push_back(std::make_pair(range, scope));
}

inline void append_back(vector<pair<Range, Scope> >& target, const vector<pair<Range, Scope> >& source ) {
    std::move(source.begin(), source.end(), std::back_inserter(target));
}

void Tokenizer::process_capture(vector<pair<Range, Scope> >& tokens, const Match& match, vector<const Pattern*>& stack, const map<int, string>& capture) {
    for (auto& pair : capture) {
        unsigned int capture_num = pair.first;
        const string& name = pair.second;
        if (match.size() > capture_num) {
            add_scope(tokens, match[capture_num], stack, name);
        } else {
            if ((_option & OPTION_TOLERATE_ERROR) == 0) {
                throw InvalidSourceException("capture number out of range");
            }
        }
    }
}

Match Tokenizer::tokenize(const string& text, const Pattern& pattern, const Match& begin_lexeme, vector<const Pattern*>& stack, vector<pair<Range, Scope> >& tokens) {
    stack.push_back(&pattern);

    const Pattern* found_pattern = nullptr;
    Match last_lexeme, match;
    last_lexeme = begin_lexeme;
    while(next_lexeme(text, last_lexeme, pattern, &found_pattern, match)) {
        if (found_pattern->is_match_rule) {
            add_scope(tokens, match[0], stack, found_pattern->name);
            process_capture(tokens, match, stack, found_pattern->captures);
            last_lexeme = match;

        } else {
            vector<pair<Range, Scope> > child_tokens;

            Match end_match = tokenize(text, *found_pattern, match, stack, child_tokens);

            Range name_range = Range(match[0].position, end_match[0].end() - match[0].position);
            add_scope(tokens, name_range, stack, found_pattern->name);
            process_capture(tokens, match, stack, found_pattern->begin_captures);

            Range content_range = Range(match[0].end(), end_match[0].position - match[0].end());
            add_scope(tokens, content_range, stack, found_pattern->content_name);

            append_back(tokens, child_tokens);
            process_capture(tokens, match, stack, found_pattern->end_captures);
            last_lexeme = end_match;
        }
    }

    stack.pop_back();

    if ( found_pattern == nullptr) { //see comments for next_lexeme
        return last_lexeme;
    } else {
        return match;
    }

}

}
<|endoftext|>


<commit_before>#include <cilantro/connected_component_segmentation.hpp>
#include <stack>

#include <iostream>

ConnectedComponentSegmentation::ConnectedComponentSegmentation(const std::vector<Eigen::Vector3f> &points, const std::vector<Eigen::Vector3f> &normals, const std::vector<Eigen::Vector3f> &colors)
        : points_(&points),
          normals_((normals.size() == points.size()) ? &normals : NULL),
          colors_((colors.size() == points.size()) ? &colors : NULL),
          kd_tree_(new KDTree(points)),
          kd_tree_owned_(true)
{}

ConnectedComponentSegmentation::ConnectedComponentSegmentation(const std::vector<Eigen::Vector3f> &points, const std::vector<Eigen::Vector3f> &normals, const std::vector<Eigen::Vector3f> &colors, const KDTree &kd_tree)
        : points_(&points),
          normals_((normals.size() == points.size()) ? &normals : NULL),
          colors_((colors.size() == points.size()) ? &colors : NULL),
          kd_tree_((KDTree*)&kd_tree),
          kd_tree_owned_(false)
{}

ConnectedComponentSegmentation::ConnectedComponentSegmentation(const PointCloud &cloud)
        : points_(&cloud.points),
          normals_((cloud.normals.size() == cloud.points.size()) ? &cloud.normals : NULL),
          colors_((cloud.colors.size() == cloud.points.size()) ? &cloud.colors : NULL),
          kd_tree_(new KDTree(cloud.points)),
          kd_tree_owned_(true)
{}

ConnectedComponentSegmentation::ConnectedComponentSegmentation(const PointCloud &cloud, const KDTree &kd_tree)
        : points_(&cloud.points),
          normals_((cloud.normals.size() == cloud.points.size()) ? &cloud.normals : NULL),
          colors_((cloud.colors.size() == cloud.points.size()) ? &cloud.colors : NULL),
          kd_tree_((KDTree*)&kd_tree),
          kd_tree_owned_(false)
{}

ConnectedComponentSegmentation::~ConnectedComponentSegmentation() {
    if (kd_tree_owned_) delete kd_tree_;
}

ConnectedComponentSegmentation& ConnectedComponentSegmentation::segment(std::vector<size_t> seeds_ind,
                                                                        float dist_thresh,
                                                                        float normal_angle_thresh,
                                                                        float color_diff_thresh,
                                                                        size_t min_segment_size,
                                                                        size_t max_segment_size)
{
    dist_thresh_ = dist_thresh;
    normal_angle_thresh_ = normal_angle_thresh;
    color_diff_thresh_ = color_diff_thresh;
    min_segment_size_ = min_segment_size;
    max_segment_size_ = max_segment_size;

    std::vector<bool> has_been_assigned(points_->size(), 0);

    std::vector<size_t> neighbors;
    std::vector<float> distances;

    component_indices_.clear();
    for (size_t i = 0; i < seeds_ind.size(); i++) {
        if (has_been_assigned[seeds_ind[i]]) continue;

        std::vector<size_t> curr_cc_ind;
        std::vector<bool> is_in_stack(points_->size(), 0);

        std::stack<size_t> seeds_stack;
        seeds_stack.push(seeds_ind[i]);
        is_in_stack[seeds_ind[i]] = 1;
        while (!seeds_stack.empty()) {
            size_t curr_seed = seeds_stack.top();
            seeds_stack.pop();

            has_been_assigned[curr_seed] = 1;
            curr_cc_ind.emplace_back(curr_seed);

            kd_tree_->radiusSearch((*points_)[curr_seed], dist_thresh_, neighbors, distances);

            for (size_t j = 0; j < neighbors.size(); j++) {
                if (is_similar_(curr_seed,neighbors[j]) && !is_in_stack[neighbors[j]]) {
                    seeds_stack.push(neighbors[j]);
                    is_in_stack[neighbors[j]] = 1;
                }
            }

        }

        if (curr_cc_ind.size() >= min_segment_size_ && curr_cc_ind.size() <= max_segment_size_) {
            component_indices_.emplace_back(curr_cc_ind);
        }
    }

    std::sort(component_indices_.begin(), component_indices_.end(), vector_size_comparator_);

    label_map_ = std::vector<size_t>(points_->size(), component_indices_.size());
    for (size_t i = 0; i < component_indices_.size(); i++) {
        for (size_t j = 0; j < component_indices_[i].size(); j++) {
            label_map_[component_indices_[i][j]] = i;
        }
    }

    return *this;
}

ConnectedComponentSegmentation& ConnectedComponentSegmentation::segment(float dist_thresh,
                                                                        float normal_angle_thresh,
                                                                        float color_diff_thresh,
                                                                        size_t min_segment_size,
                                                                        size_t max_segment_size)
{
    std::vector<size_t> seeds_ind(points_->size());
    for (size_t i = 0; i < seeds_ind.size(); i++) {
        seeds_ind[i] = i;
    }
    return segment(seeds_ind, dist_thresh, normal_angle_thresh, color_diff_thresh, min_segment_size, max_segment_size);
}
<commit_msg>Minor change<commit_after>#include <cilantro/connected_component_segmentation.hpp>
#include <stack>

#include <iostream>

ConnectedComponentSegmentation::ConnectedComponentSegmentation(const std::vector<Eigen::Vector3f> &points, const std::vector<Eigen::Vector3f> &normals, const std::vector<Eigen::Vector3f> &colors)
        : points_(&points),
          normals_((normals.size() == points.size()) ? &normals : NULL),
          colors_((colors.size() == points.size()) ? &colors : NULL),
          kd_tree_(new KDTree(points)),
          kd_tree_owned_(true)
{}

ConnectedComponentSegmentation::ConnectedComponentSegmentation(const std::vector<Eigen::Vector3f> &points, const std::vector<Eigen::Vector3f> &normals, const std::vector<Eigen::Vector3f> &colors, const KDTree &kd_tree)
        : points_(&points),
          normals_((normals.size() == points.size()) ? &normals : NULL),
          colors_((colors.size() == points.size()) ? &colors : NULL),
          kd_tree_((KDTree*)&kd_tree),
          kd_tree_owned_(false)
{}

ConnectedComponentSegmentation::ConnectedComponentSegmentation(const PointCloud &cloud)
        : points_(&cloud.points),
          normals_((cloud.normals.size() == cloud.points.size()) ? &cloud.normals : NULL),
          colors_((cloud.colors.size() == cloud.points.size()) ? &cloud.colors : NULL),
          kd_tree_(new KDTree(cloud.points)),
          kd_tree_owned_(true)
{}

ConnectedComponentSegmentation::ConnectedComponentSegmentation(const PointCloud &cloud, const KDTree &kd_tree)
        : points_(&cloud.points),
          normals_((cloud.normals.size() == cloud.points.size()) ? &cloud.normals : NULL),
          colors_((cloud.colors.size() == cloud.points.size()) ? &cloud.colors : NULL),
          kd_tree_((KDTree*)&kd_tree),
          kd_tree_owned_(false)
{}

ConnectedComponentSegmentation::~ConnectedComponentSegmentation() {
    if (kd_tree_owned_) delete kd_tree_;
}

ConnectedComponentSegmentation& ConnectedComponentSegmentation::segment(std::vector<size_t> seeds_ind,
                                                                        float dist_thresh,
                                                                        float normal_angle_thresh,
                                                                        float color_diff_thresh,
                                                                        size_t min_segment_size,
                                                                        size_t max_segment_size)
{
    dist_thresh_ = dist_thresh;
    normal_angle_thresh_ = normal_angle_thresh;
    color_diff_thresh_ = color_diff_thresh;
    min_segment_size_ = min_segment_size;
    max_segment_size_ = max_segment_size;

    std::vector<bool> has_been_assigned(points_->size(), false);

    std::vector<size_t> neighbors;
    std::vector<float> distances;

    component_indices_.clear();
    for (size_t i = 0; i < seeds_ind.size(); i++) {
        if (has_been_assigned[seeds_ind[i]]) continue;

        std::vector<size_t> curr_cc_ind;
        std::vector<bool> is_in_stack(points_->size(), 0);

        std::stack<size_t> seeds_stack;
        seeds_stack.push(seeds_ind[i]);
        is_in_stack[seeds_ind[i]] = 1;
        while (!seeds_stack.empty()) {
            size_t curr_seed = seeds_stack.top();
            seeds_stack.pop();

            has_been_assigned[curr_seed] = 1;
            curr_cc_ind.emplace_back(curr_seed);

            kd_tree_->radiusSearch((*points_)[curr_seed], dist_thresh_, neighbors, distances);

            for (size_t j = 0; j < neighbors.size(); j++) {
                if (is_similar_(curr_seed,neighbors[j]) && !is_in_stack[neighbors[j]]) {
                    seeds_stack.push(neighbors[j]);
                    is_in_stack[neighbors[j]] = 1;
                }
            }

        }

        if (curr_cc_ind.size() >= min_segment_size_ && curr_cc_ind.size() <= max_segment_size_) {
            component_indices_.emplace_back(curr_cc_ind);
        }
    }

    std::sort(component_indices_.begin(), component_indices_.end(), vector_size_comparator_);

    label_map_ = std::vector<size_t>(points_->size(), component_indices_.size());
    for (size_t i = 0; i < component_indices_.size(); i++) {
        for (size_t j = 0; j < component_indices_[i].size(); j++) {
            label_map_[component_indices_[i][j]] = i;
        }
    }

    return *this;
}

ConnectedComponentSegmentation& ConnectedComponentSegmentation::segment(float dist_thresh,
                                                                        float normal_angle_thresh,
                                                                        float color_diff_thresh,
                                                                        size_t min_segment_size,
                                                                        size_t max_segment_size)
{
    std::vector<size_t> seeds_ind(points_->size());
    for (size_t i = 0; i < seeds_ind.size(); i++) {
        seeds_ind[i] = i;
    }
    return segment(seeds_ind, dist_thresh, normal_angle_thresh, color_diff_thresh, min_segment_size, max_segment_size);
}
<|endoftext|>


<commit_before>// $Id: quadrature_gauss_2D.C,v 1.16 2004-11-30 23:00:21 roystgnr Exp $

// The libMesh Finite Element Library.
// Copyright (C) 2002-2004  Benjamin S. Kirk, John W. Peterson

// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License, or (at your option) any later version.

// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
// Lesser General Public License for more details.

// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA

// Local includes
#include "quadrature_gauss.h"
#include "quadrature_jacobi.h"

void QGauss::init_2D(const ElemType _type)
{
#if DIM > 1

  //-----------------------------------------------------------------------
  // 2D quadrature rules
  switch (_type)
    {

      //---------------------------------------------
      // Quadrilateral quadrature rules
    case QUAD4:
    case QUAD8:
    case QUAD9:
      {
	// We compute the 2D quadrature rule as a tensor
	// product of the 1D quadrature rule.
	QGauss q1D(1,_order);
	q1D.init(EDGE2);
	tensor_product_quad( q1D );
	return;
      }

      //---------------------------------------------
      // Triangle quadrature rules
    case TRI3:
    case TRI6:
      {
	switch(_order)
	  {
	  case CONSTANT:
	  case FIRST:
	    {
	      // Exact for linears
	      _points.resize(1);
	      _weights.resize(1);

	      _points[0](0) = .33333333333333333333333333333333;
	      _points[0](1) = .33333333333333333333333333333333;

	      _weights[0] = .5;

	      return;
	    }
	  case SECOND:
	    {
	      // Exact for quadratics
	      _points.resize(3);
	      _weights.resize(3);

	      _points[0](0) = .5;
	      _points[0](1) = .5;

	      _points[1](0) = 0.;
	      _points[1](1) = .5;

	      _points[2](0) = .5;
	      _points[2](1) = .0;

	      _weights[0] = 1./6.;
	      _weights[1] = 1./6.;
	      _weights[2] = 1./6.;

	      return;
	    }
	  case THIRD:
	    {
	      // Exact for cubics
	      _points.resize(4);
	      _weights.resize(4);

	      _points[0](0) = .33333333333333333333333333333333;
	      _points[0](1) = .33333333333333333333333333333333;

	      _points[1](0) = .2;
	      _points[1](1) = .6;

	      _points[2](0) = .2;
	      _points[2](1) = .2;

	      _points[3](0) = .6;
	      _points[3](1) = .2;

	      _weights[0] = -27./96.;
	      _weights[1] =  25./96.;
	      _weights[2] =  25./96.;
	      _weights[3] =  25./96.;

	      return;
	    }
	  case FOURTH:
	  case FIFTH:
	    {
	      // Exact for quintics
	      // Taken from "Quadrature on Simplices of Arbitrary
	      // Dimension" by Walkington
	      _points.resize(7);
	      _weights.resize(7);

	      const Real b1 = 2./7. + sqrt(15.)/21.;
	      const Real a1 = 1. - 2.*b1;
	      const Real b2 = 2./7. - sqrt(15.)/21.;
	      const Real a2 = 1. - 2.*b2;

	      _points[0](0) = 1./3.;
	      _points[0](1) = 1./3.;

	      _points[1](0) = a1;
	      _points[1](1) = b1;

	      _points[2](0) = b1;
	      _points[2](1) = a1;

	      _points[3](0) = b1;
	      _points[3](1) = b1;

	      _points[4](0) = a2;
	      _points[4](1) = b2;

	      _points[5](0) = b2;
	      _points[5](1) = a2;

	      _points[6](0) = b2;
	      _points[6](1) = b2;

	      _weights[0] = 9./80.;
	      _weights[1] = 31./480. + sqrt(15.)/2400.;
	      _weights[2] = _weights[1];
	      _weights[3] = _weights[1];
	      _weights[4] = 31./480. - sqrt(15.)/2400.;
	      _weights[5] = _weights[4];
	      _weights[6] = _weights[4];

	      return;
	    }

	  case SIXTH:
	  case SEVENTH:
	    {
	      // Exact for seventh degree polynomials
	      // Taken from http://www.rpi.edu/~gilade/fem6.ps by
	      // Flaherty
	      _points.resize(12);
	      _weights.resize(12);
	      const Real w1 = 0.050844906370207 / 2;
	      const Real w2 = 0.116786275726379 / 2;
	      const Real w3 = 0.082851075618374 / 2;
	      const Real a1 = 0.873821971016996;
	      const Real a2 = 0.063089014491502;
	      const Real b1 = 0.501426509658179;
	      const Real b2 = 0.249286745170910;
	      const Real c1 = 0.636502499121399;
	      const Real c2 = 0.310352451033785;
	      const Real c3 = 0.053145049844816;

	      _points[0](0) = a1;
	      _points[0](1) = a2;

	      _points[1](0) = a2;
	      _points[1](1) = a1;

	      _points[2](0) = a2;
	      _points[2](1) = a2;

	      _points[3](0) = b1;
	      _points[3](1) = b2;

	      _points[4](0) = b2;
	      _points[4](1) = b1;

	      _points[5](0) = b2;
	      _points[5](1) = b2;

	      _points[6](0) = c1;
	      _points[6](1) = c2;

	      _points[7](0) = c1;
	      _points[7](1) = c3;

	      _points[8](0) = c2;
	      _points[8](1) = c1;

	      _points[9](0) = c2;
	      _points[9](1) = c3;

	      _points[10](0) = c3;
	      _points[10](1) = c1;

	      _points[11](0) = c3;
	      _points[11](1) = c2;

	      _weights[0] = w1;
	      _weights[1] = w1;
	      _weights[2] = w1;
	      _weights[3] = w2;
	      _weights[4] = w2;
	      _weights[5] = w2;
	      _weights[6] = w3;
	      _weights[7] = w3;
	      _weights[8] = w3;
	      _weights[9] = w3;
	      _weights[10] = w3;
	      _weights[11] = w3;

	      return;
	    }
	  case EIGHTH:
	  case NINTH:
	  case TENTH:
	  case ELEVENTH:
	  case TWELFTH:
	  case THIRTEENTH:
	  case FOURTEENTH:
	  case FIFTEENTH:
	  case SIXTEENTH:
	  case SEVENTEENTH:
	  case EIGHTTEENTH:
	  case NINTEENTH:
	  case TWENTIETH:
	  case TWENTYFIRST:
	  case TWENTYSECOND:
	  case TWENTYTHIRD:
	    {
	      // The following quadrature rules are
	      // generated as conical products.  These
	      // tend to be non-optimal (use too many
	      // points, cluster points in certain
	      // regions of the domain) but they are
	      // quite easy to automatically generate
	      // using a 1D Gauss rule on [0,1] and a
	      // 1D Jacobi-Gauss rule on [0,1].

	      // Define the quadrature rules...
	      QGauss  gauss1D(1,_order);
	      QJacobi jac1D(1,_order,1,0);

	      // The Gauss rule needs to be scaled to [0,1]
	      std::pair<Real, Real> old_range(-1,1);
	      std::pair<Real, Real> new_range(0,1);
	      gauss1D.scale(old_range,
			    new_range);

	      // Compute the tensor product
	      tensor_product_tri(gauss1D, jac1D);
	      return;
	    }

	  default:
	    {
	      std::cout << "Quadrature rule not supported!" << std::endl;

	      error();
	    }
	  }
      }

      //---------------------------------------------
      // Unsupported type
    default:
      {
	std::cerr << "Element type not supported!:" << _type << std::endl;
	error();
      }
    }

  error();

  return;

#endif
}
<commit_msg><commit_after>// $Id: quadrature_gauss_2D.C,v 1.17 2004-12-01 02:37:02 roystgnr Exp $

// The libMesh Finite Element Library.
// Copyright (C) 2002-2004  Benjamin S. Kirk, John W. Peterson

// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License, or (at your option) any later version.

// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
// Lesser General Public License for more details.

// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA

// Local includes
#include "quadrature_gauss.h"
#include "quadrature_jacobi.h"

void QGauss::init_2D(const ElemType _type)
{
#if DIM > 1

  //-----------------------------------------------------------------------
  // 2D quadrature rules
  switch (_type)
    {

      //---------------------------------------------
      // Quadrilateral quadrature rules
    case QUAD4:
    case QUAD8:
    case QUAD9:
      {
	// We compute the 2D quadrature rule as a tensor
	// product of the 1D quadrature rule.
	QGauss q1D(1,_order);
	q1D.init(EDGE2);
	tensor_product_quad( q1D );
	return;
      }

      //---------------------------------------------
      // Triangle quadrature rules
    case TRI3:
    case TRI6:
      {
	switch(_order)
	  {
	  case CONSTANT:
	  case FIRST:
	    {
	      // Exact for linears
	      _points.resize(1);
	      _weights.resize(1);

	      _points[0](0) = .33333333333333333333333333333333;
	      _points[0](1) = .33333333333333333333333333333333;

	      _weights[0] = .5;

	      return;
	    }
	  case SECOND:
	    {
	      // Exact for quadratics
	      _points.resize(3);
	      _weights.resize(3);

	      _points[0](0) = .5;
	      _points[0](1) = .5;

	      _points[1](0) = 0.;
	      _points[1](1) = .5;

	      _points[2](0) = .5;
	      _points[2](1) = .0;

	      _weights[0] = 1./6.;
	      _weights[1] = 1./6.;
	      _weights[2] = 1./6.;

	      return;
	    }
	  case THIRD:
	    {
	      // Exact for cubics
	      _points.resize(4);
	      _weights.resize(4);

	      _points[0](0) = .33333333333333333333333333333333;
	      _points[0](1) = .33333333333333333333333333333333;

	      _points[1](0) = .2;
	      _points[1](1) = .6;

	      _points[2](0) = .2;
	      _points[2](1) = .2;

	      _points[3](0) = .6;
	      _points[3](1) = .2;

	      _weights[0] = -27./96.;
	      _weights[1] =  25./96.;
	      _weights[2] =  25./96.;
	      _weights[3] =  25./96.;

	      return;
	    }
	  case FOURTH:
	  case FIFTH:
	    {
	      // Exact for quintics
	      // Taken from "Quadrature on Simplices of Arbitrary
	      // Dimension" by Walkington
	      _points.resize(7);
	      _weights.resize(7);

	      const Real b1 = 2./7. + sqrt(15.)/21.;
	      const Real a1 = 1. - 2.*b1;
	      const Real b2 = 2./7. - sqrt(15.)/21.;
	      const Real a2 = 1. - 2.*b2;

	      _points[0](0) = 1./3.;
	      _points[0](1) = 1./3.;

	      _points[1](0) = a1;
	      _points[1](1) = b1;

	      _points[2](0) = b1;
	      _points[2](1) = a1;

	      _points[3](0) = b1;
	      _points[3](1) = b1;

	      _points[4](0) = a2;
	      _points[4](1) = b2;

	      _points[5](0) = b2;
	      _points[5](1) = a2;

	      _points[6](0) = b2;
	      _points[6](1) = b2;

	      _weights[0] = 9./80.;
	      _weights[1] = 31./480. + sqrt(15.)/2400.;
	      _weights[2] = _weights[1];
	      _weights[3] = _weights[1];
	      _weights[4] = 31./480. - sqrt(15.)/2400.;
	      _weights[5] = _weights[4];
	      _weights[6] = _weights[4];

	      return;
	    }

	  case SIXTH:
	  case SEVENTH:
	    {
	      // Exact for seventh degree polynomials
	      // Taken from http://www.rpi.edu/~gilade/fem6.ps by
	      // Flaherty
	      _points.resize(12);
	      _weights.resize(12);
	      const Real w1 = 0.050844906370207 / 2.0;
	      const Real w2 = 0.116786275726379 / 2.0;
	      const Real w3 = 0.082851075618374 / 2.0;
	      const Real a1 = 0.873821971016996;
	      const Real a2 = 0.063089014491502;
	      const Real b1 = 0.501426509658179;
	      const Real b2 = 0.249286745170910;
	      const Real c1 = 0.636502499121399;
	      const Real c2 = 0.310352451033785;
	      const Real c3 = 0.053145049844816;

	      _points[0](0) = a1;
	      _points[0](1) = a2;

	      _points[1](0) = a2;
	      _points[1](1) = a1;

	      _points[2](0) = a2;
	      _points[2](1) = a2;

	      _points[3](0) = b1;
	      _points[3](1) = b2;

	      _points[4](0) = b2;
	      _points[4](1) = b1;

	      _points[5](0) = b2;
	      _points[5](1) = b2;

	      _points[6](0) = c1;
	      _points[6](1) = c2;

	      _points[7](0) = c1;
	      _points[7](1) = c3;

	      _points[8](0) = c2;
	      _points[8](1) = c1;

	      _points[9](0) = c2;
	      _points[9](1) = c3;

	      _points[10](0) = c3;
	      _points[10](1) = c1;

	      _points[11](0) = c3;
	      _points[11](1) = c2;

	      _weights[0] = w1;
	      _weights[1] = w1;
	      _weights[2] = w1;
	      _weights[3] = w2;
	      _weights[4] = w2;
	      _weights[5] = w2;
	      _weights[6] = w3;
	      _weights[7] = w3;
	      _weights[8] = w3;
	      _weights[9] = w3;
	      _weights[10] = w3;
	      _weights[11] = w3;

	      return;
	    }
	  case EIGHTH:
	  case NINTH:
	  case TENTH:
	  case ELEVENTH:
	  case TWELFTH:
	  case THIRTEENTH:
	  case FOURTEENTH:
	  case FIFTEENTH:
	  case SIXTEENTH:
	  case SEVENTEENTH:
	  case EIGHTTEENTH:
	  case NINTEENTH:
	  case TWENTIETH:
	  case TWENTYFIRST:
	  case TWENTYSECOND:
	  case TWENTYTHIRD:
	    {
	      // The following quadrature rules are
	      // generated as conical products.  These
	      // tend to be non-optimal (use too many
	      // points, cluster points in certain
	      // regions of the domain) but they are
	      // quite easy to automatically generate
	      // using a 1D Gauss rule on [0,1] and a
	      // 1D Jacobi-Gauss rule on [0,1].

	      // Define the quadrature rules...
	      QGauss  gauss1D(1,_order);
	      QJacobi jac1D(1,_order,1,0);

	      // The Gauss rule needs to be scaled to [0,1]
	      std::pair<Real, Real> old_range(-1,1);
	      std::pair<Real, Real> new_range(0,1);
	      gauss1D.scale(old_range,
			    new_range);

	      // Compute the tensor product
	      tensor_product_tri(gauss1D, jac1D);
	      return;
	    }

	  default:
	    {
	      std::cout << "Quadrature rule not supported!" << std::endl;

	      error();
	    }
	  }
      }

      //---------------------------------------------
      // Unsupported type
    default:
      {
	std::cerr << "Element type not supported!:" << _type << std::endl;
	error();
      }
    }

  error();

  return;

#endif
}
<|endoftext|>