<commit_before>#include <stan/math/matrix/trace_inv_quad_form_ldlt.hpp>
#include <stan/math/matrix/typedefs.hpp>
#include <gtest/gtest.h>

<commit_msg>adding math test for trace_inv_quad_form_ldlt<commit_after>#include <stan/math/matrix/trace_inv_quad_form_ldlt.hpp>
#include <stan/math/matrix/typedefs.hpp>
#include <gtest/gtest.h>

TEST(MathMatrix, trace_inv_quad_form_ldlt) {
  stan::math::matrix_d A(4,4), B(4,2);
  stan::math::LDLT_factor<double,-1,-1> ldlt_A;
  A <<
    9.0,  3.0, 3.0,   3.0,
    3.0, 10.0, 2.0,   2.0,
    3.0,  2.0, 7.0,   1.0,
    3.0,  2.0, 1.0, 112.0;
  B <<
    100, 10,
    0,  1,
    -3, -3,
    5,  2;
  ldlt_A.compute(A);

  EXPECT_FLOAT_EQ(1439.1061766207,
                  trace_inv_quad_form_ldlt(ldlt_A,B));
  EXPECT_FLOAT_EQ((B.transpose() * A.inverse() * B).trace(),
                  trace_inv_quad_form_ldlt(ldlt_A,B));
}
<|endoftext|>


<commit_before>/*
 * Copyright (c) 2012-2018 Daniele Bartolini and individual contributors.
 * License: https://github.com/dbartolini/crown/blob/master/LICENSE
 */

#include "core/thread/condition_variable.h"

namespace crown
{
ConditionVariable::ConditionVariable()
{
#if CROWN_PLATFORM_POSIX
	int err = pthread_cond_init(&_cond, NULL);
	CE_ASSERT(err == 0, "pthread_cond_init: errno = %d", err);
	CE_UNUSED(err);
#elif CROWN_PLATFORM_WINDOWS
	InitializeConditionVariable(&_cv);
#endif
}

ConditionVariable::~ConditionVariable()
{
#if CROWN_PLATFORM_POSIX
	int err = pthread_cond_destroy(&_cond);
	CE_ASSERT(err == 0, "pthread_cond_destroy: errno = %d", err);
	CE_UNUSED(err);
#elif CROWN_PLATFORM_WINDOWS
	// Do nothing
#endif
}

void ConditionVariable::wait(Mutex& mutex)
{
#if CROWN_PLATFORM_POSIX
	int err = pthread_cond_wait(&_cond, &mutex._mutex);
	CE_ASSERT(err == 0, "pthread_cond_wait: errno = %d", err);
	CE_UNUSED(err);
#elif CROWN_PLATFORM_WINDOWS
	SleepConditionVariableCS(&_cv, &mutex._cs);
#endif
}

void ConditionVariable::signal()
{
#if CROWN_PLATFORM_POSIX
	int err = pthread_cond_signal(&_cond);
	CE_ASSERT(err == 0, "pthread_cond_signal: errno = %d", err);
	CE_UNUSED(err);
#elif CROWN_PLATFORM_WINDOWS
	WakeConditionVariable(&_cv);
#endif
}

} // namespace crown
<commit_msg>core: fix windows build<commit_after>/*
 * Copyright (c) 2012-2018 Daniele Bartolini and individual contributors.
 * License: https://github.com/dbartolini/crown/blob/master/LICENSE
 */

#include "core/thread/condition_variable.h"

namespace crown
{
ConditionVariable::ConditionVariable()
{
#if CROWN_PLATFORM_POSIX
	int err = pthread_cond_init(&_cond, NULL);
	CE_ASSERT(err == 0, "pthread_cond_init: errno = %d", err);
	CE_UNUSED(err);
#elif CROWN_PLATFORM_WINDOWS
	InitializeConditionVariable(&_cv);
#endif
}

ConditionVariable::~ConditionVariable()
{
#if CROWN_PLATFORM_POSIX
	int err = pthread_cond_destroy(&_cond);
	CE_ASSERT(err == 0, "pthread_cond_destroy: errno = %d", err);
	CE_UNUSED(err);
#elif CROWN_PLATFORM_WINDOWS
	// Do nothing
#endif
}

void ConditionVariable::wait(Mutex& mutex)
{
#if CROWN_PLATFORM_POSIX
	int err = pthread_cond_wait(&_cond, &mutex._mutex);
	CE_ASSERT(err == 0, "pthread_cond_wait: errno = %d", err);
	CE_UNUSED(err);
#elif CROWN_PLATFORM_WINDOWS
	SleepConditionVariableCS(&_cv, &mutex._cs, INFINITE);
#endif
}

void ConditionVariable::signal()
{
#if CROWN_PLATFORM_POSIX
	int err = pthread_cond_signal(&_cond);
	CE_ASSERT(err == 0, "pthread_cond_signal: errno = %d", err);
	CE_UNUSED(err);
#elif CROWN_PLATFORM_WINDOWS
	WakeConditionVariable(&_cv);
#endif
}

} // namespace crown
<|endoftext|>


<commit_before>/***************************************************************************
**
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (directui@nokia.com)
**
** This file is part of libmeegotouch.
**
** If you have questions regarding the use of this file, please contact
** Nokia at directui@nokia.com.
**
** This library is free software; you can redistribute it and/or
** modify it under the terms of the GNU Lesser General Public
** License version 2.1 as published by the Free Software Foundation
** and appearing in the file LICENSE.LGPL included in the packaging
** of this file.
**
****************************************************************************/

#include "msceneeventeater.h"
#include "mscene.h"
#include "mscenemanager.h"

#include <QEvent>
#include <QGraphicsScene>
#include <QGraphicsView>
#include <QDebug>
#include <float.h>

MSceneEventEater::MSceneEventEater(QGraphicsItem *parent) :
        QGraphicsWidget(parent)
{
    setFlag(QGraphicsItem::ItemHasNoContents);

    //FLT_MAX is maximal value for single precision floating-point number
    //We want this item to be on top of everything
    setZValue(FLT_MAX);
    setVisible(false);
}

bool MSceneEventEater::event(QEvent *event)
{
    if ((event->type() > QEvent::MouseButtonPress && event->type() < QEvent::MouseMove) ||
        (event->type() > QEvent::GraphicsSceneMouseMove && event->type() < QEvent::GraphicsSceneWheel) ||
        (event->type() > QEvent::HoverEnter && event->type() < QEvent::HoverMove)) {

        event->accept();
        return true;
    }
    return false;
}
<commit_msg>Fixes: NB#171501 - Back button is not displayed in Text and IM Message Viewer<commit_after>/***************************************************************************
**
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (directui@nokia.com)
**
** This file is part of libmeegotouch.
**
** If you have questions regarding the use of this file, please contact
** Nokia at directui@nokia.com.
**
** This library is free software; you can redistribute it and/or
** modify it under the terms of the GNU Lesser General Public
** License version 2.1 as published by the Free Software Foundation
** and appearing in the file LICENSE.LGPL included in the packaging
** of this file.
**
****************************************************************************/

#include "msceneeventeater.h"
#include "mscene.h"
#include "mscenemanager.h"

#include <QEvent>
#include <QGraphicsScene>
#include <QGraphicsView>
#include <QDebug>
#include <float.h>

MSceneEventEater::MSceneEventEater(QGraphicsItem *parent) :
        QGraphicsWidget(parent)
{
    setFlag(QGraphicsItem::ItemHasNoContents);
    setFlag(QGraphicsItem::ItemStopsClickFocusPropagation);

    //FLT_MAX is maximal value for single precision floating-point number
    //We want this item to be on top of everything
    setZValue(FLT_MAX);
    setVisible(false);
}

bool MSceneEventEater::event(QEvent *event)
{
    if ((event->type() > QEvent::MouseButtonPress && event->type() < QEvent::MouseMove) ||
        (event->type() > QEvent::GraphicsSceneMouseMove && event->type() < QEvent::GraphicsSceneWheel) ||
        (event->type() > QEvent::HoverEnter && event->type() < QEvent::HoverMove)) {

        event->accept();
        return true;
    }
    return false;
}
<|endoftext|>


<commit_before>/*
 * FileInfo.hpp
 *
 * Copyright (C) 2009-11 by RStudio, Inc.
 *
 * This program is licensed to you under the terms of version 3 of the
 * GNU Affero General Public License. This program is distributed WITHOUT
 * ANY EXPRESS OR IMPLIED WARRANTY, INCLUDING THOSE OF NON-INFRINGEMENT,
 * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Please refer to the
 * AGPL (http://www.gnu.org/licenses/agpl-3.0.txt) for more details.
 *
 */

#ifndef CORE_FILE_INFO_HPP
#define CORE_FILE_INFO_HPP

#include <stdint.h>
#include <ctime>

#include <string>
#include <iosfwd>

namespace core {

class FilePath;

class FileInfo
{
public:
   FileInfo()
      : absolutePath_(),
        isDirectory_(false),
        size_(0),
        lastWriteTime_(0)
   {
   }

   explicit FileInfo(const FilePath& filePath) ;

   FileInfo(const std::string& absolutePath, bool isDirectory);

   FileInfo(const std::string& absolutePath,
            bool isDirectory,
            uintmax_t size,
            std::time_t lastWriteTime);

   virtual ~FileInfo()
   {
   }

   // COPYING: via compliler (copyable members)

public:
   bool empty() const { return absolutePath_.empty(); }

   bool operator==(const FileInfo& other) const
   {
      return absolutePath_ == other.absolutePath_ &&
             isDirectory_ == other.isDirectory_ &&
             size_ == other.size_ &&
             lastWriteTime_ == other.lastWriteTime_;
   }

   bool operator!=(const FileInfo& other) const
   {
      return !(*this == other);
   }

public:
   std::string absolutePath() const { return absolutePath_.c_str(); }
   bool isDirectory() const { return isDirectory_; }
   uintmax_t size() const { return size_; }
   std::time_t lastWriteTime() const { return lastWriteTime_; }

private:
   std::string absolutePath_;
   bool isDirectory_;
   uintmax_t size_;
   std::time_t lastWriteTime_;
};

inline int fileInfoPathCompare(const FileInfo& a, const FileInfo& b)
{
   // use stcoll because that is what alphasort (comp function passed to
   // scandir) uses for its sorting)
   int result = ::strcoll(a.absolutePath().c_str(), b.absolutePath().c_str());

   if (result != 0)
      return result;

   if (a.isDirectory() == b.isDirectory())
      return 0;

   return a.isDirectory() ? -1 : 1;
}

inline bool fileInfoPathLessThan(const FileInfo& a, const FileInfo& b)
{
   return fileInfoPathCompare(a, b) < 0;
}

inline bool fileInfoHasPath(const FileInfo& fileInfo, const std::string& path)
{
   return fileInfo.absolutePath() == path;
}

std::ostream& operator << (std::ostream& stream, const FileInfo& fileInfo) ;

} // namespace core

#endif // CORE_FILE_INFO_HPP

<commit_msg>fix windows build (strcoll header)<commit_after>/*
 * FileInfo.hpp
 *
 * Copyright (C) 2009-11 by RStudio, Inc.
 *
 * This program is licensed to you under the terms of version 3 of the
 * GNU Affero General Public License. This program is distributed WITHOUT
 * ANY EXPRESS OR IMPLIED WARRANTY, INCLUDING THOSE OF NON-INFRINGEMENT,
 * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Please refer to the
 * AGPL (http://www.gnu.org/licenses/agpl-3.0.txt) for more details.
 *
 */

#ifndef CORE_FILE_INFO_HPP
#define CORE_FILE_INFO_HPP

#include <stdint.h>
#include <ctime>

#ifdef _WIN32
#include <string.h>
#endif

#include <string>
#include <iosfwd>

namespace core {

class FilePath;

class FileInfo
{
public:
   FileInfo()
      : absolutePath_(),
        isDirectory_(false),
        size_(0),
        lastWriteTime_(0)
   {
   }

   explicit FileInfo(const FilePath& filePath) ;

   FileInfo(const std::string& absolutePath, bool isDirectory);

   FileInfo(const std::string& absolutePath,
            bool isDirectory,
            uintmax_t size,
            std::time_t lastWriteTime);

   virtual ~FileInfo()
   {
   }

   // COPYING: via compliler (copyable members)

public:
   bool empty() const { return absolutePath_.empty(); }

   bool operator==(const FileInfo& other) const
   {
      return absolutePath_ == other.absolutePath_ &&
             isDirectory_ == other.isDirectory_ &&
             size_ == other.size_ &&
             lastWriteTime_ == other.lastWriteTime_;
   }

   bool operator!=(const FileInfo& other) const
   {
      return !(*this == other);
   }

public:
   std::string absolutePath() const { return absolutePath_.c_str(); }
   bool isDirectory() const { return isDirectory_; }
   uintmax_t size() const { return size_; }
   std::time_t lastWriteTime() const { return lastWriteTime_; }

private:
   std::string absolutePath_;
   bool isDirectory_;
   uintmax_t size_;
   std::time_t lastWriteTime_;
};

inline int fileInfoPathCompare(const FileInfo& a, const FileInfo& b)
{
   // use stcoll because that is what alphasort (comp function passed to
   // scandir) uses for its sorting)
   int result = ::strcoll(a.absolutePath().c_str(), b.absolutePath().c_str());

   if (result != 0)
      return result;

   if (a.isDirectory() == b.isDirectory())
      return 0;

   return a.isDirectory() ? -1 : 1;
}

inline bool fileInfoPathLessThan(const FileInfo& a, const FileInfo& b)
{
   return fileInfoPathCompare(a, b) < 0;
}

inline bool fileInfoHasPath(const FileInfo& fileInfo, const std::string& path)
{
   return fileInfo.absolutePath() == path;
}

std::ostream& operator << (std::ostream& stream, const FileInfo& fileInfo) ;

} // namespace core

