<commit_before>
//
// This source file is part of appleseed.
// Visit http://appleseedhq.net/ for additional information and resources.
//
// This software is released under the MIT license.
//
// Copyright (c) 2014 Esteban Tovagliari, The appleseedhq Organization
//
// 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.
//

// Interface header.
#include "closures.h"

// appleseed.renderer headers.
#include "renderer/global/globallogger.h"

// appleseed.foundation headers.
#include "foundation/image/colorspace.h"
#include "foundation/utility/otherwise.h"

// OSL headers.
#include <OSL/genclosure.h>
#include <OSL/oslclosure.h>

using namespace foundation;
using namespace renderer;

namespace renderer
{
namespace
{
    //
    // Closure parameters.
    //

    struct EmptyClosureParams {};

    struct AshikhminShirleyClosureParams
    {
        OSL::Vec3   N;
        OSL::Vec3   T;
        OSL::Color3 kd;
        OSL::Color3 ks;
        float       nu;
        float       nv;
    };

    struct LambertClosureParams
    {
        OSL::Vec3   N;
    };

    struct MicrofacetBRDFClosureParams
    {
        OSL::Vec3   N;
        float       glossiness;
    };

    struct RefractionClosureParams
    {
        OSL::Vec3   N;
        float       from_ior;
        float       to_ior;
    };

    struct ReflectionClosureParams
    {
        OSL::Vec3   N;
    };

    struct TranslucentClosureParams
    {
        OSL::Vec3   N;
    };
}

//
// CompositeClosure class implementation.
//

CompositeClosure::CompositeClosure(
    const OSL::ClosureColor* ci)
  : m_num_closures(0)
  , m_num_bytes(0)
{
    process_closure_tree(ci, Color3f(1.0f));

    // Compute sum of weights.
    double total_weight = 0.0;
    for (size_t i = 0, e = num_closures(); i != e; ++i)
        total_weight += m_weights[i];

    // Normalize weights.
    for (size_t i = 0, e = num_closures(); i != e; ++i)
        m_weights[i] /= total_weight;

    // Build CDF.
    if (num_closures() != 0)
    {
        m_cdf.reserve(num_closures());
        for (size_t i = 0, e = num_closures(); i != e; ++i)
            m_cdf.insert(i, closure_weight(i));
        m_cdf.prepare();
    }
}

size_t CompositeClosure::choose_closure(const double w) const
{
    return m_cdf.sample(w).first;
}

void CompositeClosure::process_closure_tree(
    const OSL::ClosureColor*    closure,
    const Color3f&              weight)
{
    if (closure == 0)
        return;

    switch (closure->type)
    {
      case OSL::ClosureColor::MUL:
        {
            const OSL::ClosureMul* c = reinterpret_cast<const OSL::ClosureMul*>(closure);
            const Color3f w = weight * Color3f(c->weight.x, c->weight.y, c->weight.z);
            process_closure_tree(c->closure, w);
        }
        break;

      case OSL::ClosureColor::ADD:
        {
            const OSL::ClosureAdd* c = reinterpret_cast<const OSL::ClosureAdd*>(closure);
            process_closure_tree(c->closureA, weight);
            process_closure_tree(c->closureB, weight);
        }
        break;

      case OSL::ClosureColor::COMPONENT:
        {
            const OSL::ClosureComponent* c = reinterpret_cast<const OSL::ClosureComponent*>(closure);
            const Color3f w = weight * Color3f(c->w.x, c->w.y, c->w.z);

            switch (c->id)
            {
              case AshikhminShirleyID:
                {
                    const AshikhminShirleyClosureParams* p =
                        reinterpret_cast<const AshikhminShirleyClosureParams*>(c->data());

                    AshikminBRDFInputValues values;

                    const Color3f wd = w * Color3f(p->kd.x, p->kd.y, p->kd.z);
                    linear_rgb_reflectance_to_spectrum(wd, values.m_rd);
                    values.m_rd_alpha = Alpha(1.0f);
                    values.m_rd_multiplier = 1.0;

                    const Color3f wg = w * Color3f(p->ks.x, p->ks.y, p->ks.z);
                    linear_rgb_reflectance_to_spectrum(wg, values.m_rg);
                    values.m_rg_alpha = Alpha(1.0f);
                    values.m_rg_multiplier = 1.0;
                    values.m_fr_multiplier = 1.0;
                    values.m_nu = p->nu;
                    values.m_nv = p->nv;

                    add_closure<AshikminBRDFInputValues>(
                        static_cast<ClosureID>(c->id),
                        w,
                        Vector3d(p->N.x, p->N.y, p->N.z),
                        Vector3d(p->T.x, p->T.y, p->T.z),
                        values);
                }
                break;

              case LambertID:
                {
                    const LambertClosureParams* p =
                        reinterpret_cast<const LambertClosureParams*>(c->data());

                    LambertianBRDFInputValues values;
                    linear_rgb_reflectance_to_spectrum(w, values.m_reflectance);
                    values.m_reflectance_alpha = Alpha(1.0f);
                    values.m_reflectance_multiplier = 1.0;

                    add_closure<LambertianBRDFInputValues>(
                        static_cast<ClosureID>(c->id),
                        w,
                        Vector3d(p->N.x, p->N.y, p->N.z),
                        values);
                }
                break;

              case MicrofacetBeckmannID:
              case MicrofacetBlinnID:
              case MicrofacetGGXID:
              case MicrofacetWardID:
                {
                    const MicrofacetBRDFClosureParams* p =
                        reinterpret_cast<const MicrofacetBRDFClosureParams*>(c->data());

                    MicrofacetBRDFInputValues values;
                    linear_rgb_reflectance_to_spectrum(w, values.m_reflectance);
                    values.m_reflectance_alpha = Alpha(1.0f);
                    values.m_reflectance_multiplier = 1.0;
                    values.m_glossiness = p->glossiness;
                    values.m_glossiness_multiplier = 1.0;
                    values.m_fr_multiplier = 1.0;

                    add_closure<MicrofacetBRDFInputValues>(
                        static_cast<ClosureID>(c->id),
                        w,
                        Vector3d(p->N.x, p->N.y, p->N.z),
                        values);
                }
                break;

              case ReflectionID:
                {
                    const ReflectionClosureParams* p =
                        reinterpret_cast<const ReflectionClosureParams*>(c->data());

                    SpecularBRDFInputValues values;
                    linear_rgb_reflectance_to_spectrum(w, values.m_reflectance);
                    values.m_reflectance_alpha = Alpha(1.0f);
                    values.m_reflectance_multiplier = 1.0;

                    add_closure<SpecularBRDFInputValues>(
                        static_cast<ClosureID>(c->id),
                        w,
                        Vector3d(p->N.x, p->N.y, p->N.z),
                        values);
                }
                break;

              case RefractionID:
                {
                    const RefractionClosureParams* p =
                        reinterpret_cast<const RefractionClosureParams*>(c->data());

                    SpecularBTDFInputValues values;
                    linear_rgb_reflectance_to_spectrum(w, values.m_reflectance);
                    values.m_from_ior = p->from_ior;
                    values.m_to_ior = p->to_ior;
                    values.m_reflectance_alpha = Alpha(1.0);
                    values.m_reflectance_multiplier = 1.0;

                    add_closure<SpecularBTDFInputValues>(
                        static_cast<ClosureID>(c->id),
                        w,
                        Vector3d(p->N.x, p->N.y, p->N.z),
                        values);
                }
                break;

              case TranslucentID:
                {
                    const TranslucentClosureParams* p =
                        reinterpret_cast<const TranslucentClosureParams*>(c->data());

                    DiffuseBTDFInputValues values;
                    linear_rgb_reflectance_to_spectrum(w, values.m_transmittance);
                    values.m_transmittance_alpha = Alpha(1.0);
                    values.m_transmittance_multiplier = 1.0;

                    add_closure<DiffuseBTDFInputValues>(
                        static_cast<ClosureID>(c->id),
                        w,
                        Vector3d(p->N.x, p->N.y, p->N.z),
                        values);
                }
                break;

              case EmissionID:
              case HoldoutID:
              case TransparentID:
                {
                    assert(!"Not implemented yet.");
                }
                break;

              assert_otherwise;
            }
        }
        break;
    }
}

template <typename InputValues>
void CompositeClosure::add_closure(
    const ClosureID             closure_type,
    const Color3f&              weight,
    const Vector3d&             normal,
    const InputValues&          params)
{
    do_add_closure<InputValues>(
        closure_type,
        weight,
        normal,
        false,
        Vector3d(0.0),
        params);
}

template <typename InputValues>
void CompositeClosure::add_closure(
    const ClosureID             closure_type,
    const Color3f&              weight,
    const Vector3d&             normal,
    const Vector3d&             tangent,
    const InputValues&          params)
{
    do_add_closure<InputValues>(
        closure_type,
        weight,
        normal,
        true,
        tangent,
        params);
}

template <typename InputValues>
void CompositeClosure::do_add_closure(
    const ClosureID             closure_type,
    const Color3f&              weight,
    const Vector3d&             normal,
    const bool                  has_tangent,
    const Vector3d&             tangent,
    const InputValues&          params)
{
    // Make sure we have enough space.
    if (num_closures() >= MaxClosureEntries)
    {
        RENDERER_LOG_WARNING("maximum number of closures in OSL shadergroup exceeded; ignoring closure.");
        return;
    }

    assert(m_num_bytes + sizeof(InputValues) <= MaxPoolSize);

    // We use the luminance of the weight as the BSDF weight.
    const double w = luminance(weight);
    if (w <= 0.0)
    {
        // This can generate millions of warnings. It's better to disable it.
        //RENDERER_LOG_WARNING("closure with negative or zero weight found; ignoring closure.");
        return;
    }

    m_weights[m_num_closures] = w;
    m_normals[m_num_closures] = normalize(normal);
    m_has_tangent[m_num_closures] = has_tangent;

    if (has_tangent)
        m_tangents[m_num_closures] = normalize(tangent);

    m_closure_types[m_num_closures] = closure_type;

    m_input_values[m_num_closures] = m_pool + m_num_bytes;
    new (m_input_values[m_num_closures]) InputValues(params);

    m_num_bytes += sizeof(InputValues);
    ++m_num_closures;
}

}   // namespace renderer

// We probably want to reuse OSL macros to declare closure params
// and register the closures. We can use them only inside the OSL namespace.
OSL_NAMESPACE_ENTER

