<commit_before>//===-- StringExtractor.cpp -------------------------------------*- C++ -*-===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

#include "StringExtractor.h"

// C Includes
// C++ Includes
// Other libraries and framework includes
// Project includes

static inline int
xdigit_to_sint (char ch)
{
    ch = tolower(ch);
    if (ch >= 'a' && ch <= 'f')
        return 10 + ch - 'a';
    return ch - '0';
}

static inline unsigned int
xdigit_to_uint (uint8_t ch)
{
    ch = tolower(ch);
    if (ch >= 'a' && ch <= 'f')
        return 10u + ch - 'a';
    return ch - '0';
}

//----------------------------------------------------------------------
// StringExtractor constructor
//----------------------------------------------------------------------
StringExtractor::StringExtractor() :
    m_packet(),
    m_index (0)
{
}

StringExtractor::StringExtractor(const char *packet_cstr) :
    m_packet(),
    m_index (0)
{
    if (packet_cstr)
        m_packet.assign (packet_cstr);
}

//----------------------------------------------------------------------
// StringExtractor copy constructor
//----------------------------------------------------------------------
StringExtractor::StringExtractor(const StringExtractor& rhs) :
    m_packet (rhs.m_packet),
    m_index (rhs.m_index)
{

}

//----------------------------------------------------------------------
// StringExtractor assignment operator
//----------------------------------------------------------------------
const StringExtractor&
StringExtractor::operator=(const StringExtractor& rhs)
{
    if (this != &rhs)
    {
        m_packet = rhs.m_packet;
        m_index = rhs.m_index;

    }
    return *this;
}

//----------------------------------------------------------------------
// Destructor
//----------------------------------------------------------------------
StringExtractor::~StringExtractor()
{
}

char
StringExtractor::GetChar (char fail_value)
{
    if (m_index < m_packet.size())
    {
        char ch = m_packet[m_index];
        ++m_index;
        return ch;
    }
    m_index = UINT32_MAX;
    return fail_value;
}

uint32_t
StringExtractor::GetNumHexASCIICharsAtFilePos (uint32_t max) const
{
    uint32_t idx = m_index;
    const size_t size = m_packet.size();
    while (idx < size && idx - m_index < max && isxdigit(m_packet[idx]))
        ++idx;
    return idx - m_index;
}
//----------------------------------------------------------------------
// Extract a signed character from two hex ASCII chars in the packet
// string
//----------------------------------------------------------------------
int8_t
StringExtractor::GetHexS8 (int8_t fail_value)
{
    if (GetNumHexASCIICharsAtFilePos(2))
    {
        char hi_nibble_char = m_packet[m_index];
        char lo_nibble_char = m_packet[m_index+1];

        if (isxdigit(hi_nibble_char) && isxdigit(lo_nibble_char))
        {
            char hi_nibble = xdigit_to_sint (hi_nibble_char);
            char lo_nibble = xdigit_to_sint (lo_nibble_char);
            m_index += 2;
            return (hi_nibble << 4) + lo_nibble;
        }
    }
    m_index = UINT32_MAX;
    return fail_value;
}

//----------------------------------------------------------------------
// Extract an unsigned character from two hex ASCII chars in the packet
// string
//----------------------------------------------------------------------
uint8_t
StringExtractor::GetHexU8 (uint8_t fail_value)
{
    if (GetNumHexASCIICharsAtFilePos(2))
    {
        uint8_t hi_nibble_char = m_packet[m_index];
        uint8_t lo_nibble_char = m_packet[m_index+1];

        if (isxdigit(hi_nibble_char) && isxdigit(lo_nibble_char))
        {
            uint8_t hi_nibble = xdigit_to_sint (hi_nibble_char);
            uint8_t lo_nibble = xdigit_to_sint (lo_nibble_char);
            m_index += 2;
            return (hi_nibble << 4) + lo_nibble;
        }
    }
    m_index = UINT32_MAX;
    return fail_value;
}

uint32_t
StringExtractor::GetHexMaxU32 (bool little_endian, uint32_t fail_value)
{
    uint32_t result = 0;
    uint32_t nibble_count = 0;

    if (little_endian)
    {
        uint32_t shift_amount = 0;
        while (m_index < m_packet.size() && ::isxdigit (m_packet[m_index]))
        {
            // Make sure we don't exceed the size of a uint32_t...
            if (nibble_count >= (sizeof(uint32_t) * 2))
            {
                m_index = UINT32_MAX;
                return fail_value;
            }

            uint8_t nibble_lo;
            uint8_t nibble_hi = xdigit_to_sint (m_packet[m_index]);
            ++m_index;
            if (m_index < m_packet.size() && ::isxdigit (m_packet[m_index]))
            {
                nibble_lo = xdigit_to_sint (m_packet[m_index]);
                ++m_index;
                result |= ((uint32_t)nibble_hi << (shift_amount + 4));
                result |= ((uint32_t)nibble_lo << shift_amount);
                nibble_count += 2;
                shift_amount += 8;
            }
            else
            {
                result |= ((uint32_t)nibble_hi << shift_amount);
                nibble_count += 1;
                shift_amount += 4;
            }

        }
    }
    else
    {
        while (m_index < m_packet.size() && ::isxdigit (m_packet[m_index]))
        {
            // Make sure we don't exceed the size of a uint32_t...
            if (nibble_count >= (sizeof(uint32_t) * 2))
            {
                m_index = UINT32_MAX;
                return fail_value;
            }

            uint8_t nibble = xdigit_to_sint (m_packet[m_index]);
            // Big Endian
            result <<= 4;
            result |= nibble;

            ++m_index;
            ++nibble_count;
        }
    }
    return result;
}

uint64_t
StringExtractor::GetHexMaxU64 (bool little_endian, uint64_t fail_value)
{
    uint64_t result = 0;
    uint32_t nibble_count = 0;

    if (little_endian)
    {
        uint32_t shift_amount = 0;
        while (m_index < m_packet.size() && ::isxdigit (m_packet[m_index]))
        {
            // Make sure we don't exceed the size of a uint64_t...
            if (nibble_count >= (sizeof(uint64_t) * 2))
            {
                m_index = UINT32_MAX;
                return fail_value;
            }

            uint8_t nibble_lo;
            uint8_t nibble_hi = xdigit_to_sint (m_packet[m_index]);
            ++m_index;
            if (m_index < m_packet.size() && ::isxdigit (m_packet[m_index]))
            {
                nibble_lo = xdigit_to_sint (m_packet[m_index]);
                ++m_index;
                result |= ((uint64_t)nibble_hi << (shift_amount + 4));
                result |= ((uint64_t)nibble_lo << shift_amount);
                nibble_count += 2;
                shift_amount += 8;
            }
            else
            {
                result |= ((uint64_t)nibble_hi << shift_amount);
                nibble_count += 1;
                shift_amount += 4;
            }

        }
    }
    else
    {
        while (m_index < m_packet.size() && ::isxdigit (m_packet[m_index]))
        {
            // Make sure we don't exceed the size of a uint64_t...
            if (nibble_count >= (sizeof(uint64_t) * 2))
            {
                m_index = UINT32_MAX;
                return fail_value;
            }

            uint8_t nibble = xdigit_to_sint (m_packet[m_index]);
            // Big Endian
            result <<= 4;
            result |= nibble;

            ++m_index;
            ++nibble_count;
        }
    }
    return result;
}

size_t
StringExtractor::GetHexBytes (void *dst_void, size_t dst_len, uint8_t fail_fill_value)
{
    uint8_t *dst = (uint8_t*)dst_void;
    size_t bytes_extracted = 0;
    while (bytes_extracted < dst_len && GetBytesLeft ())
    {
        dst[bytes_extracted] = GetHexU8 (fail_fill_value);
        if (IsGood())
            ++bytes_extracted;
        else
            break;
    }

    for (size_t i = bytes_extracted; i < dst_len; ++i)
        dst[i] = fail_fill_value;

    return bytes_extracted;
}

// Consume ASCII hex nibble character pairs until we have decoded byte_size
// bytes of data.

uint64_t
StringExtractor::GetHexWithFixedSize (uint32_t byte_size, bool little_endian, uint64_t fail_value)
{
    if (byte_size <= 8 && GetBytesLeft() >= byte_size * 2)
    {
        uint64_t result = 0;
        uint32_t i;
        if (little_endian)
        {
            // Little Endian
            uint32_t shift_amount;
            for (i = 0, shift_amount = 0;
                 i < byte_size && m_index != UINT32_MAX;
                 ++i, shift_amount += 8)
            {
                result |= ((uint64_t)GetHexU8() << shift_amount);
            }
        }
        else
        {
            // Big Endian
            for (i = 0; i < byte_size && m_index != UINT32_MAX; ++i)
            {
                result <<= 8;
                result |= GetHexU8();
            }
        }
    }
    m_index = UINT32_MAX;
    return fail_value;
}

bool
StringExtractor::GetNameColonValue (std::string &name, std::string &value)
{
    // Read something in the form of NNNN:VVVV; where NNNN is any character
    // that is not a colon, followed by a ':' character, then a value (one or
    // more ';' chars), followed by a ';'
    if (m_index < m_packet.size())
    {
        const size_t colon_idx = m_packet.find (':', m_index);
        if (colon_idx != std::string::npos)
        {
            const size_t semicolon_idx = m_packet.find (';', colon_idx);
            if (semicolon_idx != std::string::npos)
            {
                name.assign (m_packet, m_index, colon_idx - m_index);
                value.assign (m_packet, colon_idx + 1, semicolon_idx - (colon_idx + 1));
                m_index = semicolon_idx + 1;
                return true;
            }
        }
    }
    m_index = UINT32_MAX;
    return false;
}
<commit_msg>Avoid tolower, it's slow and unnecessary.<commit_after>//===-- StringExtractor.cpp -------------------------------------*- C++ -*-===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

#include "StringExtractor.h"

// C Includes
// C++ Includes
// Other libraries and framework includes
// Project includes

static inline int
xdigit_to_sint (char ch)
{
    if (ch >= 'a' && ch <= 'f')
        return 10 + ch - 'a';
    if (ch >= 'A' && ch <= 'F')
        return 10 + ch - 'A';
    return ch - '0';
}

static inline unsigned int
xdigit_to_uint (uint8_t ch)
{
    if (ch >= 'a' && ch <= 'f')
        return 10u + ch - 'a';
    if (ch >= 'A' && ch <= 'F')
        return 10u + ch - 'A';
    return ch - '0';
}

//----------------------------------------------------------------------
// StringExtractor constructor
//----------------------------------------------------------------------
StringExtractor::StringExtractor() :
    m_packet(),
    m_index (0)
{
}

StringExtractor::StringExtractor(const char *packet_cstr) :
    m_packet(),
    m_index (0)
{
    if (packet_cstr)
        m_packet.assign (packet_cstr);
}

//----------------------------------------------------------------------
// StringExtractor copy constructor
//----------------------------------------------------------------------
StringExtractor::StringExtractor(const StringExtractor& rhs) :
    m_packet (rhs.m_packet),
    m_index (rhs.m_index)
{

}

//----------------------------------------------------------------------
// StringExtractor assignment operator
//----------------------------------------------------------------------
const StringExtractor&
StringExtractor::operator=(const StringExtractor& rhs)
{
    if (this != &rhs)
    {
        m_packet = rhs.m_packet;
        m_index = rhs.m_index;

    }
    return *this;
}

//----------------------------------------------------------------------
// Destructor
//----------------------------------------------------------------------
StringExtractor::~StringExtractor()
{
}

char
StringExtractor::GetChar (char fail_value)
{
    if (m_index < m_packet.size())
    {
        char ch = m_packet[m_index];
        ++m_index;
        return ch;
    }
    m_index = UINT32_MAX;
    return fail_value;
}

uint32_t
StringExtractor::GetNumHexASCIICharsAtFilePos (uint32_t max) const
{
    uint32_t idx = m_index;
    const size_t size = m_packet.size();
    while (idx < size && idx - m_index < max && isxdigit(m_packet[idx]))
        ++idx;
    return idx - m_index;
}
//----------------------------------------------------------------------
// Extract a signed character from two hex ASCII chars in the packet
// string
//----------------------------------------------------------------------
int8_t
StringExtractor::GetHexS8 (int8_t fail_value)
{
    if (GetNumHexASCIICharsAtFilePos(2))
    {
        char hi_nibble_char = m_packet[m_index];
        char lo_nibble_char = m_packet[m_index+1];

        if (isxdigit(hi_nibble_char) && isxdigit(lo_nibble_char))
        {
            char hi_nibble = xdigit_to_sint (hi_nibble_char);
            char lo_nibble = xdigit_to_sint (lo_nibble_char);
            m_index += 2;
            return (hi_nibble << 4) + lo_nibble;
        }
    }
    m_index = UINT32_MAX;
    return fail_value;
}