#endif // CORE_FILE_INFO_HPP

<|endoftext|>


<commit_before>#include "narf/texteditor.h"
#include "narf/console.h"
#include <chrono>
#include "math.h"

narf::TextEditor::TextEditor() {
	homeCursor();
}

narf::TextEditor::~TextEditor() {
}

void narf::TextEditor::updated() {
	last_edited = std::chrono::system_clock::now();
}

void narf::TextEditor::clear() {
	str_.clear();
	cursor = 0;
	updated();
}

void narf::TextEditor::addString(const std::string &s) {
	str_.insert(cursor, s);
	cursor += 1;
	updated();
}

void narf::TextEditor::setString(const std::string &s) {
	str_ = s;
	cursor = int(str_.size());
	updated();
}

void narf::TextEditor::moveCursor(const int count) {
	cursor += count;
	cursor = std::max(0, std::min(cursor, (int)str_.size()));
}

void narf::TextEditor::delAtCursor(const int count) {
	if (count < 0) {
		cursor = std::max(0, cursor + count);
	}
	str_.erase(cursor, std::abs(count));
	updated();
}

void narf::TextEditor::homeCursor() {
	cursor = 0;
	updated();
}

void narf::TextEditor::endCursor() {
	cursor = int(str_.size());
	updated();
}
<commit_msg>TextEditor: make cursor movement reset blink<commit_after>#include "narf/texteditor.h"
#include "narf/console.h"
#include <chrono>
#include "math.h"

narf::TextEditor::TextEditor() {
	homeCursor();
}

narf::TextEditor::~TextEditor() {
}

void narf::TextEditor::updated() {
	last_edited = std::chrono::system_clock::now();
}

void narf::TextEditor::clear() {
	str_.clear();
	cursor = 0;
	updated();
}

void narf::TextEditor::addString(const std::string &s) {
	str_.insert(cursor, s);
	cursor += 1;
	updated();
}

void narf::TextEditor::setString(const std::string &s) {
	str_ = s;
	cursor = int(str_.size());
	updated();
}

void narf::TextEditor::moveCursor(const int count) {
	cursor += count;
	cursor = std::max(0, std::min(cursor, (int)str_.size()));
	updated();
}

void narf::TextEditor::delAtCursor(const int count) {
	if (count < 0) {
		cursor = std::max(0, cursor + count);
	}
	str_.erase(cursor, std::abs(count));
	updated();
}

void narf::TextEditor::homeCursor() {
	cursor = 0;
	updated();
}

void narf::TextEditor::endCursor() {
	cursor = int(str_.size());
	updated();
}
<|endoftext|>


<commit_before>// copyright (c) 2010 power4projects software

#include "eql.h"
#include "ecl_fun.h"
#include "gen/_lobjects.h"
#include <QApplication>
#include <QTimer>
#include <QStringList>

extern "C" void ini_EQL(cl_object);

bool EQL::ini = false;

EQL::EQL() : QObject(), fun(0) {
    iniCLFunctions();
    registerMetaTypes();
    LObjects::ini(this);
    read_VV(OBJNULL, ini_EQL); } // see src/make-eql-lib.lisp

EQL::~EQL() {
    cl_shutdown(); }

QString EQL::home() {
    static QString path;
    if(path.isEmpty()) {
        path = QApplication::applicationDirPath();
#ifdef Q_OS_DARWIN
        path.truncate(path.lastIndexOf('/', path.indexOf(".app")));
#endif
        path.append('/'); }
    return path; }

void EQL::singleShot() {
    if(fun) {
        cl_funcall(1, (cl_object)fun);
        fun = 0; }}

static void eval(const char* lisp_code) {
    CL_CATCH_ALL_BEGIN(ecl_process_env()) {
        si_safe_eval(2, ecl_read_from_cstring(lisp_code), Cnil); }
    CL_CATCH_ALL_END; }

void EQL::exec(const QStringList& args) {
    si_select_package(make_simple_base_string((char*)"EQL"));
    eval(QString("(SET-HOME \"%1\")").arg(home()).toAscii().constData());
    if(args.contains("-qgui")) {
        eval("(QGUI)"); }
    bool quit = false;
    const char* lisp_code = 0;
    QString load;
    if(args.count() == 1) {
        quit = true;
        lisp_code = "(SI:TOP-LEVEL)"; }
    else if(args.contains("-qtpl")) {
        quit = true;
        lisp_code = "(SI::QTOP-LEVEL)"; } // see src/lisp/ini.lisp
    else if((args.count() == 2) && !args.at(1).startsWith("-")) {
        load = QString("(LOAD \"%1\")").arg(args.at(1));
        lisp_code = load.toAscii().constData(); }
    if(lisp_code) {
        eval(lisp_code); }
    if(quit) {
        qquit(); }}

void EQL::exec(lisp_ini ini, const QByteArray& command, const QByteArray& package) {
    eval(QString("(EQL::SET-HOME \"%1\")").arg(home()).toAscii().constData());
    read_VV(OBJNULL, ini);
    si_select_package(make_simple_base_string((char*)package.constData()));
    eval(command.constData()); }
<commit_msg>fix passing additional command line arguments, see (qfun "QCoreApplication" "arguments")<commit_after>// copyright (c) 2010 power4projects software

#include "eql.h"
#include "ecl_fun.h"
#include "gen/_lobjects.h"
#include <QApplication>
#include <QTimer>
#include <QStringList>

extern "C" void ini_EQL(cl_object);

bool EQL::ini = false;

EQL::EQL() : QObject(), fun(0) {
    iniCLFunctions();
    registerMetaTypes();
    LObjects::ini(this);
    read_VV(OBJNULL, ini_EQL); } // see src/make-eql-lib.lisp

EQL::~EQL() {
    cl_shutdown(); }

QString EQL::home() {
    static QString path;
    if(path.isEmpty()) {
        path = QApplication::applicationDirPath();
#ifdef Q_OS_DARWIN
        path.truncate(path.lastIndexOf('/', path.indexOf(".app")));
#endif
        path.append('/'); }
    return path; }

void EQL::singleShot() {
    if(fun) {
        cl_funcall(1, (cl_object)fun);
        fun = 0; }}

static void eval(const char* lisp_code) {
    CL_CATCH_ALL_BEGIN(ecl_process_env()) {
        si_safe_eval(2, ecl_read_from_cstring(lisp_code), Cnil); }
    CL_CATCH_ALL_END; }

void EQL::exec(const QStringList& args) {
    si_select_package(make_simple_base_string((char*)"EQL"));
    eval(QString("(SET-HOME \"%1\")").arg(home()).toAscii().constData());
    bool qgui = false;
    int count = args.count();
    if(count > 1) {
        if(args.at(1) == "-qgui") {
            qgui = true;
            eval("(QGUI)"); }}
    bool quit = false;
    const char* lisp_code = 0;
    QString load;
    if(count == 1) {
        quit = true;
        lisp_code = "(SI:TOP-LEVEL)"; }
    else if(args.contains("-qtpl")) {
        quit = true;
        lisp_code = "(SI::QTOP-LEVEL)"; } // see src/lisp/ini.lisp
    else if(count >= 2) {
        if(!(qgui && (count == 2))) {
            load = QString("(LOAD \"%1\")")
                   .arg(args.at(((count > 2) && qgui) ? 2 : 1));
            lisp_code = load.toAscii().constData(); }}
    if(lisp_code) {
        eval(lisp_code); }
    if(quit) {
        qquit(); }}

void EQL::exec(lisp_ini ini, const QByteArray& command, const QByteArray& package) {
    eval(QString("(EQL::SET-HOME \"%1\")").arg(home()).toAscii().constData());
    read_VV(OBJNULL, ini);
    si_select_package(make_simple_base_string((char*)package.constData()));
    eval(command.constData()); }
<|endoftext|>


<commit_before>#include "array_view.hh"
#include "vector.hh"

#include <functional>
#include <iterator>

namespace Kakoune
{

template<typename T>
struct MirroredArray : public ArrayView<T>
{
    MirroredArray(ArrayView<T> data, int size)
        : ArrayView<T>(data), size(size)
    {
        kak_assert(2 * size + 1 <= data.size());
        (*this)[1] = 0;
    }

    [[gnu::always_inline]]
    T& operator[](int n) { return ArrayView<T>::operator[](n + size); }
    [[gnu::always_inline]]
    const T& operator[](int n) const { return ArrayView<T>::operator[](n + size); }
private:
    int size;
};

struct Snake{ int x, y, u, v; bool add; };

template<typename Iterator, typename Equal>
Snake find_end_snake_of_further_reaching_dpath(Iterator a, int N, Iterator b, int M,
                                               const MirroredArray<int>& V,
                                               const int D, const int k, Equal eq)
{
    int x; // our position along a

    const bool add = k == -D or (k != D and V[k-1] < V[k+1]);

    // if diagonal on the right goes further along x than diagonal on the left,
    // then we take a vertical edge from it to this diagonal, hence x = V[k+1]
    if (add)
        x = V[k+1];
    // else, we take an horizontal edge from our left diagonal,x = V[k-1]+1
    else
        x = V[k-1]+1;

    int y = x - k; // we are by construction on diagonal k, so our position along
                   // b (y) is x - k.

    int u = x, v = y;
    // follow end snake along diagonal k
    while (u < N and v < M and eq(a[u], b[v]))
        ++u, ++v;

    return { x, y, u, v, add };
}

struct SnakeLen : Snake
{
    SnakeLen(Snake s, int d) : Snake(s), d(d) {}
    int d;
};

template<typename Iterator, typename Equal>
SnakeLen find_middle_snake(Iterator a, int N, Iterator b, int M,
                           ArrayView<int> data1, ArrayView<int> data2,
                           Equal eq)
{
    const int delta = N - M;
    MirroredArray<int> V1{data1, N + M};
    MirroredArray<int> V2{data2, N + M};

    std::reverse_iterator<Iterator> ra{a + N}, rb{b + M};

    for (int D = 0; D <= (M + N + 1) / 2; ++D)
    {
        for (int k1 = -D; k1 <= D; k1 += 2)
        {
            auto p = find_end_snake_of_further_reaching_dpath(a, N, b, M, V1, D, k1, eq);
            V1[k1] = p.u;

            const int k2 = -(k1 - delta);
            if ((delta % 2 != 0) and -(D-1) <= k2 and k2 <= (D-1))
            {
                if (V1[k1] + V2[k2] >= N)
                    return { p, 2 * D - 1 };// return last snake on forward path
            }
        }

        for (int k2 = -D; k2 <= D; k2 += 2)
        {
            auto p = find_end_snake_of_further_reaching_dpath(ra, N, rb, M, V2, D, k2, eq);
            V2[k2] = p.u;

            const int k1 = -(k2 - delta);
            if ((delta % 2 == 0) and -D <= k1 and k1 <= D)
            {
                if (V1[k1] + V2[k2] >= N)
                    return { { N - p.u, M - p.v, N - p.x , M - p.y, p.add } , 2 * D };// return last snake on reverse path
            }
        }
    }

    kak_assert(false);
    return { {}, 0 };
}

struct Diff
{
    enum { Keep, Add, Remove } mode;
    int len;
    int posB;
    int posA;
};

inline void append_diff(Vector<Diff>& diffs, Diff diff)
{
    if (not diffs.empty() and diffs.back().mode == diff.mode
        and (diff.mode != Diff::Add or
             diffs.back().posB + diffs.back().len == diff.posB))
        diffs.back().len += diff.len;
    else
        diffs.push_back(diff);
}

template<typename Iterator, typename Equal>
void find_diff_rec(Iterator a, int offA, int lenA,
                   Iterator b, int offB, int lenB,
                   ArrayView<int> data1, ArrayView<int> data2,
                   Equal eq, Vector<Diff>& diffs)
{
    if (lenA > 0 and lenB > 0)
    {
        auto middle_snake = find_middle_snake(a + offA, lenA, b + offB, lenB, data1, data2, eq);
        kak_assert(middle_snake.u <= lenA and middle_snake.v <= lenB);
        if (middle_snake.d > 1)
        {
            find_diff_rec(a, offA, middle_snake.x,
                          b, offB, middle_snake.y,
                          data1, data2, eq, diffs);

            if (int len = middle_snake.u - middle_snake.x)
                append_diff(diffs, {Diff::Keep, len, 0});

            find_diff_rec(a, offA + middle_snake.u, lenA - middle_snake.u,
                          b, offB + middle_snake.v, lenB - middle_snake.v,
                          data1, data2, eq, diffs);
        }
        else
        {
            if (middle_snake.d == 1)
            {
                const int diag = middle_snake.x - (middle_snake.add ? 0 : 1);
                if (diag != 0)
                    append_diff(diffs, {Diff::Keep, diag, 0});

                if (middle_snake.add)
                    append_diff(diffs, {Diff::Add, 1, offB + diag});
                else
                    append_diff(diffs, {Diff::Remove, 1, 0});
            }
            if (int len = middle_snake.u - middle_snake.x)
                append_diff(diffs, {Diff::Keep, len, 0});
        }
    }
    else if (lenB > 0)
        append_diff(diffs, {Diff::Add, lenB, offB});
    else if (lenA > 0)
        append_diff(diffs, {Diff::Remove, lenA, 0});
}

template<typename Iterator, typename Equal = std::equal_to<typename std::iterator_traits<Iterator>::value_type>>
Vector<Diff> find_diff(Iterator a, int N, Iterator b, int M,
                                 Equal eq = Equal{})
{
    const int max = 2 * (N + M) + 1;
    Vector<int> data(2*max);
    Vector<Diff> diffs;
    find_diff_rec(a, 0, N, b, 0, M,
                  {data.data(), (size_t)max}, {data.data() + max, (size_t)max},
                  eq, diffs);

    return diffs;
}

}
<commit_msg>Add headers guard to diff.hh along with a comment about the algorithm<commit_after>#ifndef diff_hh_INCLUDED
#define diff_hh_INCLUDED