void register_appleseed_closures(OSL::ShadingSystem& shading_system)
{
    // Describe the memory layout of each closure type to the OSL runtime.
    const size_t MaxParams = 32;
    struct BuiltinClosures
    {
        const char*     name;
        int             id;
        ClosureParam    params[MaxParams];
    };

    static const BuiltinClosures builtins[] =
    {
        { "ashikhmin_shirley", AshikhminShirleyID, { CLOSURE_VECTOR_PARAM(AshikhminShirleyClosureParams, N),
                                                     CLOSURE_VECTOR_PARAM(AshikhminShirleyClosureParams, T),
                                                     CLOSURE_COLOR_PARAM(AshikhminShirleyClosureParams, kd),
                                                     CLOSURE_COLOR_PARAM(AshikhminShirleyClosureParams, ks),
                                                     CLOSURE_FLOAT_PARAM(AshikhminShirleyClosureParams, nu),
                                                     CLOSURE_FLOAT_PARAM(AshikhminShirleyClosureParams, nv),
                                                     CLOSURE_FINISH_PARAM(AshikhminShirleyClosureParams) } },

        { "diffuse", LambertID, { CLOSURE_VECTOR_PARAM(LambertClosureParams, N),
                                  CLOSURE_FINISH_PARAM(LambertClosureParams) } },

        { "emission", EmissionID, { CLOSURE_FINISH_PARAM(EmptyClosureParams) } },

        { "holdout", HoldoutID, { CLOSURE_FINISH_PARAM(EmptyClosureParams) } },

        { "microfacet_beckmann", MicrofacetBeckmannID, { CLOSURE_VECTOR_PARAM(MicrofacetBRDFClosureParams, N),
                                                         CLOSURE_FLOAT_PARAM(MicrofacetBRDFClosureParams, glossiness),
                                                         CLOSURE_FINISH_PARAM(MicrofacetBRDFClosureParams) } },

        { "microfacet_blinn", MicrofacetBlinnID, { CLOSURE_VECTOR_PARAM(MicrofacetBRDFClosureParams, N),
                                                   CLOSURE_FLOAT_PARAM(MicrofacetBRDFClosureParams, glossiness),
                                                   CLOSURE_FINISH_PARAM(MicrofacetBRDFClosureParams) } },

        { "microfacet_ggx", MicrofacetGGXID, { CLOSURE_VECTOR_PARAM(MicrofacetBRDFClosureParams, N),
                                               CLOSURE_FLOAT_PARAM(MicrofacetBRDFClosureParams, glossiness),
                                               CLOSURE_FINISH_PARAM(MicrofacetBRDFClosureParams) } },

        { "microfacet_ward", MicrofacetWardID, { CLOSURE_VECTOR_PARAM(MicrofacetBRDFClosureParams, N),
                                                 CLOSURE_FLOAT_PARAM(MicrofacetBRDFClosureParams, glossiness),
                                                 CLOSURE_FINISH_PARAM(MicrofacetBRDFClosureParams) } },

        { "reflection", ReflectionID, { CLOSURE_VECTOR_PARAM(ReflectionClosureParams, N),
                                        CLOSURE_FINISH_PARAM(ReflectionClosureParams) } },

        { "refraction", RefractionID, { CLOSURE_VECTOR_PARAM(RefractionClosureParams, N),
                                        CLOSURE_FLOAT_PARAM(RefractionClosureParams, from_ior),
                                        CLOSURE_FLOAT_PARAM(RefractionClosureParams, to_ior),
                                        CLOSURE_FINISH_PARAM(RefractionClosureParams) } },

        { "translucent", TranslucentID, { CLOSURE_VECTOR_PARAM(LambertClosureParams, N),
                                          CLOSURE_FINISH_PARAM(LambertClosureParams) } },

        { "transparency", TransparentID, { CLOSURE_FINISH_PARAM(EmptyClosureParams) } },

        { 0, 0, {} }    // mark end of the array
    };

    for (size_t i = 0; builtins[i].name != 0; ++i)
    {
        shading_system.register_closure(
            builtins[i].name,
            builtins[i].id,
            builtins[i].params,
            0,
            0);

        RENDERER_LOG_INFO("registered OSL closure %s.", builtins[i].name);
    }
}

OSL_NAMESPACE_EXIT

namespace renderer
{

void register_closures(OSL::ShadingSystem& shading_system)
{
    OSL::register_appleseed_closures(shading_system);
}

}   // namespace renderer
<commit_msg>Simplify conversions between Imath and foundation colors / vectors.<commit_after>
//
// This source file is part of appleseed.
// Visit http://appleseedhq.net/ for additional information and resources.
//
// This software is released under the MIT license.
//
// Copyright (c) 2014 Esteban Tovagliari, The appleseedhq Organization
//
// 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.
//

// Interface header.
#include "closures.h"

// appleseed.renderer headers.
#include "renderer/global/globallogger.h"

// appleseed.foundation headers.
#include "foundation/image/colorspace.h"
#include "foundation/utility/otherwise.h"

// OSL headers.
#include <OSL/genclosure.h>
#include <OSL/oslclosure.h>

using namespace foundation;
using namespace renderer;

namespace renderer
{
namespace
{
    //
    // Closure parameters.
    //

    struct EmptyClosureParams {};

    struct AshikhminShirleyClosureParams
    {
        OSL::Vec3   N;
        OSL::Vec3   T;
        OSL::Color3 kd;
        OSL::Color3 ks;
        float       nu;
        float       nv;
    };

    struct LambertClosureParams
    {
        OSL::Vec3   N;
    };

    struct MicrofacetBRDFClosureParams
    {
        OSL::Vec3   N;
        float       glossiness;
    };

    struct RefractionClosureParams
    {
        OSL::Vec3   N;
        float       from_ior;
        float       to_ior;
    };

    struct ReflectionClosureParams
    {
        OSL::Vec3   N;
    };

    struct TranslucentClosureParams
    {
        OSL::Vec3   N;
    };
}

//
// CompositeClosure class implementation.
//

CompositeClosure::CompositeClosure(
    const OSL::ClosureColor* ci)
  : m_num_closures(0)
  , m_num_bytes(0)
{
    process_closure_tree(ci, Color3f(1.0f));

    // Compute sum of weights.
    double total_weight = 0.0;
    for (size_t i = 0, e = num_closures(); i != e; ++i)
        total_weight += m_weights[i];

    // Normalize weights.
    for (size_t i = 0, e = num_closures(); i != e; ++i)
        m_weights[i] /= total_weight;

    // Build CDF.
    if (num_closures() != 0)
    {
        m_cdf.reserve(num_closures());
        for (size_t i = 0, e = num_closures(); i != e; ++i)
            m_cdf.insert(i, closure_weight(i));
        m_cdf.prepare();
    }
}

size_t CompositeClosure::choose_closure(const double w) const
{
    return m_cdf.sample(w).first;
}

void CompositeClosure::process_closure_tree(
    const OSL::ClosureColor*    closure,
    const Color3f&              weight)
{
    if (closure == 0)
        return;

    switch (closure->type)
    {
      case OSL::ClosureColor::MUL:
        {
            const OSL::ClosureMul* c = reinterpret_cast<const OSL::ClosureMul*>(closure);
            const Color3f w = weight * Color3f(c->weight);
            process_closure_tree(c->closure, w);
        }
        break;

      case OSL::ClosureColor::ADD:
        {
            const OSL::ClosureAdd* c = reinterpret_cast<const OSL::ClosureAdd*>(closure);
            process_closure_tree(c->closureA, weight);
            process_closure_tree(c->closureB, weight);
        }
        break;

      case OSL::ClosureColor::COMPONENT:
        {
            const OSL::ClosureComponent* c = reinterpret_cast<const OSL::ClosureComponent*>(closure);
            const Color3f w = weight * Color3f(c->w);

            switch (c->id)
            {
              case AshikhminShirleyID:
                {
                    const AshikhminShirleyClosureParams* p =
                        reinterpret_cast<const AshikhminShirleyClosureParams*>(c->data());

                    AshikminBRDFInputValues values;

                    const Color3f wd = w * Color3f(p->kd);
                    linear_rgb_reflectance_to_spectrum(wd, values.m_rd);
                    values.m_rd_alpha = Alpha(1.0f);
                    values.m_rd_multiplier = 1.0;

                    const Color3f wg = w * Color3f(p->ks);
                    linear_rgb_reflectance_to_spectrum(wg, values.m_rg);
                    values.m_rg_alpha = Alpha(1.0f);
                    values.m_rg_multiplier = 1.0;
                    values.m_fr_multiplier = 1.0;
                    values.m_nu = p->nu;
                    values.m_nv = p->nv;

                    add_closure<AshikminBRDFInputValues>(
                        static_cast<ClosureID>(c->id),
                        w,
                        Vector3d(p->N),
                        Vector3d(p->T),
                        values);
                }
                break;

              case LambertID:
                {
                    const LambertClosureParams* p =
                        reinterpret_cast<const LambertClosureParams*>(c->data());

                    LambertianBRDFInputValues values;
                    linear_rgb_reflectance_to_spectrum(w, values.m_reflectance);
                    values.m_reflectance_alpha = Alpha(1.0f);
                    values.m_reflectance_multiplier = 1.0;

                    add_closure<LambertianBRDFInputValues>(
                        static_cast<ClosureID>(c->id),
                        w,
                        Vector3d(p->N),
                        values);
                }
                break;

              case MicrofacetBeckmannID:
              case MicrofacetBlinnID:
              case MicrofacetGGXID:
              case MicrofacetWardID:
                {
                    const MicrofacetBRDFClosureParams* p =
                        reinterpret_cast<const MicrofacetBRDFClosureParams*>(c->data());

                    MicrofacetBRDFInputValues values;
                    linear_rgb_reflectance_to_spectrum(w, values.m_reflectance);
                    values.m_reflectance_alpha = Alpha(1.0f);
                    values.m_reflectance_multiplier = 1.0;
                    values.m_glossiness = p->glossiness;
                    values.m_glossiness_multiplier = 1.0;
                    values.m_fr_multiplier = 1.0;

                    add_closure<MicrofacetBRDFInputValues>(
                        static_cast<ClosureID>(c->id),
                        w,
                        Vector3d(p->N),
                        values);
                }
                break;

              case ReflectionID:
                {
                    const ReflectionClosureParams* p =
                        reinterpret_cast<const ReflectionClosureParams*>(c->data());

                    SpecularBRDFInputValues values;
                    linear_rgb_reflectance_to_spectrum(w, values.m_reflectance);
                    values.m_reflectance_alpha = Alpha(1.0f);
                    values.m_reflectance_multiplier = 1.0;

                    add_closure<SpecularBRDFInputValues>(
                        static_cast<ClosureID>(c->id),
                        w,
                        Vector3d(p->N),
                        values);
                }
                break;

              case RefractionID:
                {
                    const RefractionClosureParams* p =
                        reinterpret_cast<const RefractionClosureParams*>(c->data());

                    SpecularBTDFInputValues values;
                    linear_rgb_reflectance_to_spectrum(w, values.m_reflectance);
                    values.m_from_ior = p->from_ior;
                    values.m_to_ior = p->to_ior;
                    values.m_reflectance_alpha = Alpha(1.0);
                    values.m_reflectance_multiplier = 1.0;

                    add_closure<SpecularBTDFInputValues>(
                        static_cast<ClosureID>(c->id),
                        w,
                        Vector3d(p->N),
                        values);
                }
                break;

              case TranslucentID:
                {
                    const TranslucentClosureParams* p =
                        reinterpret_cast<const TranslucentClosureParams*>(c->data());

                    DiffuseBTDFInputValues values;
                    linear_rgb_reflectance_to_spectrum(w, values.m_transmittance);
                    values.m_transmittance_alpha = Alpha(1.0);
                    values.m_transmittance_multiplier = 1.0;

                    add_closure<DiffuseBTDFInputValues>(
                        static_cast<ClosureID>(c->id),
                        w,
                        Vector3d(p->N),
                        values);
                }
                break;

              case EmissionID:
              case HoldoutID:
              case TransparentID:
                {
                    assert(!"Not implemented yet.");
                }
                break;

              assert_otherwise;
            }
        }
        break;
    }
}

template <typename InputValues>
void CompositeClosure::add_closure(
    const ClosureID             closure_type,
    const Color3f&              weight,
    const Vector3d&             normal,
    const InputValues&          params)
{
    do_add_closure<InputValues>(
        closure_type,
        weight,
        normal,
        false,
        Vector3d(0.0),
        params);
}

template <typename InputValues>
void CompositeClosure::add_closure(
    const ClosureID             closure_type,
    const Color3f&              weight,
    const Vector3d&             normal,
    const Vector3d&             tangent,
    const InputValues&          params)
{
    do_add_closure<InputValues>(
        closure_type,
        weight,
        normal,
        true,
        tangent,
        params);
}

template <typename InputValues>
void CompositeClosure::do_add_closure(
    const ClosureID             closure_type,
    const Color3f&              weight,
    const Vector3d&             normal,
    const bool                  has_tangent,
    const Vector3d&             tangent,
    const InputValues&          params)
{
    // Make sure we have enough space.
    if (num_closures() >= MaxClosureEntries)
    {
        RENDERER_LOG_WARNING("maximum number of closures in OSL shadergroup exceeded; ignoring closure.");
        return;
    }

    assert(m_num_bytes + sizeof(InputValues) <= MaxPoolSize);

    // We use the luminance of the weight as the BSDF weight.
    const double w = luminance(weight);
    if (w <= 0.0)
    {
        // This can generate millions of warnings. It's better to disable it.
        //RENDERER_LOG_WARNING("closure with negative or zero weight found; ignoring closure.");
        return;
    }

    m_weights[m_num_closures] = w;
    m_normals[m_num_closures] = normalize(normal);
    m_has_tangent[m_num_closures] = has_tangent;

    if (has_tangent)
        m_tangents[m_num_closures] = normalize(tangent);

    m_closure_types[m_num_closures] = closure_type;

    m_input_values[m_num_closures] = m_pool + m_num_bytes;
    new (m_input_values[m_num_closures]) InputValues(params);

    m_num_bytes += sizeof(InputValues);
    ++m_num_closures;
}

}   // namespace renderer

