<commit_before>#include "../base/SRC_FIRST.hpp"
#include "renderer.hpp"
#include "utils.hpp"
#include "framebuffer.hpp"
#include "renderbuffer.hpp"
#include "resource_manager.hpp"
#include "internal/opengl.hpp"
#include "../base/logging.hpp"

namespace yg
{
  namespace gl
  {
    const yg::Color Renderer::s_bgColor(192, 192, 192, 255);

    void Renderer::State::apply(BaseState const * prevBase)
    {
      State const * prevState = static_cast<State const *>(prevBase);

      if (m_frameBuffer)
      {
        bool shouldApply = false;

        if (m_frameBuffer == prevState->m_frameBuffer)
        {
          if (m_isDebugging)
          {
            std::ostringstream out;
            out << "equal frameBuffers, ";
            if (m_frameBuffer)
              out << m_frameBuffer->id() << ", " << prevState->m_frameBuffer->id();
            else
              out << "(null), (null)";

            LOG(LINFO, (out.str().c_str()));
          }

          if (m_renderTarget != prevState->m_renderTarget)
          {
            if (m_isDebugging)
            {
              std::ostringstream out;
              out << "non-equal renderBuffers, ";

              if (prevState->m_renderTarget)
                out << prevState->m_renderTarget->id();
              else
                out << "(null)";

              out << " => ";

              if (m_renderTarget)
                out << m_renderTarget->id();
              else
                out << "(null)";

              LOG(LINFO, (out.str().c_str()));
            }

            m_frameBuffer->setRenderTarget(m_renderTarget);
            shouldApply = true;
          }
          else
          {
            if (m_isDebugging)
            {
              std::ostringstream out;
              out << "equal renderBuffers, ";

              if (m_renderTarget)
                out << m_renderTarget->id() << ", " << m_renderTarget->id();
              else
                out << "(null), (null)";
              LOG(LINFO, (out.str().c_str()));
            }
          }

          if (m_depthBuffer != prevState->m_depthBuffer)
          {
            if (m_isDebugging)
            {
              std::ostringstream out;
              out << "non-equal depthBuffers, ";

              if (prevState->m_depthBuffer)
                out << prevState->m_depthBuffer->id();
              else
                out << "(null)";

              out << " => ";

              if (m_depthBuffer)
                out << m_depthBuffer->id();
              else
                out << "(null)";

              LOG(LINFO, (out.str().c_str()));
            }

            m_frameBuffer->setDepthBuffer(m_depthBuffer);
            shouldApply = true;
          }
          else
          {
            if (m_isDebugging)
            {
              std::ostringstream out;
              out << "equal depthBuffers, ";
              if (m_depthBuffer)
                out << m_depthBuffer->id() << ", " << m_depthBuffer->id();
              else
                out << "(null), (null)";
              LOG(LINFO, (out.str().c_str()));
            }
          }

        }
        else
        {
          if (m_isDebugging)
          {
            ostringstream out;
            out << "non-equal frameBuffers, ";
            if (prevState->m_frameBuffer)
              out << prevState->m_frameBuffer->id() << ", ";
            else
              out << "(null)";

            out << " => ";

            if (m_frameBuffer)
              out << m_frameBuffer->id() << ", ";
            else
              out << "(null)";

            LOG(LINFO, (out.str().c_str()));

            out.str("");
            out << "renderTarget=";
            if (m_renderTarget)
              out << m_renderTarget->id();
            else
              out << "(null)";

            out << ", depthBuffer=";
            if (m_depthBuffer)
              out << m_depthBuffer->id();
            else
              out << "(null)";

            LOG(LINFO, (out.str().c_str()));
          }

          m_frameBuffer->setRenderTarget(m_renderTarget);
          m_frameBuffer->setDepthBuffer(m_depthBuffer);
          shouldApply = true;
        }

        if (shouldApply)
          m_frameBuffer->makeCurrent();
      }
      else
        CHECK(false, ());
    }

    Renderer::Params::Params()
      : m_isDebugging(false),
        m_renderQueue(0)
    {}

    Renderer::Renderer(Params const & params)
      : m_isDebugging(params.m_isDebugging),
        m_isRendering(false)
    {
      m_frameBuffer = params.m_frameBuffer;
      m_resourceManager = params.m_resourceManager;

      if (m_frameBuffer)
      {
        m_renderTarget = m_frameBuffer->renderTarget();
        m_depthBuffer = m_frameBuffer->depthBuffer();
      }

      m_renderQueue = params.m_renderQueue;
    }

    Renderer::~Renderer()
    {}

    shared_ptr<ResourceManager> const & Renderer::resourceManager() const
    {
      return m_resourceManager;
    }

    void Renderer::beginFrame()
    {
      m_isRendering = true;

      if (m_renderQueue)
        return;

      if (m_frameBuffer)
        m_frameBuffer->makeCurrent();
    }

    bool Renderer::isRendering() const
    {
      return m_isRendering;
    }

    void Renderer::endFrame()
    {
        m_isRendering = false;
    }

    shared_ptr<FrameBuffer> const & Renderer::frameBuffer() const
    {
      return m_frameBuffer;
    }

    shared_ptr<RenderTarget> const & Renderer::renderTarget() const
    {
      return m_renderTarget;
    }

    void Renderer::setRenderTarget(shared_ptr<RenderTarget> const & rt)
    {
      m_renderTarget = rt;

      if (!m_renderQueue)
      {
        m_frameBuffer->setRenderTarget(rt);
        m_frameBuffer->makeCurrent(); //< to attach renderTarget
      }
    }

    void Renderer::resetRenderTarget()
    {
      m_renderTarget.reset();
      if (!m_renderQueue)
        m_frameBuffer->resetRenderTarget();
    }

    shared_ptr<RenderBuffer> const & Renderer::depthBuffer() const
    {
      return m_depthBuffer;
    }

    void Renderer::setDepthBuffer(shared_ptr<RenderBuffer> const & rt)
    {
      m_depthBuffer = rt;

      if (!m_renderQueue)
        m_frameBuffer->setDepthBuffer(rt);
    }

    void Renderer::resetDepthBuffer()
    {
      m_depthBuffer.reset();

      if (!m_renderQueue)
        m_frameBuffer->resetDepthBuffer();
    }

    Renderer::ClearCommand::ClearCommand(yg::Color const & color,
                                         bool clearRT,
                                         float depth,
                                         bool clearDepth)
      : m_color(color),
        m_clearRT(clearRT),
        m_depth(depth),
        m_clearDepth(clearDepth)
    {}

    void Renderer::ClearCommand::perform()
    {
      if (isDebugging())
        LOG(LINFO, ("performing clear command"));
      OGLCHECK(glClearColor(m_color.r / 255.0f,
                            m_color.g / 255.0f,
                            m_color.b / 255.0f,
                            m_color.a / 255.0f));
 #ifdef OMIM_GL_ES
      OGLCHECK(glClearDepthf(m_depth));
 #else
      OGLCHECK(glClearDepth(m_depth));
 #endif

      GLbitfield mask = 0;
      if (m_clearRT)
        mask |= GL_COLOR_BUFFER_BIT;
      if (m_clearDepth)
        mask |= GL_DEPTH_BUFFER_BIT;

      OGLCHECK(glDepthMask(GL_TRUE));

      OGLCHECK(glClear(mask));
    }

    void Renderer::clear(yg::Color const & c, bool clearRT, float depth, bool clearDepth)
    {
      shared_ptr<ClearCommand> command(new ClearCommand(c, clearRT, depth, clearDepth));
      processCommand(command);
    }

    shared_ptr<BaseState> const Renderer::createState() const
    {
      return shared_ptr<BaseState>(new State());
    }

    void Renderer::getState(BaseState * baseState)
    {
      State * state = static_cast<State *>(baseState);

      state->m_frameBuffer = m_frameBuffer;
      state->m_renderTarget = m_renderTarget;
      state->m_depthBuffer = m_depthBuffer;
      state->m_resourceManager = m_resourceManager;
    }

    void Renderer::FinishCommand::perform()
    {
      if (m_isDebugging)
        LOG(LINFO, ("performing FinishCommand command"));
      OGLCHECK(glFinish());
    }

    void Renderer::finish()
    {
      shared_ptr<Command> command(new FinishCommand());
      processCommand(command);
    }

    void Renderer::onSize(unsigned int width, unsigned int height)
    {
      if (width < 2) width = 2;
      if (height < 2) height = 2;

      m_width = width;
      m_height = height;

      if (m_frameBuffer)
        m_frameBuffer->onSize(width, height);
    }

    unsigned int Renderer::width() const
    {
      return m_width;
    }

    unsigned int Renderer::height() const
    {
      return m_height;
    }

    bool Renderer::isDebugging() const
    {
      return m_isDebugging;
    }

    void Renderer::processCommand(shared_ptr<Command> const & command, Packet::EType type)
    {
//      command->m_isDebugging = false;
      command->m_isDebugging = renderQueue();

      if (renderQueue())
      {
        shared_ptr<BaseState> state = createState();
        getState(state.get());
        m_renderQueue->processPacket(Packet(state, command, type));
      }
      else
        command->perform();
    }

    PacketsQueue * Renderer::renderQueue()
    {
      return m_renderQueue;
    }

    void Renderer::markFrameBoundary()
    {
      if (m_renderQueue)
        m_renderQueue->processPacket(Packet(Packet::ECheckPoint));
    }
  }
}
<commit_msg>initializing width and height with invalid values.<commit_after>#include "../base/SRC_FIRST.hpp"
#include "renderer.hpp"
#include "utils.hpp"
#include "framebuffer.hpp"
#include "renderbuffer.hpp"
#include "resource_manager.hpp"
#include "internal/opengl.hpp"
#include "../base/logging.hpp"

namespace yg
{
  namespace gl
  {
    const yg::Color Renderer::s_bgColor(192, 192, 192, 255);

    void Renderer::State::apply(BaseState const * prevBase)
    {
      State const * prevState = static_cast<State const *>(prevBase);

      if (m_frameBuffer)
      {
        bool shouldApply = false;

        if (m_frameBuffer == prevState->m_frameBuffer)
        {
          if (m_isDebugging)
          {
            std::ostringstream out;
            out << "equal frameBuffers, ";
            if (m_frameBuffer)
              out << m_frameBuffer->id() << ", " << prevState->m_frameBuffer->id();
            else
              out << "(null), (null)";

            LOG(LINFO, (out.str().c_str()));
          }

          if (m_renderTarget != prevState->m_renderTarget)
          {
            if (m_isDebugging)
            {
              std::ostringstream out;
              out << "non-equal renderBuffers, ";

              if (prevState->m_renderTarget)
                out << prevState->m_renderTarget->id();
              else
                out << "(null)";

              out << " => ";

              if (m_renderTarget)
                out << m_renderTarget->id();
              else
                out << "(null)";

              LOG(LINFO, (out.str().c_str()));
            }

            m_frameBuffer->setRenderTarget(m_renderTarget);
            shouldApply = true;
          }
          else
          {
            if (m_isDebugging)
            {
              std::ostringstream out;
              out << "equal renderBuffers, ";

              if (m_renderTarget)
                out << m_renderTarget->id() << ", " << m_renderTarget->id();
              else
                out << "(null), (null)";
              LOG(LINFO, (out.str().c_str()));
            }
          }

          if (m_depthBuffer != prevState->m_depthBuffer)
          {
            if (m_isDebugging)
            {
              std::ostringstream out;
              out << "non-equal depthBuffers, ";

              if (prevState->m_depthBuffer)
                out << prevState->m_depthBuffer->id();
              else
                out << "(null)";

              out << " => ";

              if (m_depthBuffer)
                out << m_depthBuffer->id();
              else
                out << "(null)";

              LOG(LINFO, (out.str().c_str()));
            }

            m_frameBuffer->setDepthBuffer(m_depthBuffer);
            shouldApply = true;
          }
          else
          {
            if (m_isDebugging)
            {
              std::ostringstream out;
              out << "equal depthBuffers, ";
              if (m_depthBuffer)
                out << m_depthBuffer->id() << ", " << m_depthBuffer->id();
              else
                out << "(null), (null)";
              LOG(LINFO, (out.str().c_str()));
            }
          }

        }
        else
        {
          if (m_isDebugging)
          {
            ostringstream out;
            out << "non-equal frameBuffers, ";
            if (prevState->m_frameBuffer)
              out << prevState->m_frameBuffer->id() << ", ";
            else
              out << "(null)";

            out << " => ";

            if (m_frameBuffer)
              out << m_frameBuffer->id() << ", ";
            else
              out << "(null)";

            LOG(LINFO, (out.str().c_str()));

            out.str("");
            out << "renderTarget=";
            if (m_renderTarget)
              out << m_renderTarget->id();
            else
              out << "(null)";

            out << ", depthBuffer=";
            if (m_depthBuffer)
              out << m_depthBuffer->id();
            else
              out << "(null)";

            LOG(LINFO, (out.str().c_str()));
          }

          m_frameBuffer->setRenderTarget(m_renderTarget);
          m_frameBuffer->setDepthBuffer(m_depthBuffer);
          shouldApply = true;
        }

        if (shouldApply)
          m_frameBuffer->makeCurrent();
      }
      else
        CHECK(false, ());
    }