// Implementation of the linear space variant of the algorithm described in
// "An O(ND) Difference Algorithm and Its Variations"
// (http://xmailserver.org/diff2.pdf)

#include "array_view.hh"
#include "vector.hh"

#include <functional>
#include <iterator>

namespace Kakoune
{

template<typename T>
struct MirroredArray : public ArrayView<T>
{
    MirroredArray(ArrayView<T> data, int size)
        : ArrayView<T>(data), size(size)
    {
        kak_assert(2 * size + 1 <= data.size());
        (*this)[1] = 0;
    }

    [[gnu::always_inline]]
    T& operator[](int n) { return ArrayView<T>::operator[](n + size); }
    [[gnu::always_inline]]
    const T& operator[](int n) const { return ArrayView<T>::operator[](n + size); }
private:
    int size;
};

struct Snake{ int x, y, u, v; bool add; };

template<typename Iterator, typename Equal>
Snake find_end_snake_of_further_reaching_dpath(Iterator a, int N, Iterator b, int M,
                                               const MirroredArray<int>& V,
                                               const int D, const int k, Equal eq)
{
    int x; // our position along a

    const bool add = k == -D or (k != D and V[k-1] < V[k+1]);

    // if diagonal on the right goes further along x than diagonal on the left,
    // then we take a vertical edge from it to this diagonal, hence x = V[k+1]
    if (add)
        x = V[k+1];
    // else, we take an horizontal edge from our left diagonal,x = V[k-1]+1
    else
        x = V[k-1]+1;

    int y = x - k; // we are by construction on diagonal k, so our position along
                   // b (y) is x - k.

    int u = x, v = y;
    // follow end snake along diagonal k
    while (u < N and v < M and eq(a[u], b[v]))
        ++u, ++v;

    return { x, y, u, v, add };
}

struct SnakeLen : Snake
{
    SnakeLen(Snake s, int d) : Snake(s), d(d) {}
    int d;
};

template<typename Iterator, typename Equal>
SnakeLen find_middle_snake(Iterator a, int N, Iterator b, int M,
                           ArrayView<int> data1, ArrayView<int> data2,
                           Equal eq)
{
    const int delta = N - M;
    MirroredArray<int> V1{data1, N + M};
    MirroredArray<int> V2{data2, N + M};

    std::reverse_iterator<Iterator> ra{a + N}, rb{b + M};

    for (int D = 0; D <= (M + N + 1) / 2; ++D)
    {
        for (int k1 = -D; k1 <= D; k1 += 2)
        {
            auto p = find_end_snake_of_further_reaching_dpath(a, N, b, M, V1, D, k1, eq);
            V1[k1] = p.u;

            const int k2 = -(k1 - delta);
            if ((delta % 2 != 0) and -(D-1) <= k2 and k2 <= (D-1))
            {
                if (V1[k1] + V2[k2] >= N)
                    return { p, 2 * D - 1 };// return last snake on forward path
            }
        }

        for (int k2 = -D; k2 <= D; k2 += 2)
        {
            auto p = find_end_snake_of_further_reaching_dpath(ra, N, rb, M, V2, D, k2, eq);
            V2[k2] = p.u;

            const int k1 = -(k2 - delta);
            if ((delta % 2 == 0) and -D <= k1 and k1 <= D)
            {
                if (V1[k1] + V2[k2] >= N)
                    return { { N - p.u, M - p.v, N - p.x , M - p.y, p.add } , 2 * D };// return last snake on reverse path
            }
        }
    }

    kak_assert(false);
    return { {}, 0 };
}

struct Diff
{
    enum { Keep, Add, Remove } mode;
    int len;
    int posB;
    int posA;
};

inline void append_diff(Vector<Diff>& diffs, Diff diff)
{
    if (not diffs.empty() and diffs.back().mode == diff.mode
        and (diff.mode != Diff::Add or
             diffs.back().posB + diffs.back().len == diff.posB))
        diffs.back().len += diff.len;
    else
        diffs.push_back(diff);
}

template<typename Iterator, typename Equal>
void find_diff_rec(Iterator a, int offA, int lenA,
                   Iterator b, int offB, int lenB,
                   ArrayView<int> data1, ArrayView<int> data2,
                   Equal eq, Vector<Diff>& diffs)
{
    if (lenA > 0 and lenB > 0)
    {
        auto middle_snake = find_middle_snake(a + offA, lenA, b + offB, lenB, data1, data2, eq);
        kak_assert(middle_snake.u <= lenA and middle_snake.v <= lenB);
        if (middle_snake.d > 1)
        {
            find_diff_rec(a, offA, middle_snake.x,
                          b, offB, middle_snake.y,
                          data1, data2, eq, diffs);

            if (int len = middle_snake.u - middle_snake.x)
                append_diff(diffs, {Diff::Keep, len, 0});

            find_diff_rec(a, offA + middle_snake.u, lenA - middle_snake.u,
                          b, offB + middle_snake.v, lenB - middle_snake.v,
                          data1, data2, eq, diffs);
        }
        else
        {
            if (middle_snake.d == 1)
            {
                const int diag = middle_snake.x - (middle_snake.add ? 0 : 1);
                if (diag != 0)
                    append_diff(diffs, {Diff::Keep, diag, 0});

                if (middle_snake.add)
                    append_diff(diffs, {Diff::Add, 1, offB + diag});
                else
                    append_diff(diffs, {Diff::Remove, 1, 0});
            }
            if (int len = middle_snake.u - middle_snake.x)
                append_diff(diffs, {Diff::Keep, len, 0});
        }
    }
    else if (lenB > 0)
        append_diff(diffs, {Diff::Add, lenB, offB});
    else if (lenA > 0)
        append_diff(diffs, {Diff::Remove, lenA, 0});
}

template<typename Iterator, typename Equal = std::equal_to<typename std::iterator_traits<Iterator>::value_type>>
Vector<Diff> find_diff(Iterator a, int N, Iterator b, int M,
                                 Equal eq = Equal{})
{
    const int max = 2 * (N + M) + 1;
    Vector<int> data(2*max);
    Vector<Diff> diffs;
    find_diff_rec(a, 0, N, b, 0, M,
                  {data.data(), (size_t)max}, {data.data() + max, (size_t)max},
                  eq, diffs);

    return diffs;
}

}

#endif // diff_hh_INCLUDED
<|endoftext|>


<commit_before>#ifndef diff_hh_INCLUDED
#define diff_hh_INCLUDED

// Implementation of the linear space variant of the algorithm described in
// "An O(ND) Difference Algorithm and Its Variations"
// (http://xmailserver.org/diff2.pdf)

#include "array_view.hh"
#include "vector.hh"

#include <functional>
#include <iterator>

namespace Kakoune
{

template<typename T>
struct MirroredArray : public ArrayView<T>
{
    MirroredArray(ArrayView<T> data, int size)
        : ArrayView<T>(data), size(size)
    {
        kak_assert(2 * size + 1 <= data.size());
        (*this)[1] = 0;
    }

    [[gnu::always_inline]]
    T& operator[](int n) { return ArrayView<T>::operator[](n + size); }
    [[gnu::always_inline]]
    const T& operator[](int n) const { return ArrayView<T>::operator[](n + size); }
private:
    int size;
};

struct Snake{ int x, y, u, v; bool add; };

template<typename Iterator, typename Equal>
Snake find_end_snake_of_further_reaching_dpath(Iterator a, int N, Iterator b, int M,
                                               const MirroredArray<int>& V,
                                               const int D, const int k, Equal eq)
{
    int x; // our position along a

    const bool add = k == -D or (k != D and V[k-1] < V[k+1]);

    // if diagonal on the right goes further along x than diagonal on the left,
    // then we take a vertical edge from it to this diagonal, hence x = V[k+1]
    if (add)
        x = V[k+1];
    // else, we take an horizontal edge from our left diagonal,x = V[k-1]+1
    else
        x = V[k-1]+1;

    int y = x - k; // we are by construction on diagonal k, so our position along
                   // b (y) is x - k.

    int u = x, v = y;
    // follow end snake along diagonal k
    while (u < N and v < M and eq(a[u], b[v]))
        ++u, ++v;

    return { x, y, u, v, add };
}

struct SnakeLen : Snake
{
    SnakeLen(Snake s, int d) : Snake(s), d(d) {}
    int d;
};

template<typename Iterator, typename Equal>
SnakeLen find_middle_snake(Iterator a, int N, Iterator b, int M,
                           ArrayView<int> data1, ArrayView<int> data2,
                           Equal eq)
{
    const int delta = N - M;
    MirroredArray<int> V1{data1, N + M};
    MirroredArray<int> V2{data2, N + M};

    std::reverse_iterator<Iterator> ra{a + N}, rb{b + M};

    for (int D = 0; D <= (M + N + 1) / 2; ++D)
    {
        for (int k1 = -D; k1 <= D; k1 += 2)
        {
            auto p = find_end_snake_of_further_reaching_dpath(a, N, b, M, V1, D, k1, eq);
            V1[k1] = p.u;

            const int k2 = -(k1 - delta);
            if ((delta % 2 != 0) and -(D-1) <= k2 and k2 <= (D-1))
            {
                if (V1[k1] + V2[k2] >= N)
                    return { p, 2 * D - 1 };// return last snake on forward path
            }
        }

        for (int k2 = -D; k2 <= D; k2 += 2)
        {
            auto p = find_end_snake_of_further_reaching_dpath(ra, N, rb, M, V2, D, k2, eq);
            V2[k2] = p.u;

            const int k1 = -(k2 - delta);
            if ((delta % 2 == 0) and -D <= k1 and k1 <= D)
            {
                if (V1[k1] + V2[k2] >= N)
                    return { { N - p.u, M - p.v, N - p.x , M - p.y, p.add } , 2 * D };// return last snake on reverse path
            }
        }
    }

    kak_assert(false);
    return { {}, 0 };
}

struct Diff
{
    enum { Keep, Add, Remove } mode;
    int len;
    int posB;
    int posA;
};

inline void append_diff(Vector<Diff>& diffs, Diff diff)
{
    if (not diffs.empty() and diffs.back().mode == diff.mode
        and (diff.mode != Diff::Add or
             diffs.back().posB + diffs.back().len == diff.posB))
        diffs.back().len += diff.len;
    else
        diffs.push_back(diff);
}

template<typename Iterator, typename Equal>
void find_diff_rec(Iterator a, int offA, int lenA,
                   Iterator b, int offB, int lenB,
                   ArrayView<int> data1, ArrayView<int> data2,
                   Equal eq, Vector<Diff>& diffs)
{
    if (lenA > 0 and lenB > 0)
    {
        auto middle_snake = find_middle_snake(a + offA, lenA, b + offB, lenB, data1, data2, eq);
        kak_assert(middle_snake.u <= lenA and middle_snake.v <= lenB);
        if (middle_snake.d > 1)
        {
            find_diff_rec(a, offA, middle_snake.x,
                          b, offB, middle_snake.y,
                          data1, data2, eq, diffs);

            if (int len = middle_snake.u - middle_snake.x)
                append_diff(diffs, {Diff::Keep, len, 0});

            find_diff_rec(a, offA + middle_snake.u, lenA - middle_snake.u,
                          b, offB + middle_snake.v, lenB - middle_snake.v,
                          data1, data2, eq, diffs);
        }
        else
        {
            if (middle_snake.d == 1)
            {
                const int diag = middle_snake.x - (middle_snake.add ? 0 : 1);
                if (diag != 0)
                    append_diff(diffs, {Diff::Keep, diag, 0});

                if (middle_snake.add)
                    append_diff(diffs, {Diff::Add, 1, offB + diag});
                else
                    append_diff(diffs, {Diff::Remove, 1, 0});
            }
            if (int len = middle_snake.u - middle_snake.x)
                append_diff(diffs, {Diff::Keep, len, 0});
        }
    }
    else if (lenB > 0)
        append_diff(diffs, {Diff::Add, lenB, offB});
    else if (lenA > 0)
        append_diff(diffs, {Diff::Remove, lenA, 0});
}

template<typename Iterator, typename Equal = std::equal_to<typename std::iterator_traits<Iterator>::value_type>>
Vector<Diff> find_diff(Iterator a, int N, Iterator b, int M, Equal eq = Equal{})
{
    const int max = 2 * (N + M) + 1;
    Vector<int> data(2*max);
    Vector<Diff> diffs;
    find_diff_rec(a, 0, N, b, 0, M,
                  {data.data(), (size_t)max}, {data.data() + max, (size_t)max},
                  eq, diffs);

    return diffs;
}

}