//----------------------------------------------------------------------
// Extract an unsigned character from two hex ASCII chars in the packet
// string
//----------------------------------------------------------------------
uint8_t
StringExtractor::GetHexU8 (uint8_t fail_value)
{
    if (GetNumHexASCIICharsAtFilePos(2))
    {
        uint8_t hi_nibble_char = m_packet[m_index];
        uint8_t lo_nibble_char = m_packet[m_index+1];

        if (isxdigit(hi_nibble_char) && isxdigit(lo_nibble_char))
        {
            uint8_t hi_nibble = xdigit_to_sint (hi_nibble_char);
            uint8_t lo_nibble = xdigit_to_sint (lo_nibble_char);
            m_index += 2;
            return (hi_nibble << 4) + lo_nibble;
        }
    }
    m_index = UINT32_MAX;
    return fail_value;
}

uint32_t
StringExtractor::GetHexMaxU32 (bool little_endian, uint32_t fail_value)
{
    uint32_t result = 0;
    uint32_t nibble_count = 0;

    if (little_endian)
    {
        uint32_t shift_amount = 0;
        while (m_index < m_packet.size() && ::isxdigit (m_packet[m_index]))
        {
            // Make sure we don't exceed the size of a uint32_t...
            if (nibble_count >= (sizeof(uint32_t) * 2))
            {
                m_index = UINT32_MAX;
                return fail_value;
            }

            uint8_t nibble_lo;
            uint8_t nibble_hi = xdigit_to_sint (m_packet[m_index]);
            ++m_index;
            if (m_index < m_packet.size() && ::isxdigit (m_packet[m_index]))
            {
                nibble_lo = xdigit_to_sint (m_packet[m_index]);
                ++m_index;
                result |= ((uint32_t)nibble_hi << (shift_amount + 4));
                result |= ((uint32_t)nibble_lo << shift_amount);
                nibble_count += 2;
                shift_amount += 8;
            }
            else
            {
                result |= ((uint32_t)nibble_hi << shift_amount);
                nibble_count += 1;
                shift_amount += 4;
            }

        }
    }
    else
    {
        while (m_index < m_packet.size() && ::isxdigit (m_packet[m_index]))
        {
            // Make sure we don't exceed the size of a uint32_t...
            if (nibble_count >= (sizeof(uint32_t) * 2))
            {
                m_index = UINT32_MAX;
                return fail_value;
            }

            uint8_t nibble = xdigit_to_sint (m_packet[m_index]);
            // Big Endian
            result <<= 4;
            result |= nibble;

            ++m_index;
            ++nibble_count;
        }
    }
    return result;
}

uint64_t
StringExtractor::GetHexMaxU64 (bool little_endian, uint64_t fail_value)
{
    uint64_t result = 0;
    uint32_t nibble_count = 0;

    if (little_endian)
    {
        uint32_t shift_amount = 0;
        while (m_index < m_packet.size() && ::isxdigit (m_packet[m_index]))
        {
            // Make sure we don't exceed the size of a uint64_t...
            if (nibble_count >= (sizeof(uint64_t) * 2))
            {
                m_index = UINT32_MAX;
                return fail_value;
            }

            uint8_t nibble_lo;
            uint8_t nibble_hi = xdigit_to_sint (m_packet[m_index]);
            ++m_index;
            if (m_index < m_packet.size() && ::isxdigit (m_packet[m_index]))
            {
                nibble_lo = xdigit_to_sint (m_packet[m_index]);
                ++m_index;
                result |= ((uint64_t)nibble_hi << (shift_amount + 4));
                result |= ((uint64_t)nibble_lo << shift_amount);
                nibble_count += 2;
                shift_amount += 8;
            }
            else
            {
                result |= ((uint64_t)nibble_hi << shift_amount);
                nibble_count += 1;
                shift_amount += 4;
            }

        }
    }
    else
    {
        while (m_index < m_packet.size() && ::isxdigit (m_packet[m_index]))
        {
            // Make sure we don't exceed the size of a uint64_t...
            if (nibble_count >= (sizeof(uint64_t) * 2))
            {
                m_index = UINT32_MAX;
                return fail_value;
            }

            uint8_t nibble = xdigit_to_sint (m_packet[m_index]);
            // Big Endian
            result <<= 4;
            result |= nibble;

            ++m_index;
            ++nibble_count;
        }
    }
    return result;
}

size_t
StringExtractor::GetHexBytes (void *dst_void, size_t dst_len, uint8_t fail_fill_value)
{
    uint8_t *dst = (uint8_t*)dst_void;
    size_t bytes_extracted = 0;
    while (bytes_extracted < dst_len && GetBytesLeft ())
    {
        dst[bytes_extracted] = GetHexU8 (fail_fill_value);
        if (IsGood())
            ++bytes_extracted;
        else
            break;
    }

    for (size_t i = bytes_extracted; i < dst_len; ++i)
        dst[i] = fail_fill_value;

    return bytes_extracted;
}

// Consume ASCII hex nibble character pairs until we have decoded byte_size
// bytes of data.

uint64_t
StringExtractor::GetHexWithFixedSize (uint32_t byte_size, bool little_endian, uint64_t fail_value)
{
    if (byte_size <= 8 && GetBytesLeft() >= byte_size * 2)
    {
        uint64_t result = 0;
        uint32_t i;
        if (little_endian)
        {
            // Little Endian
            uint32_t shift_amount;
            for (i = 0, shift_amount = 0;
                 i < byte_size && m_index != UINT32_MAX;
                 ++i, shift_amount += 8)
            {
                result |= ((uint64_t)GetHexU8() << shift_amount);
            }
        }
        else
        {
            // Big Endian
            for (i = 0; i < byte_size && m_index != UINT32_MAX; ++i)
            {
                result <<= 8;
                result |= GetHexU8();
            }
        }
    }
    m_index = UINT32_MAX;
    return fail_value;
}

bool
StringExtractor::GetNameColonValue (std::string &name, std::string &value)
{
    // Read something in the form of NNNN:VVVV; where NNNN is any character
    // that is not a colon, followed by a ':' character, then a value (one or
    // more ';' chars), followed by a ';'
    if (m_index < m_packet.size())
    {
        const size_t colon_idx = m_packet.find (':', m_index);
        if (colon_idx != std::string::npos)
        {
            const size_t semicolon_idx = m_packet.find (';', colon_idx);
            if (semicolon_idx != std::string::npos)
            {
                name.assign (m_packet, m_index, colon_idx - m_index);
                value.assign (m_packet, colon_idx + 1, semicolon_idx - (colon_idx + 1));
                m_index = semicolon_idx + 1;
                return true;
            }
        }
    }
    m_index = UINT32_MAX;
    return false;
}
<|endoftext|>


<commit_before>//                      MFEM Example 33
//
// Compile with: make ex33p
//
// Sample runs:  mpirun -np 4 ex33p -m ../data/square-disc.mesh -alpha 0.33 -o 2
//               mpirun -np 4 ex33p -m ../data/star.mesh -alpha 0.99 -o 3
//               mpirun -np 4 ex33p -m ../data/inline-quad.mesh -alpha 0.2 -o 3
//               mpirun -np 4 ex33p -m ../data/disc-nurbs.mesh -alpha 0.33 -o 3
//               mpirun -np 4 ex33p -m ../data/l-shape.mesh -alpha 0.33 -o 3 -r 4
//
//
// Description:
//
//  In this example we solve the following fractional PDE with MFEM:
//
//    ( - Δ )^α u = f  in Ω,      u = 0  on ∂Ω,      0 < α < 1,
//
//  To solve this FPDE, we rely on a rational approximation [2] of the normal
//  linear operator A^{-α}, where A = - Δ (with associated homogenous
//  boundary conditions). Namely, we first approximate the operator
//
//    A^{-α} ≈ Σ_{i=0}^N c_i (A + d_i I)^{-1},      d_0 = 0,   d_i > 0,
//
//  where I is the L2-identity operator and the coefficients c_i and d_i
//  are generated offline to a prescribed accuracy in a pre-processing step.
//  We use the triple-A algorithm [1] to generate the rational approximation
//  that this partial fractional expansion derives from. We then solve N+1
//  independent integer-order PDEs,
//
//    A u_i + d_i u_i = c_i f  in Ω,      u_i = 0  on ∂Ω,      i=0,...,N,
//
//  using MFEM and sum u_i to arrive at an approximate solution of the FPDE
//
//    u ≈ Σ_{i=0}^N u_i.
//
//
// References:
//
// [1] Nakatsukasa, Y., Sète, O., & Trefethen, L. N. (2018). The AAA algorithm
//     for rational approximation. SIAM Journal on Scientific Computing, 40(3),
//     A1494-A1522.
//
// [2] Harizanov, S., Lazarov, R., Margenov, S., Marinov, P., & Pasciak, J.
//     (2020). Analysis of numerical methods for spectral fractional elliptic
//     equations based on the best uniform rational approximation. Journal of
//     Computational Physics, 408, 109285.
//

#include "mfem.hpp"
#include <fstream>
#include <iostream>
#include "ex33.hpp"

using namespace std;
using namespace mfem;

int main(int argc, char *argv[])
{
   // 0. Initialize MPI.
   MPI_Session mpi;
   int num_procs = mpi.WorldSize();
   int myid = mpi.WorldRank();

   // 1. Parse command-line options.
   const char *mesh_file = "../data/star.mesh";
   int order = 1;
   int num_refs = 3;
   bool visualization = true;
   double alpha = 0.5;

   OptionsParser args(argc, argv);
   args.AddOption(&mesh_file, "-m", "--mesh",
                  "Mesh file to use.");
   args.AddOption(&order, "-o", "--order",
                  "Finite element order (polynomial degree) or -1 for"
                  " isoparametric space.");
   args.AddOption(&num_refs, "-r", "--refs",
                  "Number of uniform refinements");
   args.AddOption(&alpha, "-alpha", "--alpha",
                  "Fractional exponent");
   args.AddOption(&visualization, "-vis", "--visualization", "-no-vis",
                  "--no-visualization",
                  "Enable or disable GLVis visualization.");
   args.Parse();
   if (!args.Good())
   {
      args.PrintUsage(cout);
      return 1;
   }
   if (myid == 0)
   {
      args.PrintOptions(cout);
   }

   Array<double> coeffs, poles;

   // 2. Compute the coefficients that define the integer-order PDEs.
   ComputePartialFractionApproximation(alpha,coeffs,poles);

   // 3. Read the mesh from the given mesh file.
   Mesh mesh(mesh_file, 1, 1);
   int dim = mesh.Dimension();

   // 4. Refine the mesh to increase the resolution.
   for (int i = 0; i < num_refs; i++)
   {
      mesh.UniformRefinement();
   }

   ParMesh pmesh(MPI_COMM_WORLD, mesh);
   mesh.Clear();

   // 5. Define a finite element space on the mesh.
   FiniteElementCollection *fec = new H1_FECollection(order, dim);
   ParFiniteElementSpace fespace(&pmesh, fec);
   if (myid == 0)
   {
      cout << "Number of finite element unknowns: "
           << fespace.GetTrueVSize() << endl;
   }

   // 6. Determine the list of true (i.e. conforming) essential boundary dofs.
   Array<int> ess_tdof_list;
   if (pmesh.bdr_attributes.Size())
   {
      Array<int> ess_bdr(pmesh.bdr_attributes.Max());
      ess_bdr = 1;
      fespace.GetEssentialTrueDofs(ess_bdr, ess_tdof_list);
   }

   // 7. Define diffusion coefficient, load, and solution GridFunction.
   ConstantCoefficient f(1.0);
   ConstantCoefficient one(1.0);
   ParGridFunction u(&fespace);
   u = 0.;

   // 8. Prepare for visualization.
   char vishost[] = "localhost";
   int  visport   = 19916;
   socketstream xout;
   socketstream uout;
   if (visualization)
   {
      xout.open(vishost, visport);
      xout.precision(8);
      uout.open(vishost, visport);
      uout.precision(8);
   }

   for (int i = 0; i<coeffs.Size(); i++)
   {
      // 9. Set up the linear form b(.) for integer-order PDE solve.
      ParLinearForm b(&fespace);
      ProductCoefficient cf(coeffs[i], f);
      b.AddDomainIntegrator(new DomainLFIntegrator(cf));
      b.Assemble();

      // 10. Define GridFunction for integer-order PDE solve.
      ParGridFunction x(&fespace);
      x = 0.0;

      // 11. Set up the bilinear form a(.,.) for integer-order PDE solve.
      ParBilinearForm a(&fespace);
      a.AddDomainIntegrator(new DiffusionIntegrator(one));
      ConstantCoefficient c2(-poles[i]);
      a.AddDomainIntegrator(new MassIntegrator(c2));
      a.Assemble();

      // 12. Assemble the bilinear form and the corresponding linear system.
      OperatorPtr A;
      Vector B, X;
      a.FormLinearSystem(ess_tdof_list, x, b, A, X, B);

      // 13. Solve the linear system A X = B.
      Solver *M = new OperatorJacobiSmoother(a, ess_tdof_list);;
      CGSolver cg(MPI_COMM_WORLD);
      cg.SetRelTol(1e-12);
      cg.SetMaxIter(2000);
      cg.SetPrintLevel(3);
      cg.SetPreconditioner(*M);
      cg.SetOperator(*A);
      cg.Mult(B, X);
      delete M;

      // 14. Recover the solution as a finite element grid function.
      a.RecoverFEMSolution(X, b, x);

      // 15. Accumulate integer-order PDE solutions.
      u+=x;

      // 16. Send the solutions by socket to a GLVis server.
      if (visualization)
      {
         xout << "parallel " << num_procs << " " << myid << "\n";
         xout << "solution\n" << pmesh << x << flush;
         uout << "parallel " << num_procs << " " << myid << "\n";
         uout << "solution\n" << pmesh << u << flush;
      }
   }

   delete fec;
   return 0;
}
<commit_msg>using amg prec in ex33p<commit_after>//                      MFEM Example 33
//
// Compile with: make ex33p
//
// Sample runs:  mpirun -np 4 ex33p -m ../data/square-disc.mesh -alpha 0.33 -o 2
//               mpirun -np 4 ex33p -m ../data/star.mesh -alpha 0.99 -o 3
//               mpirun -np 4 ex33p -m ../data/inline-quad.mesh -alpha 0.2 -o 3
//               mpirun -np 4 ex33p -m ../data/disc-nurbs.mesh -alpha 0.33 -o 3
//               mpirun -np 4 ex33p -m ../data/l-shape.mesh -alpha 0.33 -o 3 -r 4
//
//
// Description:
//
//  In this example we solve the following fractional PDE with MFEM:
//
//    ( - Δ )^α u = f  in Ω,      u = 0  on ∂Ω,      0 < α < 1,
//
//  To solve this FPDE, we rely on a rational approximation [2] of the normal
//  linear operator A^{-α}, where A = - Δ (with associated homogenous
//  boundary conditions). Namely, we first approximate the operator
//
//    A^{-α} ≈ Σ_{i=0}^N c_i (A + d_i I)^{-1},      d_0 = 0,   d_i > 0,
//
//  where I is the L2-identity operator and the coefficients c_i and d_i
//  are generated offline to a prescribed accuracy in a pre-processing step.
//  We use the triple-A algorithm [1] to generate the rational approximation
//  that this partial fractional expansion derives from. We then solve N+1
//  independent integer-order PDEs,
//
//    A u_i + d_i u_i = c_i f  in Ω,      u_i = 0  on ∂Ω,      i=0,...,N,
//
//  using MFEM and sum u_i to arrive at an approximate solution of the FPDE
//
//    u ≈ Σ_{i=0}^N u_i.
//
//
// References:
//
// [1] Nakatsukasa, Y., Sète, O., & Trefethen, L. N. (2018). The AAA algorithm
//     for rational approximation. SIAM Journal on Scientific Computing, 40(3),
//     A1494-A1522.
//
// [2] Harizanov, S., Lazarov, R., Margenov, S., Marinov, P., & Pasciak, J.
//     (2020). Analysis of numerical methods for spectral fractional elliptic
//     equations based on the best uniform rational approximation. Journal of
//     Computational Physics, 408, 109285.
//