// We probably want to reuse OSL macros to declare closure params
// and register the closures. We can use them only inside the OSL namespace.
OSL_NAMESPACE_ENTER

void register_appleseed_closures(OSL::ShadingSystem& shading_system)
{
    // Describe the memory layout of each closure type to the OSL runtime.
    const size_t MaxParams = 32;
    struct BuiltinClosures
    {
        const char*     name;
        int             id;
        ClosureParam    params[MaxParams];
    };

    static const BuiltinClosures builtins[] =
    {
        { "ashikhmin_shirley", AshikhminShirleyID, { CLOSURE_VECTOR_PARAM(AshikhminShirleyClosureParams, N),
                                                     CLOSURE_VECTOR_PARAM(AshikhminShirleyClosureParams, T),
                                                     CLOSURE_COLOR_PARAM(AshikhminShirleyClosureParams, kd),
                                                     CLOSURE_COLOR_PARAM(AshikhminShirleyClosureParams, ks),
                                                     CLOSURE_FLOAT_PARAM(AshikhminShirleyClosureParams, nu),
                                                     CLOSURE_FLOAT_PARAM(AshikhminShirleyClosureParams, nv),
                                                     CLOSURE_FINISH_PARAM(AshikhminShirleyClosureParams) } },

        { "diffuse", LambertID, { CLOSURE_VECTOR_PARAM(LambertClosureParams, N),
                                  CLOSURE_FINISH_PARAM(LambertClosureParams) } },

        { "emission", EmissionID, { CLOSURE_FINISH_PARAM(EmptyClosureParams) } },

        { "holdout", HoldoutID, { CLOSURE_FINISH_PARAM(EmptyClosureParams) } },

        { "microfacet_beckmann", MicrofacetBeckmannID, { CLOSURE_VECTOR_PARAM(MicrofacetBRDFClosureParams, N),
                                                         CLOSURE_FLOAT_PARAM(MicrofacetBRDFClosureParams, glossiness),
                                                         CLOSURE_FINISH_PARAM(MicrofacetBRDFClosureParams) } },

        { "microfacet_blinn", MicrofacetBlinnID, { CLOSURE_VECTOR_PARAM(MicrofacetBRDFClosureParams, N),
                                                   CLOSURE_FLOAT_PARAM(MicrofacetBRDFClosureParams, glossiness),
                                                   CLOSURE_FINISH_PARAM(MicrofacetBRDFClosureParams) } },

        { "microfacet_ggx", MicrofacetGGXID, { CLOSURE_VECTOR_PARAM(MicrofacetBRDFClosureParams, N),
                                               CLOSURE_FLOAT_PARAM(MicrofacetBRDFClosureParams, glossiness),
                                               CLOSURE_FINISH_PARAM(MicrofacetBRDFClosureParams) } },

        { "microfacet_ward", MicrofacetWardID, { CLOSURE_VECTOR_PARAM(MicrofacetBRDFClosureParams, N),
                                                 CLOSURE_FLOAT_PARAM(MicrofacetBRDFClosureParams, glossiness),
                                                 CLOSURE_FINISH_PARAM(MicrofacetBRDFClosureParams) } },

        { "reflection", ReflectionID, { CLOSURE_VECTOR_PARAM(ReflectionClosureParams, N),
                                        CLOSURE_FINISH_PARAM(ReflectionClosureParams) } },

        { "refraction", RefractionID, { CLOSURE_VECTOR_PARAM(RefractionClosureParams, N),
                                        CLOSURE_FLOAT_PARAM(RefractionClosureParams, from_ior),
                                        CLOSURE_FLOAT_PARAM(RefractionClosureParams, to_ior),
                                        CLOSURE_FINISH_PARAM(RefractionClosureParams) } },

        { "translucent", TranslucentID, { CLOSURE_VECTOR_PARAM(LambertClosureParams, N),
                                          CLOSURE_FINISH_PARAM(LambertClosureParams) } },

        { "transparency", TransparentID, { CLOSURE_FINISH_PARAM(EmptyClosureParams) } },

        { 0, 0, {} }    // mark end of the array
    };

    for (size_t i = 0; builtins[i].name != 0; ++i)
    {
        shading_system.register_closure(
            builtins[i].name,
            builtins[i].id,
            builtins[i].params,
            0,
            0);

        RENDERER_LOG_INFO("registered OSL closure %s.", builtins[i].name);
    }
}

OSL_NAMESPACE_EXIT

namespace renderer
{

void register_closures(OSL::ShadingSystem& shading_system)
{
    OSL::register_appleseed_closures(shading_system);
}

}   // namespace renderer
<|endoftext|>