    Renderer::Params::Params()
      : m_isDebugging(false),
        m_renderQueue(0)
    {}

    Renderer::Renderer(Params const & params)
      : m_isDebugging(params.m_isDebugging),
        m_isRendering(false),
        m_width(0),
        m_height(0)
    {
      m_frameBuffer = params.m_frameBuffer;
      m_resourceManager = params.m_resourceManager;

      if (m_frameBuffer)
      {
        m_renderTarget = m_frameBuffer->renderTarget();
        m_depthBuffer = m_frameBuffer->depthBuffer();
      }

      m_renderQueue = params.m_renderQueue;
    }

    Renderer::~Renderer()
    {}

    shared_ptr<ResourceManager> const & Renderer::resourceManager() const
    {
      return m_resourceManager;
    }

    void Renderer::beginFrame()
    {
      m_isRendering = true;

      if (m_renderQueue)
        return;

      if (m_frameBuffer)
        m_frameBuffer->makeCurrent();
    }

    bool Renderer::isRendering() const
    {
      return m_isRendering;
    }

    void Renderer::endFrame()
    {
        m_isRendering = false;
    }

    shared_ptr<FrameBuffer> const & Renderer::frameBuffer() const
    {
      return m_frameBuffer;
    }

    shared_ptr<RenderTarget> const & Renderer::renderTarget() const
    {
      return m_renderTarget;
    }

    void Renderer::setRenderTarget(shared_ptr<RenderTarget> const & rt)
    {
      m_renderTarget = rt;

      if (!m_renderQueue)
      {
        m_frameBuffer->setRenderTarget(rt);
        m_frameBuffer->makeCurrent(); //< to attach renderTarget
      }
    }

    void Renderer::resetRenderTarget()
    {
      m_renderTarget.reset();
      if (!m_renderQueue)
        m_frameBuffer->resetRenderTarget();
    }

    shared_ptr<RenderBuffer> const & Renderer::depthBuffer() const
    {
      return m_depthBuffer;
    }

    void Renderer::setDepthBuffer(shared_ptr<RenderBuffer> const & rt)
    {
      m_depthBuffer = rt;

      if (!m_renderQueue)
        m_frameBuffer->setDepthBuffer(rt);
    }

    void Renderer::resetDepthBuffer()
    {
      m_depthBuffer.reset();

      if (!m_renderQueue)
        m_frameBuffer->resetDepthBuffer();
    }

    Renderer::ClearCommand::ClearCommand(yg::Color const & color,
                                         bool clearRT,
                                         float depth,
                                         bool clearDepth)
      : m_color(color),
        m_clearRT(clearRT),
        m_depth(depth),
        m_clearDepth(clearDepth)
    {}

    void Renderer::ClearCommand::perform()
    {
      if (isDebugging())
        LOG(LINFO, ("performing clear command"));
      OGLCHECK(glClearColor(m_color.r / 255.0f,
                            m_color.g / 255.0f,
                            m_color.b / 255.0f,
                            m_color.a / 255.0f));
 #ifdef OMIM_GL_ES
      OGLCHECK(glClearDepthf(m_depth));
 #else
      OGLCHECK(glClearDepth(m_depth));
 #endif

      GLbitfield mask = 0;
      if (m_clearRT)
        mask |= GL_COLOR_BUFFER_BIT;
      if (m_clearDepth)
        mask |= GL_DEPTH_BUFFER_BIT;

      OGLCHECK(glDepthMask(GL_TRUE));

      OGLCHECK(glClear(mask));
    }

    void Renderer::clear(yg::Color const & c, bool clearRT, float depth, bool clearDepth)
    {
      shared_ptr<ClearCommand> command(new ClearCommand(c, clearRT, depth, clearDepth));
      processCommand(command);
    }

    shared_ptr<BaseState> const Renderer::createState() const
    {
      return shared_ptr<BaseState>(new State());
    }

    void Renderer::getState(BaseState * baseState)
    {
      State * state = static_cast<State *>(baseState);

      state->m_frameBuffer = m_frameBuffer;
      state->m_renderTarget = m_renderTarget;
      state->m_depthBuffer = m_depthBuffer;
      state->m_resourceManager = m_resourceManager;
    }

    void Renderer::FinishCommand::perform()
    {
      if (m_isDebugging)
        LOG(LINFO, ("performing FinishCommand command"));
      OGLCHECK(glFinish());
    }

    void Renderer::finish()
    {
      shared_ptr<Command> command(new FinishCommand());
      processCommand(command);
    }

    void Renderer::onSize(unsigned int width, unsigned int height)
    {
      if (width < 2) width = 2;
      if (height < 2) height = 2;

      m_width = width;
      m_height = height;

      if (m_frameBuffer)
        m_frameBuffer->onSize(width, height);
    }

    unsigned int Renderer::width() const
    {
      return m_width;
    }

    unsigned int Renderer::height() const
    {
      return m_height;
    }

    bool Renderer::isDebugging() const
    {
      return m_isDebugging;
    }

    void Renderer::processCommand(shared_ptr<Command> const & command, Packet::EType type)
    {
//      command->m_isDebugging = false;
      command->m_isDebugging = renderQueue();

      if (renderQueue())
      {
        shared_ptr<BaseState> state = createState();
        getState(state.get());
        m_renderQueue->processPacket(Packet(state, command, type));
      }
      else
        command->perform();
    }

    PacketsQueue * Renderer::renderQueue()
    {
      return m_renderQueue;
    }

    void Renderer::markFrameBoundary()
    {
      if (m_renderQueue)
        m_renderQueue->processPacket(Packet(Packet::ECheckPoint));
    }
  }
}
<|endoftext|>


<commit_before>/*-------------Lanczos.cpp----------------------------------------------------//
*
* Purpose: To diagonalize a random matrix using the Lanczos algorithm
*
*   Notes: Compile with (for Arch systems):
*              g++ -I /usr/include/eigen3/ Lanczos.cpp
*          0's along the prime diagonal. I don't know what this means.
*
*-----------------------------------------------------------------------------*/

#include <iostream>
#include <Eigen/Core>
#include <Eigen/QR>
#include <random>
#include <vector>
#include <math.h>

using namespace Eigen;

// Function for the lanczos algorithm, returns Tri-diagonal matrix
MatrixXd lanczos(MatrixXd &d_matrix);

// Function for QR decomposition
MatrixXd qrdecomp(MatrixXd &Tridiag);

// Function to perform the Power Method
void p_method(MatrixXd &Tridiag, MatrixXd &Q);

// Function to return sign of value (signum function)
int sign(double value);

// Function to check eigenvectors and values
void eigentest(MatrixXd &d_matrix, MatrixXd &Q);

/*----------------------------------------------------------------------------//
* MAIN
*-----------------------------------------------------------------------------*/

int main(){
    int size = 200;
    MatrixXd d_matrix(size,size);

    // set up random device
    static std::random_device rd;
    int seed = rd();
    static std::mt19937 gen(seed);
    std::uniform_real_distribution<double> dist(0,1);

    for (size_t i = 0; i < d_matrix.rows(); ++i){
        for (size_t j = 0; j <= i; ++j){
            d_matrix(i,j) = dist(gen);
            d_matrix(j,i) = d_matrix(i,j);
        }
    }

    MatrixXd Tridiag = lanczos(d_matrix);

    std::cout << '\n' << "Tridiagonal matrix is: \n";

    for (size_t i = 0; i < Tridiag.rows(); ++i){
        for (size_t j = 0; j < Tridiag.cols(); ++j){
            std::cout << Tridiag(i, j) << '\t';
        }
        std::cout << '\n';
    }

    std::cout << '\n';

    MatrixXd Q = qrdecomp(Tridiag);

    MatrixXd Qtemp = Q;

    std::cout << Q << '\n';

    std::cout << "Finding eigenvalues: " << '\n';
    p_method(Tridiag, Q);

    Qtemp = Qtemp - Q;
    std::cout << "After the Power Method: " << Qtemp.squaredNorm() << '\n';
    eigentest(Tridiag, Q);

}

/*----------------------------------------------------------------------------//
* SUBROUTINE
*-----------------------------------------------------------------------------*/

// Function for the lanczos algorithm, returns Tri-diagonal matrix
MatrixXd lanczos(MatrixXd &d_matrix){

    // Creating random device
    static std::random_device rd;
    int seed = rd();
    static std::mt19937 gen(seed);
    std::uniform_real_distribution<double> dist(0,1);

    // Defining values
    double threshold = 0.01;
    int j = 0, j_tot = 5;
    int size = d_matrix.rows();

    // Setting beta arbitrarily large for now
    double beta = 10;

    // generating the first rayleigh vector
    // alpha is actually just a double... sorry about that.
    MatrixXd rayleigh(d_matrix.rows(),1), q(d_matrix.rows(),1),
             alpha(1, 1);
    MatrixXd identity = MatrixXd::Identity(d_matrix.rows(), d_matrix.cols());

    // krylov is the krylovian subspace... Note, there might be a dynamic way to
    // do this. Something like:
    //std::vector <MatrixXd> krylov;
    MatrixXd krylov(d_matrix.rows(), j_tot);

    for (size_t i = 0; i < size; ++i){
        rayleigh(i) = dist(gen);
    }

    //std::cout << rayleigh << '\n';

    //while (beta > threshold){
    for (size_t i = 0; i < j_tot; ++i){
        beta = rayleigh.norm();
        //std::cout << "beta is: \n" << beta << '\n';

        q = rayleigh / beta;
        //std::cout << "q is: \n" << q << '\n';

        alpha = q.transpose() * d_matrix * q;
        //std::cout << "alpha is \n" << alpha << '\n';

        if (j == 0){
            rayleigh = (d_matrix - alpha(0,0) * identity) * q;
        }
        else{
            rayleigh = (d_matrix - alpha(0,0) * identity) * q
                       - beta * krylov.col(j - 1);

        }
        //std::cout << "rayleigh is: \n" << rayleigh <<'\n';
        //std::cout << "i is: " << i << '\n';

        //krylov.push_back(q);
        krylov.col(j) = q;
        j = j+1;
        // std::cout << j << '\n';
    }

    MatrixXd krylov_id = krylov.transpose() * krylov;
    std::cout << "The identity matrix from the krylov subspace is: \n"
              << krylov_id << '\n';

    MatrixXd T(j_tot,j_tot);
    T = krylov.transpose() * d_matrix * krylov;

    return T;
}