#include "mfem.hpp"
#include <fstream>
#include <iostream>
#include "ex33.hpp"

using namespace std;
using namespace mfem;

int main(int argc, char *argv[])
{
   // 0. Initialize MPI.
   MPI_Session mpi;
   int num_procs = mpi.WorldSize();
   int myid = mpi.WorldRank();

   // 1. Parse command-line options.
   const char *mesh_file = "../data/star.mesh";
   int order = 1;
   int num_refs = 3;
   bool visualization = true;
   double alpha = 0.5;

   OptionsParser args(argc, argv);
   args.AddOption(&mesh_file, "-m", "--mesh",
                  "Mesh file to use.");
   args.AddOption(&order, "-o", "--order",
                  "Finite element order (polynomial degree) or -1 for"
                  " isoparametric space.");
   args.AddOption(&num_refs, "-r", "--refs",
                  "Number of uniform refinements");
   args.AddOption(&alpha, "-alpha", "--alpha",
                  "Fractional exponent");
   args.AddOption(&visualization, "-vis", "--visualization", "-no-vis",
                  "--no-visualization",
                  "Enable or disable GLVis visualization.");
   args.Parse();
   if (!args.Good())
   {
      args.PrintUsage(cout);
      return 1;
   }
   if (myid == 0)
   {
      args.PrintOptions(cout);
   }

   Array<double> coeffs, poles;

   // 2. Compute the coefficients that define the integer-order PDEs.
   ComputePartialFractionApproximation(alpha,coeffs,poles);

   // 3. Read the mesh from the given mesh file.
   Mesh mesh(mesh_file, 1, 1);
   int dim = mesh.Dimension();

   // 4. Refine the mesh to increase the resolution.
   for (int i = 0; i < num_refs; i++)
   {
      mesh.UniformRefinement();
   }

   ParMesh pmesh(MPI_COMM_WORLD, mesh);
   mesh.Clear();

   // 5. Define a finite element space on the mesh.
   FiniteElementCollection *fec = new H1_FECollection(order, dim);
   ParFiniteElementSpace fespace(&pmesh, fec);
   if (myid == 0)
   {
      cout << "Number of finite element unknowns: "
           << fespace.GetTrueVSize() << endl;
   }

   // 6. Determine the list of true (i.e. conforming) essential boundary dofs.
   Array<int> ess_tdof_list;
   if (pmesh.bdr_attributes.Size())
   {
      Array<int> ess_bdr(pmesh.bdr_attributes.Max());
      ess_bdr = 1;
      fespace.GetEssentialTrueDofs(ess_bdr, ess_tdof_list);
   }

   // 7. Define diffusion coefficient, load, and solution GridFunction.
   ConstantCoefficient f(1.0);
   ConstantCoefficient one(1.0);
   ParGridFunction u(&fespace);
   u = 0.;

   // 8. Prepare for visualization.
   char vishost[] = "localhost";
   int  visport   = 19916;
   socketstream xout;
   socketstream uout;
   if (visualization)
   {
      xout.open(vishost, visport);
      xout.precision(8);
      uout.open(vishost, visport);
      uout.precision(8);
   }

   for (int i = 0; i<coeffs.Size(); i++)
   {
      // 9. Set up the linear form b(.) for integer-order PDE solve.
      ParLinearForm b(&fespace);
      ProductCoefficient cf(coeffs[i], f);
      b.AddDomainIntegrator(new DomainLFIntegrator(cf));
      b.Assemble();

      // 10. Define GridFunction for integer-order PDE solve.
      ParGridFunction x(&fespace);
      x = 0.0;

      // 11. Set up the bilinear form a(.,.) for integer-order PDE solve.
      ParBilinearForm a(&fespace);
      a.AddDomainIntegrator(new DiffusionIntegrator(one));
      ConstantCoefficient c2(-poles[i]);
      a.AddDomainIntegrator(new MassIntegrator(c2));
      a.Assemble();

      // 12. Assemble the bilinear form and the corresponding linear system.
      OperatorPtr A;
      Vector B, X;
      a.FormLinearSystem(ess_tdof_list, x, b, A, X, B);

      // 13. Solve the linear system A X = B.
      HypreBoomerAMG * prec = new HypreBoomerAMG;
      prec->SetPrintLevel(-1);

      CGSolver cg(MPI_COMM_WORLD);
      cg.SetRelTol(1e-12);
      cg.SetMaxIter(2000);
      cg.SetPrintLevel(3);
      cg.SetPreconditioner(*prec);
      cg.SetOperator(*A);
      cg.Mult(B, X);
      delete prec;

      // 14. Recover the solution as a finite element grid function.
      a.RecoverFEMSolution(X, b, x);

      // 15. Accumulate integer-order PDE solutions.
      u+=x;

      // 16. Send the solutions by socket to a GLVis server.
      if (visualization)
      {
         xout << "parallel " << num_procs << " " << myid << "\n";
         xout << "solution\n" << pmesh << x << flush;
         uout << "parallel " << num_procs << " " << myid << "\n";
         uout << "solution\n" << pmesh << u << flush;
      }
   }

   delete fec;
   return 0;
}
<|endoftext|>


<commit_before>//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.

#include <cassert>
#include <vector>
#include <set>
#include <fstream>
#include <sstream>

#include "llvm/IR/DataLayout.h"
#include "llvm/IR/BasicBlock.h"
#include "llvm/IR/Constants.h"
#include "llvm/IR/Function.h"
#include "llvm/IR/GlobalVariable.h"
#include "llvm/IR/Instructions.h"
#include "llvm/IR/Module.h"
#include "llvm/Pass.h"
#include "llvm/IR/Type.h"
#include "llvm/IR/TypeBuilder.h"
#if LLVM_VERSION_MAJOR >= 4 || (LLVM_VERSION_MAJOR == 3 && LLVM_VERSION_MINOR >= 5)
  #include "llvm/IR/InstIterator.h"
#else
  #include "llvm/Support/InstIterator.h"
#endif
#include "llvm/Support/raw_ostream.h"
#include "llvm/Transforms/Utils/BasicBlockUtils.h"

#include "llvm/Support/CommandLine.h"

using namespace llvm;

static cl::opt<std::string> source_name("rename-verifier-funs-source",
                                        cl::desc("Specify source filename"),
                                        cl::value_desc("filename"));

class RenameVerifierFuns : public ModulePass
{
  // every item is (line number, call)
  std::vector<std::pair<unsigned, CallInst *>> calls_to_replace;
  std::set<unsigned> lines_nums;
  std::map<unsigned, std::string> lines;

  void handleCall(Function& F, CallInst *CI);
  void mapLines();
  void replaceCalls(Module& M);

public:
  static char ID;

  RenameVerifierFuns() : ModulePass(ID) {}
  bool runOnFunction(Function &F);
  // must be module pass, so that we can iterate over
  // declarations too
  virtual bool runOnModule(Module &M) {
    for (auto& F : M)
      runOnFunction(F);

    mapLines();
    replaceCalls(M);
    return !calls_to_replace.empty();
  }
};

bool RenameVerifierFuns::runOnFunction(Function &F) {
  if (!F.isDeclaration())
    return false;

  StringRef name = F.getName();
  if (!name.startswith("__VERIFIER_nondet_"))
    return false;

  bool changed = false;

  //llvm::errs() << "Got __VERIFIER_fun: " << name << "\n";

  for (auto I = F.use_begin(), E = F.use_end(); I != E; ++I) {
#if ((LLVM_VERSION_MAJOR == 3) && (LLVM_VERSION_MINOR < 5))
    Value *use = *I;
#else
    Value *use = I->getUser();
#endif

    if (CallInst *CI = dyn_cast<CallInst>(use)) {
      handleCall(F, CI);
    }
  }

  return changed;
}

void RenameVerifierFuns::handleCall(Function& F, CallInst *CI) {
  const DebugLoc& Loc = CI->getDebugLoc();
  if (Loc) {
	calls_to_replace.emplace_back(Loc.getLine(), CI);
    lines_nums.insert(Loc.getLine());
  }
}

void RenameVerifierFuns::mapLines() {
  if (lines_nums.empty()) {
    assert(calls_to_replace.empty());
    return;
  }

  std::ifstream file(source_name);

  if (file.is_open()) {
    unsigned n = 1;
    std::string line;

    while (getline(file,line)) {
      if (lines_nums.count(n) > 0)
		lines[n] = std::move(line);
      ++n;
    }

    file.close();
  } else {
	errs() << "Couldn't open file: " << source_name << "\n";
    abort();
  }

  assert(lines.size() == lines_nums.size());
}

static void replaceCall(Module& M, CallInst *CI, unsigned line, const std::string& var) {
  std::string parent_name = cast<Function>(CI->getCalledValue()->stripPointerCasts())->getName();
  std::string name = parent_name + ":" + var + ":" + std::to_string(line);
  Function *called_func = CI->getCalledFunction();
  Constant *new_func = M.getOrInsertFunction(called_func->getName().str() + "_named",
										     called_func->getAttributes(),
									         called_func->getReturnType(),
                                             Type::getInt8PtrTy(M.getContext()),
                                             nullptr);
  assert(new_func);

  std::vector<Value *> args;
  Constant *name_const = ConstantDataArray::getString(M.getContext(), name);
  GlobalVariable *nameG = new GlobalVariable(M, name_const->getType(), true /*constant */,
                                             GlobalVariable::PrivateLinkage, name_const);
  args.push_back(ConstantExpr::getPointerCast(nameG,
                                              Type::getInt8PtrTy(M.getContext())));

  CallInst *new_CI = CallInst::Create(new_func, args);
  SmallVector<std::pair<unsigned, MDNode *>, 8> metadata;
  CI->getAllMetadata(metadata);
  // copy the metadata
  for (auto& md : metadata)
    new_CI->setMetadata(md.first, md.second);
  // copy the attributes (like zeroext etc.)
  new_CI->setAttributes(CI->getAttributes());

  new_CI->insertBefore(CI);
  CI->replaceAllUsesWith(new_CI);
  CI->eraseFromParent();
}