#endif // diff_hh_INCLUDED
<commit_msg>Remove unused Diff::posA field<commit_after>#ifndef diff_hh_INCLUDED
#define diff_hh_INCLUDED

// Implementation of the linear space variant of the algorithm described in
// "An O(ND) Difference Algorithm and Its Variations"
// (http://xmailserver.org/diff2.pdf)

#include "array_view.hh"
#include "vector.hh"

#include <functional>
#include <iterator>

namespace Kakoune
{

template<typename T>
struct MirroredArray : public ArrayView<T>
{
    MirroredArray(ArrayView<T> data, int size)
        : ArrayView<T>(data), size(size)
    {
        kak_assert(2 * size + 1 <= data.size());
        (*this)[1] = 0;
    }

    [[gnu::always_inline]]
    T& operator[](int n) { return ArrayView<T>::operator[](n + size); }
    [[gnu::always_inline]]
    const T& operator[](int n) const { return ArrayView<T>::operator[](n + size); }
private:
    int size;
};

struct Snake{ int x, y, u, v; bool add; };

template<typename Iterator, typename Equal>
Snake find_end_snake_of_further_reaching_dpath(Iterator a, int N, Iterator b, int M,
                                               const MirroredArray<int>& V,
                                               const int D, const int k, Equal eq)
{
    int x; // our position along a

    const bool add = k == -D or (k != D and V[k-1] < V[k+1]);

    // if diagonal on the right goes further along x than diagonal on the left,
    // then we take a vertical edge from it to this diagonal, hence x = V[k+1]
    if (add)
        x = V[k+1];
    // else, we take an horizontal edge from our left diagonal,x = V[k-1]+1
    else
        x = V[k-1]+1;

    int y = x - k; // we are by construction on diagonal k, so our position along
                   // b (y) is x - k.

    int u = x, v = y;
    // follow end snake along diagonal k
    while (u < N and v < M and eq(a[u], b[v]))
        ++u, ++v;

    return { x, y, u, v, add };
}

struct SnakeLen : Snake
{
    SnakeLen(Snake s, int d) : Snake(s), d(d) {}
    int d;
};

template<typename Iterator, typename Equal>
SnakeLen find_middle_snake(Iterator a, int N, Iterator b, int M,
                           ArrayView<int> data1, ArrayView<int> data2,
                           Equal eq)
{
    const int delta = N - M;
    MirroredArray<int> V1{data1, N + M};
    MirroredArray<int> V2{data2, N + M};

    std::reverse_iterator<Iterator> ra{a + N}, rb{b + M};

    for (int D = 0; D <= (M + N + 1) / 2; ++D)
    {
        for (int k1 = -D; k1 <= D; k1 += 2)
        {
            auto p = find_end_snake_of_further_reaching_dpath(a, N, b, M, V1, D, k1, eq);
            V1[k1] = p.u;

            const int k2 = -(k1 - delta);
            if ((delta % 2 != 0) and -(D-1) <= k2 and k2 <= (D-1))
            {
                if (V1[k1] + V2[k2] >= N)
                    return { p, 2 * D - 1 };// return last snake on forward path
            }
        }

        for (int k2 = -D; k2 <= D; k2 += 2)
        {
            auto p = find_end_snake_of_further_reaching_dpath(ra, N, rb, M, V2, D, k2, eq);
            V2[k2] = p.u;

            const int k1 = -(k2 - delta);
            if ((delta % 2 == 0) and -D <= k1 and k1 <= D)
            {
                if (V1[k1] + V2[k2] >= N)
                    return { { N - p.u, M - p.v, N - p.x , M - p.y, p.add } , 2 * D };// return last snake on reverse path
            }
        }
    }

    kak_assert(false);
    return { {}, 0 };
}

struct Diff
{
    enum { Keep, Add, Remove } mode;
    int len;
    int posB;
};

inline void append_diff(Vector<Diff>& diffs, Diff diff)
{
    if (not diffs.empty() and diffs.back().mode == diff.mode
        and (diff.mode != Diff::Add or
             diffs.back().posB + diffs.back().len == diff.posB))
        diffs.back().len += diff.len;
    else
        diffs.push_back(diff);
}

template<typename Iterator, typename Equal>
void find_diff_rec(Iterator a, int offA, int lenA,
                   Iterator b, int offB, int lenB,
                   ArrayView<int> data1, ArrayView<int> data2,
                   Equal eq, Vector<Diff>& diffs)
{
    if (lenA > 0 and lenB > 0)
    {
        auto middle_snake = find_middle_snake(a + offA, lenA, b + offB, lenB, data1, data2, eq);
        kak_assert(middle_snake.u <= lenA and middle_snake.v <= lenB);
        if (middle_snake.d > 1)
        {
            find_diff_rec(a, offA, middle_snake.x,
                          b, offB, middle_snake.y,
                          data1, data2, eq, diffs);

            if (int len = middle_snake.u - middle_snake.x)
                append_diff(diffs, {Diff::Keep, len, 0});

            find_diff_rec(a, offA + middle_snake.u, lenA - middle_snake.u,
                          b, offB + middle_snake.v, lenB - middle_snake.v,
                          data1, data2, eq, diffs);
        }
        else
        {
            if (middle_snake.d == 1)
            {
                const int diag = middle_snake.x - (middle_snake.add ? 0 : 1);
                if (diag != 0)
                    append_diff(diffs, {Diff::Keep, diag, 0});

                if (middle_snake.add)
                    append_diff(diffs, {Diff::Add, 1, offB + diag});
                else
                    append_diff(diffs, {Diff::Remove, 1, 0});
            }
            if (int len = middle_snake.u - middle_snake.x)
                append_diff(diffs, {Diff::Keep, len, 0});
        }
    }
    else if (lenB > 0)
        append_diff(diffs, {Diff::Add, lenB, offB});
    else if (lenA > 0)
        append_diff(diffs, {Diff::Remove, lenA, 0});
}

template<typename Iterator, typename Equal = std::equal_to<typename std::iterator_traits<Iterator>::value_type>>
Vector<Diff> find_diff(Iterator a, int N, Iterator b, int M, Equal eq = Equal{})
{
    const int max = 2 * (N + M) + 1;
    Vector<int> data(2*max);
    Vector<Diff> diffs;
    find_diff_rec(a, 0, N, b, 0, M,
                  {data.data(), (size_t)max}, {data.data() + max, (size_t)max},
                  eq, diffs);

    return diffs;
}

}

#endif // diff_hh_INCLUDED
<|endoftext|>


<commit_before>#ifndef STAN_MATH_PRIM_MAT_PROB_CATEGORICAL_LOGIT_GLM_LPMF_HPP
#define STAN_MATH_PRIM_MAT_PROB_CATEGORICAL_LOGIT_GLM_LPMF_HPP

#include <stan/math/prim/scal/meta/partials_return_type.hpp>
#include <stan/math/prim/scal/meta/return_type.hpp>
#include <stan/math/prim/scal/meta/operands_and_partials.hpp>
#include <stan/math/prim/scal/err/check_consistent_size.hpp>
#include <stan/math/prim/scal/meta/as_array_or_scalar.hpp>
#include <stan/math/prim/mat/meta/as_column_vector_or_scalar.hpp>
#include <stan/math/prim/scal/meta/include_summand.hpp>
#include <stan/math/prim/scal/fun/size_zero.hpp>
#include <Eigen/Core>

namespace stan {
namespace math {

/**
 * Returns the log PMF of the Generalized Linear Model (GLM)
 * with categorical distribution and logit (softmax) link function.
 *
 * @tparam T_x_scalar type of a scalar in the matrix of independent variables
 * (features);
 * @tparam T_alpha type of the intercept(s); This can be Eigen::RowVector or
 * std::vector
 * @tparam T_beta_scalar type of a scalar in the matrix of weights
 * @param y vector of classes; Values should be between 1 and number of classes,
 * including endpoints
 * @param x design matrix
 * @param alpha intercept (in log odds)
 * @param beta weight matrix
 * @return log probability or log sum of probabilities
 * @throw std::domain_error x, beta or alpha is infinite or y is not within
 * bounds
 * @throw std::invalid_argument if container sizes mismatch.
 */
template <bool propto, typename T_x_scalar, typename T_alpha,
          typename T_beta_scalar>
typename return_type<T_x_scalar, T_alpha, T_beta_scalar>::type
categorical_logit_glm_lpmf(
    const Eigen::Matrix<int, Eigen::Dynamic, 1>& y,
    const Eigen::Matrix<T_x_scalar, Eigen::Dynamic, Eigen::Dynamic>& x,
    const T_alpha& alpha,
    const Eigen::Matrix<T_beta_scalar, Eigen::Dynamic, Eigen::Dynamic>& beta) {
  typedef typename stan::partials_return_type<
      T_x_scalar, T_alpha, T_beta_scalar>::type T_partials_return;
  static const char* function = "categorical_logit_glm_lpmf";

  using Eigen::Array;
  using Eigen::Dynamic;
  using Eigen::Matrix;
  using std::exp;
  using std::log;

  const size_t N_instances = x.rows();
  const size_t N_attributes = x.cols();
  const size_t N_classes = beta.cols();

  check_consistent_size(function, "Vector of dependent variables", y,
                        N_instances);
  check_consistent_size(function, "Intercept vector", alpha, N_classes);
  check_size_match(function, "x.cols()", N_attributes, "beta.rows()",
                   beta.rows());
  check_bounded(function, "categorical outcome out of support", y, 1,
                N_classes);

  if (size_zero(y, x, beta))
    return 0;

  if (!include_summand<propto, T_x_scalar, T_alpha, T_beta_scalar>::value)
    return 0;

  const auto& x_val = value_of_rec(x);
  const auto& beta_val = value_of_rec(beta);
  const auto& alpha_val = value_of_rec(alpha);

  const auto& alpha_val_vec = as_column_vector_or_scalar(alpha_val).transpose();

  Array<T_partials_return, Dynamic, Dynamic> lin
      = (x_val * beta_val).rowwise() + alpha_val_vec;
  Array<T_partials_return, Dynamic, 1> lin_max
      = lin.rowwise()
            .maxCoeff();  // This is used to prevent overflow when
                          // calculating softmax/log_sum_exp and similar
                          // expressions
  Array<T_partials_return, Dynamic, Dynamic> exp_lin
      = exp(lin.colwise() - lin_max);
  Array<T_partials_return, Dynamic, 1> inv_sum_exp_lin
      = 1 / exp_lin.rowwise().sum();

  T_partials_return logp = log(inv_sum_exp_lin).sum() - lin_max.sum();
  for (int i = 0; i < N_instances; i++) {
    logp += lin(i, y[i] - 1);
  }
  // TODO(Tadej) maybe we can replace previous block with the following line
  // when we have newer Eigen  T_partials_return logp =
  // lin(Eigen::all,y-1).sum() + log(inv_sum_exp_lin).sum() - lin_max.sum();

  if (!std::isfinite(logp)) {
    check_finite(function, "Weight vector", beta);
    check_finite(function, "Intercept", alpha);
    check_finite(function, "Matrix of independent variables", x);
  }

  // Compute the derivatives.
  operands_and_partials<Matrix<T_x_scalar, Dynamic, Dynamic>, T_alpha,
                        Matrix<T_beta_scalar, Dynamic, Dynamic>>
      ops_partials(x, alpha, beta);

  if (!is_constant_struct<T_x_scalar>::value) {
    Array<double, Dynamic, Dynamic> beta_y(N_instances, N_attributes);
    for (int i = 0; i < N_instances; i++) {
      beta_y.row(i) = beta_val.col(y[i] - 1);
    }
    ops_partials.edge1_.partials_
        = beta_y
          - (exp_lin.matrix() * beta_val.transpose()).array().colwise()
                * inv_sum_exp_lin;
    // TODO(Tadej) maybe we can replace previous block with the following line
    // when we have newer Eigen  ops_partials.edge1_.partials_ = beta_val(y - 1,
    // all) - (exp_lin.matrix() * beta.transpose()).colwise() * inv_sum_exp_lin;
  }
  if (!is_constant_struct<T_alpha>::value
      || !is_constant_struct<T_beta_scalar>::value) {
    Array<T_partials_return, Dynamic, Dynamic> neg_softmax_lin
        = exp_lin.colwise() * -inv_sum_exp_lin;
    if (!is_constant_struct<T_alpha>::value) {
      ops_partials.edge2_.partials_ = neg_softmax_lin.colwise().sum();
      for (int i = 0; i < N_instances; i++) {
        ops_partials.edge2_.partials_[y[i] - 1] += 1;
      }
    }
    if (!is_constant_struct<T_beta_scalar>::value) {
      Matrix<T_partials_return, Dynamic, Dynamic> beta_derivative
          = x_val.transpose() * neg_softmax_lin.matrix();

      for (int i = 0; i < N_instances; i++) {
        beta_derivative.col(y[i] - 1) += x_val.row(i);
      }
      // TODO(Tadej) maybe we can replace previous loop with the following line
      // when we have newer Eigen  ops_partials.edge3_.partials_(Eigen::all, y -
      // 1) += x_val.colwise.sum().transpose();

      ops_partials.edge3_.partials_ = std::move(beta_derivative);
    }
  }
  return ops_partials.build(logp);
}

template <typename T_x, typename T_alpha, typename T_beta>
typename return_type<T_x, T_alpha, T_beta>::type categorical_logit_glm_lpmf(
    const Eigen::Matrix<int, Eigen::Dynamic, 1>& y,
    const Eigen::Matrix<T_x, Eigen::Dynamic, Eigen::Dynamic>& x,
    const T_alpha& alpha,
    const Eigen::Matrix<T_beta, Eigen::Dynamic, Eigen::Dynamic>& beta) {
  return categorical_logit_glm_lpmf<false>(y, x, alpha, beta);
}

}  // namespace math
}  // namespace stan