<commit_before>/*
    OpenDeck MIDI platform firmware
    Copyright (C) 2015-2018 Igor Petrovic

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

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

    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/

#include "board/Board.h"

void Board::init()
{
    cli();
    //disable watchdog
    MCUSR &= ~(1 << WDRF);
    wdt_disable();
    initPins();
    initAnalog();
    initEncoders();

    initUSB_MIDI();

    configureTimers();
}

void Board::initPins()
{
    setInput(SR_IN_DATA_PORT, SR_IN_DATA_PIN);
    setOutput(SR_IN_CLK_PORT, SR_IN_CLK_PIN);
    setOutput(SR_IN_LATCH_PORT, SR_IN_LATCH_PIN);

    setInput(SR_OUT_DATA_PORT, SR_OUT_DATA_PIN);
    setOutput(SR_OUT_CLK_PORT, SR_OUT_CLK_PIN);
    setOutput(SR_OUT_LATCH_PORT, SR_OUT_LATCH_PIN);

    setOutput(MUX_S0_PORT, MUX_S0_PIN);
    setOutput(MUX_S1_PORT, MUX_S1_PIN);
    setOutput(MUX_S2_PORT, MUX_S2_PIN);
    setOutput(MUX_S3_PORT, MUX_S3_PIN);

    setInput(MUX_1_IN_PORT, MUX_1_IN_PIN);
    setInput(MUX_2_IN_PORT, MUX_2_IN_PIN);
    setInput(MUX_3_IN_PORT, MUX_3_IN_PIN);
    setInput(MUX_4_IN_PORT, MUX_4_IN_PIN);

    //unused pins
    setOutput(PORTB, 0);
    setOutput(PORTB, 4);
    setOutput(PORTB, 5);
    setOutput(PORTB, 7);

    setOutput(PORTC, 6);
    setOutput(PORTC, 7);

    setOutput(PORTD, 6);
    setOutput(PORTD, 7);

    setOutput(PORTE, 2);

    setOutput(PORTF, 0);
    setOutput(PORTF, 1);
    setOutput(PORTF, 4);
    setOutput(PORTF, 5);

    //make sure all unused pins are logic low
    setLow(PORTB, 0);
    setLow(PORTB, 4);
    setLow(PORTB, 5);
    setLow(PORTB, 7);

    setLow(PORTC, 6);
    setLow(PORTC, 7);

    setLow(PORTD, 6);
    setLow(PORTD, 7);

    setLow(PORTE, 2);

    setLow(PORTF, 0);
    setLow(PORTF, 1);
    setLow(PORTF, 4);
    setLow(PORTF, 5);
}

void Board::configureTimers()
{
    //clear timer0 conf
    TCCR0A = 0;
    TCCR0B = 0;
    TIMSK0 = 0;

    //clear timer1 conf
    TCCR1A = 0;
    TCCR1B = 0;

    //clear timer3 conf
    TCCR3A = 0;
    TCCR3B = 0;

    //clear timer4 conf
    TCCR4A = 0;
    TCCR4B = 0;
    TCCR4C = 0;
    TCCR4D = 0;
    TCCR4E = 0;

    //set timer0 to ctc, used for millis/led matrix
    TCCR0A |= (1<<WGM01);           //CTC mode
    TCCR0B |= (1<<CS01)|(1<<CS00);  //prescaler 64
    OCR0A = 62;                     //250us
    TIMSK0 |= (1<<OCIE0A);          //compare match interrupt
}
<commit_msg>remove incorrect init<commit_after>/*
    OpenDeck MIDI platform firmware
    Copyright (C) 2015-2018 Igor Petrovic

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

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

    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/

#include "board/Board.h"

void Board::init()
{
    cli();
    //disable watchdog
    MCUSR &= ~(1 << WDRF);
    wdt_disable();
    initPins();
    initAnalog();
    initEncoders();

    initUSB_MIDI();

    configureTimers();
}

void Board::initPins()
{
    setInput(SR_IN_DATA_PORT, SR_IN_DATA_PIN);
    setOutput(SR_IN_CLK_PORT, SR_IN_CLK_PIN);
    setOutput(SR_IN_LATCH_PORT, SR_IN_LATCH_PIN);

    setInput(SR_OUT_DATA_PORT, SR_OUT_DATA_PIN);
    setOutput(SR_OUT_CLK_PORT, SR_OUT_CLK_PIN);
    setOutput(SR_OUT_LATCH_PORT, SR_OUT_LATCH_PIN);

    setOutput(MUX_S0_PORT, MUX_S0_PIN);
    setOutput(MUX_S1_PORT, MUX_S1_PIN);
    setOutput(MUX_S2_PORT, MUX_S2_PIN);
    setOutput(MUX_S3_PORT, MUX_S3_PIN);

    setInput(MUX_1_IN_PORT, MUX_1_IN_PIN);
    setInput(MUX_2_IN_PORT, MUX_2_IN_PIN);
    setInput(MUX_3_IN_PORT, MUX_3_IN_PIN);
    setInput(MUX_4_IN_PORT, MUX_4_IN_PIN);

    //unused pins
    setOutput(PORTB, 0);
    setOutput(PORTB, 4);
    setOutput(PORTB, 5);
    setOutput(PORTB, 7);

    setOutput(PORTC, 6);
    setOutput(PORTC, 7);

    setOutput(PORTD, 6);
    setOutput(PORTD, 7);

    setOutput(PORTE, 2);

    setOutput(PORTF, 0);
    setOutput(PORTF, 1);
    setOutput(PORTF, 4);

    //make sure all unused pins are logic low
    setLow(PORTB, 0);
    setLow(PORTB, 4);
    setLow(PORTB, 5);
    setLow(PORTB, 7);

    setLow(PORTC, 6);
    setLow(PORTC, 7);

    setLow(PORTD, 6);
    setLow(PORTD, 7);

    setLow(PORTE, 2);

    setLow(PORTF, 0);
    setLow(PORTF, 1);
    setLow(PORTF, 4);
}

void Board::configureTimers()
{
    //clear timer0 conf
    TCCR0A = 0;
    TCCR0B = 0;
    TIMSK0 = 0;

    //clear timer1 conf
    TCCR1A = 0;
    TCCR1B = 0;

    //clear timer3 conf
    TCCR3A = 0;
    TCCR3B = 0;

    //clear timer4 conf
    TCCR4A = 0;
    TCCR4B = 0;
    TCCR4C = 0;
    TCCR4D = 0;
    TCCR4E = 0;

    //set timer0 to ctc, used for millis/led matrix
    TCCR0A |= (1<<WGM01);           //CTC mode
    TCCR0B |= (1<<CS01)|(1<<CS00);  //prescaler 64
    OCR0A = 62;                     //250us
    TIMSK0 |= (1<<OCIE0A);          //compare match interrupt
}
<|endoftext|>


<commit_before>
#include "geometry/cartesian_product.hpp"

#include <algorithm>
#include <type_traits>

#include "quantities/named_quantities.hpp"
#include "quantities/tuples.hpp"

namespace principia {
namespace geometry {
namespace internal_cartesian_product {

using quantities::Apply;
using quantities::Apply2;

template<typename LTuple, typename RTuple, int... indices>
struct CartesianProductAdditiveGroup<LTuple, RTuple,
                                     std::integer_sequence<int, indices...>> {
  // The types of the result of addition and subtraction, with suitable
  // checks for the void case of Apply2.
  template<typename L, typename R>
  using Sum =
      std::conditional_t<std::is_void_v<L>, R,
                         std::conditional_t<std::is_void_v<R>, L,
                                            quantities::Sum<L, R>>>;
  template<typename L, typename R>
  using Difference =
      std::conditional_t<std::is_void_v<L>, R,
                         std::conditional_t<std::is_void_v<R>, L,
                                            quantities::Difference<L, R>>>;

  static constexpr Apply2<Sum, LTuple, RTuple> Add(
      LTuple const& left,
      RTuple const& right);
  static constexpr Apply2<Difference, LTuple, RTuple> Subtract(
      LTuple const& left,
      RTuple const& right);
};

template<typename LTuple, typename RTuple, int... indices>
constexpr auto CartesianProductAdditiveGroup<
    LTuple, RTuple,
    std::integer_sequence<int, indices...>>::Add(LTuple const& left,
                                                 RTuple const& right)
    -> Apply2<Sum, LTuple, RTuple> {
  return {(
      indices < std::min(std::tuple_size_v<LTuple>, std::tuple_size_v<RTuple>)
          ? std::get<indices>(left) + std::get<indices>(right)
          : indices < std::tuple_size_v<LTuple>
                ? std::get<indices>(left)
                : std::get<indices>(right))...};
}

template<typename LTuple, typename RTuple, int... indices>
constexpr auto CartesianProductAdditiveGroup<
    LTuple, RTuple,
    std::integer_sequence<int, indices...>>::Subtract(LTuple const& left,
                                                      RTuple const& right)
    -> Apply2<Difference, LTuple, RTuple> {
  return {
      (indices < std::min(std::tuple_size_v<LTuple>, std::tuple_size_v<RTuple>)
           ? std::get<indices>(left) - std::get<indices>(right)
           : indices < std::tuple_size_v<LTuple>
                 ? std::get<indices>(left)
                 : -std::get<indices>(right))...};
}

template<typename Scalar, typename Tuple, int... indices>
struct CartesianProductVectorSpace<Scalar,
                                   Tuple,
                                   std::integer_sequence<int, indices...>> {
  template<typename T>
  using ScalarLeftProduct = quantities::Product<Scalar, T>;
  template<typename T>
  using ScalarRightProduct = quantities::Product<T, Scalar>;
  template<typename T>
  using Quotient = quantities::Quotient<T, Scalar>;

  static constexpr typename Apply<ScalarLeftProduct, Tuple> Multiply(
      Scalar const& left,
      Tuple const& right);
  static constexpr typename Apply<ScalarRightProduct, Tuple> Multiply(
      Tuple const& left,
      Scalar const& right);

  static constexpr typename Apply<Quotient, Tuple> Divide(
      Tuple const& left,
      Scalar const& right);
};

template<typename Scalar, typename Tuple, int... indices>
constexpr auto CartesianProductVectorSpace<
    Scalar, Tuple,
    std::integer_sequence<int, indices...>>::Multiply(Scalar const& left,
                                                      Tuple const& right)
    -> typename Apply<ScalarLeftProduct, Tuple> {
  return {left * std::get<indices>(right)...};
}

template<typename Scalar, typename Tuple, int... indices>
constexpr auto CartesianProductVectorSpace<
    Scalar, Tuple,
    std::integer_sequence<int, indices...>>::Multiply(Tuple const& left,
                                                      Scalar const& right)
    -> typename Apply<ScalarRightProduct, Tuple> {
  return {std::get<indices>(left) * right...};
}

template<typename Scalar, typename Tuple, int... indices>
constexpr auto CartesianProductVectorSpace<
    Scalar, Tuple,
    std::integer_sequence<int, indices...>>::Divide(Tuple const& left,
                                                    Scalar const& right)
    -> typename Apply<Quotient, Tuple> {
  return {std::get<indices>(left) / right...};
}

template<typename Element, typename Tuple,
         typename = std::make_integer_sequence<int, std::tuple_size_v<Tuple>>>
struct ConsGenerator;

template<typename Element, typename Tuple, int... indices>
struct ConsGenerator<Element, Tuple,
                     std::integer_sequence<int, indices...>> {
  using Type = std::tuple<Element, std::tuple_element_t<indices, Tuple>...>;
  static constexpr Type Cons(Element const& element, Tuple const& tuple);
};

template<typename Element, typename Tuple, int... indices>
constexpr auto
ConsGenerator<Element, Tuple, std::integer_sequence<int, indices...>>::
Cons(Element const& element, Tuple const& tuple) -> Type {
  return std::make_tuple(element, std::get<tail_indices>(tuple)...);
}

template<typename Tuple,
         typename = std::make_integer_sequence<int, std::tuple_size_v<Tuple>>>
struct TailGenerator;

template<typename Tuple, int head_index, int... tail_indices>
struct TailGenerator<Tuple,
                     std::integer_sequence<int, head_index, tail_indices...>> {
  using Type = std::tuple<std::tuple_element_t<tail_indices, Tuple>...>;
  static constexpr Type Tail(Tuple const& tuple);
};

template<typename Tuple, int head_index, int... tail_indices>
constexpr auto
TailGenerator<Tuple, std::integer_sequence<int, head_index, tail_indices...>>::
Tail(Tuple const& tuple) -> Type {
  return std::make_tuple(std::get<tail_indices>(tuple)...);
}

template<typename LTuple, typename RTuple, int lsize_, int rsize_>
struct CartesianProductAlgebra {
  // Right is split into head (index 0) and tail (the rest).  The tail is a
  // polynomial with valuation 1.
  using RHead = std::tuple_element_t<0, RTuple>;
  using RTail = typename TailGenerator<LTuple>::Type;

  // To implement the polynomial multiplication left * right_tail, we need to
  // insert a zero for the lowest degree (because of the valuation 1).  This is
  // the type of that zero.
  using LHead = std::tuple_element_t<0, RTuple>;
  using Zero = quantities::Product<LHead, RHead>;

  using LTupleRHeadProduct =
      decltype(CartesianProductVectorSpace<LTuple, RHead>::Multiply(
          std::declval<LTuple>(),
          std::declval<RHead>()));
  using LTupleRTailProduct =
      typename ConsGenerator<Zero,
                             decltype(
                                 CartesianProductAlgebra<LTuple, RTail>::Mult(
                                     std::declval<LTuple>(),
                                     std::declval<RTail>()))>::Type;

  using Result = decltype(
      CartesianProductAdditiveGroup<LTupleRHeadProduct, LTupleRTailProduct>::
          Add(std::declval(LTupleRHeadProduct),
              std::declval(LTupleRTailProduct)));
  static constexpr Result Mult(LTuple const& left, RTuple const& right);
};

template<typename LTuple, typename RTuple, int lsize_>
struct CartesianProductAlgebra<LTuple, RTuple, lsize_, 1> {
  using RHead = std::tuple_element_t<0, RTuple>;
  using Result = decltype(CartesianProductVectorSpace<LTuple, RHead>::Multiply(
      std::declval<LTuple>(),
      std::declval<RHead>()));
  static constexpr Result Mult(LTuple const& left, RTuple const& right);
};

template<typename LTuple, typename RTuple, int lsize_, int rsize_>
constexpr auto CartesianProductAlgebra<LTuple, RTuple, lsize_, rsize_>::Mult(
    LTuple const& left,
    RTuple const& right) -> Result {
  RHead const right_head = std::get<0>(right);
  auto const right_tail = TailGenerator<RTuple>::Tail(right);

  return CartesianProductAdditiveGroup<LTupleRHeadProduct, LTupleRTailProduct>::
      Add(CartesianProductVectorSpace<LTuple, RHead>::Multiply(left,
                                                               right_head),
          ConsGenerator<Zero, LTupleRTailProduct>::Cons(
              Zero{}, Mult(left, right_tail)));
}

template<typename LTuple, typename RTuple, int lsize_>
constexpr auto CartesianProductAlgebra<LTuple, RTuple, lsize_, 1>::Mult(
    LTuple const& left,
    RTuple const& right) -> Result {
  RHead const right_head = std::get<0>(right);
  return CartesianProductVectorSpace<LTuple, RHead>::Multiply(left, right_head);
}

}  // namespace internal_cartesian_product
}  // namespace geometry
}  // namespace principia
<commit_msg>Fix some compilation errors.<commit_after>
#include "geometry/cartesian_product.hpp"

#include <algorithm>
#include <type_traits>

#include "quantities/named_quantities.hpp"
#include "quantities/tuples.hpp"

namespace principia {
namespace geometry {
namespace internal_cartesian_product {

using quantities::Apply;
using quantities::Apply2;

template<typename LTuple, typename RTuple, int... indices>
struct CartesianProductAdditiveGroup<LTuple, RTuple,
                                     std::integer_sequence<int, indices...>> {
  // The types of the result of addition and subtraction, with suitable
  // checks for the void case of Apply2.
  template<typename L, typename R>
  using Sum =
      std::conditional_t<std::is_void_v<L>, R,
                         std::conditional_t<std::is_void_v<R>, L,
                                            quantities::Sum<L, R>>>;
  template<typename L, typename R>
  using Difference =
      std::conditional_t<std::is_void_v<L>, R,
                         std::conditional_t<std::is_void_v<R>, L,
                                            quantities::Difference<L, R>>>;

  static constexpr Apply2<Sum, LTuple, RTuple> Add(
      LTuple const& left,
      RTuple const& right);
  static constexpr Apply2<Difference, LTuple, RTuple> Subtract(
      LTuple const& left,
      RTuple const& right);
};

template<typename LTuple, typename RTuple, int... indices>
constexpr auto CartesianProductAdditiveGroup<
    LTuple, RTuple,
    std::integer_sequence<int, indices...>>::Add(LTuple const& left,
                                                 RTuple const& right)
    -> Apply2<Sum, LTuple, RTuple> {
  return {(
      indices < std::min(std::tuple_size_v<LTuple>, std::tuple_size_v<RTuple>)
          ? std::get<indices>(left) + std::get<indices>(right)
          : indices < std::tuple_size_v<LTuple>
                ? std::get<indices>(left)
                : std::get<indices>(right))...};
}

template<typename LTuple, typename RTuple, int... indices>
constexpr auto CartesianProductAdditiveGroup<
    LTuple, RTuple,
    std::integer_sequence<int, indices...>>::Subtract(LTuple const& left,
                                                      RTuple const& right)
    -> Apply2<Difference, LTuple, RTuple> {
  return {
      (indices < std::min(std::tuple_size_v<LTuple>, std::tuple_size_v<RTuple>)
           ? std::get<indices>(left) - std::get<indices>(right)
           : indices < std::tuple_size_v<LTuple>
                 ? std::get<indices>(left)
                 : -std::get<indices>(right))...};
}

template<typename Scalar, typename Tuple, int... indices>
struct CartesianProductVectorSpace<Scalar,
                                   Tuple,
                                   std::integer_sequence<int, indices...>> {
  template<typename T>
  using ScalarLeftProduct = quantities::Product<Scalar, T>;
  template<typename T>
  using ScalarRightProduct = quantities::Product<T, Scalar>;
  template<typename T>
  using Quotient = quantities::Quotient<T, Scalar>;

  static constexpr typename Apply<ScalarLeftProduct, Tuple> Multiply(
      Scalar const& left,
      Tuple const& right);
  static constexpr typename Apply<ScalarRightProduct, Tuple> Multiply(
      Tuple const& left,
      Scalar const& right);

  static constexpr typename Apply<Quotient, Tuple> Divide(
      Tuple const& left,
      Scalar const& right);
};

template<typename Scalar, typename Tuple, int... indices>
constexpr auto CartesianProductVectorSpace<
    Scalar, Tuple,
    std::integer_sequence<int, indices...>>::Multiply(Scalar const& left,
                                                      Tuple const& right)
    -> typename Apply<ScalarLeftProduct, Tuple> {
  return {left * std::get<indices>(right)...};
}

template<typename Scalar, typename Tuple, int... indices>
constexpr auto CartesianProductVectorSpace<
    Scalar, Tuple,
    std::integer_sequence<int, indices...>>::Multiply(Tuple const& left,
                                                      Scalar const& right)
    -> typename Apply<ScalarRightProduct, Tuple> {
  return {std::get<indices>(left) * right...};
}

template<typename Scalar, typename Tuple, int... indices>
constexpr auto CartesianProductVectorSpace<
    Scalar, Tuple,
    std::integer_sequence<int, indices...>>::Divide(Tuple const& left,
                                                    Scalar const& right)
    -> typename Apply<Quotient, Tuple> {
  return {std::get<indices>(left) / right...};
}

template<typename Element, typename Tuple,
         typename = std::make_integer_sequence<int, std::tuple_size_v<Tuple>>>
struct ConsGenerator;

template<typename Element, typename Tuple, int... indices>
struct ConsGenerator<Element, Tuple,
                     std::integer_sequence<int, indices...>> {
  using Type = std::tuple<Element, std::tuple_element_t<indices, Tuple>...>;
  static constexpr Type Cons(Element const& element, Tuple const& tuple);
};

template<typename Element, typename Tuple, int... indices>
constexpr auto
ConsGenerator<Element, Tuple, std::integer_sequence<int, indices...>>::
Cons(Element const& element, Tuple const& tuple) -> Type {
  return std::make_tuple(element, std::get<indices>(tuple)...);
}

template<typename Tuple,
         typename = std::make_integer_sequence<int, std::tuple_size_v<Tuple>>>
struct TailGenerator;

template<typename Tuple, int head_index, int... tail_indices>
struct TailGenerator<Tuple,
                     std::integer_sequence<int, head_index, tail_indices...>> {
  using Type = std::tuple<std::tuple_element_t<tail_indices, Tuple>...>;
  static constexpr Type Tail(Tuple const& tuple);
};

template<typename Tuple, int head_index, int... tail_indices>
constexpr auto
TailGenerator<Tuple, std::integer_sequence<int, head_index, tail_indices...>>::
Tail(Tuple const& tuple) -> Type {
  return std::make_tuple(std::get<tail_indices>(tuple)...);
}

template<typename LTuple, typename RTuple, int lsize_, int rsize_>
struct CartesianProductAlgebra {
  // Right is split into head (index 0) and tail (the rest).  The tail is a
  // polynomial with valuation 1.
  using RHead = std::tuple_element_t<0, RTuple>;
  using RTail = typename TailGenerator<LTuple>::Type;

  // To implement the polynomial multiplication left * right_tail, we need to
  // insert a zero for the lowest degree (because of the valuation 1).  This is
  // the type of that zero.
  using LHead = std::tuple_element_t<0, RTuple>;
  using Zero = quantities::Product<LHead, RHead>;

  using LTupleRHeadProduct =
      decltype(CartesianProductVectorSpace<LTuple, RHead>::Multiply(
          std::declval<LTuple>(),
          std::declval<RHead>()));
  using LTupleRTailProduct =
      typename ConsGenerator<Zero,
                             decltype(
                                 CartesianProductAlgebra<LTuple, RTail>::Mult(
                                     std::declval<LTuple>(),
                                     std::declval<RTail>()))>::Type;

  using Result = decltype(
      CartesianProductAdditiveGroup<LTupleRHeadProduct, LTupleRTailProduct>::
          Add(std::declval<LTupleRHeadProduct>(),
              std::declval<LTupleRTailProduct>()));
  static constexpr Result Mult(LTuple const& left, RTuple const& right);
};

template<typename LTuple, typename RTuple, int lsize_>
struct CartesianProductAlgebra<LTuple, RTuple, lsize_, 1> {
  using RHead = std::tuple_element_t<0, RTuple>;
  using Result = decltype(CartesianProductVectorSpace<LTuple, RHead>::Multiply(
      std::declval<LTuple>(),
      std::declval<RHead>()));
  static constexpr Result Mult(LTuple const& left, RTuple const& right);
};

template<typename LTuple, typename RTuple, int lsize_, int rsize_>
constexpr auto CartesianProductAlgebra<LTuple, RTuple, lsize_, rsize_>::Mult(
    LTuple const& left,
    RTuple const& right) -> Result {
  RHead const right_head = std::get<0>(right);
  auto const right_tail = TailGenerator<RTuple>::Tail(right);

  return CartesianProductAdditiveGroup<LTupleRHeadProduct, LTupleRTailProduct>::
      Add(CartesianProductVectorSpace<LTuple, RHead>::Multiply(left,
                                                               right_head),
          ConsGenerator<Zero, LTupleRTailProduct>::Cons(
              Zero{}, Mult(left, right_tail)));
}

template<typename LTuple, typename RTuple, int lsize_>
constexpr auto CartesianProductAlgebra<LTuple, RTuple, lsize_, 1>::Mult(
    LTuple const& left,
    RTuple const& right) -> Result {
  RHead const right_head = std::get<0>(right);
  return CartesianProductVectorSpace<LTuple, RHead>::Multiply(left, right_head);
}

}  // namespace internal_cartesian_product
}  // namespace geometry
}  // namespace principia
<|endoftext|>


<commit_before>// THIS FILE IS IN DEVELOPMENT AND IS NOT GUARANTEED TO DO ANYTHING!

#include <bitset>
#include <cassert>
#include <cmath>
#include <cstdint>
#include <cstdio>      /* printf, scanf, puts, NULL */
#include <cstdlib>
#include <cstring>
#include <ctime>
#include <iostream>
#include <fstream>
#include <cilk/cilk.h>
#include <cilk/reducer_opadd.h>
#include <cilk/reducer_list.h>