static std::string getName(const std::string& line) {
  std::istringstream iss(line);
  std::string sub, var;
  while (iss >> sub) {
    if (sub == "=") {
	  break;
    }
	var = std::move(sub);
  }

  if (!var.empty() && sub == "=") {
    // check also that after = follows the __VERIFIER_* call
    iss >> sub;
    // this may make problems with casting, line: (int) __VERIFIER_nondet_char()
    // maybe this is not needed?
    if (sub.compare(0, 18, "__VERIFIER_nondet_") == 0)
		return var;
  }

  return "--";
}

void RenameVerifierFuns::replaceCalls(Module& M) {
  for (auto& pr : calls_to_replace) {
    unsigned line_num = pr.first;
	CallInst *CI = pr.second;

    std::string line = lines[line_num];
    assert(!line.empty());

    replaceCall(M, CI, line_num, getName(line));
  }
}

static RegisterPass<RenameVerifierFuns> RVF("rename-verifier-funs",
                                            "Replace calls to verifier funs with calls to our funs");
char RenameVerifierFuns::ID;

<commit_msg>Fix getting parent function name<commit_after>//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.

#include <cassert>
#include <vector>
#include <set>
#include <fstream>
#include <sstream>

#include "llvm/IR/DataLayout.h"
#include "llvm/IR/BasicBlock.h"
#include "llvm/IR/Constants.h"
#include "llvm/IR/Function.h"
#include "llvm/IR/GlobalVariable.h"
#include "llvm/IR/Instructions.h"
#include "llvm/IR/Module.h"
#include "llvm/Pass.h"
#include "llvm/IR/Type.h"
#include "llvm/IR/TypeBuilder.h"
#if LLVM_VERSION_MAJOR >= 4 || (LLVM_VERSION_MAJOR == 3 && LLVM_VERSION_MINOR >= 5)
  #include "llvm/IR/InstIterator.h"
#else
  #include "llvm/Support/InstIterator.h"
#endif
#include "llvm/Support/raw_ostream.h"
#include "llvm/Transforms/Utils/BasicBlockUtils.h"

#include "llvm/Support/CommandLine.h"

using namespace llvm;

static cl::opt<std::string> source_name("rename-verifier-funs-source",
                                        cl::desc("Specify source filename"),
                                        cl::value_desc("filename"));

class RenameVerifierFuns : public ModulePass
{
  // every item is (line number, call)
  std::vector<std::pair<unsigned, CallInst *>> calls_to_replace;
  std::set<unsigned> lines_nums;
  std::map<unsigned, std::string> lines;

  void handleCall(Function& F, CallInst *CI);
  void mapLines();
  void replaceCalls(Module& M);

public:
  static char ID;

  RenameVerifierFuns() : ModulePass(ID) {}
  bool runOnFunction(Function &F);
  // must be module pass, so that we can iterate over
  // declarations too
  virtual bool runOnModule(Module &M) {
    for (auto& F : M)
      runOnFunction(F);

    mapLines();
    replaceCalls(M);
    return !calls_to_replace.empty();
  }
};

bool RenameVerifierFuns::runOnFunction(Function &F) {
  if (!F.isDeclaration())
    return false;

  StringRef name = F.getName();
  if (!name.startswith("__VERIFIER_nondet_"))
    return false;

  bool changed = false;

  //llvm::errs() << "Got __VERIFIER_fun: " << name << "\n";

  for (auto I = F.use_begin(), E = F.use_end(); I != E; ++I) {
#if ((LLVM_VERSION_MAJOR == 3) && (LLVM_VERSION_MINOR < 5))
    Value *use = *I;
#else
    Value *use = I->getUser();
#endif

    if (CallInst *CI = dyn_cast<CallInst>(use)) {
      handleCall(F, CI);
    }
  }

  return changed;
}

void RenameVerifierFuns::handleCall(Function& F, CallInst *CI) {
  const DebugLoc& Loc = CI->getDebugLoc();
  if (Loc) {
	calls_to_replace.emplace_back(Loc.getLine(), CI);
    lines_nums.insert(Loc.getLine());
  }
}

void RenameVerifierFuns::mapLines() {
  if (lines_nums.empty()) {
    assert(calls_to_replace.empty());
    return;
  }

  std::ifstream file(source_name);

  if (file.is_open()) {
    unsigned n = 1;
    std::string line;

    while (getline(file,line)) {
      if (lines_nums.count(n) > 0)
		lines[n] = std::move(line);
      ++n;
    }

    file.close();
  } else {
	errs() << "Couldn't open file: " << source_name << "\n";
    abort();
  }

  assert(lines.size() == lines_nums.size());
}

static void replaceCall(Module& M, CallInst *CI, unsigned line, const std::string& var) {
  std::string parent_name = cast<Function>(CI->getParent()->getParent())->getName();
  std::string name = parent_name + ":" + var + ":" + std::to_string(line);
  Function *called_func = CI->getCalledFunction();
  Constant *new_func = M.getOrInsertFunction(called_func->getName().str() + "_named",
										     called_func->getAttributes(),
									         called_func->getReturnType(),
                                             Type::getInt8PtrTy(M.getContext()),
                                             nullptr);
  assert(new_func);

  std::vector<Value *> args;
  Constant *name_const = ConstantDataArray::getString(M.getContext(), name);
  GlobalVariable *nameG = new GlobalVariable(M, name_const->getType(), true /*constant */,
                                             GlobalVariable::PrivateLinkage, name_const);
  args.push_back(ConstantExpr::getPointerCast(nameG,
                                              Type::getInt8PtrTy(M.getContext())));

  CallInst *new_CI = CallInst::Create(new_func, args);
  SmallVector<std::pair<unsigned, MDNode *>, 8> metadata;
  CI->getAllMetadata(metadata);
  // copy the metadata
  for (auto& md : metadata)
    new_CI->setMetadata(md.first, md.second);
  // copy the attributes (like zeroext etc.)
  new_CI->setAttributes(CI->getAttributes());

  new_CI->insertBefore(CI);
  CI->replaceAllUsesWith(new_CI);
  CI->eraseFromParent();
}

static std::string getName(const std::string& line) {
  std::istringstream iss(line);
  std::string sub, var;
  while (iss >> sub) {
    if (sub == "=") {
	  break;
    }
	var = std::move(sub);
  }

  if (!var.empty() && sub == "=") {
    // check also that after = follows the __VERIFIER_* call
    iss >> sub;
    // this may make problems with casting, line: (int) __VERIFIER_nondet_char()
    // maybe this is not needed?
    if (sub.compare(0, 18, "__VERIFIER_nondet_") == 0)
		return var;
  }

  return "--";
}

void RenameVerifierFuns::replaceCalls(Module& M) {
  for (auto& pr : calls_to_replace) {
    unsigned line_num = pr.first;
	CallInst *CI = pr.second;

    std::string line = lines[line_num];
    assert(!line.empty());

    replaceCall(M, CI, line_num, getName(line));
  }
}

static RegisterPass<RenameVerifierFuns> RVF("rename-verifier-funs",
                                            "Replace calls to verifier funs with calls to our funs");
char RenameVerifierFuns::ID;

<|endoftext|>


<commit_before>////////////////////////////////////////////////////////////////////////////////
//
//  File:  $Source: /usr/sci/projects/Nektar/cvs/Nektar++/libs/SpatialDomains/SpatialDomains.hpp,v $
//
//  For more information, please see: http://www.nektar.info/
//
//  The MIT License
//
//  Copyright (c) 2006 Division of Applied Mathematics, Brown University (USA),
//  Department of Aeronautics, Imperial College London (UK), and Scientific
//  Computing and Imaging Institute, University of Utah (USA).
//
//  License for the specific language governing rights and limitations under
//  Permission is hereby granted, free of charge, to any person obtaining a
//  copy of this software and associated documentation files (the "Software"),
//  to deal in the Software without restriction, including without limitation
//  the rights to use, copy, modify, merge, publish, distribute, sublicense,
//  and/or sell copies of the Software, and to permit persons to whom the
//  Software is furnished to do so, subject to the following conditions:
//
//  The above copyright notice and this permission notice shall be included
//  in all copies or substantial portions of the Software.
//
//  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
//  OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
//  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
//  THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
//  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
//  FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
//  DEALINGS IN THE SOFTWARE.
//
//  Description:
//
//
////////////////////////////////////////////////////////////////////////////////
#ifndef NEKTAR_SPATIALDOMAINS_SPATIALDOMAINS_H
#define NEKTAR_SPATIALDOMAINS_SPATIALDOMAINS_H

#include <StdRegions/StdRegions.hpp>

#include <LibUtilities/Memory/NekMemoryManager.hpp>
#include <LibUtilities/BasicUtils/ErrorUtil.hpp>
#include <LibUtilities/Graph.h>

namespace Nektar
{
    namespace SpatialDomains
    {
        const double kGeomRightAngleTol = 1e-14;

        enum GeomState
        {
            eNotFilled,
            ePtsFilled
        };

        enum MeshParams
        {
            eFieldExpansionOrder,
            eElementWork,

            // Don't change below here
            SIZE_MeshParams
        };
    }; // end of namespace
}; // end of namespace

#endif //NEKTAR_SPATIALDOMAINS_SPATIALDOMAINS_H

//
// $Log: SpatialDomains.hpp,v $
// Revision 1.1  2006/05/04 18:59:04  kirby
// *** empty log message ***
//
// Revision 1.4  2006/03/25 00:58:29  jfrazier
// Many changes dealing with fundamental structure and reading/writing.
//
// Revision 1.3  2006/03/13 11:17:03  sherwin
//
// First compiing version of Demos in SpatialDomains and LocalRegions. However they do not currently seem to execute properly
//
// Revision 1.2  2006/03/12 14:20:44  sherwin
//
// First compiling version of SpatialDomains and associated modifications
//
// Revision 1.1  2006/03/12 11:06:40  sherwin
//
// First complete copy of code standard code but still not compile tested
//
// Revision 1.7  2006/03/04 20:26:05  bnelson
// Added comments after #endif.
//
// Revision 1.6  2006/02/19 01:37:34  jfrazier
// Initial attempt at bringing into conformance with the coding standard.  Still more work to be done.  Has not been compiled.
//
//
<commit_msg>*** empty log message ***<commit_after>////////////////////////////////////////////////////////////////////////////////
//
//  File:  $Source: /usr/sci/projects/Nektar/cvs/Nektar++/libs/SpatialDomains/SpatialDomains.hpp,v $
//
//  For more information, please see: http://www.nektar.info/
//
//  The MIT License
//
//  Copyright (c) 2006 Division of Applied Mathematics, Brown University (USA),
//  Department of Aeronautics, Imperial College London (UK), and Scientific
//  Computing and Imaging Institute, University of Utah (USA).
//
//  License for the specific language governing rights and limitations under
//  Permission is hereby granted, free of charge, to any person obtaining a
//  copy of this software and associated documentation files (the "Software"),
//  to deal in the Software without restriction, including without limitation
//  the rights to use, copy, modify, merge, publish, distribute, sublicense,
//  and/or sell copies of the Software, and to permit persons to whom the
//  Software is furnished to do so, subject to the following conditions:
//
//  The above copyright notice and this permission notice shall be included
//  in all copies or substantial portions of the Software.
//
//  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
//  OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
//  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
//  THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
//  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
//  FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
//  DEALINGS IN THE SOFTWARE.
//
//  Description:
//
//
////////////////////////////////////////////////////////////////////////////////
#ifndef NEKTAR_SPATIALDOMAINS_SPATIALDOMAINS_H
#define NEKTAR_SPATIALDOMAINS_SPATIALDOMAINS_H

#include <StdRegions/StdRegions.hpp>

#include <LibUtilities/Memory/NekMemoryManager.hpp>
#include <LibUtilities/BasicUtils/ErrorUtil.hpp>
#include <LibUtilities/Foundations/Graph.h>

namespace Nektar
{
    namespace SpatialDomains
    {
        const double kGeomRightAngleTol = 1e-14;

        enum GeomState
        {
            eNotFilled,
            ePtsFilled
        };

        enum MeshParams
        {
            eFieldExpansionOrder,
            eElementWork,

            // Don't change below here
            SIZE_MeshParams
        };
    }; // end of namespace
}; // end of namespace

#endif //NEKTAR_SPATIALDOMAINS_SPATIALDOMAINS_H