#endif
<commit_msg>fix headers<commit_after>#ifndef STAN_MATH_PRIM_MAT_PROB_CATEGORICAL_LOGIT_GLM_LPMF_HPP
#define STAN_MATH_PRIM_MAT_PROB_CATEGORICAL_LOGIT_GLM_LPMF_HPP

#include <stan/math/prim/mat/meta/as_column_vector_or_scalar.hpp>
#include <stan/math/prim/scal/err/check_bounded.hpp>
#include <stan/math/prim/scal/err/check_consistent_size.hpp>
#include <stan/math/prim/scal/fun/size_zero.hpp>
#include <stan/math/prim/scal/meta/partials_return_type.hpp>
#include <stan/math/prim/scal/meta/return_type.hpp>
#include <stan/math/prim/scal/meta/operands_and_partials.hpp>
#include <stan/math/prim/scal/meta/as_array_or_scalar.hpp>
#include <stan/math/prim/scal/meta/include_summand.hpp>
#include <stan/math/prim/scal/meta/is_constant_struct.hpp>
#include <Eigen/Core>

namespace stan {
namespace math {

/**
 * Returns the log PMF of the Generalized Linear Model (GLM)
 * with categorical distribution and logit (softmax) link function.
 *
 * @tparam T_x_scalar type of a scalar in the matrix of independent variables
 * (features);
 * @tparam T_alpha type of the intercept(s); This can be Eigen::RowVector or
 * std::vector
 * @tparam T_beta_scalar type of a scalar in the matrix of weights
 * @param y vector of classes; Values should be between 1 and number of classes,
 * including endpoints
 * @param x design matrix
 * @param alpha intercept (in log odds)
 * @param beta weight matrix
 * @return log probability or log sum of probabilities
 * @throw std::domain_error x, beta or alpha is infinite or y is not within
 * bounds
 * @throw std::invalid_argument if container sizes mismatch.
 */
template <bool propto, typename T_x_scalar, typename T_alpha,
          typename T_beta_scalar>
typename return_type<T_x_scalar, T_alpha, T_beta_scalar>::type
categorical_logit_glm_lpmf(
    const Eigen::Matrix<int, Eigen::Dynamic, 1>& y,
    const Eigen::Matrix<T_x_scalar, Eigen::Dynamic, Eigen::Dynamic>& x,
    const T_alpha& alpha,
    const Eigen::Matrix<T_beta_scalar, Eigen::Dynamic, Eigen::Dynamic>& beta) {
  typedef typename stan::partials_return_type<
      T_x_scalar, T_alpha, T_beta_scalar>::type T_partials_return;
  static const char* function = "categorical_logit_glm_lpmf";

  using Eigen::Array;
  using Eigen::Dynamic;
  using Eigen::Matrix;
  using std::exp;
  using std::log;

  const size_t N_instances = x.rows();
  const size_t N_attributes = x.cols();
  const size_t N_classes = beta.cols();

  check_consistent_size(function, "Vector of dependent variables", y,
                        N_instances);
  check_consistent_size(function, "Intercept vector", alpha, N_classes);
  check_size_match(function, "x.cols()", N_attributes, "beta.rows()",
                   beta.rows());
  check_bounded(function, "categorical outcome out of support", y, 1,
                N_classes);

  if (size_zero(y, x, beta))
    return 0;

  if (!include_summand<propto, T_x_scalar, T_alpha, T_beta_scalar>::value)
    return 0;

  const auto& x_val = value_of_rec(x);
  const auto& beta_val = value_of_rec(beta);
  const auto& alpha_val = value_of_rec(alpha);

  const auto& alpha_val_vec = as_column_vector_or_scalar(alpha_val).transpose();

  Array<T_partials_return, Dynamic, Dynamic> lin
      = (x_val * beta_val).rowwise() + alpha_val_vec;
  Array<T_partials_return, Dynamic, 1> lin_max
      = lin.rowwise()
            .maxCoeff();  // This is used to prevent overflow when
                          // calculating softmax/log_sum_exp and similar
                          // expressions
  Array<T_partials_return, Dynamic, Dynamic> exp_lin
      = exp(lin.colwise() - lin_max);
  Array<T_partials_return, Dynamic, 1> inv_sum_exp_lin
      = 1 / exp_lin.rowwise().sum();

  T_partials_return logp = log(inv_sum_exp_lin).sum() - lin_max.sum();
  for (int i = 0; i < N_instances; i++) {
    logp += lin(i, y[i] - 1);
  }
  // TODO(Tadej) maybe we can replace previous block with the following line
  // when we have newer Eigen  T_partials_return logp =
  // lin(Eigen::all,y-1).sum() + log(inv_sum_exp_lin).sum() - lin_max.sum();

  if (!std::isfinite(logp)) {
    check_finite(function, "Weight vector", beta);
    check_finite(function, "Intercept", alpha);
    check_finite(function, "Matrix of independent variables", x);
  }

  // Compute the derivatives.
  operands_and_partials<Matrix<T_x_scalar, Dynamic, Dynamic>, T_alpha,
                        Matrix<T_beta_scalar, Dynamic, Dynamic>>
      ops_partials(x, alpha, beta);

  if (!is_constant_struct<T_x_scalar>::value) {
    Array<double, Dynamic, Dynamic> beta_y(N_instances, N_attributes);
    for (int i = 0; i < N_instances; i++) {
      beta_y.row(i) = beta_val.col(y[i] - 1);
    }
    ops_partials.edge1_.partials_
        = beta_y
          - (exp_lin.matrix() * beta_val.transpose()).array().colwise()
                * inv_sum_exp_lin;
    // TODO(Tadej) maybe we can replace previous block with the following line
    // when we have newer Eigen  ops_partials.edge1_.partials_ = beta_val(y - 1,
    // all) - (exp_lin.matrix() * beta.transpose()).colwise() * inv_sum_exp_lin;
  }
  if (!is_constant_struct<T_alpha>::value
      || !is_constant_struct<T_beta_scalar>::value) {
    Array<T_partials_return, Dynamic, Dynamic> neg_softmax_lin
        = exp_lin.colwise() * -inv_sum_exp_lin;
    if (!is_constant_struct<T_alpha>::value) {
      ops_partials.edge2_.partials_ = neg_softmax_lin.colwise().sum();
      for (int i = 0; i < N_instances; i++) {
        ops_partials.edge2_.partials_[y[i] - 1] += 1;
      }
    }
    if (!is_constant_struct<T_beta_scalar>::value) {
      Matrix<T_partials_return, Dynamic, Dynamic> beta_derivative
          = x_val.transpose() * neg_softmax_lin.matrix();

      for (int i = 0; i < N_instances; i++) {
        beta_derivative.col(y[i] - 1) += x_val.row(i);
      }
      // TODO(Tadej) maybe we can replace previous loop with the following line
      // when we have newer Eigen  ops_partials.edge3_.partials_(Eigen::all, y -
      // 1) += x_val.colwise.sum().transpose();

      ops_partials.edge3_.partials_ = std::move(beta_derivative);
    }
  }
  return ops_partials.build(logp);
}

template <typename T_x, typename T_alpha, typename T_beta>
typename return_type<T_x, T_alpha, T_beta>::type categorical_logit_glm_lpmf(
    const Eigen::Matrix<int, Eigen::Dynamic, 1>& y,
    const Eigen::Matrix<T_x, Eigen::Dynamic, Eigen::Dynamic>& x,
    const T_alpha& alpha,
    const Eigen::Matrix<T_beta, Eigen::Dynamic, Eigen::Dynamic>& beta) {
  return categorical_logit_glm_lpmf<false>(y, x, alpha, beta);
}

}  // namespace math
}  // namespace stan

#endif
<|endoftext|>