// Function for QR decomposition
// Because we only need Q for the power method, I will retun only Q
MatrixXd qrdecomp(MatrixXd &Tridiag){
    // Q is and orthonormal vector => Q'Q = 1
    MatrixXd Q(Tridiag.rows(), Tridiag.cols());
    MatrixXd Id = MatrixXd::Identity(Tridiag.rows(), Tridiag.cols());

    // R is the upper triangular matrix
    MatrixXd R = Tridiag;

    int row_num = Tridiag.rows();
    int countx = 0, county = 0;

    // Scale R
    double sum = 0.0, sigma, tau, fak, max_val = 0;

/*
    for (int i = 0; i < row_num; ++i){
        for (int j = 0; j < row_num; ++j){
            if (R(i,j) > max_val){
                max_val = R(i,j);
            }
        }
    }

    for (int i = 0; i < row_num; ++i){
        for (int j = 0; j < row_num; ++j){
            R(i,j) /= max_val;
        }
    }
*/

    bool sing;

    // Defining vectors for algorithm
    MatrixXd diag(row_num,1);

    for (size_t i = 0; i < row_num; ++i){

        // determining l_2 norm
        sum = 0.0;
        for (size_t j = i; j < row_num; ++j){
            sum += R(j,i) * R(j,i);
            std::cout << R(j,i) << '\n';
        }
        sum = sqrt(sum);

        std::cout << "sum is: " << sum << '\n';

        if (sum == 0.0){
            sing = true;
            diag(i) = 0.0;
            std::cout << "MATRIX IS SINGULAR!!!" << '\n';
        }
        else{

            if (R(i,i) >= 0){
                diag(i) = -sum;
            }
            else{
                diag(i) = sum;
            }
            fak = sqrt(sum * (sum + abs(R(i,i))));
            R(i,i) = R(i,i) - diag(i);
            for (size_t j = i; j < row_num; ++j){
                R(j,i) = R(j,i) / fak;
            }

            // Creating blocks to work with
            MatrixXd block1 = R.block(i, i+1, row_num-i, row_num -i-1);
            MatrixXd block2 = R.block(i, i, row_num-i,1);

            block1 = block1 - block2 * (block2.transpose() * block1);

            std::cout << R << '\n' <<  '\n' << block1 << '\n';
            // setting values back to what they need to be
            countx = 0;
            for (int j = i+1; j < row_num; ++j){
                for (int k = i; k < row_num; ++k){
                    R(k,j) = block1(k-i, j-i-1);
                }
            }
        }
    }

    MatrixXd z(row_num, 1);

    // Explicitly defining Q
    // Create column block for multiplication
    for (size_t i = 0; i < row_num; ++i){
        MatrixXd Idblock = Id.block(0, i, row_num, 1);
        for (int j = row_num-1; j >= 0; --j){
            z = Idblock;

            // Creating blocks for multiplication
            MatrixXd zblock = z.block(j, 0, row_num - j, 1);
            MatrixXd Rblock = R.block(j, j, row_num - j, 1);

            // Performing multiplication
            zblock = zblock - Rblock * (Rblock.transpose() * zblock);

            // Set xblock up for next iteration of k
            for (int k = j; k < row_num; ++k){
                z(k) = zblock(k-j);
            }
        }

        Q.col(i) = z;

        //std::cout << Q << '\n';
    }

    // Remove lower left from R
    for (int i = 0; i < row_num; ++i){
        R(i,i) = diag(i);
        for (int j = 0; j < i; ++j){
            R(i,j) = 0;
        }
    }

    //std::cout << "R is: " << '\n' << R << '\n';

    MatrixXd temp = Q.transpose() * Q;

/*
    std::cout << "Truncated Q^T * Q is:" << '\n';
    for (int i = 0; i < temp.rows(); ++i){
        for (int j = 0; j < temp.cols(); ++j){
            if (temp(i,j) < 0.00000000001){
                std::cout << 0 << '\t';
            }
            else{
                std::cout << temp(i,j) <<'\t';
            }
        }
        std::cout << '\n';
    }
    std::cout << '\n';
*/

    //std::cout << "Q^T * Q is: " << '\n' << Q * Q.transpose() << '\n' << '\n';
    //std::cout << "QR - A is: " << '\n' << Q*R - Tridiag << '\n';
    //std::cout << "Q^T * A - R: " << '\n'
    //          << Q.transpose() * Tridiag - R << '\n' << '\n';

    return Q.transpose();
}

// Function to perform the Power Method
void p_method(MatrixXd &Tridiag, MatrixXd &Q){

    // Find all eigenvectors
    MatrixXd eigenvectors(Tridiag.rows(), Tridiag.cols());
    MatrixXd Z(Tridiag.rows(), Tridiag.cols());
    MatrixXd Qtemp = Q;

    // Iteratively defines eigenvectors
    for (int i = 0; i < Tridiag.rows(); ++i){
        Z = Tridiag * Q;
        Q = qrdecomp(Z);

    }

    Qtemp = Qtemp - Q;
    std::cout << "This should not be 0: " << Qtemp.squaredNorm() << '\n';

}

// Function to return sign of value (signum function)
int sign(double value){
    if (value < 0.0){
        return -1;
    }
    else if (value > 0){
        return 1;
    }
    else {
        return 0;
    }
}

// Function to check eigenvectors and values
void eigentest(MatrixXd &Tridiag, MatrixXd &Q){

    // Calculating the Rayleigh quotient (v^t * A * v) / (v^t * v)
    // Note, that this should be a representation of eigenvalues

    std::vector<double> eigenvalues(Tridiag.rows());
    MatrixXd eigenvector(Tridiag.rows(),1);
    double QQ, QAQ;

    for (size_t i = 0; i < Tridiag.rows(); ++i){
        QQ = Q.col(i).transpose() * Q.col(i);
        QAQ = Q.col(i).transpose() * Tridiag * Q.col(i);
        eigenvalues[i] =  QAQ / QQ;
        std::cout << "eigenvalue is: " << eigenvalues[i] << '\n';

        eigenvector = ((Tridiag * Q.col(i)) / eigenvalues[i]) - Q.col(i);
        std::cout << eigenvector << '\n' << '\n';
        std::cout << "This should be 0: " << '\t'
                  << eigenvector.squaredNorm() << '\n';

    }

}

<commit_msg>QR decomposition passing all tests Now to check diagonals<commit_after>/*-------------Lanczos.cpp----------------------------------------------------//
*
* Purpose: To diagonalize a random matrix using the Lanczos algorithm
*
*   Notes: Compile with (for Arch systems):
*              g++ -I /usr/include/eigen3/ Lanczos.cpp
*          0's along the prime diagonal. I don't know what this means.
*
*-----------------------------------------------------------------------------*/

#include <iostream>
#include <Eigen/Core>
#include <Eigen/QR>
#include <random>
#include <vector>
#include <math.h>

using namespace Eigen;

// Function for the lanczos algorithm, returns Tri-diagonal matrix
MatrixXd lanczos(MatrixXd &d_matrix);

// Function for QR decomposition
MatrixXd qrdecomp(MatrixXd &Tridiag);

// Function to perform the Power Method
void p_method(MatrixXd &Tridiag, MatrixXd &Q);

// Function to return sign of value (signum function)
int sign(double value);

// Function to check eigenvectors and values
void eigentest(MatrixXd &d_matrix, MatrixXd &Q);

/*----------------------------------------------------------------------------//
* MAIN
*-----------------------------------------------------------------------------*/

int main(){
/*
    int size = 200;
    MatrixXd d_matrix(size,size);

    // set up random device
    static std::random_device rd;
    int seed = rd();
    static std::mt19937 gen(seed);
    std::uniform_real_distribution<double> dist(0,1);

    for (size_t i = 0; i < d_matrix.rows(); ++i){
        for (size_t j = 0; j <= i; ++j){
            d_matrix(i,j) = dist(gen);
            d_matrix(j,i) = d_matrix(i,j);
        }
    }

    Tridiag = lanczos(d_matrix);

    std::cout << '\n' << "Tridiagonal matrix is: \n";

    for (size_t i = 0; i < Tridiag.rows(); ++i){
        for (size_t j = 0; j < Tridiag.cols(); ++j){
            std::cout << Tridiag(i, j) << '\t';
        }
        std::cout << '\n';
    }

    std::cout << '\n';
*/

    MatrixXd Tridiag(4,4);
    Tridiag <<  2, 1, 3, 5,
                -1, 0, 7, 1,
                0,-1,-1,3,
                -3,7,4,3;

    MatrixXd Q = qrdecomp(Tridiag);

/*
    MatrixXd Qtemp = Q;

    std::cout << Q << '\n';

    std::cout << "Finding eigenvalues: " << '\n';
    p_method(Tridiag, Q);

    Qtemp = Qtemp - Q;
    std::cout << "After the Power Method: " << Qtemp.squaredNorm() << '\n';
    eigentest(Tridiag, Q);
*/

}

/*----------------------------------------------------------------------------//
* SUBROUTINE
*-----------------------------------------------------------------------------*/

// Function for the lanczos algorithm, returns Tri-diagonal matrix
MatrixXd lanczos(MatrixXd &d_matrix){

    // Creating random device
    static std::random_device rd;
    int seed = rd();
    static std::mt19937 gen(seed);
    std::uniform_real_distribution<double> dist(0,1);

    // Defining values
    double threshold = 0.01;
    int j = 0, j_tot = 5;
    int size = d_matrix.rows();

    // Setting beta arbitrarily large for now
    double beta = 10;

    // generating the first rayleigh vector
    // alpha is actually just a double... sorry about that.
    MatrixXd rayleigh(d_matrix.rows(),1), q(d_matrix.rows(),1),
             alpha(1, 1);
    MatrixXd identity = MatrixXd::Identity(d_matrix.rows(), d_matrix.cols());

    // krylov is the krylovian subspace... Note, there might be a dynamic way to
    // do this. Something like:
    //std::vector <MatrixXd> krylov;
    MatrixXd krylov(d_matrix.rows(), j_tot);

    for (size_t i = 0; i < size; ++i){
        rayleigh(i) = dist(gen);
    }

    //std::cout << rayleigh << '\n';

    //while (beta > threshold){
    for (size_t i = 0; i < j_tot; ++i){
        beta = rayleigh.norm();
        //std::cout << "beta is: \n" << beta << '\n';

        q = rayleigh / beta;
        //std::cout << "q is: \n" << q << '\n';

        alpha = q.transpose() * d_matrix * q;
        //std::cout << "alpha is \n" << alpha << '\n';

        if (j == 0){
            rayleigh = (d_matrix - alpha(0,0) * identity) * q;
        }
        else{
            rayleigh = (d_matrix - alpha(0,0) * identity) * q
                       - beta * krylov.col(j - 1);

        }
        //std::cout << "rayleigh is: \n" << rayleigh <<'\n';
        //std::cout << "i is: " << i << '\n';

        //krylov.push_back(q);
        krylov.col(j) = q;
        j = j+1;
        // std::cout << j << '\n';
    }

    MatrixXd krylov_id = krylov.transpose() * krylov;
    std::cout << "The identity matrix from the krylov subspace is: \n"
              << krylov_id << '\n';

    MatrixXd T(j_tot,j_tot);
    T = krylov.transpose() * d_matrix * krylov;

    return T;
}