//
// $Log: SpatialDomains.hpp,v $
// Revision 1.2  2006/06/01 13:42:26  kirby
// *** empty log message ***
//
// Revision 1.1  2006/05/04 18:59:04  kirby
// *** empty log message ***
//
// Revision 1.4  2006/03/25 00:58:29  jfrazier
// Many changes dealing with fundamental structure and reading/writing.
//
// Revision 1.3  2006/03/13 11:17:03  sherwin
//
// First compiing version of Demos in SpatialDomains and LocalRegions. However they do not currently seem to execute properly
//
// Revision 1.2  2006/03/12 14:20:44  sherwin
//
// First compiling version of SpatialDomains and associated modifications
//
// Revision 1.1  2006/03/12 11:06:40  sherwin
//
// First complete copy of code standard code but still not compile tested
//
// Revision 1.7  2006/03/04 20:26:05  bnelson
// Added comments after #endif.
//
// Revision 1.6  2006/02/19 01:37:34  jfrazier
// Initial attempt at bringing into conformance with the coding standard.  Still more work to be done.  Has not been compiled.
//
//
<|endoftext|>


<commit_before>//===----------------------------------------------------------------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is dual licensed under the MIT and the University of Illinois Open
// Source Licenses. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

// <list>

// explicit list(size_type n);

#include <list>
#include <cassert>
#include "../../../DefaultOnly.h"
#include "../../../stack_allocator.h"
#include "../../../min_allocator.h"

template <class T, class Allocator>
void
test3(unsigned n, Allocator const &alloc = Allocator())
{
#if _LIBCPP_STD_VER > 11
    typedef std::list<T, Allocator> C;
    typedef typename C::const_iterator const_iterator;
    {
    C d(n, alloc);
    assert(d.size() == n);
    assert(std::distance(d.begin(), d.end()) == n);
    assert(d.get_allocator() == alloc);
    }
#endif
}

int main()
{
    {
        std::list<int> l(3);
        assert(l.size() == 3);
        assert(std::distance(l.begin(), l.end()) == 3);
        std::list<int>::const_iterator i = l.begin();
        assert(*i == 0);
        ++i;
        assert(*i == 0);
        ++i;
        assert(*i == 0);
    }
    {
        std::list<int, stack_allocator<int, 3> > l(3);
        assert(l.size() == 3);
        assert(std::distance(l.begin(), l.end()) == 3);
        std::list<int>::const_iterator i = l.begin();
        assert(*i == 0);
        ++i;
        assert(*i == 0);
        ++i;
        assert(*i == 0);
    }
#if _LIBCPP_STD_VER > 11
    {
    	typedef std::list<int, min_allocator<int> > C;
        C l(3, min_allocator<int> ());
        assert(l.size() == 3);
        assert(std::distance(l.begin(), l.end()) == 3);
        C::const_iterator i = l.begin();
        assert(*i == 0);
        ++i;
        assert(*i == 0);
        ++i;
        assert(*i == 0);
        test3<int, min_allocator<int>> (3);
    }
#endif
#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES
    {
        std::list<DefaultOnly> l(3);
        assert(l.size() == 3);
        assert(std::distance(l.begin(), l.end()) == 3);
    }
#endif  // _LIBCPP_HAS_NO_RVALUE_REFERENCES
#if __cplusplus >= 201103L
    {
        std::list<int, min_allocator<int>> l(3);
        assert(l.size() == 3);
        assert(std::distance(l.begin(), l.end()) == 3);
        std::list<int, min_allocator<int>>::const_iterator i = l.begin();
        assert(*i == 0);
        ++i;
        assert(*i == 0);
        ++i;
        assert(*i == 0);
    }
#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES
    {
        std::list<DefaultOnly, min_allocator<DefaultOnly>> l(3);
        assert(l.size() == 3);
        assert(std::distance(l.begin(), l.end()) == 3);
    }
#endif  // _LIBCPP_HAS_NO_RVALUE_REFERENCES
#endif
}
<commit_msg>Remove a tab that snuck in<commit_after>//===----------------------------------------------------------------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is dual licensed under the MIT and the University of Illinois Open
// Source Licenses. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

// <list>

// explicit list(size_type n);

#include <list>
#include <cassert>
#include "../../../DefaultOnly.h"
#include "../../../stack_allocator.h"
#include "../../../min_allocator.h"

template <class T, class Allocator>
void
test3(unsigned n, Allocator const &alloc = Allocator())
{
#if _LIBCPP_STD_VER > 11
    typedef std::list<T, Allocator> C;
    typedef typename C::const_iterator const_iterator;
    {
    C d(n, alloc);
    assert(d.size() == n);
    assert(std::distance(d.begin(), d.end()) == n);
    assert(d.get_allocator() == alloc);
    }
#endif
}

int main()
{
    {
        std::list<int> l(3);
        assert(l.size() == 3);
        assert(std::distance(l.begin(), l.end()) == 3);
        std::list<int>::const_iterator i = l.begin();
        assert(*i == 0);
        ++i;
        assert(*i == 0);
        ++i;
        assert(*i == 0);
    }
    {
        std::list<int, stack_allocator<int, 3> > l(3);
        assert(l.size() == 3);
        assert(std::distance(l.begin(), l.end()) == 3);
        std::list<int>::const_iterator i = l.begin();
        assert(*i == 0);
        ++i;
        assert(*i == 0);
        ++i;
        assert(*i == 0);
    }
#if _LIBCPP_STD_VER > 11
    {
        typedef std::list<int, min_allocator<int> > C;
        C l(3, min_allocator<int> ());
        assert(l.size() == 3);
        assert(std::distance(l.begin(), l.end()) == 3);
        C::const_iterator i = l.begin();
        assert(*i == 0);
        ++i;
        assert(*i == 0);
        ++i;
        assert(*i == 0);
        test3<int, min_allocator<int>> (3);
    }
#endif
#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES
    {
        std::list<DefaultOnly> l(3);
        assert(l.size() == 3);
        assert(std::distance(l.begin(), l.end()) == 3);
    }
#endif  // _LIBCPP_HAS_NO_RVALUE_REFERENCES
#if __cplusplus >= 201103L
    {
        std::list<int, min_allocator<int>> l(3);
        assert(l.size() == 3);
        assert(std::distance(l.begin(), l.end()) == 3);
        std::list<int, min_allocator<int>>::const_iterator i = l.begin();
        assert(*i == 0);
        ++i;
        assert(*i == 0);
        ++i;
        assert(*i == 0);
    }
#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES
    {
        std::list<DefaultOnly, min_allocator<DefaultOnly>> l(3);
        assert(l.size() == 3);
        assert(std::distance(l.begin(), l.end()) == 3);
    }
#endif  // _LIBCPP_HAS_NO_RVALUE_REFERENCES
#endif
}
<|endoftext|>


<commit_before>#include "cursor.h"
#include "page.h"
#include "../bloom_filter.h"

#include <algorithm>

using namespace dariadb;
using namespace dariadb::storage;

Cursor::Cursor(Page*page, const dariadb::IdArray&ids, dariadb::Time from, dariadb::Time to, dariadb::Flag flag) :
	link(page),
	_ids(ids),
	_from(from),
	_to(to),
	_flag(flag)
{
	reset_pos();
}

void Cursor::reset_pos() {
	_is_end = false;
	_index_end = link->index + link->header->pos_index;
	_index_it = link->index;
}

Cursor::~Cursor() {
	if (link != nullptr) {
		link->dec_reader();
		link = nullptr;
	}
}

bool Cursor::is_end()const {
	return _is_end;
}

Chunk_Ptr Cursor::readNext() {
	for (; !_is_end; _index_it++) {
		if (_index_it == _index_end) {
			_is_end = true;
			return nullptr;
		}
		if ((_ids.size() != 0) && (std::find(_ids.begin(), _ids.end(), _index_it->info.first.id) == _ids.end())) {
			continue;
		}

		if (!dariadb::bloom_check(_index_it->info.flag_bloom, _flag)) {
			continue;
		}

		if ((dariadb::utils::inInterval(_from, _to, _index_it->info.minTime)) || (dariadb::utils::inInterval(_from, _to, _index_it->info.maxTime))) {
			Chunk_Ptr c = std::make_shared<Chunk>(_index_it->info, link->chunks + _index_it->offset, link->header->chunk_size);
			_index_it++;
			return c;
		}
	}
	return nullptr;
}

ChuncksList Cursor::readAll() {
	ChuncksList result;
	while (!_is_end) {
		auto c = readNext();
		if (c != nullptr) {
			result.push_back(c);
		}
	}
	return result;
}<commit_msg>strange git client.<commit_after>#include "cursor.h"
#include "page.h"
#include "../bloom_filter.h"

#include <algorithm>

using namespace dariadb;
using namespace dariadb::storage;

class Cursor_ListAppend_callback:public Cursor::Callback{
  public:
    ChuncksList*_out;
    Cursor_ListAppend_callback(ChuncksList*out){
        _out=out;

    }
    void call(Chunk_Ptr &ptr) override{
        _out->push_back(ptr);
    }
};

Cursor::Cursor(Page*page, const dariadb::IdArray&ids, dariadb::Time from, dariadb::Time to, dariadb::Flag flag) :
	link(page),
	_ids(ids),
	_from(from),
	_to(to),
	_flag(flag)
{
	reset_pos();
}

void Cursor::reset_pos() {
	_is_end = false;
	_index_end = link->index + link->header->pos_index;
	_index_it = link->index;
}

Cursor::~Cursor() {
	if (link != nullptr) {
		link->dec_reader();
		link = nullptr;
	}
}

bool Cursor::is_end()const {
	return _is_end;
}

void Cursor::readNext( Cursor::Callback*cbk) {
	for (; !_is_end; _index_it++) {
		if (_index_it == _index_end) {
			_is_end = true;
            break;
		}
		if ((_ids.size() != 0) && (std::find(_ids.begin(), _ids.end(), _index_it->info.first.id) == _ids.end())) {
			continue;
		}

		if (!dariadb::bloom_check(_index_it->info.flag_bloom, _flag)) {
			continue;
		}

		if ((dariadb::utils::inInterval(_from, _to, _index_it->info.minTime)) || (dariadb::utils::inInterval(_from, _to, _index_it->info.maxTime))) {
			Chunk_Ptr c = std::make_shared<Chunk>(_index_it->info, link->chunks + _index_it->offset, link->header->chunk_size);
            cbk->call(c);
			_index_it++;
            break;
		}
	}
}

void Cursor::readAll(ChuncksList*output){
    std::unique_ptr<Cursor_ListAppend_callback> clbk{new Cursor_ListAppend_callback{output}};
    readAll(clbk.get());
}

void Cursor::readAll(Callback*cbk) {
	while (!_is_end) {
        readNext(cbk);
	}
}
<|endoftext|>


<commit_before>#include "ExecutionEngine.h"

#include <array>
#include <mutex>
#include <iostream>

#include "preprocessor/llvm_includes_start.h"
#include <llvm/IR/Module.h>
#include <llvm/ADT/Triple.h>
#include <llvm/ExecutionEngine/ExecutionEngine.h>
#include <llvm/ExecutionEngine/SectionMemoryManager.h>
#include <llvm/ExecutionEngine/MCJIT.h>
#include <llvm/Support/TargetSelect.h>
#include <llvm/Support/Host.h>
#include <llvm/Support/CommandLine.h>
#include "preprocessor/llvm_includes_end.h"

#include "Runtime.h"
#include "Compiler.h"
#include "Optimizer.h"
#include "Cache.h"
#include "ExecStats.h"
#include "Utils.h"
#include "BuildInfo.gen.h"