#include <queue>
#include <sys/time.h>
#include <vector>
#include "hashdb.h"
#include "hashmap.h"
//#include "wordavoidance.h"
#include "utilities.h"
#include "perm.h"
using namespace std;

// THINGS TO BE CAREFUL ABOUT:
// Words could now take val -1 if they are large, screwing up hash table. That includes fingerprint (but is not an issue in our current implementation for fingerprint).
// to distinguish words, DO need to know size. Thus avoidset and word fingerprint BOTH include this in their representatinos

// Returns the unique fingerprint of pattern represented by word
// Requires
// letters of value <= 31
// More importantly, never more than 7 letters preceeding another letter and larger than it (assuming uint64_t perm)
// Also size of word  + 1 < max allowed size of word
// SUFFICES to have letters of value <= 31 and word size 8 or less
perm_t wordfingerprint(perm_t word, int size) {
  perm_t print = setdigit(0, size, 1); // so that finger print marks size
  uint32_t seenletters = 0;
  for (int i = 0; i < size; i++) {
    unsigned long long reldig = 0;
    int digit = getdigit(word, i);
    unsigned int temp = seenletters >> (digit);
    reldig = 2*__builtin_popcount(temp);
    if ((seenletters & (1 << digit))  != 0) reldig--;
    // now relcount is count 2 * number larger digits + 1 if current digit also appears
    // have to be careful to do this because can have letters appearing multiple times
    seenletters = seenletters | (1 << digit);
    print = setdigit(print, i, reldig);
  }
  return print;
}