// Function for QR decomposition
// Because we only need Q for the power method, I will retun only Q
MatrixXd qrdecomp(MatrixXd &Tridiag){
    // Q is and orthonormal vector => Q'Q = 1
    MatrixXd Id = MatrixXd::Identity(Tridiag.rows(), Tridiag.cols());
    MatrixXd Q = Id;
    MatrixXd P(Tridiag.rows(), Tridiag.cols());

    // R is the upper triangular matrix
    MatrixXd R = Tridiag;

    int row_num = Tridiag.rows();
    int countx = 0, county = 0;

    // Scale R
    double sum = 0.0, sigma, tau, fak, max_val = 0;

    bool sing;

    // Defining vectors for algorithm
    MatrixXd diag(row_num,1);

    std::cout << R << '\n';

    for (int i = 0; i < row_num-1; ++i){
        diag = MatrixXd::Zero(row_num, 1);

        sum = 0;
        for (size_t j = i; j < row_num; ++j){
            sum += R(j,i) * R(j,i);
            std::cout << R(j,i) << '\n';
        }
        sum = sqrt(sum);

        if (R(i,i) > 0){
            sigma = -sum;
        }
        else{
            sigma = sum;
        }

        std::cout << "sigma is: " << sigma << '\n';

        sum = 0;
        //diag = R.block(i,i, row_num - i, 1);
        std::cout << "diag is: " << '\n';
        for (int j = i; j < row_num; ++j){
            //std::cout << i << '\t' << j << '\n';
            if (j == i){
                diag(j) = R(j,i) + sigma;
            }
            else{
                diag(j) = R(j, i);
            }
            std::cout << diag(j) << '\n';
            sum = sum + diag(j) * diag(j);
        }
        sum = sqrt(sum);

        std::cout << "sum is: " << sum << '\n';

        if (sum > 0.000000000000001){

            for (int j = i; j < row_num; ++j){
                diag(j) = diag(j) / sum;
            }

            std::cout << "normalized diag is: " << '\n' << diag << '\n';

            P = Id - (diag * diag.transpose()) * 2.0;

            R = P * R;
            Q = Q * P;
        }

        std::cout << "R is: " << R << '\n';

    }
    std::cout << "R is: " << R << '\n';
    std::cout << "Q is: " << Q << '\n';

    std::cout << "QR is: " << '\n' << Q*R << '\n';

    std::cout << "Q^T * Q is: " << '\n' << Q.transpose() * Q << '\n' << '\n';
    std::cout << "QR - A is: " << '\n' << Q*R - Tridiag << '\n';
    std::cout << "Q^T * A - R: " << '\n'
              << Q.transpose() * Tridiag - R << '\n' << '\n';

    return Q.transpose();
}

// Function to perform the Power Method
void p_method(MatrixXd &Tridiag, MatrixXd &Q){

    // Find all eigenvectors
    MatrixXd eigenvectors(Tridiag.rows(), Tridiag.cols());
    MatrixXd Z(Tridiag.rows(), Tridiag.cols());
    MatrixXd Qtemp = Q;

    // Iteratively defines eigenvectors
    for (int i = 0; i < Tridiag.rows(); ++i){
        Z = Tridiag * Q;
        Q = qrdecomp(Z);

    }

    Qtemp = Qtemp - Q;
    std::cout << "This should not be 0: " << Qtemp.squaredNorm() << '\n';

}

// Function to return sign of value (signum function)
int sign(double value){
    if (value < 0.0){
        return -1;
    }
    else if (value > 0){
        return 1;
    }
    else {
        return 0;
    }
}

// Function to check eigenvectors and values
void eigentest(MatrixXd &Tridiag, MatrixXd &Q){

    // Calculating the Rayleigh quotient (v^t * A * v) / (v^t * v)
    // Note, that this should be a representation of eigenvalues

    std::vector<double> eigenvalues(Tridiag.rows());
    MatrixXd eigenvector(Tridiag.rows(),1);
    double QQ, QAQ;

    for (size_t i = 0; i < Tridiag.rows(); ++i){
        QQ = Q.col(i).transpose() * Q.col(i);
        QAQ = Q.col(i).transpose() * Tridiag * Q.col(i);
        eigenvalues[i] =  QAQ / QQ;
        std::cout << "eigenvalue is: " << eigenvalues[i] << '\n';

        eigenvector = ((Tridiag * Q.col(i)) / eigenvalues[i]) - Q.col(i);
        std::cout << eigenvector << '\n' << '\n';
        std::cout << "This should be 0: " << '\t'
                  << eigenvector.squaredNorm() << '\n';

    }

}

<|endoftext|>


<commit_before>//===- SILLowerAggregateInstrs.cpp - Aggregate insts to Scalar insts  -----===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2015 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See http://swift.org/LICENSE.txt for license information
// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//
//
// Simplify aggregate instructions into scalar instructions.
//
//===----------------------------------------------------------------------===//

#define DEBUG_TYPE "sil-lower-aggregate-instrs"
#include "swift/SILPasses/Passes.h"
#include "swift/SILPasses/Utils/Local.h"
#include "swift/SIL/SILInstruction.h"
#include "swift/SIL/SILVisitor.h"
#include "swift/SIL/SILBuilder.h"
#include "swift/SIL/SILModule.h"
#include "llvm/ADT/Statistic.h"
#include "llvm/Support/Debug.h"
using namespace swift;
using namespace swift::Lowering;

STATISTIC(NumExpand, "Number of instructions expanded");

//===----------------------------------------------------------------------===//
//                      Higher Level Operation Expansion
//===----------------------------------------------------------------------===//

/// \brief Lower copy_addr into loads/stores/retain/release if we have a
/// non-address only type. We do this here so we can process the resulting
/// loads/stores.
///
/// This peephole implements the following optimizations:
///
/// copy_addr %0 to %1 : $*T
/// ->
///     %new = load %0 : $*T        // Load the new value from the source
///     %old = load %1 : $*T        // Load the old value from the destination
///     strong_retain %new : $T     // Retain the new value
///     strong_release %old : $T    // Release the old
///     store %new to %1 : $*T      // Store the new value to the destination
///
/// copy_addr [take] %0 to %1 : $*T
/// ->
///     %new = load %0 : $*T
///     %old = load %1 : $*T
///     // no retain of %new!
///     strong_release %old : $T
///     store %new to %1 : $*T
///
/// copy_addr %0 to [initialization] %1 : $*T
/// ->
///     %new = load %0 : $*T
///     strong_retain %new : $T
///     // no load/release of %old!
///     store %new to %1 : $*T
///
/// copy_addr [take] %0 to [initialization] %1 : $*T
/// ->
///     %new = load %0 : $*T
///     // no retain of %new!
///     // no load/release of %old!
///     store %new to %1 : $*T
static bool expandCopyAddr(CopyAddrInst *CA) {
  SILModule &M = CA->getModule();
  SILValue Source = CA->getSrc();

  // If we have an address only type don't do anything.
  SILType SrcType = Source.getType();
  if (SrcType.isAddressOnly(M))
    return false;

  SILBuilder Builder(CA);

  // %new = load %0 : $*T
  LoadInst *New = Builder.createLoad(CA->getLoc(), Source);

  SILValue Destination = CA->getDest();

  // If our object type is not trivial, we may need to release the old value and
  // retain the new one.

  // If we have a non-trivial type...
  if (!SrcType.isTrivial(M)) {

    // If we are not initializing:
    // %old = load %1 : $*T
    IsInitialization_t IsInit = CA->isInitializationOfDest();
    LoadInst *Old = nullptr;
    if (IsInitialization_t::IsNotInitialization == IsInit) {
      Old = Builder.createLoad(CA->getLoc(), Destination);
    }

    // If we are not taking and have a reference type:
    //   strong_retain %new : $*T
    // or if we have a non-trivial non-reference type.
    //   copy_value %new : $*T
    IsTake_t IsTake = CA->isTakeOfSrc();
    if (IsTake_t::IsNotTake == IsTake) {
      if (SrcType.hasReferenceSemantics())
        Builder.createStrongRetain(CA->getLoc(), New);
      else
        Builder.createCopyValue(CA->getLoc(), New);
    }

    // If we are not initializing:
    // strong_release %old : $*T
    //   *or*
    // destroy_value %new : $*T
    if (Old) {
      if (SrcType.hasReferenceSemantics())
        Builder.createStrongRelease(CA->getLoc(), Old);
      else
        Builder.createDestroyValue(CA->getLoc(), Old);
    }
  }

  // Create the store.
  Builder.createStore(CA->getLoc(), New, Destination);

  ++NumExpand;
  return true;
}

static bool expandDestroyAddr(DestroyAddrInst *DA) {
  SILModule &Module = DA->getModule();
  SILBuilder Builder(DA);

  // Strength reduce destroy_addr inst into release/store if
  // we have a non-address only type.
  SILValue Addr = DA->getOperand();

  // If we have an address only type, do nothing.
  SILType Type = Addr.getType();
  if (Type.isAddressOnly(Module))
    return false;

  // If we have a non-trivial type...
  if (!Type.isTrivial(Module)) {
    // If we have a type with reference semantics, emit a load/strong release.
    LoadInst *LI = Builder.createLoad(DA->getLoc(), Addr);
    if (Type.hasReferenceSemantics())
      Builder.createStrongRelease(DA->getLoc(), LI);
    else
      Builder.createDestroyValue(DA->getLoc(), LI);
  }

  ++NumExpand;
  return true;
}

static bool expandDestroyValue(DestroyValueInst *DV) {
  SILModule &Module = DV->getModule();
  SILBuilder Builder(DV);

  // Strength reduce destroy_addr inst into release/store if
  // we have a non-address only type.
  SILValue Value = DV->getOperand();

  // If we have an address only type, do nothing.
  SILType Type = Value.getType();
  assert(!Type.isAddressOnly(Module) &&
         "destroy_value should never be called on a non-loadable type.");

  auto &TL = Module.getTypeLowering(Type);
  TL.emitLoweredDestroyValue(Builder, DV->getLoc(), Value,
                             TypeLowering::LoweringStyle::DeepNoEnum);

  DEBUG(llvm::dbgs() << "    Expanding Destroy Value: " << *DV);

  ++NumExpand;
  return true;
}

//===----------------------------------------------------------------------===//
//                              Top Level Driver
//===----------------------------------------------------------------------===//

static void processFunction(SILFunction &Fn) {
  for (auto BI = Fn.begin(), BE = Fn.end(); BI != BE; ++BI) {
    auto II = BI->begin(), IE = BI->end();
    while (II != IE) {
      SILInstruction *Inst = &*II;

      DEBUG(llvm::dbgs() << "Visiting: " << *Inst);

      if (auto *CA = dyn_cast<CopyAddrInst>(Inst))
        if (expandCopyAddr(CA)) {
          ++II;
          CA->eraseFromParent();
          continue;
        }

      if (auto *DA = dyn_cast<DestroyAddrInst>(Inst))
        if (expandDestroyAddr(DA)) {
          ++II;
          DA->eraseFromParent();
          continue;
        }

      if (auto *DV = dyn_cast<DestroyValueInst>(Inst))
        if (expandDestroyValue(DV)) {
          ++II;
          DV->eraseFromParent();
          continue;
        }

      ++II;
    }
  }
}

void swift::performSILLowerAggregateInstrs(SILModule *M) {

  DEBUG(llvm::dbgs() << "*** SIL LowerAggregateInstrs ***\n");

  // For each function Fn in M...
  for (auto &Fn : *M) {

    // If Fn has no basic blocks skip it.
    if (Fn.empty())
      continue;

    DEBUG(llvm::dbgs() << "***** Visiting " << Fn.getName() << " *****\n");

    // Otherwise perform LowerAggregateInstrs.
    processFunction(Fn);
  }
}
<commit_msg>[lower-aggregate-instrs] Change one usage of !isAddressOnly => isLoadable.<commit_after>//===- SILLowerAggregateInstrs.cpp - Aggregate insts to Scalar insts  -----===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2015 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See http://swift.org/LICENSE.txt for license information
// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//
//
// Simplify aggregate instructions into scalar instructions.
//
//===----------------------------------------------------------------------===//

#define DEBUG_TYPE "sil-lower-aggregate-instrs"
#include "swift/SILPasses/Passes.h"
#include "swift/SILPasses/Utils/Local.h"
#include "swift/SIL/SILInstruction.h"
#include "swift/SIL/SILVisitor.h"
#include "swift/SIL/SILBuilder.h"
#include "swift/SIL/SILModule.h"
#include "llvm/ADT/Statistic.h"
#include "llvm/Support/Debug.h"
using namespace swift;
using namespace swift::Lowering;

STATISTIC(NumExpand, "Number of instructions expanded");

//===----------------------------------------------------------------------===//
//                      Higher Level Operation Expansion
//===----------------------------------------------------------------------===//