<commit_before>/*
 * Copyright 2013-2016 Christian Lockley
 *
 * 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 "watchdogd.hpp"
#include "logutils.hpp"
#include "linux.hpp"
#include "sub.hpp"
#include "exe.hpp"
#include "user.hpp"

int Spawn(int timeout, struct cfgoptions *const config, const char *file,
	  const char *args, ...)
{
	static spawnattr_t attr;

	if (file == NULL) {
		return -1;
	}

	va_list a;
	va_start(a, args);
	int ret = SpawnAttr(&attr, file, args, a);
	va_end(a);
	return ret;
}

int SpawnAttr(spawnattr_t * spawnattr, const char *file, const char *args, ...)
{
	pid_t intermediate = fork();
	pid_t mpid = getppid();
	if (intermediate == 0) {

		OnParentDeathSend(SIGKILL);
		pid_t worker = fork();
		if (worker == 0) {
#if defined(NSIG)
			ResetSignalHandlers(NSIG);
#endif
			setpgid(0, mpid);
			if (nice(spawnattr->nice) == -1) {
				Logmsg(LOG_ERR, "nice failed: %s",
				       MyStrerror(errno));
			}

			char buf[512] = {"watchdogdRepairScript="};
			strncat(buf, file, sizeof(buf) - strlen(buf) - 1);
			buf[511] = '\0';

			int fd = sd_journal_stream_fd(buf, LOG_INFO, true);

			if (fd < 0) {
				Logmsg(LOG_CRIT, "Unable to open log file for helper executable");
			}

			va_list ap;
			const char *array[64] = { "\0" };
			int argno = 0;

			va_start(ap, args);

			while (args != NULL && argno < 63) {
				array[argno++] = args;
				args = va_arg(ap, const char *);
			}
			array[argno] = NULL;
			va_end(ap);

			if (spawnattr->workingDirectory != NULL) {
				if (chdir(spawnattr->workingDirectory) < 0) {
					Logmsg(LOG_CRIT,
					       "Unable to change working directory to: %s: %s",
					       spawnattr->workingDirectory,
					       MyStrerror(errno));
				}
			}

			if (RunAsUser(spawnattr->user, spawnattr->group) != 0) {
				Logmsg(LOG_CRIT,
				       "Unable to run: %s as user: %s", file,
				       spawnattr->user);
			}

			if (spawnattr->noNewPrivileges == true) {
				int ret = NoNewProvileges();
				if (ret != 0) {
					if (ret < 0) {
						Logmsg(LOG_CRIT,
						       "NoNewPrivileges %s",
						       MyStrerror(-ret));
					} else {
						Logmsg(LOG_CRIT,
						       "unable to set no new privleges bit");
					}
				}
			}

			if (spawnattr->hasUmask == true) {
				umask(spawnattr->umask);
			}

			if (dup2(fd, STDOUT_FILENO) < 0) {
				Logmsg(LOG_CRIT,
				       "dup2 failed: STDOUT_FILENO: %s",
				       MyStrerror(errno));
				return -1;
			}

			if (dup2(fd, STDERR_FILENO) < 0) {
				Logmsg(LOG_CRIT,
				       "dup2 failed: STDERR_FILENO %s",
				       MyStrerror(errno));
				return -1;
			}

			execv(file, (char *const *)array);

			Logmsg(LOG_CRIT, "execv failed %s", file);

			close(fd);
			return -1;
		}

		char stack[2048] = {0};
		if (spawnattr->timeout > 0) {

			struct para {
				int t;
				pid_t m;
			};
			para a = {spawnattr->timeout, mpid};
			pid_t timer = clone([](void *s)->int {
				para *a = (para*)s;
				setpgid(0, a->m);
				int t = a->t;
				struct timeval tv = {0};
				tv.tv_sec = t;
				syscall(SYS_select, 0, NULL, NULL, NULL, &tv);
				_Exit(0);
			}, stack+sizeof(stack), CLONE_VM|CLONE_FILES|CLONE_FS|SIGCHLD, &a);
			if (timer < 0) {
				abort();
			}

			int ret = 0;
			pid_t first = wait(&ret);
			if (first == timer) {
				Logmsg(LOG_ERR, "binary %s exceeded time limit %i",
				       file, spawnattr->timeout);
				kill(worker, SIGKILL);
				wait(NULL);
				_Exit(EXIT_FAILURE);
			} else {
				syscall(SYS_tgkill, timer, timer, SIGKILL);
				wait(NULL);
				_Exit(WEXITSTATUS(ret));
			}
		} else {
			int ret = 0;
			wait(&ret);
			_Exit(WEXITSTATUS(ret));
		}
	} else {
		int status = 0;
		while (waitpid(intermediate, &status, 0) != intermediate) ;
		return WEXITSTATUS(status);
	}

	return 0;
}
<commit_msg>don't call setpgid in thread<commit_after>/*
 * Copyright 2013-2016 Christian Lockley
 *
 * 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 "watchdogd.hpp"
#include "logutils.hpp"
#include "linux.hpp"
#include "sub.hpp"
#include "exe.hpp"
#include "user.hpp"

int Spawn(int timeout, struct cfgoptions *const config, const char *file,
	  const char *args, ...)
{
	static spawnattr_t attr;

	if (file == NULL) {
		return -1;
	}

	va_list a;
	va_start(a, args);
	int ret = SpawnAttr(&attr, file, args, a);
	va_end(a);
	return ret;
}

int SpawnAttr(spawnattr_t * spawnattr, const char *file, const char *args, ...)
{
	pid_t intermediate = fork();
	pid_t mpid = getppid();
	if (intermediate == 0) {

		OnParentDeathSend(SIGKILL);
		pid_t worker = fork();
		if (worker == 0) {
#if defined(NSIG)
			ResetSignalHandlers(NSIG);
#endif
			setpgid(0, mpid);
			if (nice(spawnattr->nice) == -1) {
				Logmsg(LOG_ERR, "nice failed: %s",
				       MyStrerror(errno));
			}

			char buf[512] = {"watchdogdRepairScript="};
			strncat(buf, file, sizeof(buf) - strlen(buf) - 1);
			buf[511] = '\0';

			int fd = sd_journal_stream_fd(buf, LOG_INFO, true);

			if (fd < 0) {
				Logmsg(LOG_CRIT, "Unable to open log file for helper executable");
			}

			va_list ap;
			const char *array[64] = { "\0" };
			int argno = 0;

			va_start(ap, args);

			while (args != NULL && argno < 63) {
				array[argno++] = args;
				args = va_arg(ap, const char *);
			}
			array[argno] = NULL;
			va_end(ap);

			if (spawnattr->workingDirectory != NULL) {
				if (chdir(spawnattr->workingDirectory) < 0) {
					Logmsg(LOG_CRIT,
					       "Unable to change working directory to: %s: %s",
					       spawnattr->workingDirectory,
					       MyStrerror(errno));
				}
			}

			if (RunAsUser(spawnattr->user, spawnattr->group) != 0) {
				Logmsg(LOG_CRIT,
				       "Unable to run: %s as user: %s", file,
				       spawnattr->user);
			}

			if (spawnattr->noNewPrivileges == true) {
				int ret = NoNewProvileges();
				if (ret != 0) {
					if (ret < 0) {
						Logmsg(LOG_CRIT,
						       "NoNewPrivileges %s",
						       MyStrerror(-ret));
					} else {
						Logmsg(LOG_CRIT,
						       "unable to set no new privleges bit");
					}
				}
			}

			if (spawnattr->hasUmask == true) {
				umask(spawnattr->umask);
			}

			if (dup2(fd, STDOUT_FILENO) < 0) {
				Logmsg(LOG_CRIT,
				       "dup2 failed: STDOUT_FILENO: %s",
				       MyStrerror(errno));
				return -1;
			}

			if (dup2(fd, STDERR_FILENO) < 0) {
				Logmsg(LOG_CRIT,
				       "dup2 failed: STDERR_FILENO %s",
				       MyStrerror(errno));
				return -1;
			}

			execv(file, (char *const *)array);

			Logmsg(LOG_CRIT, "execv failed %s", file);

			close(fd);
			return -1;
		}

		char stack[2048] = {0};
		if (spawnattr->timeout > 0) {
			pid_t timer = clone([](void *s)->int {
				struct timeval tv;
				tv.tv_sec = *(int*)s;
				syscall(SYS_select, 0, NULL, NULL, NULL, &tv);
				_Exit(0);
			}, stack+sizeof(stack), CLONE_VM|CLONE_FILES|CLONE_FS|SIGCHLD, &spawnattr->timeout);
			if (timer < 0) {
				abort();
			}

			int ret = 0;
			pid_t first = wait(&ret);
			if (first == timer) {
				Logmsg(LOG_ERR, "binary %s exceeded time limit %i",
				       file, spawnattr->timeout);
				kill(worker, SIGKILL);
				wait(NULL);
				_Exit(EXIT_FAILURE);
			} else {
				syscall(SYS_tgkill, timer, timer, SIGKILL);
				wait(NULL);
				_Exit(WEXITSTATUS(ret));
			}
		} else {
			int ret = 0;
			wait(&ret);
			_Exit(WEXITSTATUS(ret));
		}
	} else {
		int status = 0;
		while (waitpid(intermediate, &status, 0) != intermediate) ;
		return WEXITSTATUS(status);
	}

	return 0;
}
<|endoftext|>


<commit_before>#include <v8.h>
#include <node.h>
#include <uv.h>
#include <cstring>
#include <stdlib.h>
#include <dbus/dbus.h>

#include "dbus.h"
#include "connection.h"
#include "signal.h"
#include "decoder.h"
#include "encoder.h"
#include "introspect.h"
#include "object_handler.h"

namespace NodeDBus {

	static void method_callback(DBusPendingCall *pending, void *user_data)
	{
		DBusError error;
		DBusMessage *reply_message;
		DBusAsyncData *data = static_cast<DBusAsyncData *>(user_data);

		dbus_error_init(&error);

		// Getting reply message
		reply_message = dbus_pending_call_steal_reply(pending);
		if (!reply_message) {
			dbus_pending_call_unref(pending);
			return;
		}
		dbus_pending_call_unref(pending);

		// Get current context from V8
		Local<Context> context = Context::GetCurrent();
		Context::Scope ctxScope(context);
		HandleScope scope;

		Handle<Value> err = Null();
		if (dbus_error_is_set(&error)) {
			err = Exception::Error(String::New(error.message));
			dbus_error_free(&error);
		} else if (dbus_message_get_type(message) == DBUS_MESSAGE_TYPE_ERROR) {
			err = Exception::Error(String::New(dbus_message_get_error_name(message)));
		}

		// Decode message for arguments
		Handle<Value> result = Decoder::DecodeMessage(reply_message);
		Handle<Value> args[] = {
			err,
			result
		};

		// Release
		dbus_message_unref(reply_message);

		// Invoke
		MakeCallback(data->callback, data->callback, 2, args);
	}

	static void method_free(void *user_data)
	{
		DBusAsyncData *data = static_cast<DBusAsyncData *>(user_data);

		data->callback.Dispose();
		data->callback.Clear();
		data->pending = NULL;
		delete data;
	}

	Handle<Value> GetBus(const Arguments& args)
	{
		HandleScope scope;
		DBusConnection *connection = NULL;
		DBusError error;

		dbus_error_init(&error);

		if (!args[0]->IsNumber())
			return ThrowException(Exception::Error(String::New("First parameter is integer")));

		// Create connection
		switch(args[0]->IntegerValue()) {
		case NODE_DBUS_BUS_SYSTEM:
			connection = dbus_bus_get(DBUS_BUS_SYSTEM, &error);
			break;

		case NODE_DBUS_BUS_SESSION:
			connection = dbus_bus_get(DBUS_BUS_SESSION, &error);
			break;
		}

		if (connection == NULL)
			return ThrowException(Exception::Error(String::New("Failed to get bus object")));

		// Initializing connection object
		Handle<ObjectTemplate> object_template = ObjectTemplate::New();
		object_template->SetInternalFieldCount(1);
		Persistent<ObjectTemplate> object_instance = Persistent<ObjectTemplate>::New(object_template);

		// Create bus object
		BusObject *bus = new BusObject;
		bus->type = static_cast<BusType>(args[0]->IntegerValue());
		bus->connection = connection;

		// Create a JavaScript object to store bus object
		Local<Object> bus_object = object_instance->NewInstance();
		bus_object->SetInternalField(0, External::New(bus));
		bus_object->Set(String::NewSymbol("uniqueName"), String::New(dbus_bus_get_unique_name(connection)));

		// Initializing connection handler
		Connection::Init(bus);

		return scope.Close(bus_object);
	}

	Handle<Value> ReleaseBus(const Arguments& args)
	{
		HandleScope scope;

		Local<Object> bus_object = args[0]->ToObject();
		BusObject *bus = static_cast<BusObject *>(External::Unwrap(bus_object->GetInternalField(0)));

		// Release connection handler
		Connection::UnInit(bus);

		return Undefined();
	}

	Handle<Value> CallMethod(const Arguments& args)
	{
		HandleScope scope;
		DBusError error;

		if (!args[8]->IsFunction())
			return ThrowException(Exception::Error(String::New("Require callback function")));

		int timeout = -1;
		if (args[6]->IsInt32())
			timeout = args[6]->Int32Value();

		// Get bus from internal field
		if (!args[0]->IsObject())
			return ThrowException(Exception::Error(String::New("First argument must be a object ")));

		Local<Object> bus_object = args[0]->ToObject();
		BusObject *bus = static_cast<BusObject *>(External::Unwrap(bus_object->GetInternalField(0)));

		// Initializing error handler
		dbus_error_init(&error);

		// Create message for method call
		if (!args[1]->IsString() || !args[2]->IsString() || !args[3]->IsString() || !args[4]->IsString())
			return ThrowException(Exception::Error(String::New("Require service name, object path, interface and method")));

		char *service_name = strdup(*String::Utf8Value(args[1]->ToString()));
		char *object_path = strdup(*String::Utf8Value(args[2]->ToString()));
		char *interface_name = strdup(*String::Utf8Value(args[3]->ToString()));
		char *method = strdup(*String::Utf8Value(args[4]->ToString()));

		DBusMessage *message = dbus_message_new_method_call(service_name, object_path, interface_name, method);

		dbus_free(service_name);
		dbus_free(object_path);
		dbus_free(interface_name);
		dbus_free(method);

		if (message == NULL)
			return ThrowException(Exception::Error(String::New("Failed to call method")));

		// Preparing method arguments
		if (args[7]->IsObject()) {
			DBusMessageIter iter;
			DBusSignatureIter siter;

			Handle<Array> argument_arr = Local<Array>::Cast(args[7]);
			if (argument_arr->Length() > 0) {

				// Initializing augument message
				dbus_message_iter_init_append(message, &iter);

				// Initializing signature
				char *sig = strdup(*String::Utf8Value(args[5]->ToString()));
				if (!dbus_signature_validate(sig, &error)) {
					return ThrowException(Exception::Error(String::New(error.message)));
				}

				// Getting all signatures
				dbus_signature_iter_init(&siter, sig);
				for (unsigned int i = 0; i < argument_arr->Length(); ++i) {
					char *arg_sig = dbus_signature_iter_get_signature(&siter);
					Handle<Value> arg = argument_arr->Get(i);

					if (!Encoder::EncodeObject(arg, &iter, arg_sig)) {
						dbus_free(arg_sig);
						break;
					}

					dbus_free(arg_sig);

					if (!dbus_signature_iter_next(&siter))
						break;
				}

				dbus_free(sig);
			}
		}

		// Send message and call method
		if (!args[8]->IsFunction()) {

			dbus_connection_send(bus->connection, message, NULL);

		} else {

			DBusPendingCall *pending;
			if (!dbus_connection_send_with_reply(bus->connection, message, &pending, timeout) || !pending) {
				if (message != NULL)
					dbus_message_unref(message);

				return ThrowException(Exception::Error(String::New("Failed to call method: Out of Memory")));
			}

			// Set callback for waiting
			DBusAsyncData *data = new DBusAsyncData;
			data->pending = pending;
			Handle<Function> callback = Handle<Function>::Cast(args[8]);
			data->callback = Persistent<Function>::New(callback);
			if (!dbus_pending_call_set_notify(pending, method_callback, data, method_free)) {
				if (message != NULL)
					dbus_message_unref(message);

				return ThrowException(Exception::Error(String::New("Failed to call method: Out of Memory")));
			}
		}

		if (message != NULL)
			dbus_message_unref(message);

		dbus_connection_flush(bus->connection);

		return Undefined();
	}

	Handle<Value> RequestName(Arguments const &args)
	{
		HandleScope scope;

		if (!args[0]->IsObject()) {
			return ThrowException(Exception::TypeError(
				String::New("first argument must be a object (bus)")
			));
		}

		if (!args[1]->IsString()) {
			return ThrowException(Exception::TypeError(
				String::New("first argument must be a string (Bus Name)")
			));
		}

		BusObject *bus = static_cast<BusObject *>(External::Unwrap(args[0]->ToObject()->GetInternalField(0)));
		char *service_name = strdup(*String::Utf8Value(args[1]->ToString()));

		// Request bus name
		dbus_bus_request_name(bus->connection, service_name, 0, NULL);
		dbus_connection_flush(bus->connection);

		dbus_free(service_name);

		return Undefined();
	}

	Handle<Value> ParseIntrospectSource(const Arguments& args)
	{
		HandleScope scope;

		if (!args[0]->IsString())
			return Null();

		char *src = strdup(*String::Utf8Value(args[0]->ToString()));

		Handle<Value> obj = Introspect::CreateObject(src);

		dbus_free(src);

		return scope.Close(obj);
	}

	Handle<Value> AddSignalFilter(const Arguments& args)
	{
		HandleScope scope;
		DBusError error;

		Local<Object> bus_object = args[0]->ToObject();
		char *rule_str = strdup(*String::Utf8Value(args[1]->ToString()));

		BusObject *bus = static_cast<BusObject *>(External::Unwrap(bus_object->GetInternalField(0)));

		dbus_error_init(&error);

		dbus_bus_add_match(bus->connection, rule_str, &error);
		dbus_connection_flush(bus->connection);

		if (dbus_error_is_set(&error)) {
			printf("Failed to add rule: %s\n", rule_str);
			dbus_free(rule_str);

			return ThrowException(Exception::SyntaxError(
				String::New(error.message)
			));
		}

		dbus_free(rule_str);

		return Undefined();
	}

	Handle<Value> SetMaxMessageSize(const Arguments& args)
	{
		HandleScope scope;

		Local<Object> bus_object = args[0]->ToObject();

		BusObject *bus = static_cast<BusObject *>(External::Unwrap(bus_object->GetInternalField(0)));

		dbus_connection_set_max_message_size(bus->connection, args[1]->ToInteger()->Value());
		dbus_connection_flush(bus->connection);

		return Undefined();
	}

	static void init(Handle<Object> target) {
		HandleScope scope;

		NODE_SET_METHOD(target, "getBus", GetBus);
		NODE_SET_METHOD(target, "releaseBus", ReleaseBus);
		NODE_SET_METHOD(target, "callMethod", CallMethod);
		NODE_SET_METHOD(target, "requestName", RequestName);
		NODE_SET_METHOD(target, "registerObjectPath", ObjectHandler::RegisterObjectPath);
		NODE_SET_METHOD(target, "sendMessageReply", ObjectHandler::SendMessageReply);
		NODE_SET_METHOD(target, "setObjectHandler", ObjectHandler::SetObjectHandler);
		NODE_SET_METHOD(target, "parseIntrospectSource", ParseIntrospectSource);
		NODE_SET_METHOD(target, "setSignalHandler", Signal::SetSignalHandler);
		NODE_SET_METHOD(target, "addSignalFilter", AddSignalFilter);
		NODE_SET_METHOD(target, "setMaxMessageSize", SetMaxMessageSize);
		NODE_SET_METHOD(target, "emitSignal", Signal::EmitSignal);
	}

	NODE_MODULE(dbus, init);
}
<commit_msg>fixed typo<commit_after>#include <v8.h>
#include <node.h>
#include <uv.h>
#include <cstring>
#include <stdlib.h>
#include <dbus/dbus.h>

#include "dbus.h"
#include "connection.h"
#include "signal.h"
#include "decoder.h"
#include "encoder.h"
#include "introspect.h"
#include "object_handler.h"

namespace NodeDBus {

	static void method_callback(DBusPendingCall *pending, void *user_data)
	{
		DBusError error;
		DBusMessage *reply_message;
		DBusAsyncData *data = static_cast<DBusAsyncData *>(user_data);

		dbus_error_init(&error);

		// Getting reply message
		reply_message = dbus_pending_call_steal_reply(pending);
		if (!reply_message) {
			dbus_pending_call_unref(pending);
			return;
		}
		dbus_pending_call_unref(pending);

		// Get current context from V8
		Local<Context> context = Context::GetCurrent();
		Context::Scope ctxScope(context);
		HandleScope scope;

		Handle<Value> err = Null();
		if (dbus_error_is_set(&error)) {
			err = Exception::Error(String::New(error.message));
			dbus_error_free(&error);
		} else if (dbus_message_get_type(reply_message) == DBUS_MESSAGE_TYPE_ERROR) {
			err = Exception::Error(String::New(dbus_message_get_error_name(reply_message)));
		}

		// Decode message for arguments
		Handle<Value> result = Decoder::DecodeMessage(reply_message);
		Handle<Value> args[] = {
			err,
			result
		};

		// Release
		dbus_message_unref(reply_message);

		// Invoke
		MakeCallback(data->callback, data->callback, 2, args);
	}

	static void method_free(void *user_data)
	{
		DBusAsyncData *data = static_cast<DBusAsyncData *>(user_data);

		data->callback.Dispose();
		data->callback.Clear();
		data->pending = NULL;
		delete data;
	}

	Handle<Value> GetBus(const Arguments& args)
	{
		HandleScope scope;
		DBusConnection *connection = NULL;
		DBusError error;

		dbus_error_init(&error);

		if (!args[0]->IsNumber())
			return ThrowException(Exception::Error(String::New("First parameter is integer")));

		// Create connection
		switch(args[0]->IntegerValue()) {
		case NODE_DBUS_BUS_SYSTEM:
			connection = dbus_bus_get(DBUS_BUS_SYSTEM, &error);
			break;

		case NODE_DBUS_BUS_SESSION:
			connection = dbus_bus_get(DBUS_BUS_SESSION, &error);
			break;
		}

		if (connection == NULL)
			return ThrowException(Exception::Error(String::New("Failed to get bus object")));

		// Initializing connection object
		Handle<ObjectTemplate> object_template = ObjectTemplate::New();
		object_template->SetInternalFieldCount(1);
		Persistent<ObjectTemplate> object_instance = Persistent<ObjectTemplate>::New(object_template);

		// Create bus object
		BusObject *bus = new BusObject;
		bus->type = static_cast<BusType>(args[0]->IntegerValue());
		bus->connection = connection;

		// Create a JavaScript object to store bus object
		Local<Object> bus_object = object_instance->NewInstance();
		bus_object->SetInternalField(0, External::New(bus));
		bus_object->Set(String::NewSymbol("uniqueName"), String::New(dbus_bus_get_unique_name(connection)));

		// Initializing connection handler
		Connection::Init(bus);

		return scope.Close(bus_object);
	}

	Handle<Value> ReleaseBus(const Arguments& args)
	{
		HandleScope scope;

		Local<Object> bus_object = args[0]->ToObject();
		BusObject *bus = static_cast<BusObject *>(External::Unwrap(bus_object->GetInternalField(0)));

		// Release connection handler
		Connection::UnInit(bus);

		return Undefined();
	}

	Handle<Value> CallMethod(const Arguments& args)
	{
		HandleScope scope;
		DBusError error;

		if (!args[8]->IsFunction())
			return ThrowException(Exception::Error(String::New("Require callback function")));

		int timeout = -1;
		if (args[6]->IsInt32())
			timeout = args[6]->Int32Value();

		// Get bus from internal field
		if (!args[0]->IsObject())
			return ThrowException(Exception::Error(String::New("First argument must be a object ")));

		Local<Object> bus_object = args[0]->ToObject();
		BusObject *bus = static_cast<BusObject *>(External::Unwrap(bus_object->GetInternalField(0)));

		// Initializing error handler
		dbus_error_init(&error);

		// Create message for method call
		if (!args[1]->IsString() || !args[2]->IsString() || !args[3]->IsString() || !args[4]->IsString())
			return ThrowException(Exception::Error(String::New("Require service name, object path, interface and method")));

		char *service_name = strdup(*String::Utf8Value(args[1]->ToString()));
		char *object_path = strdup(*String::Utf8Value(args[2]->ToString()));
		char *interface_name = strdup(*String::Utf8Value(args[3]->ToString()));
		char *method = strdup(*String::Utf8Value(args[4]->ToString()));

		DBusMessage *message = dbus_message_new_method_call(service_name, object_path, interface_name, method);

		dbus_free(service_name);
		dbus_free(object_path);
		dbus_free(interface_name);
		dbus_free(method);

		if (message == NULL)
			return ThrowException(Exception::Error(String::New("Failed to call method")));

		// Preparing method arguments
		if (args[7]->IsObject()) {
			DBusMessageIter iter;
			DBusSignatureIter siter;

			Handle<Array> argument_arr = Local<Array>::Cast(args[7]);
			if (argument_arr->Length() > 0) {

				// Initializing augument message
				dbus_message_iter_init_append(message, &iter);

				// Initializing signature
				char *sig = strdup(*String::Utf8Value(args[5]->ToString()));
				if (!dbus_signature_validate(sig, &error)) {
					return ThrowException(Exception::Error(String::New(error.message)));
				}

				// Getting all signatures
				dbus_signature_iter_init(&siter, sig);
				for (unsigned int i = 0; i < argument_arr->Length(); ++i) {
					char *arg_sig = dbus_signature_iter_get_signature(&siter);
					Handle<Value> arg = argument_arr->Get(i);

					if (!Encoder::EncodeObject(arg, &iter, arg_sig)) {
						dbus_free(arg_sig);
						break;
					}

					dbus_free(arg_sig);

					if (!dbus_signature_iter_next(&siter))
						break;
				}

				dbus_free(sig);
			}
		}

		// Send message and call method
		if (!args[8]->IsFunction()) {

			dbus_connection_send(bus->connection, message, NULL);

		} else {

			DBusPendingCall *pending;
			if (!dbus_connection_send_with_reply(bus->connection, message, &pending, timeout) || !pending) {
				if (message != NULL)
					dbus_message_unref(message);

				return ThrowException(Exception::Error(String::New("Failed to call method: Out of Memory")));
			}

			// Set callback for waiting
			DBusAsyncData *data = new DBusAsyncData;
			data->pending = pending;
			Handle<Function> callback = Handle<Function>::Cast(args[8]);
			data->callback = Persistent<Function>::New(callback);
			if (!dbus_pending_call_set_notify(pending, method_callback, data, method_free)) {
				if (message != NULL)
					dbus_message_unref(message);

				return ThrowException(Exception::Error(String::New("Failed to call method: Out of Memory")));
			}
		}

		if (message != NULL)
			dbus_message_unref(message);

		dbus_connection_flush(bus->connection);

		return Undefined();
	}

	Handle<Value> RequestName(Arguments const &args)
	{
		HandleScope scope;

		if (!args[0]->IsObject()) {
			return ThrowException(Exception::TypeError(
				String::New("first argument must be a object (bus)")
			));
		}

		if (!args[1]->IsString()) {
			return ThrowException(Exception::TypeError(
				String::New("first argument must be a string (Bus Name)")
			));
		}

		BusObject *bus = static_cast<BusObject *>(External::Unwrap(args[0]->ToObject()->GetInternalField(0)));
		char *service_name = strdup(*String::Utf8Value(args[1]->ToString()));

		// Request bus name
		dbus_bus_request_name(bus->connection, service_name, 0, NULL);
		dbus_connection_flush(bus->connection);

		dbus_free(service_name);

		return Undefined();
	}

	Handle<Value> ParseIntrospectSource(const Arguments& args)
	{
		HandleScope scope;

		if (!args[0]->IsString())
			return Null();

		char *src = strdup(*String::Utf8Value(args[0]->ToString()));

		Handle<Value> obj = Introspect::CreateObject(src);

		dbus_free(src);

		return scope.Close(obj);
	}

	Handle<Value> AddSignalFilter(const Arguments& args)
	{
		HandleScope scope;
		DBusError error;

		Local<Object> bus_object = args[0]->ToObject();
		char *rule_str = strdup(*String::Utf8Value(args[1]->ToString()));

		BusObject *bus = static_cast<BusObject *>(External::Unwrap(bus_object->GetInternalField(0)));

		dbus_error_init(&error);

		dbus_bus_add_match(bus->connection, rule_str, &error);
		dbus_connection_flush(bus->connection);

		if (dbus_error_is_set(&error)) {
			printf("Failed to add rule: %s\n", rule_str);
			dbus_free(rule_str);

			return ThrowException(Exception::SyntaxError(
				String::New(error.message)
			));
		}

		dbus_free(rule_str);

		return Undefined();
	}

	Handle<Value> SetMaxMessageSize(const Arguments& args)
	{
		HandleScope scope;

		Local<Object> bus_object = args[0]->ToObject();

		BusObject *bus = static_cast<BusObject *>(External::Unwrap(bus_object->GetInternalField(0)));

		dbus_connection_set_max_message_size(bus->connection, args[1]->ToInteger()->Value());
		dbus_connection_flush(bus->connection);

		return Undefined();
	}

	static void init(Handle<Object> target) {
		HandleScope scope;

		NODE_SET_METHOD(target, "getBus", GetBus);
		NODE_SET_METHOD(target, "releaseBus", ReleaseBus);
		NODE_SET_METHOD(target, "callMethod", CallMethod);
		NODE_SET_METHOD(target, "requestName", RequestName);
		NODE_SET_METHOD(target, "registerObjectPath", ObjectHandler::RegisterObjectPath);
		NODE_SET_METHOD(target, "sendMessageReply", ObjectHandler::SendMessageReply);
		NODE_SET_METHOD(target, "setObjectHandler", ObjectHandler::SetObjectHandler);
		NODE_SET_METHOD(target, "parseIntrospectSource", ParseIntrospectSource);
		NODE_SET_METHOD(target, "setSignalHandler", Signal::SetSignalHandler);
		NODE_SET_METHOD(target, "addSignalFilter", AddSignalFilter);
		NODE_SET_METHOD(target, "setMaxMessageSize", SetMaxMessageSize);
		NODE_SET_METHOD(target, "emitSignal", Signal::EmitSignal);
	}

	NODE_MODULE(dbus, init);
}
<|endoftext|>


<commit_before>#include "eval.h"
#include "env.h"

namespace mclisp
{
ConsCell *Eval(const ConsCell *exp, ConsCell *env /* env::g_user_env */)
{
  if (Atom(exp))
    return env::Lookup(env, exp);

  if (Atom(Car(exp)))
  {
    if (Eq(Car(exp), g_builtin_symbols["QUOTE"]))
      return Cadr(exp);

    if (Eq(Car(exp), g_builtin_symbols["ATOM"]))
      return FromBool(Atom(Eval(Cadr(exp), env)));
  }

  return MakeSymbol("42");
}

} // namespace mclisp
<commit_msg>Add EQ, COND, CAR, CDR and CONS to Eval.<commit_after>#include "eval.h"
#include "env.h"