perm_t prepareforavoidset(perm_t word, int length) {
  return setdigit(word, length, 1); // mark length
}

// PATTERNS HAVE TO BE AT LEAST SIZE THREE DUE TO HOW AVOIDMAP IS SET UP
void wordavoiders_raw_dynamic(const hashdb &patternprintset, int maxavoidsize, int maxsize, vector < uint64_t > &numavoiders, int base) {
  hashdb avoidset = hashdb(1000);
  hashmap avoidmap(1<<8, 8);
  std::queue<perm_t> avoiderstoextend; // queue of avoiders built so far.
  //for (int i = 0; i < base; i++)  avoidset.add(prepareforavoidset(setdigit(0, 0, i), 1));
  uint64_t trivialmap = (((uint64_t)1) << base) - 1;
  for (int i = 0; i < base; i++)  avoidmap.add(prepareforavoidset(setdigit(0, 0, i), 1), &trivialmap);
  numavoiders[1] = base;

  for (int i = 0; i < base; i++) {
    for (int j = 0; j < base; j++) {
      perm_t temp_perm = setdigit(setdigit(0, 0, i), 1, j);
      avoiderstoextend.push(prepareforavoidset(temp_perm, 2));
      //avoidset.add(prepareforavoidset(temp_perm, 2));
      avoidmap.add(prepareforavoidset(temp_perm, 2), &trivialmap);
    }
  }
  numavoiders[2] = base * base;

  for (int size = 2; size < maxsize; size++) { // build avoiders of length size + 1
    // cout<<numavoiders[size]<<endl;
    //cout<<size<<" ----------------"<<endl;
    for (int index = 0; index < numavoiders[size]; index++) {
      perm_t word = avoiderstoextend.front();
      avoiderstoextend.pop();
      uint64_t avoidbits = trivialmap; // first base bits are ones
      for (int killedpos = 0; killedpos < size && killedpos <= maxavoidsize; killedpos++) {
	perm_t shrunkword = killpos(word, killedpos);
	uint64_t bitmap_temp = *((uint64_t *)(avoidmap.getpayload(prepareforavoidset(shrunkword, size - 1))));
	avoidbits = avoidbits & bitmap_temp;
      }
      // still need to check if each of detected avoider might actually be a pattern:
      if (size + 1 <= maxavoidsize) {
	for (int addval = 0; addval < base; addval++) {
	  if ((avoidbits & (1 << addval)) != 0) {
	    perm_t newword = setdigit(word, size, addval);
	    perm_t wordaspattern = 0;
	    wordaspattern = wordfingerprint(newword, size + 1);
	    if (patternprintset.contains(wordaspattern)) {
	      avoidbits = avoidbits - (1 << addval); // was not an avoider after all
	    }
	  }
	}
      }
      // Now we have completely determined which extensions of word are avoiders
      if (size + 1 < maxsize) avoidmap.add(prepareforavoidset(word, size), &avoidbits);
      numavoiders[size + 1] += __builtin_popcount((uint32_t)avoidbits);
      if (size + 1 < maxsize) {
	for (int addval = 0; addval < base; addval++) {
	  if ((avoidbits & (1 << addval)) != 0) {
	    perm_t newword = setdigit(word, size, addval);
	    avoiderstoextend.push(newword);
	    //avoidset.add(prepareforavoidset(newword, size + 1));
	    //cout<<size + 1<<endl;
	    //displayperm(newword);
	  }
	}
      }
    }
  }
}

// REQUIREMENTS:
// patternlist contains patterns of size 8 or less (b/c of fingerprint function)
// base <= 31 and base <= max digit size in word (first requirement because of fingerprint function)
// Cannot have word comprised of 16 16s if using 64 bit permutation representation (hash table -1 error)
// maxwordsize <= number of digits we can store in word
void countavoidersfrompatternlist(string patternlist, int base, int maxwordsize, vector < uint64_t > &numavoiders) {
  hashdb patternprintset(1);
  numavoiders.resize(maxwordsize + 1);
  int maxpatternsize = 0;
  int pos = 0;
  perm_t word = 0;
  //cout<<"Pattern set: "<<endl;
  for (int i = 0; i < patternlist.size(); i++) {
    if (patternlist[i] == ' ') {
      patternprintset.add(wordfingerprint(word, pos));
      maxpatternsize = max(pos, maxpatternsize);
      pos = 0;
      word = 0;
    } else {
      word = setdigit(word, pos, (int)(patternlist[i] - '0' - 1));
      pos++;
    }
  }
  if (patternlist[patternlist.size() - 1] != ' ') { // if no space at end
    patternprintset.add(wordfingerprint(word, pos));
  }
  maxpatternsize = max(pos, maxpatternsize);

  wordavoiders_raw_dynamic(patternprintset, maxpatternsize, maxwordsize, numavoiders, base);
}

int main() {
  int maxwordsize = 10;
  int base = 7;
  string patternlist = "1234";
  vector < uint64_t > numavoiders; //(11);
  countavoidersfrompatternlist(patternlist, base, maxwordsize, numavoiders);
  //wordavoiders_raw_dynamic(patternprintset, 2, 10, numavoiders, 2);
  for (int i = 1; i <= maxwordsize; i++) {
    cout<<numavoiders[i]<<" ";
  }
  cout<<endl;
  return 0;
}
<commit_msg>improved documentation a bit<commit_after>// THIS FILE IS IN DEVELOPMENT AND IS NOT GUARANTEED TO DO ANYTHING!

#include <bitset>
#include <cassert>
#include <cmath>
#include <cstdint>
#include <cstdio>      /* printf, scanf, puts, NULL */
#include <cstdlib>
#include <cstring>
#include <ctime>
#include <iostream>
#include <fstream>
#include <cilk/cilk.h>
#include <cilk/reducer_opadd.h>
#include <cilk/reducer_list.h>

#include <queue>
#include <sys/time.h>
#include <vector>
#include "hashdb.h"
#include "hashmap.h"
//#include "wordavoidance.h"
#include "utilities.h"
#include "perm.h"
using namespace std;

// THINGS TO BE CAREFUL ABOUT:
// Words could now take val -1 if they are large, screwing up hash table. That includes fingerprint (but is not an issue in our current implementation for fingerprint).
// to distinguish words, DO need to know size. Thus avoidset and word fingerprint BOTH include this in their representatinos