/// \brief Lower copy_addr into loads/stores/retain/release if we have a
/// non-address only type. We do this here so we can process the resulting
/// loads/stores.
///
/// This peephole implements the following optimizations:
///
/// copy_addr %0 to %1 : $*T
/// ->
///     %new = load %0 : $*T        // Load the new value from the source
///     %old = load %1 : $*T        // Load the old value from the destination
///     strong_retain %new : $T     // Retain the new value
///     strong_release %old : $T    // Release the old
///     store %new to %1 : $*T      // Store the new value to the destination
///
/// copy_addr [take] %0 to %1 : $*T
/// ->
///     %new = load %0 : $*T
///     %old = load %1 : $*T
///     // no retain of %new!
///     strong_release %old : $T
///     store %new to %1 : $*T
///
/// copy_addr %0 to [initialization] %1 : $*T
/// ->
///     %new = load %0 : $*T
///     strong_retain %new : $T
///     // no load/release of %old!
///     store %new to %1 : $*T
///
/// copy_addr [take] %0 to [initialization] %1 : $*T
/// ->
///     %new = load %0 : $*T
///     // no retain of %new!
///     // no load/release of %old!
///     store %new to %1 : $*T
static bool expandCopyAddr(CopyAddrInst *CA) {
  SILModule &M = CA->getModule();
  SILValue Source = CA->getSrc();

  // If we have an address only type don't do anything.
  SILType SrcType = Source.getType();
  if (SrcType.isAddressOnly(M))
    return false;

  SILBuilder Builder(CA);

  // %new = load %0 : $*T
  LoadInst *New = Builder.createLoad(CA->getLoc(), Source);

  SILValue Destination = CA->getDest();

  // If our object type is not trivial, we may need to release the old value and
  // retain the new one.

  // If we have a non-trivial type...
  if (!SrcType.isTrivial(M)) {

    // If we are not initializing:
    // %old = load %1 : $*T
    IsInitialization_t IsInit = CA->isInitializationOfDest();
    LoadInst *Old = nullptr;
    if (IsInitialization_t::IsNotInitialization == IsInit) {
      Old = Builder.createLoad(CA->getLoc(), Destination);
    }

    // If we are not taking and have a reference type:
    //   strong_retain %new : $*T
    // or if we have a non-trivial non-reference type.
    //   copy_value %new : $*T
    IsTake_t IsTake = CA->isTakeOfSrc();
    if (IsTake_t::IsNotTake == IsTake) {
      if (SrcType.hasReferenceSemantics())
        Builder.createStrongRetain(CA->getLoc(), New);
      else
        Builder.createCopyValue(CA->getLoc(), New);
    }

    // If we are not initializing:
    // strong_release %old : $*T
    //   *or*
    // destroy_value %new : $*T
    if (Old) {
      if (SrcType.hasReferenceSemantics())
        Builder.createStrongRelease(CA->getLoc(), Old);
      else
        Builder.createDestroyValue(CA->getLoc(), Old);
    }
  }

  // Create the store.
  Builder.createStore(CA->getLoc(), New, Destination);

  ++NumExpand;
  return true;
}

static bool expandDestroyAddr(DestroyAddrInst *DA) {
  SILModule &Module = DA->getModule();
  SILBuilder Builder(DA);

  // Strength reduce destroy_addr inst into release/store if
  // we have a non-address only type.
  SILValue Addr = DA->getOperand();

  // If we have an address only type, do nothing.
  SILType Type = Addr.getType();
  if (Type.isAddressOnly(Module))
    return false;

  // If we have a non-trivial type...
  if (!Type.isTrivial(Module)) {
    // If we have a type with reference semantics, emit a load/strong release.
    LoadInst *LI = Builder.createLoad(DA->getLoc(), Addr);
    if (Type.hasReferenceSemantics())
      Builder.createStrongRelease(DA->getLoc(), LI);
    else
      Builder.createDestroyValue(DA->getLoc(), LI);
  }

  ++NumExpand;
  return true;
}

static bool expandDestroyValue(DestroyValueInst *DV) {
  SILModule &Module = DV->getModule();
  SILBuilder Builder(DV);

  // Strength reduce destroy_addr inst into release/store if
  // we have a non-address only type.
  SILValue Value = DV->getOperand();

  // If we have an address only type, do nothing.
  SILType Type = Value.getType();
  assert(Type.isLoadable(Module) &&
         "destroy_value should never be called on a non-loadable type.");

  auto &TL = Module.getTypeLowering(Type);
  TL.emitLoweredDestroyValue(Builder, DV->getLoc(), Value,
                             TypeLowering::LoweringStyle::DeepNoEnum);

  DEBUG(llvm::dbgs() << "    Expanding Destroy Value: " << *DV);

  ++NumExpand;
  return true;
}

//===----------------------------------------------------------------------===//
//                              Top Level Driver
//===----------------------------------------------------------------------===//

static void processFunction(SILFunction &Fn) {
  for (auto BI = Fn.begin(), BE = Fn.end(); BI != BE; ++BI) {
    auto II = BI->begin(), IE = BI->end();
    while (II != IE) {
      SILInstruction *Inst = &*II;

      DEBUG(llvm::dbgs() << "Visiting: " << *Inst);

      if (auto *CA = dyn_cast<CopyAddrInst>(Inst))
        if (expandCopyAddr(CA)) {
          ++II;
          CA->eraseFromParent();
          continue;
        }

      if (auto *DA = dyn_cast<DestroyAddrInst>(Inst))
        if (expandDestroyAddr(DA)) {
          ++II;
          DA->eraseFromParent();
          continue;
        }

      if (auto *DV = dyn_cast<DestroyValueInst>(Inst))
        if (expandDestroyValue(DV)) {
          ++II;
          DV->eraseFromParent();
          continue;
        }

      ++II;
    }
  }
}

void swift::performSILLowerAggregateInstrs(SILModule *M) {

  DEBUG(llvm::dbgs() << "*** SIL LowerAggregateInstrs ***\n");

  // For each function Fn in M...
  for (auto &Fn : *M) {

    // If Fn has no basic blocks skip it.
    if (Fn.empty())
      continue;

    DEBUG(llvm::dbgs() << "***** Visiting " << Fn.getName() << " *****\n");

    // Otherwise perform LowerAggregateInstrs.
    processFunction(Fn);
  }
}
<|endoftext|>


<commit_before>// Copyright (c) 2011-2013 The Bitcoin developers
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#include "askpassphrasedialog.h"
#include "ui_askpassphrasedialog.h"

#include "guiconstants.h"
#include "walletmodel.h"

#include <QMessageBox>
#include <QPushButton>
#include <QKeyEvent>