namespace dev
{
namespace eth
{
namespace jit
{

namespace
{
using EntryFuncPtr = ReturnCode(*)(Runtime*);

std::string codeHash(i256 const& _hash)
{
	static const auto size = sizeof(_hash);
	static const auto hexChars = "0123456789abcdef";
	std::string str;
	str.resize(size * 2);
	auto outIt = str.rbegin(); // reverse for BE
	auto& arr = *(std::array<byte, size>*)&_hash;
	for (auto b : arr)
	{
		*(outIt++) = hexChars[b & 0xf];
		*(outIt++) = hexChars[b >> 4];
	}
	return str;
}

void printVersion()
{
	std::cout << "Ethereum EVM JIT Compiler (http://github.com/ethereum/evmjit):\n"
			  << "  EVMJIT version " << EVMJIT_VERSION << "\n"
#ifdef NDEBUG
			  << "  Optimized build, " EVMJIT_VERSION_FULL "\n"
#else
			  << "  DEBUG build, " EVMJIT_VERSION_FULL "\n"
#endif
			  << "  Built " << __DATE__ << " (" << __TIME__ << ")\n"
			  << std::endl;
}

namespace cl = llvm::cl;
cl::opt<bool> g_optimize{"O", cl::desc{"Optimize"}};
cl::opt<bool> g_cache{"cache", cl::desc{"Cache compiled EVM code on disk"}, cl::init(true)};
cl::opt<bool> g_stats{"st", cl::desc{"Statistics"}};
cl::opt<bool> g_dump{"dump", cl::desc{"Dump LLVM IR module"}};

void parseOptions()
{
	cl::AddExtraVersionPrinter(printVersion);
	cl::ParseEnvironmentOptions("evmjit", "EVMJIT", "Ethereum EVM JIT Compiler");
}

}

ReturnCode ExecutionEngine::run(RuntimeData* _data, Env* _env)
{
	static std::once_flag flag;
	std::call_once(flag, parseOptions);

	std::unique_ptr<ExecStats> listener{new ExecStats};
	listener->stateChanged(ExecState::Started);

	auto objectCache = g_cache ? Cache::getObjectCache(listener.get()) : nullptr;

	static std::unique_ptr<llvm::ExecutionEngine> ee;
	if (!ee)
	{
		llvm::InitializeNativeTarget();
		llvm::InitializeNativeTargetAsmPrinter();

		auto module = std::unique_ptr<llvm::Module>(new llvm::Module({}, llvm::getGlobalContext()));
		llvm::EngineBuilder builder(module.get());
		builder.setEngineKind(llvm::EngineKind::JIT);
		builder.setUseMCJIT(true);
		builder.setOptLevel(g_optimize ? llvm::CodeGenOpt::Default : llvm::CodeGenOpt::None);

		auto triple = llvm::Triple(llvm::sys::getProcessTriple());
		if (triple.getOS() == llvm::Triple::OSType::Win32)
			triple.setObjectFormat(llvm::Triple::ObjectFormatType::ELF);  // MCJIT does not support COFF format
		module->setTargetTriple(triple.str());

		ee.reset(builder.create());
		if (!CHECK(ee))
			return ReturnCode::LLVMConfigError;
		module.release();  // Successfully created llvm::ExecutionEngine takes ownership of the module
		ee->setObjectCache(objectCache);
	}

	static StatsCollector statsCollector;

	auto mainFuncName = codeHash(_data->codeHash);
	Runtime runtime(_data, _env);	// TODO: I don't know why but it must be created before getFunctionAddress() calls

	auto entryFuncPtr = (EntryFuncPtr)ee->getFunctionAddress(mainFuncName);
	if (!entryFuncPtr)
	{
		auto module = objectCache ? Cache::getObject(mainFuncName) : nullptr;
		if (!module)
		{
			listener->stateChanged(ExecState::Compilation);
			assert(_data->code || !_data->codeSize); //TODO: Is it good idea to execute empty code?
			module = Compiler{{}}.compile(_data->code, _data->code + _data->codeSize, mainFuncName);

			if (g_optimize)
			{
				listener->stateChanged(ExecState::Optimization);
				optimize(*module);
			}
		}
		if (g_dump)
			module->dump();

		ee->addModule(module.get());
		module.release();
		listener->stateChanged(ExecState::CodeGen);
		entryFuncPtr = (EntryFuncPtr)ee->getFunctionAddress(mainFuncName);
	}
	if (!CHECK(entryFuncPtr))
		return ReturnCode::LLVMLinkError;

	listener->stateChanged(ExecState::Execution);
	auto returnCode = entryFuncPtr(&runtime);
	listener->stateChanged(ExecState::Return);

	if (returnCode == ReturnCode::Return)
	{
		returnData = runtime.getReturnData();     // Save reference to return data
		std::swap(m_memory, runtime.getMemory()); // Take ownership of memory
	}
	listener->stateChanged(ExecState::Finished);

	if (g_stats)
		statsCollector.stats.push_back(std::move(listener));

	return returnCode;
}

}
}
}
<commit_msg>Destroy LLVM ManagedStatics<commit_after>#include "ExecutionEngine.h"

#include <array>
#include <mutex>
#include <iostream>

#include "preprocessor/llvm_includes_start.h"
#include <llvm/IR/Module.h>
#include <llvm/ADT/Triple.h>
#include <llvm/ExecutionEngine/ExecutionEngine.h>
#include <llvm/ExecutionEngine/SectionMemoryManager.h>
#include <llvm/ExecutionEngine/MCJIT.h>
#include <llvm/Support/TargetSelect.h>
#include <llvm/Support/Host.h>
#include <llvm/Support/CommandLine.h>
#include <llvm/Support/ManagedStatic.h>
#include "preprocessor/llvm_includes_end.h"

#include "Runtime.h"
#include "Compiler.h"
#include "Optimizer.h"
#include "Cache.h"
#include "ExecStats.h"
#include "Utils.h"
#include "BuildInfo.gen.h"

namespace dev
{
namespace eth
{
namespace jit
{

namespace
{
using EntryFuncPtr = ReturnCode(*)(Runtime*);

std::string codeHash(i256 const& _hash)
{
	static const auto size = sizeof(_hash);
	static const auto hexChars = "0123456789abcdef";
	std::string str;
	str.resize(size * 2);
	auto outIt = str.rbegin(); // reverse for BE
	auto& arr = *(std::array<byte, size>*)&_hash;
	for (auto b : arr)
	{
		*(outIt++) = hexChars[b & 0xf];
		*(outIt++) = hexChars[b >> 4];
	}
	return str;
}

void printVersion()
{
	std::cout << "Ethereum EVM JIT Compiler (http://github.com/ethereum/evmjit):\n"
			  << "  EVMJIT version " << EVMJIT_VERSION << "\n"
#ifdef NDEBUG
			  << "  Optimized build, " EVMJIT_VERSION_FULL "\n"
#else
			  << "  DEBUG build, " EVMJIT_VERSION_FULL "\n"
#endif
			  << "  Built " << __DATE__ << " (" << __TIME__ << ")\n"
			  << std::endl;
}

namespace cl = llvm::cl;
cl::opt<bool> g_optimize{"O", cl::desc{"Optimize"}};
cl::opt<bool> g_cache{"cache", cl::desc{"Cache compiled EVM code on disk"}, cl::init(true)};
cl::opt<bool> g_stats{"st", cl::desc{"Statistics"}};
cl::opt<bool> g_dump{"dump", cl::desc{"Dump LLVM IR module"}};

void parseOptions()
{
	static llvm::llvm_shutdown_obj shutdownObj{};
	cl::AddExtraVersionPrinter(printVersion);
	cl::ParseEnvironmentOptions("evmjit", "EVMJIT", "Ethereum EVM JIT Compiler");
}

}

ReturnCode ExecutionEngine::run(RuntimeData* _data, Env* _env)
{
	static std::once_flag flag;
	std::call_once(flag, parseOptions);

	std::unique_ptr<ExecStats> listener{new ExecStats};
	listener->stateChanged(ExecState::Started);

	auto objectCache = g_cache ? Cache::getObjectCache(listener.get()) : nullptr;

	static std::unique_ptr<llvm::ExecutionEngine> ee;
	if (!ee)
	{
		llvm::InitializeNativeTarget();
		llvm::InitializeNativeTargetAsmPrinter();

		auto module = std::unique_ptr<llvm::Module>(new llvm::Module({}, llvm::getGlobalContext()));
		llvm::EngineBuilder builder(module.get());
		builder.setEngineKind(llvm::EngineKind::JIT);
		builder.setUseMCJIT(true);
		builder.setOptLevel(g_optimize ? llvm::CodeGenOpt::Default : llvm::CodeGenOpt::None);

		auto triple = llvm::Triple(llvm::sys::getProcessTriple());
		if (triple.getOS() == llvm::Triple::OSType::Win32)
			triple.setObjectFormat(llvm::Triple::ObjectFormatType::ELF);  // MCJIT does not support COFF format
		module->setTargetTriple(triple.str());

		ee.reset(builder.create());
		if (!CHECK(ee))
			return ReturnCode::LLVMConfigError;
		module.release();  // Successfully created llvm::ExecutionEngine takes ownership of the module
		ee->setObjectCache(objectCache);
	}

	static StatsCollector statsCollector;

	auto mainFuncName = codeHash(_data->codeHash);
	Runtime runtime(_data, _env);	// TODO: I don't know why but it must be created before getFunctionAddress() calls

	auto entryFuncPtr = (EntryFuncPtr)ee->getFunctionAddress(mainFuncName);
	if (!entryFuncPtr)
	{
		auto module = objectCache ? Cache::getObject(mainFuncName) : nullptr;
		if (!module)
		{
			listener->stateChanged(ExecState::Compilation);
			assert(_data->code || !_data->codeSize); //TODO: Is it good idea to execute empty code?
			module = Compiler{{}}.compile(_data->code, _data->code + _data->codeSize, mainFuncName);

			if (g_optimize)
			{
				listener->stateChanged(ExecState::Optimization);
				optimize(*module);
			}
		}
		if (g_dump)
			module->dump();

		ee->addModule(module.get());
		module.release();
		listener->stateChanged(ExecState::CodeGen);
		entryFuncPtr = (EntryFuncPtr)ee->getFunctionAddress(mainFuncName);
	}
	if (!CHECK(entryFuncPtr))
		return ReturnCode::LLVMLinkError;

	listener->stateChanged(ExecState::Execution);
	auto returnCode = entryFuncPtr(&runtime);
	listener->stateChanged(ExecState::Return);

	if (returnCode == ReturnCode::Return)
	{
		returnData = runtime.getReturnData();     // Save reference to return data
		std::swap(m_memory, runtime.getMemory()); // Take ownership of memory
	}
	listener->stateChanged(ExecState::Finished);

	if (g_stats)
		statsCollector.stats.push_back(std::move(listener));

	return returnCode;
}

}
}
}
<|endoftext|>


<commit_before>/* * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* BSD 3-Clause License
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * *
Code by Cassius Fiorin - cafiorin@gmail.com
http://pinballhomemade.blogspot.com.br
* * * * * * * * * * * * * * * * * * * * * * * * * * * * */

#include "PinballSlave.h"
#include "PinballObject.h"
#include "Pinball.h"
#include "HardwareSerial.h"
#include "Vector.h"
#include "Utils.h"
#include "Input.h"
#include "DefinesMp3.h"

#ifdef DOS
#include "PinballMaster.h"
#endif // DOS

#ifdef ARDUINOLIB
#include <Wire.h>
PinballSlave *m_PinballSlave = NULL;

//-----------------------------------------------------------------------//
void receiveMessageFromAnotherArduinoSlave(int howMany)
//-----------------------------------------------------------------------//
{
	m_PinballSlave->receiveMessageFromAnotherArduino(howMany);
}

//-----------------------------------------------------------------------//
void SetupWire()
//-----------------------------------------------------------------------//
{
	Wire.begin(ADDRESS_SLAVE); // join I2C bus using this address
	Wire.onReceive(receiveMessageFromAnotherArduinoSlave); // register event to handle requests
}

#endif // ARDUINOLIB

/*---------------------------------------------------------------------*/
//							C L A S S
/*---------------------------------------------------------------------*/

#ifdef ARDUINOLIB
/*---------------------------------------------------------------------*/
PinballSlave::PinballSlave()
/*---------------------------------------------------------------------*/
{
	m_PinballSlave = this;
	SetupWire();
}

/*---------------------------------------------------------------------*/
void PinballSlave::Setup(SFEMP3Shield *MP3player, HardwareSerial *serial)
/*---------------------------------------------------------------------*/
{
	m_serial = serial;
	m_MP3player = MP3player;
	playSong(MP3_STARTBUTTONPORT);
	Init();
}

#endif

#ifdef DOS
/*---------------------------------------------------------------------*/
PinballSlave::PinballSlave(const char *szName, HardwareSerial *serial) : Pinball(szName, serial)
/*---------------------------------------------------------------------*/
{
	m_PinballMaster = NULL;
	m_Status = StatusPinball::initializing;
<<<<<<< HEAD

	#ifdef DEBUGMESSAGES
=======

	#ifdef DEBUGMESSAGESCREATION
>>>>>>> 100661e6dee3b3d54eb7cb80f222eb79a8c56a8b
	LogMessage("PinballSlave Constructor");
	#endif
}
#endif

/*---------------------------------------------------------------------*/
PinballSlave::~PinballSlave()
/*---------------------------------------------------------------------*/
{
	#ifdef DEBUGMESSAGESCREATION
	LogMessage("PinballSlave Destructor");
	#endif
}

/*---------------------------------------------------------------------*/
bool PinballSlave::Init()
/*---------------------------------------------------------------------*/
{
	#ifdef DEBUGMESSAGES
	LogMessage("PinballSlave Init");
	#endif

	m_Status = StatusPinball::waitingmessages;
	return true;
}

/*---------------------------------------------------------------------*/
bool PinballSlave::Loop(int value)
/*---------------------------------------------------------------------*/
{
	#ifdef DEBUGMESSAGESLOOP
	LogMessage("PinballSlave::Loop");
	#endif

	return true;
}