// Returns the unique fingerprint of pattern represented by word
// Requires
// letters of value <= 31
// More importantly, never more than 7 letters preceeding another letter and larger than it (assuming uint64_t perm)
// Also size of word  + 1 < max allowed size of word
// SUFFICES to have letters of value <= 31 and word size 8 or less
perm_t wordfingerprint(perm_t word, int size) {
  perm_t print = setdigit(0, size, 1); // so that finger print marks size
  uint32_t seenletters = 0;
  for (int i = 0; i < size; i++) {
    unsigned long long reldig = 0;
    int digit = getdigit(word, i);
    unsigned int temp = seenletters >> (digit);
    reldig = 2*__builtin_popcount(temp);
    if ((seenletters & (1 << digit))  != 0) reldig--;
    // now relcount is count 2 * number larger digits + 1 if current digit also appears
    // have to be careful to do this because can have letters appearing multiple times
    seenletters = seenletters | (1 << digit);
    print = setdigit(print, i, reldig);
  }
  return print;
}

perm_t prepareforavoidset(perm_t word, int length) {
  return setdigit(word, length, 1); // mark length
}

// PATTERNS HAVE TO BE AT LEAST SIZE THREE DUE TO HOW AVOIDMAP IS SET UP
void wordavoiders_raw_dynamic(const hashdb &patternprintset, int maxavoidsize, int maxsize, vector < uint64_t > &numavoiders, int base) {
  hashdb avoidset = hashdb(1000);
  hashmap avoidmap(1<<8, 8);
  std::queue<perm_t> avoiderstoextend; // queue of avoiders built so far.
  //for (int i = 0; i < base; i++)  avoidset.add(prepareforavoidset(setdigit(0, 0, i), 1));
  uint64_t trivialmap = (((uint64_t)1) << base) - 1;
  for (int i = 0; i < base; i++)  avoidmap.add(prepareforavoidset(setdigit(0, 0, i), 1), &trivialmap);
  numavoiders[1] = base;

  for (int i = 0; i < base; i++) {
    for (int j = 0; j < base; j++) {
      perm_t temp_perm = setdigit(setdigit(0, 0, i), 1, j);
      avoiderstoextend.push(prepareforavoidset(temp_perm, 2));
      //avoidset.add(prepareforavoidset(temp_perm, 2));
      avoidmap.add(prepareforavoidset(temp_perm, 2), &trivialmap);
    }
  }
  numavoiders[2] = base * base;

  for (int size = 2; size < maxsize; size++) { // build avoiders of length size + 1
    // cout<<numavoiders[size]<<endl;
    //cout<<size<<" ----------------"<<endl;
    for (int index = 0; index < numavoiders[size]; index++) {
      perm_t word = avoiderstoextend.front();
      avoiderstoextend.pop();
      uint64_t avoidbits = trivialmap; // first base bits are ones
      for (int killedpos = 0; killedpos < size && killedpos <= maxavoidsize; killedpos++) {
	perm_t shrunkword = killpos(word, killedpos);
	uint64_t bitmap_temp = *((uint64_t *)(avoidmap.getpayload(prepareforavoidset(shrunkword, size - 1))));
	avoidbits = avoidbits & bitmap_temp;
      }
      // still need to check if each of detected avoider might actually be a pattern:
      if (size + 1 <= maxavoidsize) {
	// Not worth messing with bithacks to make this loop more efficient
	// since we only enter this if statement in small cases.
	for (int addval = 0; addval < base; addval++) {
	  if ((avoidbits & (1 << addval)) != 0) {
	    perm_t newword = setdigit(word, size, addval);
	    perm_t wordaspattern = 0;
	    wordaspattern = wordfingerprint(newword, size + 1);
	    if (patternprintset.contains(wordaspattern)) {
	      avoidbits = avoidbits - (1 << addval); // was not an avoider after all
	    }
	  }
	}
      }
      // Now we have completely determined which extensions of word are avoiders
      if (size + 1 < maxsize) avoidmap.add(prepareforavoidset(word, size), &avoidbits);
      numavoiders[size + 1] += __builtin_popcount((uint32_t)avoidbits);
      if (size + 1 < maxsize)
	for (int addval = 0; addval < base; addval++) {
	  // Probably not worth messing around with bit hacks to improve asymptoics on this for loop.
	  // In particular, if number of avoiders grows even sort of fast, then for the
	  // avoiders we push onto avoiderstoextend we're going to be doing enough work
	  // to amortize the wasted cost in this for loop.
	  if ((avoidbits & (1 << addval)) != 0) {
	    perm_t newword = setdigit(word, size, addval);
	    avoiderstoextend.push(newword);
	    //avoidset.add(prepareforavoidset(newword, size + 1));
	    //cout<<size + 1<<endl;
	    //displayperm(newword);
	  }
	}
      }
    }
  }
}

// REQUIREMENTS:
// patternlist contains patterns of size 8 or less (b/c of fingerprint function)
// base <= 31 and base <= max digit size in word (first requirement because of fingerprint function)
// Cannot have word comprised of 16 16s if using 64 bit permutation representation (hash table -1 error)
// maxwordsize <= number of digits we can store in word
void countavoidersfrompatternlist(string patternlist, int base, int maxwordsize, vector < uint64_t > &numavoiders) {
  hashdb patternprintset(1);
  numavoiders.resize(maxwordsize + 1);
  int maxpatternsize = 0;
  int pos = 0;
  perm_t word = 0;
  //cout<<"Pattern set: "<<endl;
  for (int i = 0; i < patternlist.size(); i++) {
    if (patternlist[i] == ' ') {
      patternprintset.add(wordfingerprint(word, pos));
      maxpatternsize = max(pos, maxpatternsize);
      pos = 0;
      word = 0;
    } else {
      word = setdigit(word, pos, (int)(patternlist[i] - '0' - 1));
      pos++;
    }
  }
  if (patternlist[patternlist.size() - 1] != ' ') { // if no space at end
    patternprintset.add(wordfingerprint(word, pos));
  }
  maxpatternsize = max(pos, maxpatternsize);

  wordavoiders_raw_dynamic(patternprintset, maxpatternsize, maxwordsize, numavoiders, base);
}

int main() {
  int maxwordsize = 10;
  int base = 7;
  string patternlist = "1234";
  vector < uint64_t > numavoiders; //(11);
  countavoidersfrompatternlist(patternlist, base, maxwordsize, numavoiders);
  //wordavoiders_raw_dynamic(patternprintset, 2, 10, numavoiders, 2);
  for (int i = 1; i <= maxwordsize; i++) {
    cout<<numavoiders[i]<<" ";
  }
  cout<<endl;
  return 0;
}
<|endoftext|>


<commit_before>#include "worker.hpp"

#include <boost/date_time/posix_time/posix_time.hpp>
#include <bitcoin/utility/logger.hpp>

#include <shared/zmq_message.hpp>

using namespace bc;
namespace posix_time = boost::posix_time;
using posix_time::milliseconds;
using posix_time::seconds;
using posix_time::microsec_clock;

const posix_time::time_duration heartbeat_interval = milliseconds(1000);
constexpr size_t interval_init = 4, interval_max = 32;

auto now = []() { return microsec_clock::universal_time(); };

bool send_string(zmq::socket_t& socket, const std::string& str)
{
    zmq::message_t message(str.size());
    char* msg_begin = reinterpret_cast<char*>(message.data());
    std::copy(str.begin(), str.end(), msg_begin);
    return socket.send(message);
}

request_worker::request_worker()
  : context_(1)
{
    create_new_socket();
    last_heartbeat_ = now();
    heartbeat_at_ = now() + heartbeat_interval;
    interval_ = interval_init;
}

void request_worker::create_new_socket()
{
    socket_ = std::make_shared<zmq::socket_t>(context_, ZMQ_DEALER);
    socket_->connect("tcp://localhost:5556");
    // Configure socket to not wait at close time
    int linger = 0;
    socket_->setsockopt(ZMQ_LINGER, &linger, sizeof (linger));
    // Tell queue we're ready for work
    log_info() << "I: worker ready";
    send_string(*socket_, "READY");
}

void request_worker::attach(
    const std::string& command, command_handler handler)
{
    handlers_[command] = handler;
}

void request_worker::update()
{
    zmq::pollitem_t items [] = { { *socket_,  0, ZMQ_POLLIN, 0 } };
    zmq::poll(items, 1, 0);

    if (items [0].revents & ZMQ_POLLIN)
    {
        // Get message
        // - 6-part envelope + content -> request
        // - 1-part "HEARTBEAT" -> heartbeat
        incoming_message request;
        request.recv(*socket_);

        if (!request.is_signal())
        {
            last_heartbeat_ = now();
            auto it = handlers_.find(request.command());
            // Perform request if found.
            if (it != handlers_.end())
            {
                log_info() << "I: normal reply";
                it->second(request, socket_);
            }
            else
            {
                log_warning() << "Unhandled command '"
                    << request.command() << "'";
            }
        }
        else if (request.command() == "HEARTBEAT")
        {
            last_heartbeat_ = now();
        }
        else
        {
            log_warning() << "E: invalid message";
        }
        interval_ = interval_init;
    }
    else if (now() - last_heartbeat_ > seconds(interval_))
    {
        log_warning() << "W: heartbeat failure, can't reach queue";
        log_warning() << "W: reconnecting in " << interval_ << " seconds...";

        if (interval_ < interval_max)
        {
            interval_ *= 2;
        }
        create_new_socket();
        last_heartbeat_ = now();
    }

    // Send heartbeat to queue if it's time
    if (now() > heartbeat_at_)
    {
        heartbeat_at_ = now() + heartbeat_interval;
        log_info() << "I: worker heartbeat";
        send_string(*socket_, "HEARTBEAT");
    }
}

<commit_msg>use proper logging facilities for worker.<commit_after>#include "worker.hpp"

#include <boost/date_time/posix_time/posix_time.hpp>
#include <bitcoin/utility/logger.hpp>

#include <shared/zmq_message.hpp>
#include "echo.hpp"

using namespace bc;
namespace posix_time = boost::posix_time;
using posix_time::milliseconds;
using posix_time::seconds;
using posix_time::microsec_clock;

const posix_time::time_duration heartbeat_interval = milliseconds(1000);
constexpr size_t interval_init = 4, interval_max = 32;

auto now = []() { return microsec_clock::universal_time(); };