AskPassphraseDialog::AskPassphraseDialog(Mode mode, QWidget *parent) :
    QDialog(parent),
    ui(new Ui::AskPassphraseDialog),
    mode(mode),
    model(0),
    fCapsLock(false)
{
    ui->setupUi(this);
    ui->passEdit1->setMaxLength(MAX_PASSPHRASE_SIZE);
    ui->passEdit2->setMaxLength(MAX_PASSPHRASE_SIZE);
    ui->passEdit3->setMaxLength(MAX_PASSPHRASE_SIZE);

    // Setup Caps Lock detection.
    ui->passEdit1->installEventFilter(this);
    ui->passEdit2->installEventFilter(this);
    ui->passEdit3->installEventFilter(this);

    switch(mode)
    {
        case Encrypt: // Ask passphrase x2
            ui->passLabel1->hide();
            ui->passEdit1->hide();
            ui->warningLabel->setText(tr("Enter the new passphrase to the wallet.
Please use a passphrase of 10 or more random characters, or eight or more words."));
            setWindowTitle(tr("Encrypt wallet"));
            break;
        case Unlock: // Ask passphrase
            ui->warningLabel->setText(tr("This operation needs your wallet passphrase to unlock the wallet."));
            ui->passLabel2->hide();
            ui->passEdit2->hide();
            ui->passLabel3->hide();
            ui->passEdit3->hide();
            setWindowTitle(tr("Unlock wallet"));
            break;
        case Decrypt:   // Ask passphrase
            ui->warningLabel->setText(tr("This operation needs your wallet passphrase to decrypt the wallet."));
            ui->passLabel2->hide();
            ui->passEdit2->hide();
            ui->passLabel3->hide();
            ui->passEdit3->hide();
            setWindowTitle(tr("Decrypt wallet"));
            break;
        case ChangePass: // Ask old passphrase + new passphrase x2
            setWindowTitle(tr("Change passphrase"));
            ui->warningLabel->setText(tr("Enter the old and new passphrase to the wallet."));
            break;
    }

    textChanged();
    connect(ui->passEdit1, SIGNAL(textChanged(QString)), this, SLOT(textChanged()));
    connect(ui->passEdit2, SIGNAL(textChanged(QString)), this, SLOT(textChanged()));
    connect(ui->passEdit3, SIGNAL(textChanged(QString)), this, SLOT(textChanged()));
}

AskPassphraseDialog::~AskPassphraseDialog()
{
    // Attempt to overwrite text so that they do not linger around in memory
    ui->passEdit1->setText(QString(" ").repeated(ui->passEdit1->text().size()));
    ui->passEdit2->setText(QString(" ").repeated(ui->passEdit2->text().size()));
    ui->passEdit3->setText(QString(" ").repeated(ui->passEdit3->text().size()));
    delete ui;
}

void AskPassphraseDialog::setModel(WalletModel *model)
{
    this->model = model;
}

void AskPassphraseDialog::accept()
{
    SecureString oldpass, newpass1, newpass2;
    if(!model)
        return;
    oldpass.reserve(MAX_PASSPHRASE_SIZE);
    newpass1.reserve(MAX_PASSPHRASE_SIZE);
    newpass2.reserve(MAX_PASSPHRASE_SIZE);
    // TODO: get rid of this .c_str() by implementing SecureString::operator=(std::string)
    // Alternately, find a way to make this input mlock()'d to begin with.
    oldpass.assign(ui->passEdit1->text().toStdString().c_str());
    newpass1.assign(ui->passEdit2->text().toStdString().c_str());
    newpass2.assign(ui->passEdit3->text().toStdString().c_str());

    switch(mode)
    {
    case Encrypt: {
        if(newpass1.empty() || newpass2.empty())
        {
            // Cannot encrypt with empty passphrase
            break;
        }
        QMessageBox::StandardButton retval = QMessageBox::question(this, tr("Confirm wallet encryption"),
                 tr("Warning: If you encrypt your wallet and lose your passphrase, you will LOSE ALL OF YOUR LITECOINS!") + "

" + tr("Are you sure you wish to encrypt your wallet?"),
                 QMessageBox::Yes|QMessageBox::Cancel,
                 QMessageBox::Cancel);
        if(retval == QMessageBox::Yes)
        {
            if(newpass1 == newpass2)
            {
                if(model->setWalletEncrypted(true, newpass1))
                {
                    QMessageBox::warning(this, tr("Wallet encrypted"),
                                         "<qt>" +
                                         tr("Sakuracoin will close now to finish the encryption process. "
                                         "Remember that encrypting your wallet cannot fully protect "
                                         "your sakuracoins from being stolen by malware infecting your computer.") +
                                         "

" +
                                         tr("IMPORTANT: Any previous backups you have made of your wallet file "
                                         "should be replaced with the newly generated, encrypted wallet file. "
                                         "For security reasons, previous backups of the unencrypted wallet file "
                                         "will become useless as soon as you start using the new, encrypted wallet.") +
                                         "</qt>");
                    QApplication::quit();
                }
                else
                {
                    QMessageBox::critical(this, tr("Wallet encryption failed"),
                                         tr("Wallet encryption failed due to an internal error. Your wallet was not encrypted."));
                }
                QDialog::accept(); // Success
            }
            else
            {
                QMessageBox::critical(this, tr("Wallet encryption failed"),
                                     tr("The supplied passphrases do not match."));
            }
        }
        else
        {
            QDialog::reject(); // Cancelled
        }
        } break;
    case Unlock:
        if(!model->setWalletLocked(false, oldpass))
        {
            QMessageBox::critical(this, tr("Wallet unlock failed"),
                                  tr("The passphrase entered for the wallet decryption was incorrect."));
        }
        else
        {
            QDialog::accept(); // Success
        }
        break;
    case Decrypt:
        if(!model->setWalletEncrypted(false, oldpass))
        {
            QMessageBox::critical(this, tr("Wallet decryption failed"),
                                  tr("The passphrase entered for the wallet decryption was incorrect."));
        }
        else
        {
            QDialog::accept(); // Success
        }
        break;
    case ChangePass:
        if(newpass1 == newpass2)
        {
            if(model->changePassphrase(oldpass, newpass1))
            {
                QMessageBox::information(this, tr("Wallet encrypted"),
                                     tr("Wallet passphrase was successfully changed."));
                QDialog::accept(); // Success
            }
            else
            {
                QMessageBox::critical(this, tr("Wallet encryption failed"),
                                     tr("The passphrase entered for the wallet decryption was incorrect."));
            }
        }
        else
        {
            QMessageBox::critical(this, tr("Wallet encryption failed"),
                                 tr("The supplied passphrases do not match."));
        }
        break;
    }
}

void AskPassphraseDialog::textChanged()
{
    // Validate input, set Ok button to enabled when acceptable
    bool acceptable = false;
    switch(mode)
    {
    case Encrypt: // New passphrase x2
        acceptable = !ui->passEdit2->text().isEmpty() && !ui->passEdit3->text().isEmpty();
        break;
    case Unlock: // Old passphrase x1
    case Decrypt:
        acceptable = !ui->passEdit1->text().isEmpty();
        break;
    case ChangePass: // Old passphrase x1, new passphrase x2
        acceptable = !ui->passEdit1->text().isEmpty() && !ui->passEdit2->text().isEmpty() && !ui->passEdit3->text().isEmpty();
        break;
    }
    ui->buttonBox->button(QDialogButtonBox::Ok)->setEnabled(acceptable);
}

bool AskPassphraseDialog::event(QEvent *event)
{
    // Detect Caps Lock key press.
    if (event->type() == QEvent::KeyPress) {
        QKeyEvent *ke = static_cast<QKeyEvent *>(event);
        if (ke->key() == Qt::Key_CapsLock) {
            fCapsLock = !fCapsLock;
        }
        if (fCapsLock) {
            ui->capsLabel->setText(tr("Warning: The Caps Lock key is on!"));
        } else {
            ui->capsLabel->clear();
        }
    }
    return QWidget::event(event);
}

bool AskPassphraseDialog::eventFilter(QObject *object, QEvent *event)
{
    /* Detect Caps Lock.
     * There is no good OS-independent way to check a key state in Qt, but we
     * can detect Caps Lock by checking for the following condition:
     * Shift key is down and the result is a lower case character, or
     * Shift key is not down and the result is an upper case character.
     */
    if (event->type() == QEvent::KeyPress) {
        QKeyEvent *ke = static_cast<QKeyEvent *>(event);
        QString str = ke->text();
        if (str.length() != 0) {
            const QChar *psz = str.unicode();
            bool fShift = (ke->modifiers() & Qt::ShiftModifier) != 0;
            if ((fShift && *psz >= 'a' && *psz <= 'z') || (!fShift && *psz >= 'A' && *psz <= 'Z')) {
                fCapsLock = true;
                ui->capsLabel->setText(tr("Warning: The Caps Lock key is on!"));
            } else if (psz->isLetter()) {
                fCapsLock = false;
                ui->capsLabel->clear();
            }
        }
    }
    return QDialog::eventFilter(object, event);
}
<commit_msg>LITECOIN to SAKURACOIN<commit_after>// Copyright (c) 2011-2013 The Bitcoin developers
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#include "askpassphrasedialog.h"
#include "ui_askpassphrasedialog.h"

#include "guiconstants.h"
#include "walletmodel.h"

#include <QMessageBox>
#include <QPushButton>
#include <QKeyEvent>

AskPassphraseDialog::AskPassphraseDialog(Mode mode, QWidget *parent) :
    QDialog(parent),
    ui(new Ui::AskPassphraseDialog),
    mode(mode),
    model(0),
    fCapsLock(false)
{
    ui->setupUi(this);
    ui->passEdit1->setMaxLength(MAX_PASSPHRASE_SIZE);
    ui->passEdit2->setMaxLength(MAX_PASSPHRASE_SIZE);
    ui->passEdit3->setMaxLength(MAX_PASSPHRASE_SIZE);

    // Setup Caps Lock detection.
    ui->passEdit1->installEventFilter(this);
    ui->passEdit2->installEventFilter(this);
    ui->passEdit3->installEventFilter(this);

    switch(mode)
    {
        case Encrypt: // Ask passphrase x2
            ui->passLabel1->hide();
            ui->passEdit1->hide();
            ui->warningLabel->setText(tr("Enter the new passphrase to the wallet.
Please use a passphrase of 10 or more random characters, or eight or more words."));
            setWindowTitle(tr("Encrypt wallet"));
            break;
        case Unlock: // Ask passphrase
            ui->warningLabel->setText(tr("This operation needs your wallet passphrase to unlock the wallet."));
            ui->passLabel2->hide();
            ui->passEdit2->hide();
            ui->passLabel3->hide();
            ui->passEdit3->hide();
            setWindowTitle(tr("Unlock wallet"));
            break;
        case Decrypt:   // Ask passphrase
            ui->warningLabel->setText(tr("This operation needs your wallet passphrase to decrypt the wallet."));
            ui->passLabel2->hide();
            ui->passEdit2->hide();
            ui->passLabel3->hide();
            ui->passEdit3->hide();
            setWindowTitle(tr("Decrypt wallet"));
            break;
        case ChangePass: // Ask old passphrase + new passphrase x2
            setWindowTitle(tr("Change passphrase"));
            ui->warningLabel->setText(tr("Enter the old and new passphrase to the wallet."));
            break;
    }

    textChanged();
    connect(ui->passEdit1, SIGNAL(textChanged(QString)), this, SLOT(textChanged()));
    connect(ui->passEdit2, SIGNAL(textChanged(QString)), this, SLOT(textChanged()));
    connect(ui->passEdit3, SIGNAL(textChanged(QString)), this, SLOT(textChanged()));
}

AskPassphraseDialog::~AskPassphraseDialog()
{
    // Attempt to overwrite text so that they do not linger around in memory
    ui->passEdit1->setText(QString(" ").repeated(ui->passEdit1->text().size()));
    ui->passEdit2->setText(QString(" ").repeated(ui->passEdit2->text().size()));
    ui->passEdit3->setText(QString(" ").repeated(ui->passEdit3->text().size()));
    delete ui;
}

void AskPassphraseDialog::setModel(WalletModel *model)
{
    this->model = model;
}

void AskPassphraseDialog::accept()
{
    SecureString oldpass, newpass1, newpass2;
    if(!model)
        return;
    oldpass.reserve(MAX_PASSPHRASE_SIZE);
    newpass1.reserve(MAX_PASSPHRASE_SIZE);
    newpass2.reserve(MAX_PASSPHRASE_SIZE);
    // TODO: get rid of this .c_str() by implementing SecureString::operator=(std::string)
    // Alternately, find a way to make this input mlock()'d to begin with.
    oldpass.assign(ui->passEdit1->text().toStdString().c_str());
    newpass1.assign(ui->passEdit2->text().toStdString().c_str());
    newpass2.assign(ui->passEdit3->text().toStdString().c_str());

    switch(mode)
    {
    case Encrypt: {
        if(newpass1.empty() || newpass2.empty())
        {
            // Cannot encrypt with empty passphrase
            break;
        }
        QMessageBox::StandardButton retval = QMessageBox::question(this, tr("Confirm wallet encryption"),
                 tr("Warning: If you encrypt your wallet and lose your passphrase, you will LOSE ALL OF YOUR SAKURACOINS!") + "

" + tr("Are you sure you wish to encrypt your wallet?"),
                 QMessageBox::Yes|QMessageBox::Cancel,
                 QMessageBox::Cancel);
        if(retval == QMessageBox::Yes)
        {
            if(newpass1 == newpass2)
            {
                if(model->setWalletEncrypted(true, newpass1))
                {
                    QMessageBox::warning(this, tr("Wallet encrypted"),
                                         "<qt>" +
                                         tr("Sakuracoin will close now to finish the encryption process. "
                                         "Remember that encrypting your wallet cannot fully protect "
                                         "your sakuracoins from being stolen by malware infecting your computer.") +
                                         "

" +
                                         tr("IMPORTANT: Any previous backups you have made of your wallet file "
                                         "should be replaced with the newly generated, encrypted wallet file. "
                                         "For security reasons, previous backups of the unencrypted wallet file "
                                         "will become useless as soon as you start using the new, encrypted wallet.") +
                                         "</qt>");
                    QApplication::quit();
                }
                else
                {
                    QMessageBox::critical(this, tr("Wallet encryption failed"),
                                         tr("Wallet encryption failed due to an internal error. Your wallet was not encrypted."));
                }
                QDialog::accept(); // Success
            }
            else
            {
                QMessageBox::critical(this, tr("Wallet encryption failed"),
                                     tr("The supplied passphrases do not match."));
            }
        }
        else
        {
            QDialog::reject(); // Cancelled
        }
        } break;
    case Unlock:
        if(!model->setWalletLocked(false, oldpass))
        {
            QMessageBox::critical(this, tr("Wallet unlock failed"),
                                  tr("The passphrase entered for the wallet decryption was incorrect."));
        }
        else
        {
            QDialog::accept(); // Success
        }
        break;
    case Decrypt:
        if(!model->setWalletEncrypted(false, oldpass))
        {
            QMessageBox::critical(this, tr("Wallet decryption failed"),
                                  tr("The passphrase entered for the wallet decryption was incorrect."));
        }
        else
        {
            QDialog::accept(); // Success
        }
        break;
    case ChangePass:
        if(newpass1 == newpass2)
        {
            if(model->changePassphrase(oldpass, newpass1))
            {
                QMessageBox::information(this, tr("Wallet encrypted"),
                                     tr("Wallet passphrase was successfully changed."));
                QDialog::accept(); // Success
            }
            else
            {
                QMessageBox::critical(this, tr("Wallet encryption failed"),
                                     tr("The passphrase entered for the wallet decryption was incorrect."));
            }
        }
        else
        {
            QMessageBox::critical(this, tr("Wallet encryption failed"),
                                 tr("The supplied passphrases do not match."));
        }
        break;
    }
}

void AskPassphraseDialog::textChanged()
{
    // Validate input, set Ok button to enabled when acceptable
    bool acceptable = false;
    switch(mode)
    {
    case Encrypt: // New passphrase x2
        acceptable = !ui->passEdit2->text().isEmpty() && !ui->passEdit3->text().isEmpty();
        break;
    case Unlock: // Old passphrase x1
    case Decrypt:
        acceptable = !ui->passEdit1->text().isEmpty();
        break;
    case ChangePass: // Old passphrase x1, new passphrase x2
        acceptable = !ui->passEdit1->text().isEmpty() && !ui->passEdit2->text().isEmpty() && !ui->passEdit3->text().isEmpty();
        break;
    }
    ui->buttonBox->button(QDialogButtonBox::Ok)->setEnabled(acceptable);
}

bool AskPassphraseDialog::event(QEvent *event)
{
    // Detect Caps Lock key press.
    if (event->type() == QEvent::KeyPress) {
        QKeyEvent *ke = static_cast<QKeyEvent *>(event);
        if (ke->key() == Qt::Key_CapsLock) {
            fCapsLock = !fCapsLock;
        }
        if (fCapsLock) {
            ui->capsLabel->setText(tr("Warning: The Caps Lock key is on!"));
        } else {
            ui->capsLabel->clear();
        }
    }
    return QWidget::event(event);
}

bool AskPassphraseDialog::eventFilter(QObject *object, QEvent *event)
{
    /* Detect Caps Lock.
     * There is no good OS-independent way to check a key state in Qt, but we
     * can detect Caps Lock by checking for the following condition:
     * Shift key is down and the result is a lower case character, or
     * Shift key is not down and the result is an upper case character.
     */
    if (event->type() == QEvent::KeyPress) {
        QKeyEvent *ke = static_cast<QKeyEvent *>(event);
        QString str = ke->text();
        if (str.length() != 0) {
            const QChar *psz = str.unicode();
            bool fShift = (ke->modifiers() & Qt::ShiftModifier) != 0;
            if ((fShift && *psz >= 'a' && *psz <= 'z') || (!fShift && *psz >= 'A' && *psz <= 'Z')) {
                fCapsLock = true;
                ui->capsLabel->setText(tr("Warning: The Caps Lock key is on!"));
            } else if (psz->isLetter()) {
                fCapsLock = false;
                ui->capsLabel->clear();
            }
        }
    }
    return QDialog::eventFilter(object, event);
}
<|endoftext|>


<commit_before>#include <stdio.h>
#include <time.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <errno.h>
#include <string.h>
#include "stdsneezy.h"
#include "connect.h"

#define WIZ_KEY_FILE "/mud/prod/lib/IPC_Wiznet"
#define MAIN_PORT 7900
#define BUILD_PORT 8900
#define WIZNET_FORMAT "%s %s"
#define MAX_STRING_LENGTH 4096
#define MAX_INPUT_LENGTH 1024
#define MAX_MSGBUF_LENGTH 2048

int my_ipc_id, other_ipc_id;

key_t keyval;
int qid=-2;
struct mud_msgbuf
{
    long mtype;
    char mtext[MAX_MSGBUF_LENGTH+1];
};

int openQueue()
{
  int oldqid=qid;

  if (qid==-2) {
    extern int gamePort;
    if (gamePort==MAIN_PORT) {
      my_ipc_id = MAIN_PORT;
      other_ipc_id = BUILD_PORT;
    } else {
      my_ipc_id = BUILD_PORT;
      other_ipc_id = MAIN_PORT;
    }
    keyval = ftok(WIZ_KEY_FILE, 'm');
  }
  if ((qid = msgget(keyval, IPC_CREAT|0660)) == -1) {
    vlogf(LOG_BUG, "Unable to msgget keyval %d.", keyval);
    return -1;
  }
  if (oldqid!=qid) {
    vlogf(LOG_BUG, "msgget successful, qid: %d, keyval: %d", qid, keyval);
    oldqid = qid;
  }
  return 1;
}

void closeQueue()
{
    msgctl(qid, IPC_RMID, 0);
    vlogf(LOG_BUG, "closeQueue");
}

void mudSendMessage(int mtype, int ctype, const char *arg)
{
  struct mud_msgbuf qbuf;
  int ret;

  if (openQueue()<0)
    return;

  if (mtype<=0) {
    vlogf(LOG_BUG, "invalid mtype, must be > 0, setting to 1");
    mtype = 1;
  }
  snprintf(qbuf.mtext, MAX_MSGBUF_LENGTH, "%d %s", ctype, arg);
  qbuf.mtype = mtype;

  if ((ret = msgsnd(qid, (struct msgbuf *)&qbuf, strlen(qbuf.mtext)+1, 0)) == -1)
    vlogf(LOG_BUG, "mudSendMessage: errno: %d ret: %d", errno, ret);
}

void TBeing::mudMessage(TBeing *ch, int channel, const char *arg)
{
  char tbuf[MAX_MSGBUF_LENGTH+1];
  snprintf(tbuf, MAX_MSGBUF_LENGTH, "%s: %s", ch->getName(), arg);
  mudSendMessage(other_ipc_id, channel, tbuf);
}

void recvTextHandler(const char *str)
{
  Descriptor *d;
  char arg1[MAX_INPUT_LENGTH], arg2[MAX_INPUT_LENGTH], chname[MAX_INPUT_LENGTH];
  char buf[MAX_STRING_LENGTH-1];
  int channel=-1, level=-1;

  str = one_argument(str, arg1);
  str = one_argument(str, arg2);
  str = one_argument(str, chname);
  channel = atoi(arg1);
  level = atoi(arg2);

  snprintf(buf, MAX_STRING_LENGTH, WIZNET_FORMAT, chname, str);

  for (d = descriptor_list; d; d = d->next) {
    TBeing *och;
    och = d->original ? d->original : d->character;
    if (!och)
      continue;
    if (och->hasWizPower(POWER_WIZNET)) {
      if (!d->isEditing()) {
	och->sendTo(buf);
      } else {
	// do nothing
      }
    }
  }
}

void mudRecvMessage()
{
  struct mud_msgbuf qbuf;
  int ret;

  if (openQueue() < 0)
    return;

  while ((ret = msgrcv(qid, (struct msgbuf *)&qbuf, MAX_MSGBUF_LENGTH, my_ipc_id, IPC_NOWAIT)) > 0)
    recvTextHandler(qbuf.mtext);

  if (ret==-1 && errno!=ENOMSG)
    vlogf(LOG_BUG, "mudRecvMessage: errno: %d ret: %d", errno, ret);
}

<commit_msg>fix bwiz<commit_after>#include <stdio.h>
#include <time.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <errno.h>
#include <string.h>
#include "stdsneezy.h"
#include "connect.h"

#define WIZ_KEY_FILE "/mud/prod/lib/IPC_Wiznet"
#define MAIN_PORT 7900
#define BUILD_PORT 8900
#define WIZNET_FORMAT "%s %s"
#define MAX_STRING_LENGTH 4096
#define MAX_INPUT_LENGTH 1024
#define MAX_MSGBUF_LENGTH 2048

int my_ipc_id, other_ipc_id;

key_t keyval;
int qid=-2;
struct mud_msgbuf
{
    long mtype;
    char mtext[MAX_MSGBUF_LENGTH+1];
};

int openQueue()
{
  int oldqid=qid;

  if (qid==-2) {
    extern int gamePort;
    if (gamePort==MAIN_PORT) {
      my_ipc_id = MAIN_PORT;
      other_ipc_id = BUILD_PORT;
    } else {
      my_ipc_id = BUILD_PORT;
      other_ipc_id = MAIN_PORT;
    }
    keyval = ftok(WIZ_KEY_FILE, 'm');
  }
  if ((qid = msgget(keyval, IPC_CREAT|0660)) == -1) {
    vlogf(LOG_BUG, "Unable to msgget keyval %d.", keyval);
    return -1;
  }
  if (oldqid!=qid) {
    vlogf(LOG_BUG, "msgget successful, qid: %d, keyval: %d", qid, keyval);
    oldqid = qid;
  }
  return 1;
}

void closeQueue()
{
    msgctl(qid, IPC_RMID, 0);
    vlogf(LOG_BUG, "closeQueue");
}

void mudSendMessage(int mtype, int ctype, const char *arg)
{
  struct mud_msgbuf qbuf;
  int ret;

  if (openQueue()<0)
    return;

  if (mtype<=0) {
    vlogf(LOG_BUG, "invalid mtype, must be > 0, setting to 1");
    mtype = 1;
  }
  snprintf(qbuf.mtext, MAX_MSGBUF_LENGTH, "%d %s", ctype, arg);
  qbuf.mtype = mtype;

  if ((ret = msgsnd(qid, (struct msgbuf *)&qbuf, strlen(qbuf.mtext)+1, 0)) == -1)
    vlogf(LOG_BUG, "mudSendMessage: errno: %d ret: %d", errno, ret);
}

void TBeing::mudMessage(TBeing *ch, int channel, const char *arg)
{
  char tbuf[MAX_MSGBUF_LENGTH+1];
  snprintf(tbuf, MAX_MSGBUF_LENGTH, "%s: %s", ch->getName(), arg);
  mudSendMessage(other_ipc_id, channel, tbuf);
}

void recvTextHandler(const char *str)
{
  Descriptor *d;
  char arg1[MAX_INPUT_LENGTH], arg2[MAX_INPUT_LENGTH], chname[MAX_INPUT_LENGTH];
  char buf[MAX_STRING_LENGTH-1];
  int channel=-1, level=-1;

  str = one_argument(str, arg1);
  str = one_argument(str, arg2);
  str = one_argument(str, chname);
  channel = atoi(arg1);
  level = atoi(arg2);

  snprintf(buf, MAX_STRING_LENGTH, WIZNET_FORMAT, chname, str);

  for (d = descriptor_list; d; d = d->next) {
    TBeing *och;
    och = d->original ? d->original : d->character;
    if (!och)
      continue;
    if (och->hasWizPower(POWER_WIZNET)) {
      if (och->desc->connected) {
      } else {
	och->sendTo(buf);
	// do nothing
      }
    }
  }
}

void mudRecvMessage()
{
  struct mud_msgbuf qbuf;
  int ret;

  if (openQueue() < 0)
    return;

  while ((ret = msgrcv(qid, (struct msgbuf *)&qbuf, MAX_MSGBUF_LENGTH, my_ipc_id, IPC_NOWAIT)) > 0)
    recvTextHandler(qbuf.mtext);

  if (ret==-1 && errno!=ENOMSG)
    vlogf(LOG_BUG, "mudRecvMessage: errno: %d ret: %d", errno, ret);
}

<|endoftext|>


<commit_before>/*
// Copyright (c) 2018 Intel Corporation
//
// 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.
*/
#pragma once

#include <bitset>
#include <ipmid/api.hpp>
#include <string>

namespace ipmi
{

// TODO: Has to be replaced with proper channel number assignment logic
/**
 * @enum Channel Id
 */
enum class EChannelID : uint8_t
{
    chanLan1 = 0x01
};

static constexpr uint8_t invalidUserId = 0xFF;
static constexpr uint8_t reservedUserId = 0x0;
static constexpr uint8_t ipmiMaxUserName = 16;
static constexpr uint8_t ipmiMaxUsers = 15;
static constexpr uint8_t ipmiMaxChannels = 16;
static constexpr uint8_t maxIpmi20PasswordSize = 20;
static constexpr uint8_t maxIpmi15PasswordSize = 16;
static constexpr uint8_t payloadsPerByte = 8;

/** @struct PrivAccess
 *
 *  User privilege related access data as per IPMI specification.(refer spec
 * sec 22.26)
 */
struct PrivAccess
{
#if BYTE_ORDER == LITTLE_ENDIAN
    uint8_t privilege : 4;
    uint8_t ipmiEnabled : 1;
    uint8_t linkAuthEnabled : 1;
    uint8_t accessCallback : 1;
    uint8_t reserved : 1;
#endif
#if BYTE_ORDER == BIG_ENDIAN
    uint8_t reserved : 1;
    uint8_t accessCallback : 1;
    uint8_t linkAuthEnabled : 1;
    uint8_t ipmiEnabled : 1;
    uint8_t privilege : 4;
#endif
} __attribute__((packed));

/** @struct UserPayloadAccess
 *
 *  Structure to denote payload access restrictions applicable for a
 *  given user and channel. (refer spec sec 24.6)
 */
struct PayloadAccess
{
    std::bitset<payloadsPerByte> stdPayloadEnables1;
    std::bitset<payloadsPerByte> stdPayloadEnables2Reserved;
    std::bitset<payloadsPerByte> oemPayloadEnables1;
    std::bitset<payloadsPerByte> oemPayloadEnables2Reserved;
};

/** @brief initializes user management
 *
 *  @return ccSuccess for success, others for failure.
 */
Cc ipmiUserInit();

/** @brief The ipmi get user password layer call
 *
 *  @param[in] userName - user name
 *
 *  @return password or empty string
 */
std::string ipmiUserGetPassword(const std::string& userName);

/** @brief The IPMI call to clear password entry associated with specified
 * username
 *
 *  @param[in] userName - user name to be removed
 *
 *  @return 0 on success, non-zero otherwise.
 */
Cc ipmiClearUserEntryPassword(const std::string& userName);

/** @brief The IPMI call to reuse password entry for the renamed user
 *  to another one
 *
 *  @param[in] userName - user name which has to be renamed
 *  @param[in] newUserName - new user name
 *
 *  @return 0 on success, non-zero otherwise.
 */
Cc ipmiRenameUserEntryPassword(const std::string& userName,
                               const std::string& newUserName);

/** @brief determines valid userId
 *
 *  @param[in] userId - user id
 *
 *  @return true if valid, false otherwise
 */
bool ipmiUserIsValidUserId(const uint8_t userId);

/** @brief determines valid privilege level
 *
 *  @param[in] priv - privilege level
 *
 *  @return true if valid, false otherwise
 */
bool ipmiUserIsValidPrivilege(const uint8_t priv);

/** @brief get user id corresponding to the user name
 *
 *  @param[in] userName - user name
 *
 *  @return userid. Will return 0xff if no user id found
 */
uint8_t ipmiUserGetUserId(const std::string& userName);

/** @brief set's user name
 *
 *  @param[in] userId - user id
 *  @param[in] userName - user name
 *
 *  @return ccSuccess for success, others for failure.
 */
Cc ipmiUserSetUserName(const uint8_t userId, const std::string& userName);

/** @brief set user password
 *
 *  @param[in] userId - user id
 *  @param[in] userPassword - New Password
 *
 *  @return ccSuccess for success, others for failure.
 */
Cc ipmiUserSetUserPassword(const uint8_t userId, const char* userPassword);

/** @brief set special user password (non-ipmi accounts)
 *
 *  @param[in] userName - user name
 *  @param[in] userPassword - New Password
 *
 *  @return ccSuccess for success, others for failure.
 */
Cc ipmiSetSpecialUserPassword(const std::string& userName,
                              const std::string& userPassword);

/** @brief get user name
 *
 *  @param[in] userId - user id
 *  @param[out] userName - user name
 *
 *  @return ccSuccess for success, others for failure.
 */
Cc ipmiUserGetUserName(const uint8_t userId, std::string& userName);

/** @brief provides available fixed, max, and enabled user counts
 *
 *  @param[out] maxChUsers - max channel users
 *  @param[out] enabledUsers - enabled user count
 *  @param[out] fixedUsers - fixed user count
 *
 *  @return ccSuccess for success, others for failure.
 */
Cc ipmiUserGetAllCounts(uint8_t& maxChUsers, uint8_t& enabledUsers,
                        uint8_t& fixedUsers);

/** @brief function to update user enabled state
 *
 *  @param[in] userId - user id
 *..@param[in] state - state of the user to be updated, true - user enabled.
 *
 *  @return ccSuccess for success, others for failure.
 */
Cc ipmiUserUpdateEnabledState(const uint8_t userId, const bool& state);

/** @brief determines whether user is enabled
 *
 *  @param[in] userId - user id
 *..@param[out] state - state of the user
 *
 *  @return ccSuccess for success, others for failure.
 */
Cc ipmiUserCheckEnabled(const uint8_t userId, bool& state);

/** @brief provides user privilege access data
 *
 *  @param[in] userId - user id
 *  @param[in] chNum - channel number
 *  @param[out] privAccess - privilege access data
 *
 *  @return ccSuccess for success, others for failure.
 */
Cc ipmiUserGetPrivilegeAccess(const uint8_t userId, const uint8_t chNum,
                              PrivAccess& privAccess);

/** @brief sets user privilege access data
 *
 *  @param[in] userId - user id
 *  @param[in] chNum - channel number
 *  @param[in] privAccess - privilege access data
 *  @param[in] otherPrivUpdate - flags to indicate other fields update
 *
 *  @return ccSuccess for success, others for failure.
 */
Cc ipmiUserSetPrivilegeAccess(const uint8_t userId, const uint8_t chNum,
                              const PrivAccess& privAccess,
                              const bool& otherPrivUpdate);

/** @brief check for user pam authentication. This is to determine, whether user
 * is already locked out for failed login attempt
 *
 *  @param[in] username - username
 *  @param[in] password - password
 *
 *  @return status
 */
bool ipmiUserPamAuthenticate(std::string_view userName,
                             std::string_view userPassword);

/** @brief sets user payload access data
 *
 *  @param[in] chNum - channel number
 *  @param[in] operation - ENABLE / DISABLE operation
 *  @param[in] userId - user id
 *  @param[in] payloadAccess - payload access data
 *
 *  @return ccSuccess for success, others for failure.
 */
Cc ipmiUserSetUserPayloadAccess(const uint8_t chNum, const uint8_t operation,
                                const uint8_t userId,
                                const PayloadAccess& payloadAccess);

/** @brief provides user payload access data
 *
 *  @param[in] chNum - channel number
 *  @param[in] userId - user id
 *  @param[out] payloadAccess - payload access data
 *
 *  @return ccSuccess for success, others for failure.
 */
Cc ipmiUserGetUserPayloadAccess(const uint8_t chNum, const uint8_t userId,
                                PayloadAccess& payloadAccess);

} // namespace ipmi
<commit_msg>Fix for ipmiUserSetUserName<commit_after>/*
// Copyright (c) 2018 Intel Corporation
//
// 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.
*/
#pragma once

#include <bitset>
#include <ipmid/api.hpp>
#include <string>

namespace ipmi
{

// TODO: Has to be replaced with proper channel number assignment logic
/**
 * @enum Channel Id
 */
enum class EChannelID : uint8_t
{
    chanLan1 = 0x01
};

static constexpr uint8_t invalidUserId = 0xFF;
static constexpr uint8_t reservedUserId = 0x0;
static constexpr uint8_t ipmiMaxUserName = 16;
static constexpr uint8_t ipmiMaxUsers = 15;
static constexpr uint8_t ipmiMaxChannels = 16;
static constexpr uint8_t maxIpmi20PasswordSize = 20;
static constexpr uint8_t maxIpmi15PasswordSize = 16;
static constexpr uint8_t payloadsPerByte = 8;

/** @struct PrivAccess
 *
 *  User privilege related access data as per IPMI specification.(refer spec
 * sec 22.26)
 */
struct PrivAccess
{
#if BYTE_ORDER == LITTLE_ENDIAN
    uint8_t privilege : 4;
    uint8_t ipmiEnabled : 1;
    uint8_t linkAuthEnabled : 1;
    uint8_t accessCallback : 1;
    uint8_t reserved : 1;
#endif
#if BYTE_ORDER == BIG_ENDIAN
    uint8_t reserved : 1;
    uint8_t accessCallback : 1;
    uint8_t linkAuthEnabled : 1;
    uint8_t ipmiEnabled : 1;
    uint8_t privilege : 4;
#endif
} __attribute__((packed));

/** @struct UserPayloadAccess
 *
 *  Structure to denote payload access restrictions applicable for a
 *  given user and channel. (refer spec sec 24.6)
 */
struct PayloadAccess
{
    std::bitset<payloadsPerByte> stdPayloadEnables1;
    std::bitset<payloadsPerByte> stdPayloadEnables2Reserved;
    std::bitset<payloadsPerByte> oemPayloadEnables1;
    std::bitset<payloadsPerByte> oemPayloadEnables2Reserved;
};

/** @brief initializes user management
 *
 *  @return ccSuccess for success, others for failure.
 */
Cc ipmiUserInit();

/** @brief The ipmi get user password layer call
 *
 *  @param[in] userName - user name
 *
 *  @return password or empty string
 */
std::string ipmiUserGetPassword(const std::string& userName);

/** @brief The IPMI call to clear password entry associated with specified
 * username
 *
 *  @param[in] userName - user name to be removed
 *
 *  @return 0 on success, non-zero otherwise.
 */
Cc ipmiClearUserEntryPassword(const std::string& userName);

/** @brief The IPMI call to reuse password entry for the renamed user
 *  to another one
 *
 *  @param[in] userName - user name which has to be renamed
 *  @param[in] newUserName - new user name
 *
 *  @return 0 on success, non-zero otherwise.
 */
Cc ipmiRenameUserEntryPassword(const std::string& userName,
                               const std::string& newUserName);

/** @brief determines valid userId
 *
 *  @param[in] userId - user id
 *
 *  @return true if valid, false otherwise
 */
bool ipmiUserIsValidUserId(const uint8_t userId);

/** @brief determines valid privilege level
 *
 *  @param[in] priv - privilege level
 *
 *  @return true if valid, false otherwise
 */
bool ipmiUserIsValidPrivilege(const uint8_t priv);

/** @brief get user id corresponding to the user name
 *
 *  @param[in] userName - user name
 *
 *  @return userid. Will return 0xff if no user id found
 */
uint8_t ipmiUserGetUserId(const std::string& userName);

/** @brief set's user name
 *
 *  @param[in] userId - user id
 *  @param[in] userName - user name
 *
 *  @return ccSuccess for success, others for failure.
 */
Cc ipmiUserSetUserName(const uint8_t userId, const char* userName);

/** @brief set user password
 *
 *  @param[in] userId - user id
 *  @param[in] userPassword - New Password
 *
 *  @return ccSuccess for success, others for failure.
 */
Cc ipmiUserSetUserPassword(const uint8_t userId, const char* userPassword);

/** @brief set special user password (non-ipmi accounts)
 *
 *  @param[in] userName - user name
 *  @param[in] userPassword - New Password
 *
 *  @return ccSuccess for success, others for failure.
 */
Cc ipmiSetSpecialUserPassword(const std::string& userName,
                              const std::string& userPassword);

/** @brief get user name
 *
 *  @param[in] userId - user id
 *  @param[out] userName - user name
 *
 *  @return ccSuccess for success, others for failure.
 */
Cc ipmiUserGetUserName(const uint8_t userId, std::string& userName);

/** @brief provides available fixed, max, and enabled user counts
 *
 *  @param[out] maxChUsers - max channel users
 *  @param[out] enabledUsers - enabled user count
 *  @param[out] fixedUsers - fixed user count
 *
 *  @return ccSuccess for success, others for failure.
 */
Cc ipmiUserGetAllCounts(uint8_t& maxChUsers, uint8_t& enabledUsers,
                        uint8_t& fixedUsers);

/** @brief function to update user enabled state
 *
 *  @param[in] userId - user id
 *..@param[in] state - state of the user to be updated, true - user enabled.
 *
 *  @return ccSuccess for success, others for failure.
 */
Cc ipmiUserUpdateEnabledState(const uint8_t userId, const bool& state);

/** @brief determines whether user is enabled
 *
 *  @param[in] userId - user id
 *..@param[out] state - state of the user
 *
 *  @return ccSuccess for success, others for failure.
 */
Cc ipmiUserCheckEnabled(const uint8_t userId, bool& state);

/** @brief provides user privilege access data
 *
 *  @param[in] userId - user id
 *  @param[in] chNum - channel number
 *  @param[out] privAccess - privilege access data
 *
 *  @return ccSuccess for success, others for failure.
 */
Cc ipmiUserGetPrivilegeAccess(const uint8_t userId, const uint8_t chNum,
                              PrivAccess& privAccess);

/** @brief sets user privilege access data
 *
 *  @param[in] userId - user id
 *  @param[in] chNum - channel number
 *  @param[in] privAccess - privilege access data
 *  @param[in] otherPrivUpdate - flags to indicate other fields update
 *
 *  @return ccSuccess for success, others for failure.
 */
Cc ipmiUserSetPrivilegeAccess(const uint8_t userId, const uint8_t chNum,
                              const PrivAccess& privAccess,
                              const bool& otherPrivUpdate);

/** @brief check for user pam authentication. This is to determine, whether user
 * is already locked out for failed login attempt
 *
 *  @param[in] username - username
 *  @param[in] password - password
 *
 *  @return status
 */
bool ipmiUserPamAuthenticate(std::string_view userName,
                             std::string_view userPassword);

/** @brief sets user payload access data
 *
 *  @param[in] chNum - channel number
 *  @param[in] operation - ENABLE / DISABLE operation
 *  @param[in] userId - user id
 *  @param[in] payloadAccess - payload access data
 *
 *  @return ccSuccess for success, others for failure.
 */
Cc ipmiUserSetUserPayloadAccess(const uint8_t chNum, const uint8_t operation,
                                const uint8_t userId,
                                const PayloadAccess& payloadAccess);

/** @brief provides user payload access data
 *
 *  @param[in] chNum - channel number
 *  @param[in] userId - user id
 *  @param[out] payloadAccess - payload access data
 *
 *  @return ccSuccess for success, others for failure.
 */
Cc ipmiUserGetUserPayloadAccess(const uint8_t chNum, const uint8_t userId,
                                PayloadAccess& payloadAccess);

} // namespace ipmi
<|endoftext|>