/*---------------------------------------------------------------------*/
void PinballSlave::DataReceived(char c)
/*---------------------------------------------------------------------*/
{
	#ifdef DEBUGMESSAGES
	LogMessage("PinballSlave::DataReceived");
	#endif

	switch (c)
	{
		case INIT_THEME:
		{
			playSong(MP3_THEME); //TODO:
		}
		break;
	}
}
<commit_msg>fixed merge<commit_after>/* * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* BSD 3-Clause License
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * *
Code by Cassius Fiorin - cafiorin@gmail.com
http://pinballhomemade.blogspot.com.br
* * * * * * * * * * * * * * * * * * * * * * * * * * * * */

#include "PinballSlave.h"
#include "PinballObject.h"
#include "Pinball.h"
#include "HardwareSerial.h"
#include "Vector.h"
#include "Utils.h"
#include "Input.h"
#include "DefinesMp3.h"

#ifdef DOS
#include "PinballMaster.h"
#endif // DOS

#ifdef ARDUINOLIB
#include <Wire.h>
PinballSlave *m_PinballSlave = NULL;

//-----------------------------------------------------------------------//
void receiveMessageFromAnotherArduinoSlave(int howMany)
//-----------------------------------------------------------------------//
{
	m_PinballSlave->receiveMessageFromAnotherArduino(howMany);
}

//-----------------------------------------------------------------------//
void SetupWire()
//-----------------------------------------------------------------------//
{
	Wire.begin(ADDRESS_SLAVE); // join I2C bus using this address
	Wire.onReceive(receiveMessageFromAnotherArduinoSlave); // register event to handle requests
}

#endif // ARDUINOLIB

/*---------------------------------------------------------------------*/
//							C L A S S
/*---------------------------------------------------------------------*/

#ifdef ARDUINOLIB
/*---------------------------------------------------------------------*/
PinballSlave::PinballSlave()
/*---------------------------------------------------------------------*/
{
	m_PinballSlave = this;
	SetupWire();
}

/*---------------------------------------------------------------------*/
void PinballSlave::Setup(SFEMP3Shield *MP3player, HardwareSerial *serial)
/*---------------------------------------------------------------------*/
{
	m_serial = serial;
	m_MP3player = MP3player;
	playSong(MP3_STARTBUTTONPORT);
	Init();
}

#endif

#ifdef DOS
/*---------------------------------------------------------------------*/
PinballSlave::PinballSlave(const char *szName, HardwareSerial *serial) : Pinball(szName, serial)
/*---------------------------------------------------------------------*/
{
	m_PinballMaster = NULL;
	m_Status = StatusPinball::initializing;

	#ifdef DEBUGMESSAGESCREATION
	LogMessage("PinballSlave Constructor");
	#endif
}
#endif

/*---------------------------------------------------------------------*/
PinballSlave::~PinballSlave()
/*---------------------------------------------------------------------*/
{
	#ifdef DEBUGMESSAGESCREATION
	LogMessage("PinballSlave Destructor");
	#endif
}

/*---------------------------------------------------------------------*/
bool PinballSlave::Init()
/*---------------------------------------------------------------------*/
{
	#ifdef DEBUGMESSAGES
	LogMessage("PinballSlave Init");
	#endif

	m_Status = StatusPinball::waitingmessages;
	return true;
}

/*---------------------------------------------------------------------*/
bool PinballSlave::Loop(int value)
/*---------------------------------------------------------------------*/
{
	#ifdef DEBUGMESSAGESLOOP
	LogMessage("PinballSlave::Loop");
	#endif

	return true;
}

/*---------------------------------------------------------------------*/
void PinballSlave::DataReceived(char c)
/*---------------------------------------------------------------------*/
{
	#ifdef DEBUGMESSAGES
	LogMessage("PinballSlave::DataReceived");
	#endif

	switch (c)
	{
		case INIT_THEME:
		{
			playSong(MP3_THEME); //TODO:
		}
		break;
	}
}
<|endoftext|>


<commit_before>/*=========================================================================

  Program:   ORFEO Toolbox
  Language:  C++
  Date:      $Date$
  Version:   $Revision$

  Copyright (c) Centre National d'Etudes Spatiales. All rights reserved.
  See OTBCopyright.txt for details.

  This software is distributed WITHOUT ANY WARRANTY; without even
  the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
  PURPOSE.  See the above copyright notices for more information.

=========================================================================*/
#include "otbVcaImageFilter.h"

#include "otbVectorImage.h"
#include "otbImageFileReader.h"
#include "otbImageFileWriter.h"

const unsigned int Dimension = 2;
typedef double PixelType;
typedef double PrecisionType;

typedef otb::Image<PixelType, Dimension> ImageType;
typedef otb::VectorImage<PixelType, Dimension> VectorImageType;
typedef otb::VCAImageFilter<VectorImageType> VCAFilterType;

typedef otb::ImageFileReader<VectorImageType> ReaderType;
typedef otb::ImageFileWriter<VectorImageType> WriterType;

int otbVCAImageFilterTestHighSNR(int argc, char * argv[])
{
  const char * inputImage = argv[1];
  const char * outputImage = argv[2];
  const unsigned int nbEndmembers = atoi(argv[3]);

  ReaderType::Pointer readerImage = ReaderType::New();
  readerImage->SetFileName(inputImage);

  VCAFilterType::Pointer vca = VCAFilterType::New();
  vca->SetNumberOfEndmembers(nbEndmembers);
  vca->SetInput(readerImage->GetOutput());

  WriterType::Pointer writer = WriterType::New();
  writer->SetFileName(outputImage);
  writer->SetInput(vca->GetOutput());
  writer->Update();

  return EXIT_SUCCESS;
}
<commit_msg>TEST: use float<commit_after>/*=========================================================================

  Program:   ORFEO Toolbox
  Language:  C++
  Date:      $Date$
  Version:   $Revision$

  Copyright (c) Centre National d'Etudes Spatiales. All rights reserved.
  See OTBCopyright.txt for details.

  This software is distributed WITHOUT ANY WARRANTY; without even
  the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
  PURPOSE.  See the above copyright notices for more information.

=========================================================================*/
#include "otbVcaImageFilter.h"

#include "otbVectorImage.h"
#include "otbImageFileReader.h"
#include "otbImageFileWriter.h"

const unsigned int Dimension = 2;
typedef float PixelType;
typedef float PrecisionType;

typedef otb::Image<PixelType, Dimension> ImageType;
typedef otb::VectorImage<PixelType, Dimension> VectorImageType;
typedef otb::VCAImageFilter<VectorImageType> VCAFilterType;

typedef otb::ImageFileReader<VectorImageType> ReaderType;
typedef otb::ImageFileWriter<VectorImageType> WriterType;

int otbVCAImageFilterTestHighSNR(int argc, char * argv[])
{
  const char * inputImage = argv[1];
  const char * outputImage = argv[2];
  const unsigned int nbEndmembers = atoi(argv[3]);

  ReaderType::Pointer readerImage = ReaderType::New();
  readerImage->SetFileName(inputImage);

  VCAFilterType::Pointer vca = VCAFilterType::New();
  vca->SetNumberOfEndmembers(nbEndmembers);
  vca->SetInput(readerImage->GetOutput());

  WriterType::Pointer writer = WriterType::New();
  writer->SetFileName(outputImage);
  writer->SetInput(vca->GetOutput());
  writer->Update();

  return EXIT_SUCCESS;
}
<|endoftext|>