bool send_string(zmq::socket_t& socket, const std::string& str)
{
    zmq::message_t message(str.size());
    char* msg_begin = reinterpret_cast<char*>(message.data());
    std::copy(str.begin(), str.end(), msg_begin);
    return socket.send(message);
}

request_worker::request_worker()
  : context_(1)
{
    create_new_socket();
    last_heartbeat_ = now();
    heartbeat_at_ = now() + heartbeat_interval;
    interval_ = interval_init;
}

void request_worker::create_new_socket()
{
    socket_ = std::make_shared<zmq::socket_t>(context_, ZMQ_DEALER);
    socket_->connect("tcp://localhost:5556");
    // Configure socket to not wait at close time
    int linger = 0;
    socket_->setsockopt(ZMQ_LINGER, &linger, sizeof (linger));
    // Tell queue we're ready for work
    log_info(LOG_WORKER) << "worker ready";
    send_string(*socket_, "READY");
}

void request_worker::attach(
    const std::string& command, command_handler handler)
{
    handlers_[command] = handler;
}

void request_worker::update()
{
    zmq::pollitem_t items [] = { { *socket_,  0, ZMQ_POLLIN, 0 } };
    zmq::poll(items, 1, 0);

    if (items [0].revents & ZMQ_POLLIN)
    {
        // Get message
        // - 6-part envelope + content -> request
        // - 1-part "HEARTBEAT" -> heartbeat
        incoming_message request;
        request.recv(*socket_);

        if (!request.is_signal())
        {
            last_heartbeat_ = now();
            auto it = handlers_.find(request.command());
            // Perform request if found.
            if (it != handlers_.end())
            {
                log_info(LOG_WORKER) << "normal reply";
                it->second(request, socket_);
            }
            else
            {
                log_warning(LOG_WORKER) << "Unhandled command '"
                    << request.command() << "'";
            }
        }
        else if (request.command() == "HEARTBEAT")
        {
            last_heartbeat_ = now();
        }
        else
        {
            log_warning(LOG_WORKER) << "invalid message";
        }
        interval_ = interval_init;
    }
    else if (now() - last_heartbeat_ > seconds(interval_))
    {
        log_warning(LOG_WORKER) << "heartbeat failure, can't reach queue";
        log_warning(LOG_WORKER) << "reconnecting in "
            << interval_ << " seconds...";

        if (interval_ < interval_max)
        {
            interval_ *= 2;
        }
        create_new_socket();
        last_heartbeat_ = now();
    }

    // Send heartbeat to queue if it's time
    if (now() > heartbeat_at_)
    {
        heartbeat_at_ = now() + heartbeat_interval;
        log_info(LOG_WORKER) << "worker heartbeat";
        send_string(*socket_, "HEARTBEAT");
    }
}

<|endoftext|>


<commit_before>
#include "cmdline/cmdline.h"
#include "mhap/overlap.h"
#include "mhap/parser.h"
#include "ra/include/ra/ra.hpp"
#include <algorithm>
#include <fstream>
#include <iostream>
#include <vector>

using std::cerr;
using std::cin;
using std::cout;
using std::endl;
using std::fstream;
using std::max;
using std::string;
using std::vector;

// map reads so we can access reads with mapped[read_id]
void map_reads(vector<Read*>* mapped, vector<Read*>& reads) {

  int max_id = -1;
  for (auto r: reads) {
    max_id = max(max_id, r->getId());
  }

  mapped->resize(max_id + 1, nullptr);
  for (auto r: reads) {
    (*mapped)[r->getId()] = r;
  }
}

int main(int argc, char **argv) {

  cmdline::parser args;
  args.add<string>("reads", 'r', "reads file", true);
  args.add<string>("overlaps", 'x', "overlaps file", true);
  args.add<bool>("verbose", 'v', "verbose output", false);
  args.add<string>("overlaps_format", 'f', "overlaps file format; supported: afg, mhap", false, "afg");
  args.parse_check(argc, argv);

  const int thread_num = std::max(std::thread::hardware_concurrency(), 1U);
  const string format = args.get<string>("overlaps_format");
  const string reads_filename = args.get<string>("reads");
  const string overlaps_filename = args.get<string>("overlaps");
  const bool verbose_output = args.get<bool>("verbose");

  vector<Overlap*> overlaps, filtered;
  vector<Read*> reads;
  vector<Read*> reads_mapped;

  readAfgReads(reads, reads_filename.c_str());
  map_reads(&reads_mapped, reads);

  std::cerr << "Read " << reads.size() << " reads" << std::endl;

  if (format == "afg") {
    readAfgOverlaps(overlaps, overlaps_filename.c_str());
  } else if (format == "mhap") {
    fstream overlaps_file(overlaps_filename);
    MHAP::read_overlaps(overlaps_file, &overlaps);
    overlaps_file.close();
  }

  for (auto o: overlaps) {
    const auto a = o->getA();
    const auto b = o->getB();
    assert(reads_mapped[a] != nullptr);
    assert(reads_mapped[b] != nullptr);
  }

  vector<Overlap*> nocontainments;
  filterContainedOverlaps(nocontainments, overlaps, reads_mapped, true);

  {
    int filtered = nocontainments.size() - overlaps.size();
    cerr << "Removed " << filtered << " overlaps as contained "
      << "(" << (1.*filtered)/overlaps.size() << ")" << endl;
  }

  if (verbose_output) {
    writeAfgOverlaps(nocontainments, "nocont.afg");
  }

  vector<Overlap*> notransitives;
  filterTransitiveOverlaps(notransitives, nocontainments, thread_num, true);

  {
    int filtered = notransitives.size() - nocontainments.size();
    cerr << "Removed " << filtered << " overlaps as transitive "
      << "(" << (1.*filtered)/nocontainments.size() << ")" << endl;
  }

  if (verbose_output) {
    writeAfgOverlaps(notransitives, "nocont.notran.afg");
  }

  createReverseComplements(reads, thread_num);

  StringGraph* graph = new StringGraph(reads, notransitives);
  graph->simplify();

  std::vector<StringGraphComponent*> components;
  graph->extractComponents(components);

  std::vector<Contig*> contigs;

  for (const auto& component : components) {

    Contig* contig = component->createContig();

    if (contig != nullptr) {
      contigs.emplace_back(contig);
    }
  }

  std::cerr << "number of contigs " << contigs.size() << std::endl;

  writeAfgContigs(contigs, "contigs.afg");

  for (auto r: reads)      delete r;
  for (auto o: overlaps)   delete o;
  for (auto c: components) delete c;
  for (auto c: contigs)    delete c;

  delete graph;

  return 0;
}
<commit_msg>make stats positive<commit_after>
#include "cmdline/cmdline.h"
#include "mhap/overlap.h"
#include "mhap/parser.h"
#include "ra/include/ra/ra.hpp"
#include <algorithm>
#include <fstream>
#include <iostream>
#include <vector>

using std::cerr;
using std::cin;
using std::cout;
using std::endl;
using std::fstream;
using std::max;
using std::string;
using std::vector;

// map reads so we can access reads with mapped[read_id]
void map_reads(vector<Read*>* mapped, vector<Read*>& reads) {

  int max_id = -1;
  for (auto r: reads) {
    max_id = max(max_id, r->getId());
  }

  mapped->resize(max_id + 1, nullptr);
  for (auto r: reads) {
    (*mapped)[r->getId()] = r;
  }
}

int main(int argc, char **argv) {

  cmdline::parser args;
  args.add<string>("reads", 'r', "reads file", true);
  args.add<string>("overlaps", 'x', "overlaps file", true);
  args.add<bool>("verbose", 'v', "verbose output", false);
  args.add<string>("overlaps_format", 'f', "overlaps file format; supported: afg, mhap", false, "afg");
  args.parse_check(argc, argv);

  const int thread_num = std::max(std::thread::hardware_concurrency(), 1U);
  const string format = args.get<string>("overlaps_format");
  const string reads_filename = args.get<string>("reads");
  const string overlaps_filename = args.get<string>("overlaps");
  const bool verbose_output = args.get<bool>("verbose");

  vector<Overlap*> overlaps, filtered;
  vector<Read*> reads;
  vector<Read*> reads_mapped;

  readAfgReads(reads, reads_filename.c_str());
  map_reads(&reads_mapped, reads);

  std::cerr << "Read " << reads.size() << " reads" << std::endl;

  if (format == "afg") {
    readAfgOverlaps(overlaps, overlaps_filename.c_str());
  } else if (format == "mhap") {
    fstream overlaps_file(overlaps_filename);
    MHAP::read_overlaps(overlaps_file, &overlaps);
    overlaps_file.close();
  }

  for (auto o: overlaps) {
    const auto a = o->getA();
    const auto b = o->getB();
    assert(reads_mapped[a] != nullptr);
    assert(reads_mapped[b] != nullptr);
  }

  vector<Overlap*> nocontainments;
  filterContainedOverlaps(nocontainments, overlaps, reads_mapped, true);

  {
    int filtered =  overlaps.size() - nocontainments.size();
    cerr << "Removed " << filtered << " overlaps as contained "
      << "(" << (1.*filtered)/overlaps.size() << ")" << endl;
  }

  if (verbose_output) {
    writeAfgOverlaps(nocontainments, "nocont.afg");
  }

  vector<Overlap*> notransitives;
  filterTransitiveOverlaps(notransitives, nocontainments, thread_num, true);

  {
    int filtered = nocontainments.size() - notransitives.size();
    cerr << "Removed " << filtered << " overlaps as transitive "
      << "(" << (1.*filtered)/nocontainments.size() << ")" << endl;
  }

  if (verbose_output) {
    writeAfgOverlaps(notransitives, "nocont.notran.afg");
  }

  createReverseComplements(reads, thread_num);

  StringGraph* graph = new StringGraph(reads, notransitives);
  graph->simplify();

  std::vector<StringGraphComponent*> components;
  graph->extractComponents(components);

  std::vector<Contig*> contigs;

  for (const auto& component : components) {

    Contig* contig = component->createContig();

    if (contig != nullptr) {
      contigs.emplace_back(contig);
    }
  }

  std::cerr << "number of contigs " << contigs.size() << std::endl;

  writeAfgContigs(contigs, "contigs.afg");

  for (auto r: reads)      delete r;
  for (auto o: overlaps)   delete o;
  for (auto c: components) delete c;
  for (auto c: contigs)    delete c;

  delete graph;

  return 0;
}
<|endoftext|>