namespace
{
using namespace mclisp;

ConsCell *Evcon(const ConsCell *clauses, ConsCell *env)
{
  // TODO Might want throw something more descriptive than TypeError.
  TYPECHECK(clauses, Listp);

  if (Null(clauses))
    return kNil;

  TYPECHECK(Car(clauses), Consp);

  if (*Eval(Caar(clauses), env))
    return Eval(Cadar(clauses), env);

  return Evcon(Cdr(clauses), env);
}
} // namespace

namespace mclisp
{
ConsCell *Eval(const ConsCell *exp, ConsCell *env /* env::g_user_env */)
{
#define EQ(exp, sym) Eq(exp, g_builtin_symbols[#sym])

  if (Atom(exp))
    return env::Lookup(env, exp);

  if (Atom(Car(exp)))
  {
    if (EQ(Car(exp), QUOTE))
      return Cadr(exp);

    if (EQ(Car(exp), ATOM))
      return FromBool(Atom(Eval(Cadr(exp), env)));

    if (EQ(Car(exp), EQ))
      return FromBool(Eq(Eval(Cadr(exp), env), Eval(Caddr(exp), env)));

    if (EQ(Car(exp), COND))
      return Evcon(Cdr(exp), env);

    if (EQ(Car(exp), CAR))
      return Car(Eval(Cadr(exp), env));

    if (EQ(Car(exp), CDR))
      return Cdr(Eval(Cadr(exp), env));

    if (EQ(Car(exp), CONS))
      return Cons(Eval(Cadr(exp), env), Eval(Caddr(exp), env));
  }

#undef EQ
  return MakeSymbol("42");
}

} // namespace mclisp
<|endoftext|>