<commit_before>/*
 * Copyright 2016 neurodata (http://neurodata.io/)
 * Written by Disa Mhembere (disa@jhu.edu)
 *
 * This file is part of knor
 *
 * 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 CURRENT_KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include <random>
#include <stdexcept>

#include "gmeans_coordinator.hpp"
#include "gmeans.hpp"

#include "io.hpp"
#include "clusters.hpp"
#include "linalg.hpp"
#include "AndersonDarling.hpp"
#include "hclust_id_generator.hpp"

namespace knor {

    gmeans_coordinator::gmeans_coordinator(const std::string fn,
            const size_t nrow,
            const size_t ncol, const unsigned k, const unsigned max_iters,
            const unsigned nnodes, const unsigned nthreads,
            const double* centers, const base::init_t it,
            const double tolerance, const base::dist_t dt,
            const unsigned min_clust_size, const short strictness) :
        xmeans_coordinator(fn, nrow, ncol, k, max_iters, nnodes, nthreads,
                centers, it, tolerance, dt, min_clust_size),
                strictness(strictness) {

    }

void gmeans_coordinator::build_thread_state() {
    // NUMA node affinity binding policy is round-robin
    unsigned thds_row = nrow / nthreads;

    for (unsigned thd_id = 0; thd_id < nthreads; thd_id++) {
        std::pair<unsigned, unsigned> tup = get_rid_len_tup(thd_id);
        thd_max_row_idx.push_back((thd_id*thds_row) + tup.second);
        threads.push_back(xmeans::create((thd_id % nnodes),
                    thd_id, tup.first, tup.second,
                    ncol, k, hcltrs, &cluster_assignments[0], fn,
                    _dist_t, cltr_active_vec, partition_dist, nearest_cdist,
                    compute_pdist));
        threads[thd_id]->set_parent_cond(&cond);
        threads[thd_id]->set_parent_pending_threads(&pending_threads);
        threads[thd_id]->start(WAIT); // Thread puts itself to sleep
        std::static_pointer_cast<xmeans>(threads[thd_id])
                    ->set_part_id(&part_id[0]);
        std::static_pointer_cast<xmeans>(threads[thd_id])
                    ->set_g_clusters(cltrs);
    }
}

void gmeans_coordinator::assemble_ad_vecs(std::unordered_map<unsigned,
        std::vector<double>>& ad_vecs) {
    //assert(nearest_cdist.size() == part_id.size() && part_id.size() == nrow);

    for (size_t i = 0; i < nearest_cdist.size(); i++) {
        ad_vecs[part_id[i]].push_back(nearest_cdist[i]);
    }
}

void gmeans_coordinator::compute_ad_stats(
        std::unordered_map<unsigned, std::vector<double>>& ad_vecs) {
    for (auto& kv : ad_vecs) {
         double score = base::AndersonDarling::compute_statistic(ncol,
                 &kv.second[0]);
         kv.second.push_back(score); // NOTE: We push the score onto the back
    }
}

// NOTE: This modifies hcltrs
void gmeans_coordinator::partition_decision() {
    // Each Anderson Darling (AD) vector represents the vector for which
    //  each cluster gets its AD statistic.
    std::unordered_map<unsigned, std::vector<double>> ad_vecs;
    std::vector<double> critical_values;

    // Populate the AD vectors
    assemble_ad_vecs(ad_vecs);

    for (auto& kv : ad_vecs) {
        base::linalg::scale(&(kv.second)[0], kv.second.size());
    }

    // Compute Critical values
    base::AndersonDarling::compute_critical_values(
            ad_vecs.size(), critical_values);

    // Compute AD statistics
    compute_ad_stats(ad_vecs);

    std::vector<size_t> keys;
    hcltrs.get_keys(keys);

    // NOTE: We use ad_vecs.back() to store the score
    std::unordered_map<unsigned, bool> remove_cache;

#pragma omp parallel for default(shared)
    for (size_t i = 0; i < keys.size(); i++) {
        unsigned pid = keys[i];
        auto score = ad_vecs[pid].back();

        if (score <= critical_values[strictness]) {
#if VERBOSE
            printf("\nPart: %u will NOT split! score: %.4f <= crit val: %.4f\n",
                    pid, score, critical_values[strictness]);
#endif
            unsigned lid = hcltrs[pid]->get_zeroid();
            unsigned rid = hcltrs[pid]->get_oneid();

            // Deactivate both lid and rid
            deactivate(lid); deactivate(rid);
            // Deactivate pid
            deactivate(pid);

#pragma omp critical
            {
            remove_cache[pid] = true;
            }

            final_centroids[pid] = std::vector<double>(
                    cltrs->get_mean_rawptr(pid),
                    cltrs->get_mean_rawptr(pid) + ncol);
            cluster_assignment_counts[pid] =
                cluster_assignment_counts[lid] + cluster_assignment_counts[rid];
            cluster_assignment_counts[lid] = cluster_assignment_counts[rid] = 0;
        } else {
#pragma omp critical
            {
            remove_cache[pid] = false;
            }
#if VERBOSE
            printf("\nPart: %u will split! score: %.4f > crit val: %.4f\n",
                    pid, score, critical_values[strictness]);
#endif
        }
    }

    // Assemble cluster membership
#pragma omp parallel for default(shared) firstprivate(remove_cache)
    for (size_t rid = 0; rid < nrow; rid++) {
        auto pid = part_id[rid];
        if (remove_cache[pid]) {
            // Means that row assignments needs to be reverted to part_id
            cluster_assignments[rid] = pid;
        }
    }

    for (auto const& kv : remove_cache) {
        if (kv.second)
            hcltrs.erase(kv.first);
    }
}

void gmeans_coordinator::compute_cluster_diffs() {
    auto itr = hcltrs.get_iterator();
    while (itr.has_next()) {
        auto kv = itr.next();
        auto c = std::static_pointer_cast<base::h_clusters>(kv.second);
        c->metadata.resize(ncol+1); // +1th index stores the divisor

        // Compute difference
        for (size_t i = 0; i < ncol; i++)
            base::linalg::vdiff(c->get_mean_rawptr(0),
                    c->get_mean_rawptr(1), ncol, c->metadata);

        // Compute v.dot(v)
        c->metadata[ncol] = base::linalg::dot(&c->metadata[0],
                &c->metadata[0], ncol); // NOTE: last element intentionally ignored
    }
}

// Main driver
base::cluster_t gmeans_coordinator::run(
        double* allocd_data, const bool numa_opt) {
#ifdef PROFILER
    ProfilerStart("gmeans_coordinator.perf");
#endif

    build_thread_state();

    if (!numa_opt && NULL == allocd_data) {
        wake4run(ALLOC_DATA);
        wait4complete();
    } else if (allocd_data) { // No NUMA opt
        set_thread_data_ptr(allocd_data);
    }

    struct timeval start, end;
    gettimeofday(&start , NULL);

    if (_init_t == kbase::init_t::NONE)
        _init_t = kbase::init_t::FORGY;
    run_hinit(); // Initialize clusters

    // Run loop
    size_t iter = 0;

    unsigned curr_nclust = 2;
    while (true) {
        // TODO: Do this simultaneously with H_EM step
        wake4run(MEAN);
        wait4complete();
        combine_partition_means();
        compute_pdist = true;

        for (iter = 0; iter < max_iters; iter++) {
#ifndef BIND
            printf("\nNCLUST: %u, Iteration: %lu\n", curr_nclust, iter);
#endif
            // Now pick between the cluster splits
            wake4run(H_EM);
            wait4complete();
            update_clusters();
#ifndef BIND
            printf("\nAssignment counts:\n");
            base::sparse_print(cluster_assignment_counts);
            printf("\n*****************************************************\n");
#endif
            if (compute_pdist)
                compute_pdist = false;
        }

        compute_cluster_diffs();

        wake4run(H_SPLIT);
        wait4complete();

        // Decide on split or not here
        partition_decision();

        if (curr_nclust >= k*2) {
#ifndef BIND
            printf("\n\nCLUSTER SIZE EXIT @ %u!\n", curr_nclust);
#endif
            break;
        }

        // Update global state
        init_splits(); // Initialize possible splits

        // Break when clusters are inactive due to size
        if (hcltrs.keyless()) {
            //assert(steady_state()); // NOTE: Comment when benchmarking
#ifndef BIND
            printf("\n\nSTEADY STATE EXIT!\n");
#endif
            break;
        }
        curr_nclust = hcltrs.keycount()*2 + final_centroids.size();
    }
#ifdef PROFILER
    ProfilerStop();
#endif

    gettimeofday(&end, NULL);
#ifndef BIND
    printf("\n\nAlgorithmic time taken = %.6f sec\n",
        base::time_diff(start, end));
    printf("\n******************************************\n");
#endif

#ifndef BIND
    printf("Final cluster counts: \n");
    base::sparse_print(cluster_assignment_counts);
    //printf("Final centroids\n");
    //for (auto const& kv : final_centroids) {
        //printf("k: %u, v: ", kv.first); base::print(kv.second);
    //}
    printf("\n******************************************\n");
#endif

#if 0
    return base::cluster_t(this->nrow, this->ncol, iter, this->k,
            &cluster_assignments[0], &cluster_assignment_counts[0],
            hcltrs->get_means());
#else
    return base::cluster_t(); // TODO
#endif
}
}

<commit_msg>bug: gmeans should use it's own threads<commit_after>/*
 * Copyright 2016 neurodata (http://neurodata.io/)
 * Written by Disa Mhembere (disa@jhu.edu)
 *
 * This file is part of knor
 *
 * 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 CURRENT_KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include <random>
#include <stdexcept>

#include "gmeans_coordinator.hpp"
#include "gmeans.hpp"

#include "io.hpp"
#include "clusters.hpp"
#include "linalg.hpp"
#include "AndersonDarling.hpp"
#include "hclust_id_generator.hpp"

namespace knor {

    gmeans_coordinator::gmeans_coordinator(const std::string fn,
            const size_t nrow,
            const size_t ncol, const unsigned k, const unsigned max_iters,
            const unsigned nnodes, const unsigned nthreads,
            const double* centers, const base::init_t it,
            const double tolerance, const base::dist_t dt,
            const unsigned min_clust_size, const short strictness) :
        xmeans_coordinator(fn, nrow, ncol, k, max_iters, nnodes, nthreads,
                centers, it, tolerance, dt, min_clust_size),
                strictness(strictness) {

    }

void gmeans_coordinator::build_thread_state() {
    // NUMA node affinity binding policy is round-robin
    unsigned thds_row = nrow / nthreads;

    for (unsigned thd_id = 0; thd_id < nthreads; thd_id++) {
        std::pair<unsigned, unsigned> tup = get_rid_len_tup(thd_id);
        thd_max_row_idx.push_back((thd_id*thds_row) + tup.second);
        threads.push_back(gmeans::create((thd_id % nnodes),
                    thd_id, tup.first, tup.second,
                    ncol, k, hcltrs, &cluster_assignments[0], fn,
                    _dist_t, cltr_active_vec, partition_dist, nearest_cdist,
                    compute_pdist));
        threads[thd_id]->set_parent_cond(&cond);
        threads[thd_id]->set_parent_pending_threads(&pending_threads);
        threads[thd_id]->start(WAIT); // Thread puts itself to sleep
        std::static_pointer_cast<gmeans>(threads[thd_id])
                    ->set_part_id(&part_id[0]);
        std::static_pointer_cast<gmeans>(threads[thd_id])
                    ->set_g_clusters(cltrs);
    }
}

void gmeans_coordinator::assemble_ad_vecs(std::unordered_map<unsigned,
        std::vector<double>>& ad_vecs) {
    //assert(nearest_cdist.size() == part_id.size() && part_id.size() == nrow);

    for (size_t i = 0; i < nearest_cdist.size(); i++) {
        ad_vecs[part_id[i]].push_back(nearest_cdist[i]);
    }
}

void gmeans_coordinator::compute_ad_stats(
        std::unordered_map<unsigned, std::vector<double>>& ad_vecs) {
    for (auto& kv : ad_vecs) {
         double score = base::AndersonDarling::compute_statistic(ncol,
                 &kv.second[0]);
         kv.second.push_back(score); // NOTE: We push the score onto the back
    }
}

// NOTE: This modifies hcltrs
void gmeans_coordinator::partition_decision() {
    // Each Anderson Darling (AD) vector represents the vector for which
    //  each cluster gets its AD statistic.
    std::unordered_map<unsigned, std::vector<double>> ad_vecs;
    std::vector<double> critical_values;

    // Populate the AD vectors
    assemble_ad_vecs(ad_vecs);

    for (auto& kv : ad_vecs) {
        base::linalg::scale(&(kv.second)[0], kv.second.size());
    }

    // Compute Critical values
    base::AndersonDarling::compute_critical_values(
            ad_vecs.size(), critical_values);

    // Compute AD statistics
    compute_ad_stats(ad_vecs);

    std::vector<size_t> keys;
    hcltrs.get_keys(keys);

    // NOTE: We use ad_vecs.back() to store the score
    std::unordered_map<unsigned, bool> remove_cache;

#pragma omp parallel for default(shared)
    for (size_t i = 0; i < keys.size(); i++) {
        unsigned pid = keys[i];
        auto score = ad_vecs[pid].back();

        if (score <= critical_values[strictness]) {
#if VERBOSE
            printf("\nPart: %u will NOT split! score: %.4f <= crit val: %.4f\n",
                    pid, score, critical_values[strictness]);
#endif
            unsigned lid = hcltrs[pid]->get_zeroid();
            unsigned rid = hcltrs[pid]->get_oneid();

            // Deactivate both lid and rid
            deactivate(lid); deactivate(rid);
            // Deactivate pid
            deactivate(pid);

#pragma omp critical
            {
            remove_cache[pid] = true;
            }

            final_centroids[pid] = std::vector<double>(
                    cltrs->get_mean_rawptr(pid),
                    cltrs->get_mean_rawptr(pid) + ncol);
            cluster_assignment_counts[pid] =
                cluster_assignment_counts[lid] + cluster_assignment_counts[rid];
            cluster_assignment_counts[lid] = cluster_assignment_counts[rid] = 0;
        } else {
#pragma omp critical
            {
            remove_cache[pid] = false;
            }
#if VERBOSE
            printf("\nPart: %u will split! score: %.4f > crit val: %.4f\n",
                    pid, score, critical_values[strictness]);
#endif
        }
    }

    // Assemble cluster membership
#pragma omp parallel for default(shared) firstprivate(remove_cache)
    for (size_t rid = 0; rid < nrow; rid++) {
        auto pid = part_id[rid];
        if (remove_cache[pid]) {
            // Means that row assignments needs to be reverted to part_id
            cluster_assignments[rid] = pid;
        }
    }

    for (auto const& kv : remove_cache) {
        if (kv.second)
            hcltrs.erase(kv.first);
    }
}

void gmeans_coordinator::compute_cluster_diffs() {
    auto itr = hcltrs.get_iterator();
    while (itr.has_next()) {
        auto kv = itr.next();
        auto c = std::static_pointer_cast<base::h_clusters>(kv.second);
        c->metadata.resize(ncol+1); // +1th index stores the divisor

        // Compute difference
        for (size_t i = 0; i < ncol; i++)
            base::linalg::vdiff(c->get_mean_rawptr(0),
                    c->get_mean_rawptr(1), ncol, c->metadata);

        // Compute v.dot(v)
        c->metadata[ncol] = base::linalg::dot(&c->metadata[0],
                &c->metadata[0], ncol); // NOTE: last element intentionally ignored
    }
}

// Main driver
base::cluster_t gmeans_coordinator::run(
        double* allocd_data, const bool numa_opt) {
#ifdef PROFILER
    ProfilerStart("gmeans_coordinator.perf");
#endif

    build_thread_state();

    if (!numa_opt && NULL == allocd_data) {
        wake4run(ALLOC_DATA);
        wait4complete();
    } else if (allocd_data) { // No NUMA opt
        set_thread_data_ptr(allocd_data);
    }

    struct timeval start, end;
    gettimeofday(&start , NULL);

    if (_init_t == kbase::init_t::NONE)
        _init_t = kbase::init_t::FORGY;
    run_hinit(); // Initialize clusters

    // Run loop
    size_t iter = 0;

    unsigned curr_nclust = 2;
    while (true) {
        // TODO: Do this simultaneously with H_EM step
        wake4run(MEAN);
        wait4complete();
        combine_partition_means();
        compute_pdist = true;

        for (iter = 0; iter < max_iters; iter++) {
#ifndef BIND
            printf("\nNCLUST: %u, Iteration: %lu\n", curr_nclust, iter);
#endif
            // Now pick between the cluster splits
            wake4run(H_EM);
            wait4complete();
            update_clusters();
#ifndef BIND
            printf("\nAssignment counts:\n");
            base::sparse_print(cluster_assignment_counts);
            printf("\n*****************************************************\n");
#endif
            if (compute_pdist)
                compute_pdist = false;
        }

        compute_cluster_diffs();

        wake4run(H_SPLIT);
        wait4complete();

        // Decide on split or not here
        partition_decision();

        if (curr_nclust >= k*2) {
#ifndef BIND
            printf("\n\nCLUSTER SIZE EXIT @ %u!\n", curr_nclust);
#endif
            break;
        }

        // Update global state
        init_splits(); // Initialize possible splits

        // Break when clusters are inactive due to size
        if (hcltrs.keyless()) {
            //assert(steady_state()); // NOTE: Comment when benchmarking
#ifndef BIND
            printf("\n\nSTEADY STATE EXIT!\n");
#endif
            break;
        }
        curr_nclust = hcltrs.keycount()*2 + final_centroids.size();
    }
#ifdef PROFILER
    ProfilerStop();
#endif

    gettimeofday(&end, NULL);
#ifndef BIND
    printf("\n\nAlgorithmic time taken = %.6f sec\n",
        base::time_diff(start, end));
    printf("\n******************************************\n");
#endif

#ifndef BIND
    printf("Final cluster counts: \n");
    base::sparse_print(cluster_assignment_counts);
    //printf("Final centroids\n");
    //for (auto const& kv : final_centroids) {
        //printf("k: %u, v: ", kv.first); base::print(kv.second);
    //}
    printf("\n******************************************\n");
#endif

#if 0
    return base::cluster_t(this->nrow, this->ncol, iter, this->k,
            &cluster_assignments[0], &cluster_assignment_counts[0],
            hcltrs->get_means());
#else
    return base::cluster_t(); // TODO
#endif
}
}

<|endoftext|>