<commit_before>/* Copyright (C) 2012-2017 IBM Corp.
 * This program is 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. See accompanying LICENSE file.
 */
/**
 * @file fft.cpp - computing the canonical embedding and related norms
 **/
#include <complex>
#include <cmath>
#include <numeric> // std::accumulate
#include <NTL/BasicThreadPool.h>
#include "NumbTh.h"
#include "timing.h"
#include "norms.h"
#include "PAlgebra.h"
NTL_CLIENT

const double pi = 4 * std::atan(1);

#ifdef FFT_ARMA
#warning "canonicalEmbedding implemented via Armadillo"
#include <armadillo>
void convert(zzX& to, const arma::vec& from)
{
  to.SetLength(from.size());
  NTL_EXEC_RANGE(to.length(), first, last)
  for (long i=first; i<last; i++)
    to[i] = std::round(from[i]);
  NTL_EXEC_RANGE_END
}
void convert(arma::vec& to, const zzX& from)
{
  to.resize(from.length());
  NTL_EXEC_RANGE(from.length(), first, last)
  for (long i=first; i<last; i++)
    to[i] = from[i];
  NTL_EXEC_RANGE_END
}

// Computing the canonical embedding. This function returns in v only
// the first half of the entries, the others are v[phi(m)-i]=conj(v[i])
void canonicalEmbedding(std::vector<cx_double>& v,
                        const zzX& f, const PAlgebra& palg)
{
  FHE_TIMER_START;
  long m = palg.getM();
  long phimBy2 = divc(palg.getPhiM(),2);
  arma::vec av; // convert to vector of doubles
  convert(av, f);
  arma::cx_vec avv = arma::fft(av,m); // compute the full FFT

  v.resize(phimBy2); // the first half of Zm*
  for (long i=0; i<palg.getNSlots(); i++)
    v[palg.getNSlots()-i-1] = avv[palg.ith_rep(i)];
  FHE_TIMER_STOP;
}

// Roughly the inverse of canonicalEmbedding, except for scaling and
// rounding issues. Calling embedInSlots(f,v,palg,1.0,strictInverse=true)
// after setting canonicalEmbedding(v, f, palg), is sure to recover the
// same f, but embedInSlots(f,v,palg,1.0,strictInverse=false) may return
// a different "nearby" f.
void embedInSlots(zzX& f, const std::vector<cx_double>& v,
                  const PAlgebra& palg, double scaling, bool strictInverse)
{
  FHE_TIMER_START;
  long m = palg.getM();
  arma::cx_vec avv(m);
  for (auto& x: avv) x = 0.0;
  for (long i=0; i<palg.getNSlots(); i++) {
    long j = palg.ith_rep(i);
    avv[j] = scaling*v[palg.getNSlots()-i-1];
    avv[m-j] = std::conj(avv[j]);
  }
  arma::vec av = arma::real(arma::ifft(avv,m)); // compute the inverse FFT

  // If v was obtained by canonicalEmbedding(v,f,palg,1.0) then we have
  // the guarantee that m*av is an integral polynomial, and moreover
  // m*av mod Phi_m(x) is in m*Z[X].
  if (strictInverse) av *= m; // scale up by m
  convert(f, av);    // round to an integer polynomial
  reduceModPhimX(f, palg);
  if (strictInverse) f /= m;  // scale down by m
  normalize(f);
}
#else
#ifdef FFT_NATIVE
#warning "canonicalEmbedding implemented via slow DFT, expect very slow key-generation"
// An extremely lame implementation of the canonical embedding

// evaluate poly(x) using Horner's rule
cx_double complexEvalPoly(const zzX& poly, const cx_double& x)
{
  if (lsize(poly)<=0) return cx_double(0.0,0.0);
  cx_double res(double(poly[0]), 0.0);
  for (long i=1; i<lsize(poly); i++) {
    res *= x;
    res += cx_double(double(poly[i]));
  }
  return res;
}

void canonicalEmbedding(std::vector<cx_double>& v, const zzX& f, const PAlgebra& palg)
{
  FHE_TIMER_START;
  long m = palg.getM();
  long phimBy2 = divc(palg.getPhiM(),2);
  vector<long> zmstar(phimBy2); // the first half of Zm*
  for (long i=1, idx=0; i<=m/2; i++)
    if (palg.inZmStar(i)) zmstar[idx++] = i;

  v.resize(phimBy2);
  NTL_EXEC_RANGE(phimBy2, first, last)
  for (long i=first; i < last; ++i) {
    auto rou = std::polar<double>(1.0, -(2*pi*zmstar[i])/m); // root of unity
    v[i] = complexEvalPoly(f,rou);
  }
  NTL_EXEC_RANGE_END
  FHE_TIMER_STOP;
}
void embedInSlots(zzX& f, const std::vector<cx_double>& v,
                  const PAlgebra& palg, bool strictInverse)
{
  NTL::Error("embedInSlots not implemented\n");
}
#endif // ifdef FFT_NATIVE
#endif // ifdef FFT_ARMA
<commit_msg>handle PAlgebra.NSlots < phim(m)/2<commit_after>/* Copyright (C) 2012-2017 IBM Corp.
 * This program is 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. See accompanying LICENSE file.
 */
/**
 * @file fft.cpp - computing the canonical embedding and related norms
 **/
#include <complex>
#include <cmath>
#include <numeric> // std::accumulate
#include <NTL/BasicThreadPool.h>
#include "NumbTh.h"
#include "timing.h"
#include "norms.h"
#include "PAlgebra.h"
NTL_CLIENT

const double pi = 4 * std::atan(1);

#ifdef FFT_ARMA
#warning "canonicalEmbedding implemented via Armadillo"
#include <armadillo>
void convert(zzX& to, const arma::vec& from)
{
  to.SetLength(from.size());
  NTL_EXEC_RANGE(to.length(), first, last)
  for (long i=first; i<last; i++)
    to[i] = std::round(from[i]);
  NTL_EXEC_RANGE_END
}
void convert(arma::vec& to, const zzX& from)
{
  to.resize(from.length());
  NTL_EXEC_RANGE(from.length(), first, last)
  for (long i=first; i<last; i++)
    to[i] = from[i];
  NTL_EXEC_RANGE_END
}

// Computing the canonical embedding. This function returns in v only
// the first half of the entries, the others are v[phi(m)-i]=conj(v[i])
void canonicalEmbedding(std::vector<cx_double>& v,
                        const zzX& f, const PAlgebra& palg)
{
  FHE_TIMER_START;
  long m = palg.getM();
  long phimBy2 = divc(palg.getPhiM(),2);
  arma::vec av; // convert to vector of doubles
  convert(av, f);
  arma::cx_vec avv = arma::fft(av,m); // compute the full FFT

  v.resize(phimBy2); // the first half of Zm*

  if (palg.getNSlots()==phimBy2) // order roots by the palg order
    for (long i=0; i<phimBy2; i++)
      v[phimBy2-i-1] = avv[palg.ith_rep(i)];
  else                           // order roots sequentially
    for (long i=1, idx=0; i<=m/2; i++)
      if (palg.inZmStar(i)) v[idx++] = avv[i];
}

// Roughly the inverse of canonicalEmbedding, except for scaling and
// rounding issues. Calling embedInSlots(f,v,palg,1.0,strictInverse=true)
// after setting canonicalEmbedding(v, f, palg), is sure to recover the
// same f, but embedInSlots(f,v,palg,1.0,strictInverse=false) may return
// a different "nearby" f.
void embedInSlots(zzX& f, const std::vector<cx_double>& v,
                  const PAlgebra& palg, double scaling, bool strictInverse)
{
  FHE_TIMER_START;
  long m = palg.getM();
  long phimBy2 = divc(palg.getPhiM(),2);
  arma::cx_vec avv(m);
  for (auto& x: avv) x = 0.0;

  if (palg.getNSlots()==phimBy2) // roots ordered by the palg order
    for (long i=0; i<palg.getNSlots(); i++) {
      long j = palg.ith_rep(i);
      avv[j] = scaling*v[palg.getNSlots()-i-1];
      avv[m-j] = std::conj(avv[j]);
    }
  else                           // roots ordered sequentially
    for (long i=1, idx=0; i<=m/2; i++) {
      if (palg.inZmStar(i)) {
        avv[i] = scaling*v[idx++];
        avv[m-i] = std::conj(avv[i]);
      }
    }
  arma::vec av = arma::real(arma::ifft(avv,m)); // compute the inverse FFT

  // If v was obtained by canonicalEmbedding(v,f,palg,1.0) then we have
  // the guarantee that m*av is an integral polynomial, and moreover
  // m*av mod Phi_m(x) is in m*Z[X].
  if (strictInverse) av *= m; // scale up by m
  convert(f, av);    // round to an integer polynomial
  reduceModPhimX(f, palg);
  if (strictInverse) f /= m;  // scale down by m
  normalize(f);
}
#else
#ifdef FFT_NATIVE
#warning "canonicalEmbedding implemented via slow DFT, expect very slow key-generation"
// An extremely lame implementation of the canonical embedding

// evaluate poly(x) using Horner's rule
cx_double complexEvalPoly(const zzX& poly, const cx_double& x)
{
  if (lsize(poly)<=0) return cx_double(0.0,0.0);
  cx_double res(double(poly[0]), 0.0);
  for (long i=1; i<lsize(poly); i++) {
    res *= x;
    res += cx_double(double(poly[i]));
  }
  return res;
}

void canonicalEmbedding(std::vector<cx_double>& v, const zzX& f, const PAlgebra& palg)
{
  FHE_TIMER_START;
  long m = palg.getM();
  long phimBy2 = divc(palg.getPhiM(),2);
  vector<long> zmstar(phimBy2); // the first half of Zm*

  if (palg.getNSlots()==phimBy2) // order roots by the palg order
    for (long i=0; i<phimBy2; i++)
      zmstar[phimBy2-i-1] = palg.ith_rep(i);
  else                           // order roots sequentially
    for (long i=1, idx=0; i<=m/2; i++)
      if (palg.inZmStar(i)) zmstar[idx++] = i;

  v.resize(phimBy2);
  NTL_EXEC_RANGE(phimBy2, first, last)
  for (long i=first; i < last; ++i) {
    auto rou = std::polar<double>(1.0, -(2*pi*zmstar[i])/m); // root of unity
    v[i] = complexEvalPoly(f,rou);
  }
  NTL_EXEC_RANGE_END
  FHE_TIMER_STOP;
}
void embedInSlots(zzX& f, const std::vector<cx_double>& v,
                  const PAlgebra& palg, bool strictInverse)
{
  NTL::Error("embedInSlots not implemented\n");
}
#endif // ifdef FFT_NATIVE
#endif // ifdef FFT_ARMA
<|endoftext|>