<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) 2010-2012 Francois Beaune, Jupiter Jazz Limited
//
// 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 "genericsamplerenderer.h"

// appleseed.renderer headers.
#include "renderer/kernel/intersection/intersector.h"
#include "renderer/kernel/intersection/tracecontext.h"
#include "renderer/kernel/lighting/ilightingengine.h"
#include "renderer/kernel/shading/shadingcontext.h"
#include "renderer/kernel/shading/shadingengine.h"
#include "renderer/kernel/shading/shadingpoint.h"
#include "renderer/kernel/shading/shadingray.h"
#include "renderer/kernel/shading/shadingresult.h"
#include "renderer/kernel/texturing/texturecache.h"
#include "renderer/modeling/camera/camera.h"
#include "renderer/modeling/frame/frame.h"
#include "renderer/modeling/scene/scene.h"

using namespace foundation;
using namespace std;

namespace renderer
{

namespace
{
    //
    // Generic sample renderer.
    //

    // If defined, the texture cache returns solid tiles whose color depends on whether
    // the requested tile could be found in the cache or not, and if it was found, at
    // which level it was found.
    #undef DEBUG_DISPLAY_TEXTURE_CACHE_PERFORMANCES

    class GenericSampleRenderer
      : public ISampleRenderer
    {
      public:
        GenericSampleRenderer(
            const Scene&            scene,
            const Frame&            frame,
            const TraceContext&     trace_context,
            TextureStore&           texture_store,
            ILightingEngineFactory* lighting_engine_factory,
            ShadingEngine&          shading_engine,
            const ParamArray&       params)
          : m_params(params)
          , m_scene(scene)
          , m_lighting_conditions(frame.get_lighting_conditions())
          , m_opacity_threshold(1.0f - m_params.m_transparency_threshold)
          , m_texture_cache(texture_store)
          , m_intersector(trace_context, m_texture_cache, true, m_params.m_report_self_intersections)
          , m_lighting_engine(lighting_engine_factory->create())
          , m_shading_engine(shading_engine)
        {
        }

        ~GenericSampleRenderer()
        {
            m_lighting_engine->release();
        }

        virtual void release()
        {
            delete this;
        }

        virtual void render_sample(
            SamplingContext&        sampling_context,
            const Vector2d&         image_point,        // point in image plane, in NDC
            ShadingResult&          shading_result)
        {
#ifdef DEBUG_DISPLAY_TEXTURE_CACHE_PERFORMANCES

            const uint64 initial_texcache_s0_hit_count = m_texture_cache.get_stage0_hit_count();
            const uint64 initial_texcache_s1_hit_count = m_texture_cache.get_stage1_hit_count();
            const uint64 initial_texcache_s1_miss_count = m_texture_cache.get_stage1_miss_count();

#endif

            // Construct a shading context.
            ShadingContext shading_context(
                m_intersector,
                m_texture_cache,
                m_lighting_engine,
                m_params.m_transparency_threshold,
                m_params.m_max_iterations);

            // Construct a primary ray.
            ShadingRay primary_ray;
            m_scene.get_camera()->generate_ray(
                sampling_context,
                image_point,
                primary_ray);

            ShadingPoint shading_points[2];
            size_t shading_point_index = 0;
            const ShadingPoint* shading_point_ptr = 0;
            size_t iterations = 0;

            while (true)
            {
                // Put a hard limit on the number of iterations.
                if (++iterations >= m_params.m_max_iterations)
                {
                    RENDERER_LOG_WARNING(
                        "reached hard iteration limit (%s), breaking primary ray trace loop.",
                        pretty_int(m_params.m_max_iterations).c_str());
                    break;
                }

                // Trace the ray.
                shading_points[shading_point_index].clear();
                m_intersector.trace(
                    primary_ray,
                    shading_points[shading_point_index],
                    shading_point_ptr);

                // Update the pointers to the shading points.
                shading_point_ptr = &shading_points[shading_point_index];
                shading_point_index = 1 - shading_point_index;

                if (iterations == 1)
                {
                    // Shade the intersection point.
                    m_shading_engine.shade(
                        sampling_context,
                        shading_context,
                        *shading_point_ptr,
                        shading_result);

                    // Transform the result to the linear RGB color space.
                    shading_result.transform_to_linear_rgb(m_lighting_conditions);
                }
                else
                {
                    // Shade the intersection point.
                    ShadingResult local_result;
                    local_result.m_aovs.set_size(shading_result.m_aovs.size());
                    m_shading_engine.shade(
                        sampling_context,
                        shading_context,
                        *shading_point_ptr,
                        local_result);

                    // Transform the result to the linear RGB color space.
                    local_result.transform_to_linear_rgb(m_lighting_conditions);

                    // "Over" alpha compositing.
                    shading_result.composite_over(local_result);
                }

                // Stop once we hit the environment.
                if (!shading_point_ptr->hit())
                    break;

                // Stop once we hit full opacity.
                if (max_value(shading_result.m_alpha) > m_opacity_threshold)
                    break;

                // Move the ray origin to the intersection point.
                primary_ray.m_org = shading_point_ptr->get_point();
                primary_ray.m_tmax = numeric_limits<double>::max();
            }

#ifdef DEBUG_DISPLAY_TEXTURE_CACHE_PERFORMANCES

            const Vector<uint64, 3> texcache_stats(
                m_texture_cache.get_stage0_hit_count() - initial_texcache_s0_hit_count,
                m_texture_cache.get_stage1_hit_count() - initial_texcache_s1_hit_count,
                m_texture_cache.get_stage1_miss_count() - initial_texcache_s1_miss_count);

            if (texcache_stats == Vector<uint64, 3>(0, 0, 0))
            {
                // In black: no access to the texture cache.
                shading_result.set_to_linear_rgb(Color3f(0.0f, 0.0f, 0.0f));
            }
            else
            {
                switch (max_index(texcache_stats))
                {
                  // In green: a majority of stage-0 cache hits.
                  case 0:
                    shading_result.set_to_linear_rgb(Color3f(0.0f, 1.0f, 0.0f));
                    break;

                  // In blue: a majority of stage-0 cache misses and stage-1 cache hits.
                  case 1:
                    shading_result.set_to_linear_rgb(Color3f(0.0f, 0.0f, 1.0f));
                    break;

                  // In red: a majority of stage-0 and stage-1 cache misses.
                  case 2:
                    shading_result.set_to_linear_rgb(Color3f(1.0f, 0.0f, 0.0f));
                    break;
                }
            }

#endif
        }

      private:
        struct Parameters
        {
            const float     m_transparency_threshold;
            const size_t    m_max_iterations;
            const bool      m_report_self_intersections;

            explicit Parameters(const ParamArray& params)
              : m_transparency_threshold(params.get_optional<float>("transparency_threshold", 0.001f))
              , m_max_iterations(params.get_optional<size_t>("max_iterations", 10000))
              , m_report_self_intersections(params.get_optional<bool>("report_self_intersections", false))
            {
            }
        };

        const Parameters            m_params;
        const Scene&                m_scene;
        const LightingConditions&   m_lighting_conditions;
        const float                 m_opacity_threshold;

        TextureCache                m_texture_cache;
        Intersector                 m_intersector;
        ILightingEngine*            m_lighting_engine;
        ShadingEngine&              m_shading_engine;
    };
}

//
// GenericSampleRendererFactory class implementation.
//

GenericSampleRendererFactory::GenericSampleRendererFactory(
    const Scene&            scene,
    const Frame&            frame,
    const TraceContext&     trace_context,
    TextureStore&           texture_store,
    ILightingEngineFactory* lighting_engine_factory,
    ShadingEngine&          shading_engine,
    const ParamArray&       params)
  : m_scene(scene)
  , m_frame(frame)
  , m_trace_context(trace_context)
  , m_texture_store(texture_store)
  , m_lighting_engine_factory(lighting_engine_factory)
  , m_shading_engine(shading_engine)
  , m_params(params)
{
}

void GenericSampleRendererFactory::release()
{
    delete this;
}

ISampleRenderer* GenericSampleRendererFactory::create()
{
    return
        new GenericSampleRenderer(
            m_scene,
            m_frame,
            m_trace_context,
            m_texture_store,
            m_lighting_engine_factory,
            m_shading_engine,
            m_params);
}

ISampleRenderer* GenericSampleRendererFactory::create(
    const Scene&            scene,
    const Frame&            frame,
    const TraceContext&     trace_context,
    TextureStore&           texture_store,
    ILightingEngineFactory* lighting_engine_factory,
    ShadingEngine&          shading_engine,
    const ParamArray&       params)
{
    return
        new GenericSampleRenderer(
            scene,
            frame,
            trace_context,
            texture_store,
            lighting_engine_factory,
            shading_engine,
            params);
}

}   // namespace renderer
<commit_msg>bug fix: alpha composition for first hits was missing after commit e4815cdc1ab37bfa2d764350116776b21bc5f8f2 ("don't perform sampling compositing for the first layer").<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) 2010-2012 Francois Beaune, Jupiter Jazz Limited
//
// 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 "genericsamplerenderer.h"

// appleseed.renderer headers.
#include "renderer/kernel/intersection/intersector.h"
#include "renderer/kernel/intersection/tracecontext.h"
#include "renderer/kernel/lighting/ilightingengine.h"
#include "renderer/kernel/shading/shadingcontext.h"
#include "renderer/kernel/shading/shadingengine.h"
#include "renderer/kernel/shading/shadingpoint.h"
#include "renderer/kernel/shading/shadingray.h"
#include "renderer/kernel/shading/shadingresult.h"
#include "renderer/kernel/texturing/texturecache.h"
#include "renderer/modeling/camera/camera.h"
#include "renderer/modeling/frame/frame.h"
#include "renderer/modeling/scene/scene.h"

using namespace foundation;
using namespace std;

namespace renderer
{

namespace
{
    //
    // Generic sample renderer.
    //

    // If defined, the texture cache returns solid tiles whose color depends on whether
    // the requested tile could be found in the cache or not, and if it was found, at
    // which level it was found.
    #undef DEBUG_DISPLAY_TEXTURE_CACHE_PERFORMANCES

    class GenericSampleRenderer
      : public ISampleRenderer
    {
      public:
        GenericSampleRenderer(
            const Scene&            scene,
            const Frame&            frame,
            const TraceContext&     trace_context,
            TextureStore&           texture_store,
            ILightingEngineFactory* lighting_engine_factory,
            ShadingEngine&          shading_engine,
            const ParamArray&       params)
          : m_params(params)
          , m_scene(scene)
          , m_lighting_conditions(frame.get_lighting_conditions())
          , m_opacity_threshold(1.0f - m_params.m_transparency_threshold)
          , m_texture_cache(texture_store)
          , m_intersector(trace_context, m_texture_cache, true, m_params.m_report_self_intersections)
          , m_lighting_engine(lighting_engine_factory->create())
          , m_shading_engine(shading_engine)
        {
        }

        ~GenericSampleRenderer()
        {
            m_lighting_engine->release();
        }

        virtual void release()
        {
            delete this;
        }

        virtual void render_sample(
            SamplingContext&        sampling_context,
            const Vector2d&         image_point,        // point in image plane, in NDC
            ShadingResult&          shading_result)
        {
#ifdef DEBUG_DISPLAY_TEXTURE_CACHE_PERFORMANCES

            const uint64 initial_texcache_s0_hit_count = m_texture_cache.get_stage0_hit_count();
            const uint64 initial_texcache_s1_hit_count = m_texture_cache.get_stage1_hit_count();
            const uint64 initial_texcache_s1_miss_count = m_texture_cache.get_stage1_miss_count();

#endif

            // Construct a shading context.
            ShadingContext shading_context(
                m_intersector,
                m_texture_cache,
                m_lighting_engine,
                m_params.m_transparency_threshold,
                m_params.m_max_iterations);

            // Construct a primary ray.
            ShadingRay primary_ray;
            m_scene.get_camera()->generate_ray(
                sampling_context,
                image_point,
                primary_ray);

            ShadingPoint shading_points[2];
            size_t shading_point_index = 0;
            const ShadingPoint* shading_point_ptr = 0;
            size_t iterations = 0;

            while (true)
            {
                // Put a hard limit on the number of iterations.
                if (++iterations >= m_params.m_max_iterations)
                {
                    RENDERER_LOG_WARNING(
                        "reached hard iteration limit (%s), breaking primary ray trace loop.",
                        pretty_int(m_params.m_max_iterations).c_str());
                    break;
                }

                // Trace the ray.
                shading_points[shading_point_index].clear();
                m_intersector.trace(
                    primary_ray,
                    shading_points[shading_point_index],
                    shading_point_ptr);

                // Update the pointers to the shading points.
                shading_point_ptr = &shading_points[shading_point_index];
                shading_point_index = 1 - shading_point_index;

                if (iterations == 1)
                {
                    // Shade the intersection point.
                    m_shading_engine.shade(
                        sampling_context,
                        shading_context,
                        *shading_point_ptr,
                        shading_result);

                    // Transform the result to the linear RGB color space.
                    shading_result.transform_to_linear_rgb(m_lighting_conditions);

                    // Apply alpha.
                    if (shading_point_ptr->hit())
                        shading_result.m_color *= shading_result.m_alpha[0];
                }
                else
                {
                    // Shade the intersection point.
                    ShadingResult local_result;
                    local_result.m_aovs.set_size(shading_result.m_aovs.size());
                    m_shading_engine.shade(
                        sampling_context,
                        shading_context,
                        *shading_point_ptr,
                        local_result);

                    // Transform the result to the linear RGB color space.
                    local_result.transform_to_linear_rgb(m_lighting_conditions);

                    // "Over" alpha compositing.
                    shading_result.composite_over(local_result);
                }

                // Stop once we hit the environment.
                if (!shading_point_ptr->hit())
                    break;

                // Stop once we hit full opacity.
                if (max_value(shading_result.m_alpha) > m_opacity_threshold)
                    break;

                // Move the ray origin to the intersection point.
                primary_ray.m_org = shading_point_ptr->get_point();
                primary_ray.m_tmax = numeric_limits<double>::max();
            }

#ifdef DEBUG_DISPLAY_TEXTURE_CACHE_PERFORMANCES

            const Vector<uint64, 3> texcache_stats(
                m_texture_cache.get_stage0_hit_count() - initial_texcache_s0_hit_count,
                m_texture_cache.get_stage1_hit_count() - initial_texcache_s1_hit_count,
                m_texture_cache.get_stage1_miss_count() - initial_texcache_s1_miss_count);

            if (texcache_stats == Vector<uint64, 3>(0, 0, 0))
            {
                // In black: no access to the texture cache.
                shading_result.set_to_linear_rgb(Color3f(0.0f, 0.0f, 0.0f));
            }
            else
            {
                switch (max_index(texcache_stats))
                {
                  // In green: a majority of stage-0 cache hits.
                  case 0:
                    shading_result.set_to_linear_rgb(Color3f(0.0f, 1.0f, 0.0f));
                    break;

                  // In blue: a majority of stage-0 cache misses and stage-1 cache hits.
                  case 1:
                    shading_result.set_to_linear_rgb(Color3f(0.0f, 0.0f, 1.0f));
                    break;

                  // In red: a majority of stage-0 and stage-1 cache misses.
                  case 2:
                    shading_result.set_to_linear_rgb(Color3f(1.0f, 0.0f, 0.0f));
                    break;
                }
            }

#endif
        }

      private:
        struct Parameters
        {
            const float     m_transparency_threshold;
            const size_t    m_max_iterations;
            const bool      m_report_self_intersections;

            explicit Parameters(const ParamArray& params)
              : m_transparency_threshold(params.get_optional<float>("transparency_threshold", 0.001f))
              , m_max_iterations(params.get_optional<size_t>("max_iterations", 10000))
              , m_report_self_intersections(params.get_optional<bool>("report_self_intersections", false))
            {
            }
        };

        const Parameters            m_params;
        const Scene&                m_scene;
        const LightingConditions&   m_lighting_conditions;
        const float                 m_opacity_threshold;

        TextureCache                m_texture_cache;
        Intersector                 m_intersector;
        ILightingEngine*            m_lighting_engine;
        ShadingEngine&              m_shading_engine;
    };
}

//
// GenericSampleRendererFactory class implementation.
//

GenericSampleRendererFactory::GenericSampleRendererFactory(
    const Scene&            scene,
    const Frame&            frame,
    const TraceContext&     trace_context,
    TextureStore&           texture_store,
    ILightingEngineFactory* lighting_engine_factory,
    ShadingEngine&          shading_engine,
    const ParamArray&       params)
  : m_scene(scene)
  , m_frame(frame)
  , m_trace_context(trace_context)
  , m_texture_store(texture_store)
  , m_lighting_engine_factory(lighting_engine_factory)
  , m_shading_engine(shading_engine)
  , m_params(params)
{
}

void GenericSampleRendererFactory::release()
{
    delete this;
}

ISampleRenderer* GenericSampleRendererFactory::create()
{
    return
        new GenericSampleRenderer(
            m_scene,
            m_frame,
            m_trace_context,
            m_texture_store,
            m_lighting_engine_factory,
            m_shading_engine,
            m_params);
}

ISampleRenderer* GenericSampleRendererFactory::create(
    const Scene&            scene,
    const Frame&            frame,
    const TraceContext&     trace_context,
    TextureStore&           texture_store,
    ILightingEngineFactory* lighting_engine_factory,
    ShadingEngine&          shading_engine,
    const ParamArray&       params)
{
    return
        new GenericSampleRenderer(
            scene,
            frame,
            trace_context,
            texture_store,
            lighting_engine_factory,
            shading_engine,
            params);
}

}   // namespace renderer
<|endoftext|>


<commit_before>/*
 * Copyright (C) 2018-present ScyllaDB
 */

/*
 * This file is part of Scylla.
 *
 * Scylla is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * Scylla 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 Scylla.  If not, see <http://www.gnu.org/licenses/>.
 */

#include "vint-serialization.hh"
#include "sstables/consumer.hh"

#include "bytes.hh"
#include "utils/buffer_input_stream.hh"
#include "test/lib/reader_concurrency_semaphore.hh"
#include "test/lib/random_utils.hh"

#include <boost/test/unit_test.hpp>
#include <seastar/core/iostream.hh>
#include <seastar/core/temporary_buffer.hh>
#include <seastar/core/thread.hh>
#include <seastar/testing/test_case.hh>
#include <seastar/testing/thread_test_case.hh>
#include <random>

namespace {

class test_consumer final : public data_consumer::continuous_data_consumer<test_consumer> {
    static const int MULTIPLIER = 10;
    uint64_t _tested_value;
    int _state = 0;
    int _count = 0;

    void check(uint64_t got) {
        BOOST_REQUIRE_EQUAL(_tested_value, got);
    }

    static uint64_t calculate_length(uint64_t tested_value) {
        return MULTIPLIER * unsigned_vint::serialized_size(tested_value);
    }

    static input_stream<char> prepare_stream(uint64_t tested_value) {
        temporary_buffer<char> buf(calculate_length(tested_value));
        int pos = 0;
        bytes::value_type* out = reinterpret_cast<bytes::value_type*>(buf.get_write());
        for (int i = 0; i < MULTIPLIER; ++i) {
            pos += unsigned_vint::serialize(tested_value, out + pos);
        }
        return make_buffer_input_stream(std::move(buf), [] {return 1;});
    }

public:
    test_consumer(reader_permit permit, uint64_t tested_value)
        : continuous_data_consumer(std::move(permit), prepare_stream(tested_value), 0, calculate_length(tested_value))
        , _tested_value(tested_value)
    { }

    bool non_consuming() { return false; }

    void verify_end_state() {}

    data_consumer::processing_result process_state(temporary_buffer<char>& data) {
        switch (_state) {
        case 0:
            if (read_unsigned_vint(data) != read_status::ready) {
                _state = 1;
                break;
            }
            // fall-through
        case 1:
            check(_u64);
            ++_count;
            _state = _count < MULTIPLIER ? 0 : 2;
            break;
        default:
            BOOST_FAIL("wrong consumer state");
        }
        return _state == 2 ? data_consumer::proceed::no : data_consumer::proceed::yes;
    }

    void run() {
        consume_input().get();
    }
};

}

SEASTAR_THREAD_TEST_CASE(test_read_unsigned_vint) {
    tests::reader_concurrency_semaphore_wrapper semaphore;

    auto nr_tests =
#ifdef SEASTAR_DEBUG
            10
#else
            1000
#endif
            ;
    test_consumer(semaphore.make_permit(), 0).run();
    for (int highest_bit = 0; highest_bit < 64; ++highest_bit) {
        uint64_t tested_value = uint64_t{1} << highest_bit;
        for (int i = 0; i < nr_tests; ++i) {
            test_consumer(semaphore.make_permit(), tested_value + tests::random::get_int<uint64_t>(tested_value - 1)).run();
        }
    }
}

<commit_msg>test: continuous_data_consumer_test: mark permit as used<commit_after>/*
 * Copyright (C) 2018-present ScyllaDB
 */

/*
 * This file is part of Scylla.
 *
 * Scylla is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * Scylla 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 Scylla.  If not, see <http://www.gnu.org/licenses/>.
 */

#include "vint-serialization.hh"
#include "sstables/consumer.hh"

#include "bytes.hh"
#include "utils/buffer_input_stream.hh"
#include "test/lib/reader_concurrency_semaphore.hh"
#include "test/lib/random_utils.hh"

#include <boost/test/unit_test.hpp>
#include <seastar/core/iostream.hh>
#include <seastar/core/temporary_buffer.hh>
#include <seastar/core/thread.hh>
#include <seastar/testing/test_case.hh>
#include <seastar/testing/thread_test_case.hh>
#include <random>

namespace {

class test_consumer final : public data_consumer::continuous_data_consumer<test_consumer> {
    static const int MULTIPLIER = 10;
    uint64_t _tested_value;
    int _state = 0;
    int _count = 0;
    reader_permit::used_guard _used_guard;

    void check(uint64_t got) {
        BOOST_REQUIRE_EQUAL(_tested_value, got);
    }

    static uint64_t calculate_length(uint64_t tested_value) {
        return MULTIPLIER * unsigned_vint::serialized_size(tested_value);
    }

    static input_stream<char> prepare_stream(uint64_t tested_value) {
        temporary_buffer<char> buf(calculate_length(tested_value));
        int pos = 0;
        bytes::value_type* out = reinterpret_cast<bytes::value_type*>(buf.get_write());
        for (int i = 0; i < MULTIPLIER; ++i) {
            pos += unsigned_vint::serialize(tested_value, out + pos);
        }
        return make_buffer_input_stream(std::move(buf), [] {return 1;});
    }

public:
    test_consumer(reader_permit permit, uint64_t tested_value)
        : continuous_data_consumer(std::move(permit), prepare_stream(tested_value), 0, calculate_length(tested_value))
        , _tested_value(tested_value)
        , _used_guard(_permit)
    { }

    bool non_consuming() { return false; }

    void verify_end_state() {}

    data_consumer::processing_result process_state(temporary_buffer<char>& data) {
        switch (_state) {
        case 0:
            if (read_unsigned_vint(data) != read_status::ready) {
                _state = 1;
                break;
            }
            // fall-through
        case 1:
            check(_u64);
            ++_count;
            _state = _count < MULTIPLIER ? 0 : 2;
            break;
        default:
            BOOST_FAIL("wrong consumer state");
        }
        return _state == 2 ? data_consumer::proceed::no : data_consumer::proceed::yes;
    }

    void run() {
        consume_input().get();
    }
};

}

SEASTAR_THREAD_TEST_CASE(test_read_unsigned_vint) {
    tests::reader_concurrency_semaphore_wrapper semaphore;

    auto nr_tests =
#ifdef SEASTAR_DEBUG
            10
#else
            1000
#endif
            ;
    test_consumer(semaphore.make_permit(), 0).run();
    for (int highest_bit = 0; highest_bit < 64; ++highest_bit) {
        uint64_t tested_value = uint64_t{1} << highest_bit;
        for (int i = 0; i < nr_tests; ++i) {
            test_consumer(semaphore.make_permit(), tested_value + tests::random::get_int<uint64_t>(tested_value - 1)).run();
        }
    }
}

<|endoftext|>


<commit_before>/*
 * Copyright © 2012-2013 Red Hat, Inc.
 *
 * 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 (including the next
 * paragraph) 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.
 *
 */

#if HAVE_CONFIG_H
#include <config.h>
#endif
#include <stdexcept>
#include <map>
#include <unistd.h>

#include <xorg/gtest/xorg-gtest.h>
#include <linux/input.h>

#include <X11/Xlib.h>
#include <X11/Xatom.h>
#include <X11/Xutil.h>
#include <X11/extensions/XInput.h>
#include <X11/extensions/XInput2.h>

#include <stdexcept>
#include <fstream>
#include <xorg/gtest/xorg-gtest.h>

#include <xorg/wacom-properties.h>
#include <xorg/xserver-properties.h>
#include <unistd.h>

#include "xit-server-input-test.h"
#include "device-interface.h"
#include "helpers.h"

#define EV_MASK     KeyPressMask | KeyReleaseMask | ButtonPressMask | \
		    ButtonReleaseMask | EnterWindowMask | \
		    LeaveWindowMask | PointerMotionMask | \
		    ButtonMotionMask | KeymapStateMask | \
		    ExposureMask | VisibilityChangeMask | \
		    StructureNotifyMask

/**
 * Wacom driver test class. This class takes a struct Tablet that defines
 * which device should be initialised.
 */
class WacomHoveringTest : public XITServerInputTest,
                          public DeviceInterface {
public:
    /**
     * Initializes a standard tablet device.
     */
    virtual void SetUp() {
        SetDevice("tablets/Wacom-Intuos5-touch-M-Pen.desc");
        XITServerInputTest::SetUp();
    }

    /**
     * Sets up an xorg.conf for a single mouse CorePointer device based on
     * the evemu device.
     */
    virtual void SetUpConfigAndLog() {
        server.SetOption("-retro", "");

        config.AddDefaultScreenWithDriver();
        config.AddInputSection("wacom", "Stylus",
                               "Option \"Type\"        \"stylus\"\n"
                               "Option \"DebugLevel\"  \"3\"\n"
                               "Option \"CommonDBG\"   \"3\"\n"
                               "Option \"Device\"      \"" + dev->GetDeviceNode() + "\"\n");
        config.AddInputSection("wacom", "Pad",
                               "Option \"Type\"        \"pad\"\n"
                               "Option \"Device\"      \"" + dev->GetDeviceNode() + "\"\n");
        config.AddInputSection("wacom", "Cursor",
                               "Option \"Type\"        \"cursor\"\n"
                               "Option \"Device\"      \"" + dev->GetDeviceNode() + "\"\n");
        config.AddInputSection("wacom", "Eraser",
                               "Option \"Type\"        \"eraser\"\n"
                               "Option \"Device\"      \"" + dev->GetDeviceNode() + "\"\n");
        config.WriteConfig();
    }
};

TEST_F(WacomHoveringTest, HoveringTest)
{
    XORG_TESTCASE("Test that hovering the Expresskeys pad while "
                  "using the stylus does not generate spurious "
                  "motion events to (0,0).\n"
                  "Note: This test is useless since the problem cannot be reproduced via evemu\n"
                  "https://bugs.freedesktop.org/show_bug.cgi?id=54250");

    XEvent ev;
    Window win;
    unsigned long white, black;

    /* the server takes a while to start up but the devices may not respond
       to events yet. Add a noop call that just delays everything long
       enough for this test to work */
    XInternAtom(Display(), "foo", True);
    XFlush(Display());

    white = WhitePixel(Display(), DefaultScreen (Display()));
    black = BlackPixel(Display(), DefaultScreen (Display()));

    // Create a fullscreen window
    win  = XCreateSimpleWindow (Display(),
                                DefaultRootWindow(Display()),
                                20, 20, 600, 600, 10, black, white);

    XSelectInput(Display(), win, EV_MASK);

    XMapWindow (Display(), win);
    XSync(Display(), False);
    ASSERT_TRUE(xorg::testing::XServer::WaitForEventOfType(Display(), Expose, -1, -1, 1000));

    // Play the recorded events
    dev->Play(RECORDINGS_DIR "tablets/Wacom-Intuos5-touch-M-Pen-hovering-expresskeys.events");

    XSync (Display(), False);
    EXPECT_NE(XPending(Display()), 0) << "No event received??" << std::endl;

    // Capture events and check for spurious motion events to (0,0) caused by hovering the Expresskeys
    while(XPending(Display())) {
        XNextEvent(Display(), &ev);
        if (ev.type == MotionNotify)
            EXPECT_FALSE (ev.xmotion.x_root == 0 && ev.xmotion.y_root == 0);
        else if (ev.type == EnterNotify || ev.type == LeaveNotify)
            EXPECT_FALSE (ev.xcrossing.x_root == 0 && ev.xcrossing.y_root == 0);
    }
}
<commit_msg>input/wacom: disable hovering test<commit_after>/*
 * Copyright © 2012-2013 Red Hat, Inc.
 *
 * 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 (including the next
 * paragraph) 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.
 *
 */

#if HAVE_CONFIG_H
#include <config.h>
#endif
#include <stdexcept>
#include <map>
#include <unistd.h>

#include <xorg/gtest/xorg-gtest.h>
#include <linux/input.h>

#include <X11/Xlib.h>
#include <X11/Xatom.h>
#include <X11/Xutil.h>
#include <X11/extensions/XInput.h>
#include <X11/extensions/XInput2.h>

#include <stdexcept>
#include <fstream>
#include <xorg/gtest/xorg-gtest.h>

#include <xorg/wacom-properties.h>
#include <xorg/xserver-properties.h>
#include <unistd.h>

#include "xit-server-input-test.h"
#include "device-interface.h"
#include "helpers.h"

#define EV_MASK     KeyPressMask | KeyReleaseMask | ButtonPressMask | \
		    ButtonReleaseMask | EnterWindowMask | \
		    LeaveWindowMask | PointerMotionMask | \
		    ButtonMotionMask | KeymapStateMask | \
		    ExposureMask | VisibilityChangeMask | \
		    StructureNotifyMask

/**
 * Wacom driver test class. This class takes a struct Tablet that defines
 * which device should be initialised.
 */
class WacomHoveringTest : public XITServerInputTest,
                          public DeviceInterface {
public:
    /**
     * Initializes a standard tablet device.
     */
    virtual void SetUp() {
        SetDevice("tablets/Wacom-Intuos5-touch-M-Pen.desc");
        XITServerInputTest::SetUp();
    }

    /**
     * Sets up an xorg.conf for a single mouse CorePointer device based on
     * the evemu device.
     */
    virtual void SetUpConfigAndLog() {
        server.SetOption("-retro", "");

        config.AddDefaultScreenWithDriver();
        config.AddInputSection("wacom", "Stylus",
                               "Option \"Type\"        \"stylus\"\n"
                               "Option \"DebugLevel\"  \"3\"\n"
                               "Option \"CommonDBG\"   \"3\"\n"
                               "Option \"Device\"      \"" + dev->GetDeviceNode() + "\"\n");
        config.AddInputSection("wacom", "Pad",
                               "Option \"Type\"        \"pad\"\n"
                               "Option \"Device\"      \"" + dev->GetDeviceNode() + "\"\n");
        config.AddInputSection("wacom", "Cursor",
                               "Option \"Type\"        \"cursor\"\n"
                               "Option \"Device\"      \"" + dev->GetDeviceNode() + "\"\n");
        config.AddInputSection("wacom", "Eraser",
                               "Option \"Type\"        \"eraser\"\n"
                               "Option \"Device\"      \"" + dev->GetDeviceNode() + "\"\n");
        config.WriteConfig();
    }
};

/**
 * FIXME: look at this test - is it still useful?
 */
TEST_F(WacomHoveringTest, DISABLED_HoveringTest)
{
    XORG_TESTCASE("Test that hovering the Expresskeys pad while "
                  "using the stylus does not generate spurious "
                  "motion events to (0,0).\n"
                  "Note: This test is useless since the problem cannot be reproduced via evemu\n"
                  "https://bugs.freedesktop.org/show_bug.cgi?id=54250");

    XEvent ev;
    Window win;
    unsigned long white, black;

    /* the server takes a while to start up but the devices may not respond
       to events yet. Add a noop call that just delays everything long
       enough for this test to work */
    XInternAtom(Display(), "foo", True);
    XFlush(Display());

    white = WhitePixel(Display(), DefaultScreen (Display()));
    black = BlackPixel(Display(), DefaultScreen (Display()));

    // Create a fullscreen window
    win  = XCreateSimpleWindow (Display(),
                                DefaultRootWindow(Display()),
                                20, 20, 600, 600, 10, black, white);

    XSelectInput(Display(), win, EV_MASK);

    XMapWindow (Display(), win);
    XSync(Display(), False);
    ASSERT_TRUE(xorg::testing::XServer::WaitForEventOfType(Display(), Expose, -1, -1, 1000));

    // Play the recorded events
    dev->Play(RECORDINGS_DIR "tablets/Wacom-Intuos5-touch-M-Pen-hovering-expresskeys.events");

    XSync (Display(), False);
    EXPECT_NE(XPending(Display()), 0) << "No event received??" << std::endl;

    // Capture events and check for spurious motion events to (0,0) caused by hovering the Expresskeys
    while(XPending(Display())) {
        XNextEvent(Display(), &ev);
        if (ev.type == MotionNotify)
            EXPECT_FALSE (ev.xmotion.x_root == 0 && ev.xmotion.y_root == 0);
        else if (ev.type == EnterNotify || ev.type == LeaveNotify)
            EXPECT_FALSE (ev.xcrossing.x_root == 0 && ev.xcrossing.y_root == 0);
    }
}
<|endoftext|>


<commit_before>#include <mpi.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <cassert>
#include "phiostats.h"
#include "phIO.h"
#include "phstream.h" //for makeRStream and makeGRStream
#include "syncio.h"
#include "posixio.h"
#include "streamio.h"

int main(int argc, char* argv[]) {
  MPI_Init(&argc,&argv);
  int rank;
  MPI_Comm_rank(MPI_COMM_WORLD, &rank);
  int size;
  MPI_Comm_size(MPI_COMM_WORLD, &size);
  if( argc != 2 ) {
    fprintf(stderr, "Usage: %s <numSyncFiles>\n",argv[0]);
    MPI_Finalize();
    return 1;
  }
  const char* phrase = "number of fishes";
  const char* type = "double";
  const char* iotype = "binary";
  int zero = 0;
  int one = 1;
  int numFish = 0;
  double fishWeight = 1.23;
  int nfiles = 1;
  int ppf = size/nfiles;
  const char* filename[2] = {"water-dat.", "water.dat."};
  rstream rs = makeRStream();
  phio_fp file[3];
  const char* modes[3]={"syncio", "posixio", "streamio"};
  syncio_setup_write(nfiles, one, ppf, &(file[0]));
  posixio_setup(&(file[1]), 'w');
  streamio_setup_r(&(file[2]), rs, 'w');
  for(int i=0; i<3; i++) {
    if(!rank) fprintf(stderr, "%s\n", modes[i]);
    phastaio_initStats();
    phio_openfile(filename[i], file[i]);
    for (int j = 0; j < atoi(argv[1]) ; j++) {
      phio_writeheader(file[i], phrase, &zero, &one, &zero, type, iotype);
      phio_writedatablock(file[i], phrase, &fishWeight, &zero, type, iotype);
    }
    phio_closefile(file[i]);
    phastaio_printStats();
  }
  syncio_setup_read(nfiles, &(file[0]));
  posixio_setup(&(file[1]), 'r');
  streamio_setup_r(&(file[2]), rs, 'r');
  for(int i=0; i<3; i++) {
    if(!rank) fprintf(stderr, "%s\n", modes[i]);
    phastaio_initStats();
    phio_openfile(filename[i], file[i]);
    phio_readheader(file[i], phrase, &numFish, &one, type, iotype);
    assert(!numFish);
    phio_readdatablock(file[i], phrase, &fishWeight, &numFish, type, iotype);
    assert(fishWeight == 1.23);
    phio_closefile(file[i]);
    phastaio_printStats();
  }
  MPI_Finalize();
  return 0;
}
<commit_msg>Step 5 working version<commit_after>#include <mpi.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <cassert>
#include "phiostats.h"
#include "phIO.h"
#include "phstream.h" //for makeRStream and makeGRStream
#include "syncio.h"
#include "posixio.h"
#include "streamio.h"

int main(int argc, char* argv[]) {
  MPI_Init(&argc,&argv);
  int rank;
  MPI_Comm_rank(MPI_COMM_WORLD, &rank);
  int size;
  MPI_Comm_size(MPI_COMM_WORLD, &size);
  if( argc != 2 ) {
    fprintf(stderr, "Usage: %s <numSyncFiles>\n",argv[0]);
    MPI_Finalize();
    return 1;
  }
  const char* phrase = "number of fishes";
  const char* type = "double";
  const char* iotype = "binary";
  int zero = 0;
  int one = 1;
  int numFish = 0;
  double fishWeight = 1.23;
  int nfiles = 1;
  int ppf = size/nfiles;
  const char* filename[2] = {"water-dat.", "water.dat."};
  rstream rs = makeRStream();
     phio_fp file[3];
  const char* modes[3]={"syncio", "posixio", "streamio"};
  syncio_setup_write(nfiles, one, ppf, &(file[0]));
  posixio_setup(&(file[1]), 'w');
  streamio_setup_r(&(file[2]), rs, 'w');
  fprintf(stderr, "%s\n" ,"Outside loop 1.0");
  for(int i=0; i<3; i++) {
    fprintf(stderr, "%s\n" ,"Within the i loop");
    if(!rank) fprintf(stderr, "%s\n", modes[i]);
    fprintf(stderr, "%s\n" ,"Before phastaio");
    phastaio_initStats();
    fprintf(stderr, "%s\n" ,"Opening files with ", filename[i], file[i] );
    phio_openfile(filename[i], file[i]);
    fprintf(stderr, "%s\n" ,"Entering for loop for ", atoi(argv[1]) );
   // const char* str = "Number of times "+ nfiles ;
    for (int j = 0; j < nfiles ; j++) {
      fprintf(stderr,"%s\n", "Inside loop");
      fprintf(stderr,"%d\n",atoi(argv[1]));
      const char* str = "Number of times " +j;
      fprintf(stderr,"%s\n", "Writing the header time - " );
      fprintf(stderr,"%d\n",zero);
      fprintf(stderr,"%d\n",one);
      fprintf(stderr,"%s\n",file[i] );
      fprintf(stderr,"%s\n","Should have printed the file" );
      fprintf(stderr,"%s\n",type);
      fprintf(stderr,"%s\n",iotype);
      fprintf(stderr,"%s\n","Opening the file" );
      phio_writeheader(file[i], str, &zero, &one, &zero, type, iotype);
      fprintf(stderr,"%s\n",str );
      fprintf(stderr,"%d\n",j );
      fprintf(stderr,"%s\n", "Writing the data block time - ");
      fprintf(stderr,"%d\n",j );
      phio_writedatablock(file[i], str, &fishWeight, &zero, type, iotype);
    }
    phio_closefile(file[i]);
    phastaio_printStats();
  }
  syncio_setup_read(nfiles, &(file[0]));
  posixio_setup(&(file[1]), 'r');
  streamio_setup_r(&(file[2]), rs, 'r');
  for(int i=0; i<3; i++) {
    if(!rank) fprintf(stderr, "%s\n", modes[i]);
    phastaio_initStats();
    phio_openfile(filename[i], file[i]);
    //Str was added
   // const char* str = "Number of times "+ nfiles ;
   // for (int j = 0; j < nfiles ; j++) {
    phio_readheader(file[i], phrase, &numFish, &one, type, iotype);
    //  phio_readheader(file[i], str, &numFish, &one, type, iotype);
     //Changing argument from file[i] to file[j]
    assert(!numFish);
    phio_readdatablock(file[i], phrase, &fishWeight, &numFish, type, iotype);
    //  phio_readdatablock(file[i], str, &fishWeight, &numFish, type, iotype);
    assert(fishWeight == 1.23);
    phio_closefile(file[i]);
    phastaio_printStats();
  }
  MPI_Finalize();
  return 0;
}
<|endoftext|>


<commit_before>#ifndef HEADER_TEST_TEST_HPP
#define HEADER_TEST_TEST_HPP

#include "../src/pugixml.hpp"

#include <setjmp.h>

struct test_runner
{
	test_runner(const char* name)
	{
		_name = name;
		_next = _tests;
		_tests = this;
	}

	virtual ~test_runner() {}

	virtual void run() = 0;

	const char* _name;
	test_runner* _next;

	static test_runner* _tests;
	static size_t _memory_fail_threshold;
	static bool _memory_fail_triggered;
	static jmp_buf _failure_buffer;
	static const char* _failure_message;

	static const char* _temp_path;
};

bool test_string_equal(const pugi::char_t* lhs, const pugi::char_t* rhs);

template <typename Node> inline bool test_node_name_value(const Node& node, const pugi::char_t* name, const pugi::char_t* value)
{
	return test_string_equal(node.name(), name) && test_string_equal(node.value(), value);
}

bool test_node(const pugi::xml_node& node, const pugi::char_t* contents, const pugi::char_t* indent, unsigned int flags);
bool test_double_nan(double value);

#ifndef PUGIXML_NO_XPATH
bool test_xpath_string(const pugi::xpath_node& node, const pugi::char_t* query, pugi::xpath_variable_set* variables, const pugi::char_t* expected);
bool test_xpath_boolean(const pugi::xpath_node& node, const pugi::char_t* query, pugi::xpath_variable_set* variables, bool expected);
bool test_xpath_number(const pugi::xpath_node& node, const pugi::char_t* query, pugi::xpath_variable_set* variables, double expected);
bool test_xpath_number_nan(const pugi::xpath_node& node, const pugi::char_t* query, pugi::xpath_variable_set* variables);

bool test_xpath_fail_compile(const pugi::char_t* query, pugi::xpath_variable_set* variables);

struct xpath_node_set_tester
{
	pugi::xpath_node* document_order;
	size_t document_size;

	pugi::xpath_node_set result;
	unsigned int last;
	const char* message;

	void check(bool condition);

	xpath_node_set_tester(const pugi::xpath_node_set& set, const char* message);
	~xpath_node_set_tester();

	xpath_node_set_tester& operator%(unsigned int expected);
};

#endif

struct dummy_fixture {};

#define TEST_FIXTURE(name, fixture) \
	struct test_runner_helper_##name: fixture \
	{ \
		void run(); \
	}; \
	static struct test_runner_##name: test_runner \
	{ \
		test_runner_##name(): test_runner(#name) {} \
		\
		virtual void run() PUGIXML_OVERRIDE \
		{ \
			test_runner_helper_##name helper; \
			helper.run(); \
		} \
	} test_runner_instance_##name; \
	void test_runner_helper_##name::run()

#define TEST(name) TEST_FIXTURE(name, dummy_fixture)

#define TEST_XML_FLAGS(name, xml, flags) \
	struct test_fixture_##name \
	{ \
		pugi::xml_document doc; \
		\
		test_fixture_##name() \
		{ \
			CHECK(doc.load_string(PUGIXML_TEXT(xml), flags)); \
		} \
		\
	private: \
		test_fixture_##name(const test_fixture_##name&); \
		test_fixture_##name& operator=(const test_fixture_##name&); \
	}; \
	\
	TEST_FIXTURE(name, test_fixture_##name)

#define TEST_XML(name, xml) TEST_XML_FLAGS(name, xml, pugi::parse_default)

#define CHECK_JOIN(text, file, line) text " at " file ":" #line
#define CHECK_JOIN2(text, file, line) CHECK_JOIN(text, file, line)
#define CHECK_TEXT(condition, text) if (condition) ; else test_runner::_failure_message = CHECK_JOIN2(text, __FILE__, __LINE__), longjmp(test_runner::_failure_buffer, 1)
#define CHECK_FORCE_FAIL(text) test_runner::_failure_message = CHECK_JOIN2(text, __FILE__, __LINE__), longjmp(test_runner::_failure_buffer, 1)

#if (defined(_MSC_VER) && _MSC_VER == 1200) || defined(__MWERKS__) || (defined(__BORLANDC__) && __BORLANDC__ <= 0x540)
#	define STRINGIZE(value) "??" // Some compilers have issues with stringizing expressions that contain strings w/escaping inside
#else
#	define STRINGIZE(value) #value
#endif

#define CHECK(condition) CHECK_TEXT(condition, STRINGIZE(condition) " is false")
#define CHECK_STRING(value, expected) CHECK_TEXT(test_string_equal(value, expected), STRINGIZE(value) " is not equal to " STRINGIZE(expected))
#define CHECK_DOUBLE(value, expected) CHECK_TEXT((value > expected ? value - expected : expected - value) < 1e-6, STRINGIZE(value) " is not equal to " STRINGIZE(expected))
#define CHECK_DOUBLE_NAN(value) CHECK_TEXT(test_double_nan(value), STRINGIZE(value) " is not equal to NaN")
#define CHECK_NAME_VALUE(node, name, value) CHECK_TEXT(test_node_name_value(node, name, value), STRINGIZE(node) " name/value do not match " STRINGIZE(name) " and " STRINGIZE(value))
#define CHECK_NODE_EX(node, expected, indent, flags) CHECK_TEXT(test_node(node, expected, indent, flags), STRINGIZE(node) " contents does not match " STRINGIZE(expected))
#define CHECK_NODE(node, expected) CHECK_NODE_EX(node, expected, PUGIXML_TEXT(""), pugi::format_raw)

#ifndef PUGIXML_NO_XPATH
#define CHECK_XPATH_STRING_VAR(node, query, variables, expected) CHECK_TEXT(test_xpath_string(node, query, variables, expected), STRINGIZE(query) " does not evaluate to " STRINGIZE(expected) " in context " STRINGIZE(node))
#define CHECK_XPATH_BOOLEAN_VAR(node, query, variables, expected) CHECK_TEXT(test_xpath_boolean(node, query, variables, expected), STRINGIZE(query) " does not evaluate to " STRINGIZE(expected) " in context " STRINGIZE(node))
#define CHECK_XPATH_NUMBER_VAR(node, query, variables, expected) CHECK_TEXT(test_xpath_number(node, query, variables, expected), STRINGIZE(query) " does not evaluate to " STRINGIZE(expected) " in context " STRINGIZE(node))
#define CHECK_XPATH_NUMBER_NAN_VAR(node, query, variables) CHECK_TEXT(test_xpath_number_nan(node, query, variables), STRINGIZE(query) " does not evaluate to NaN in context " STRINGIZE(node))
#define CHECK_XPATH_NODESET_VAR(node, query, variables) xpath_node_set_tester(pugi::xpath_query(query, variables).evaluate_node_set(node), CHECK_JOIN2(STRINGIZE(query) " does not evaluate to expected set in context " STRINGIZE(node), __FILE__, __LINE__))
#define CHECK_XPATH_FAIL_VAR(query, variables) CHECK_TEXT(test_xpath_fail_compile(query, variables), STRINGIZE(query) " should not compile")

#define CHECK_XPATH_STRING(node, query, expected) CHECK_XPATH_STRING_VAR(node, query, 0, expected)
#define CHECK_XPATH_BOOLEAN(node, query, expected) CHECK_XPATH_BOOLEAN_VAR(node, query, 0, expected)
#define CHECK_XPATH_NUMBER(node, query, expected) CHECK_XPATH_NUMBER_VAR(node, query, 0, expected)
#define CHECK_XPATH_NUMBER_NAN(node, query) CHECK_XPATH_NUMBER_NAN_VAR(node, query, 0)
#define CHECK_XPATH_NODESET(node, query) CHECK_XPATH_NODESET_VAR(node, query, 0)
#define CHECK_XPATH_FAIL(query) CHECK_XPATH_FAIL_VAR(query, 0)
#endif

#ifdef PUGIXML_NO_EXCEPTIONS
#define CHECK_ALLOC_FAIL(code) do { CHECK(!test_runner::_memory_fail_triggered); code; CHECK(test_runner::_memory_fail_triggered); test_runner::_memory_fail_triggered = false; } while (test_runner::_memory_fail_triggered)
#else
#define CHECK_ALLOC_FAIL(code) do { CHECK(!test_runner::_memory_fail_triggered); try { code; } catch (std::bad_alloc&) {} CHECK(test_runner::_memory_fail_triggered); test_runner::_memory_fail_triggered = false; } while (test_runner::_memory_fail_triggered)
#endif

#define STR(text) PUGIXML_TEXT(text)

#if defined(__DMC__) || defined(__BORLANDC__)
#define U_LITERALS // DMC does not understand \x01234 (it parses first three digits), but understands \u01234
#endif

#if (defined(_MSC_VER) && _MSC_VER == 1200) || (defined(__INTEL_COMPILER) && __INTEL_COMPILER == 800) || defined(__BORLANDC__)
// NaN comparison on MSVC6 is incorrect, see http://www.nabble.com/assertDoubleEquals,-NaN---Microsoft-Visual-Studio-6-td9137859.html
// IC8 and BCC are also affected by the same bug
#	define MSVC6_NAN_BUG
#endif

inline wchar_t wchar_cast(unsigned int value)
{
	return static_cast<wchar_t>(value); // to avoid C4310 on MSVC
}

bool is_little_endian();
pugi::xml_encoding get_native_encoding();

#endif
<commit_msg>tests: Fix PUGIXML_NO_XPATH,PUGIXML_COMPACT build<commit_after>#ifndef HEADER_TEST_TEST_HPP
#define HEADER_TEST_TEST_HPP

#include "../src/pugixml.hpp"

#include <setjmp.h>

#ifndef PUGIXML_NO_EXCEPTIONS
#include <exception>
#endif

struct test_runner
{
	test_runner(const char* name)
	{
		_name = name;
		_next = _tests;
		_tests = this;
	}

	virtual ~test_runner() {}

	virtual void run() = 0;

	const char* _name;
	test_runner* _next;

	static test_runner* _tests;
	static size_t _memory_fail_threshold;
	static bool _memory_fail_triggered;
	static jmp_buf _failure_buffer;
	static const char* _failure_message;

	static const char* _temp_path;
};

bool test_string_equal(const pugi::char_t* lhs, const pugi::char_t* rhs);

template <typename Node> inline bool test_node_name_value(const Node& node, const pugi::char_t* name, const pugi::char_t* value)
{
	return test_string_equal(node.name(), name) && test_string_equal(node.value(), value);
}

bool test_node(const pugi::xml_node& node, const pugi::char_t* contents, const pugi::char_t* indent, unsigned int flags);
bool test_double_nan(double value);

#ifndef PUGIXML_NO_XPATH
bool test_xpath_string(const pugi::xpath_node& node, const pugi::char_t* query, pugi::xpath_variable_set* variables, const pugi::char_t* expected);
bool test_xpath_boolean(const pugi::xpath_node& node, const pugi::char_t* query, pugi::xpath_variable_set* variables, bool expected);
bool test_xpath_number(const pugi::xpath_node& node, const pugi::char_t* query, pugi::xpath_variable_set* variables, double expected);
bool test_xpath_number_nan(const pugi::xpath_node& node, const pugi::char_t* query, pugi::xpath_variable_set* variables);

bool test_xpath_fail_compile(const pugi::char_t* query, pugi::xpath_variable_set* variables);

struct xpath_node_set_tester
{
	pugi::xpath_node* document_order;
	size_t document_size;

	pugi::xpath_node_set result;
	unsigned int last;
	const char* message;

	void check(bool condition);

	xpath_node_set_tester(const pugi::xpath_node_set& set, const char* message);
	~xpath_node_set_tester();

	xpath_node_set_tester& operator%(unsigned int expected);
};

#endif

struct dummy_fixture {};

#define TEST_FIXTURE(name, fixture) \
	struct test_runner_helper_##name: fixture \
	{ \
		void run(); \
	}; \
	static struct test_runner_##name: test_runner \
	{ \
		test_runner_##name(): test_runner(#name) {} \
		\
		virtual void run() PUGIXML_OVERRIDE \
		{ \
			test_runner_helper_##name helper; \
			helper.run(); \
		} \
	} test_runner_instance_##name; \
	void test_runner_helper_##name::run()

#define TEST(name) TEST_FIXTURE(name, dummy_fixture)

#define TEST_XML_FLAGS(name, xml, flags) \
	struct test_fixture_##name \
	{ \
		pugi::xml_document doc; \
		\
		test_fixture_##name() \
		{ \
			CHECK(doc.load_string(PUGIXML_TEXT(xml), flags)); \
		} \
		\
	private: \
		test_fixture_##name(const test_fixture_##name&); \
		test_fixture_##name& operator=(const test_fixture_##name&); \
	}; \
	\
	TEST_FIXTURE(name, test_fixture_##name)

#define TEST_XML(name, xml) TEST_XML_FLAGS(name, xml, pugi::parse_default)

#define CHECK_JOIN(text, file, line) text " at " file ":" #line
#define CHECK_JOIN2(text, file, line) CHECK_JOIN(text, file, line)
#define CHECK_TEXT(condition, text) if (condition) ; else test_runner::_failure_message = CHECK_JOIN2(text, __FILE__, __LINE__), longjmp(test_runner::_failure_buffer, 1)
#define CHECK_FORCE_FAIL(text) test_runner::_failure_message = CHECK_JOIN2(text, __FILE__, __LINE__), longjmp(test_runner::_failure_buffer, 1)

#if (defined(_MSC_VER) && _MSC_VER == 1200) || defined(__MWERKS__) || (defined(__BORLANDC__) && __BORLANDC__ <= 0x540)
#	define STRINGIZE(value) "??" // Some compilers have issues with stringizing expressions that contain strings w/escaping inside
#else
#	define STRINGIZE(value) #value
#endif

#define CHECK(condition) CHECK_TEXT(condition, STRINGIZE(condition) " is false")
#define CHECK_STRING(value, expected) CHECK_TEXT(test_string_equal(value, expected), STRINGIZE(value) " is not equal to " STRINGIZE(expected))
#define CHECK_DOUBLE(value, expected) CHECK_TEXT((value > expected ? value - expected : expected - value) < 1e-6, STRINGIZE(value) " is not equal to " STRINGIZE(expected))
#define CHECK_DOUBLE_NAN(value) CHECK_TEXT(test_double_nan(value), STRINGIZE(value) " is not equal to NaN")
#define CHECK_NAME_VALUE(node, name, value) CHECK_TEXT(test_node_name_value(node, name, value), STRINGIZE(node) " name/value do not match " STRINGIZE(name) " and " STRINGIZE(value))
#define CHECK_NODE_EX(node, expected, indent, flags) CHECK_TEXT(test_node(node, expected, indent, flags), STRINGIZE(node) " contents does not match " STRINGIZE(expected))
#define CHECK_NODE(node, expected) CHECK_NODE_EX(node, expected, PUGIXML_TEXT(""), pugi::format_raw)

#ifndef PUGIXML_NO_XPATH
#define CHECK_XPATH_STRING_VAR(node, query, variables, expected) CHECK_TEXT(test_xpath_string(node, query, variables, expected), STRINGIZE(query) " does not evaluate to " STRINGIZE(expected) " in context " STRINGIZE(node))
#define CHECK_XPATH_BOOLEAN_VAR(node, query, variables, expected) CHECK_TEXT(test_xpath_boolean(node, query, variables, expected), STRINGIZE(query) " does not evaluate to " STRINGIZE(expected) " in context " STRINGIZE(node))
#define CHECK_XPATH_NUMBER_VAR(node, query, variables, expected) CHECK_TEXT(test_xpath_number(node, query, variables, expected), STRINGIZE(query) " does not evaluate to " STRINGIZE(expected) " in context " STRINGIZE(node))
#define CHECK_XPATH_NUMBER_NAN_VAR(node, query, variables) CHECK_TEXT(test_xpath_number_nan(node, query, variables), STRINGIZE(query) " does not evaluate to NaN in context " STRINGIZE(node))
#define CHECK_XPATH_NODESET_VAR(node, query, variables) xpath_node_set_tester(pugi::xpath_query(query, variables).evaluate_node_set(node), CHECK_JOIN2(STRINGIZE(query) " does not evaluate to expected set in context " STRINGIZE(node), __FILE__, __LINE__))
#define CHECK_XPATH_FAIL_VAR(query, variables) CHECK_TEXT(test_xpath_fail_compile(query, variables), STRINGIZE(query) " should not compile")

#define CHECK_XPATH_STRING(node, query, expected) CHECK_XPATH_STRING_VAR(node, query, 0, expected)
#define CHECK_XPATH_BOOLEAN(node, query, expected) CHECK_XPATH_BOOLEAN_VAR(node, query, 0, expected)
#define CHECK_XPATH_NUMBER(node, query, expected) CHECK_XPATH_NUMBER_VAR(node, query, 0, expected)
#define CHECK_XPATH_NUMBER_NAN(node, query) CHECK_XPATH_NUMBER_NAN_VAR(node, query, 0)
#define CHECK_XPATH_NODESET(node, query) CHECK_XPATH_NODESET_VAR(node, query, 0)
#define CHECK_XPATH_FAIL(query) CHECK_XPATH_FAIL_VAR(query, 0)
#endif

#ifdef PUGIXML_NO_EXCEPTIONS
#define CHECK_ALLOC_FAIL(code) do { CHECK(!test_runner::_memory_fail_triggered); code; CHECK(test_runner::_memory_fail_triggered); test_runner::_memory_fail_triggered = false; } while (test_runner::_memory_fail_triggered)
#else
#define CHECK_ALLOC_FAIL(code) do { CHECK(!test_runner::_memory_fail_triggered); try { code; } catch (std::bad_alloc&) {} CHECK(test_runner::_memory_fail_triggered); test_runner::_memory_fail_triggered = false; } while (test_runner::_memory_fail_triggered)
#endif

#define STR(text) PUGIXML_TEXT(text)

#if defined(__DMC__) || defined(__BORLANDC__)
#define U_LITERALS // DMC does not understand \x01234 (it parses first three digits), but understands \u01234
#endif

#if (defined(_MSC_VER) && _MSC_VER == 1200) || (defined(__INTEL_COMPILER) && __INTEL_COMPILER == 800) || defined(__BORLANDC__)
// NaN comparison on MSVC6 is incorrect, see http://www.nabble.com/assertDoubleEquals,-NaN---Microsoft-Visual-Studio-6-td9137859.html
// IC8 and BCC are also affected by the same bug
#	define MSVC6_NAN_BUG
#endif

inline wchar_t wchar_cast(unsigned int value)
{
	return static_cast<wchar_t>(value); // to avoid C4310 on MSVC
}

bool is_little_endian();
pugi::xml_encoding get_native_encoding();

#endif
<|endoftext|>


<commit_before>#include <string>

#include "caffe/layer.hpp"
#include "caffe/layer_factory.hpp"
#include "caffe/proto/caffe.pb.h"
#include "caffe/vision_layers.hpp"

namespace caffe {

// GetLayer() defines the overall layer factory. The Get*Layer() functions
// define factories for layers with multiple computational engines.

// Get convolution layer according to engine.
template <typename Dtype>
Layer<Dtype>* GetConvolutionLayer(
    const LayerParameter& param) {
  ConvolutionParameter_Engine engine = param.convolution_param().engine();
  if (engine == ConvolutionParameter_Engine_DEFAULT) {
    engine = ConvolutionParameter_Engine_CAFFE;
#ifdef USE_CUDNN
    engine = ConvolutionParameter_Engine_CUDNN;
#endif
  }
  if (engine == ConvolutionParameter_Engine_CAFFE) {
    return new ConvolutionLayer<Dtype>(param);
#ifdef USE_CUDNN
  } else if (engine == ConvolutionParameter_Engine_CUDNN) {
    return new CuDNNConvolutionLayer<Dtype>(param);
#endif
  } else {
    LOG(FATAL) << "Layer " << param.name() << " has unknown engine.";
  }
}

// Get pooling layer according to engine.
template <typename Dtype>
Layer<Dtype>* GetPoolingLayer(const LayerParameter& param) {
  PoolingParameter_Engine engine = param.pooling_param().engine();
  if (engine == PoolingParameter_Engine_DEFAULT) {
    engine = PoolingParameter_Engine_CAFFE;
#ifdef USE_CUDNN
    engine = PoolingParameter_Engine_CUDNN;
#endif
  }
  if (engine == PoolingParameter_Engine_CAFFE) {
    return new PoolingLayer<Dtype>(param);
#ifdef USE_CUDNN
  } else if (engine == PoolingParameter_Engine_CUDNN) {
    PoolingParameter p_param = param.pooling_param();
    if (p_param.pad_h() || p_param.pad_w() || param.top_size() > 1) {
      LOG(INFO) << "CUDNN does not support padding or multiple tops. "
                << "Using Caffe's own pooling layer.";
      return new PoolingLayer<Dtype>(param);
    }
    return new CuDNNPoolingLayer<Dtype>(param);
#endif
  } else {
    LOG(FATAL) << "Layer " << param.name() << " has unknown engine.";
  }
}

// Get relu layer according to engine.
template <typename Dtype>
Layer<Dtype>* GetReLULayer(const LayerParameter& param) {
  ReLUParameter_Engine engine = param.relu_param().engine();
  if (engine == ReLUParameter_Engine_DEFAULT) {
    engine = ReLUParameter_Engine_CAFFE;
#ifdef USE_CUDNN
    engine = ReLUParameter_Engine_CUDNN;
#endif
  }
  if (engine == ReLUParameter_Engine_CAFFE) {
    return new ReLULayer<Dtype>(param);
#ifdef USE_CUDNN
  } else if (engine == ReLUParameter_Engine_CUDNN) {
    return new CuDNNReLULayer<Dtype>(param);
#endif
  } else {
    LOG(FATAL) << "Layer " << param.name() << " has unknown engine.";
  }
}

// Get sigmoid layer according to engine.
template <typename Dtype>
Layer<Dtype>* GetSigmoidLayer(const LayerParameter& param) {
  SigmoidParameter_Engine engine = param.sigmoid_param().engine();
  if (engine == SigmoidParameter_Engine_DEFAULT) {
    engine = SigmoidParameter_Engine_CAFFE;
#ifdef USE_CUDNN
    engine = SigmoidParameter_Engine_CUDNN;
#endif
  }
  if (engine == SigmoidParameter_Engine_CAFFE) {
    return new SigmoidLayer<Dtype>(param);
#ifdef USE_CUDNN
  } else if (engine == SigmoidParameter_Engine_CUDNN) {
    return new CuDNNSigmoidLayer<Dtype>(param);
#endif
  } else {
    LOG(FATAL) << "Layer " << param.name() << " has unknown engine.";
  }
}

// Get tanh layer according to engine.
template <typename Dtype>
Layer<Dtype>* GetTanHLayer(const LayerParameter& param) {
  TanHParameter_Engine engine = param.tanh_param().engine();
  if (engine == TanHParameter_Engine_DEFAULT) {
    engine = TanHParameter_Engine_CAFFE;
#ifdef USE_CUDNN
    engine = TanHParameter_Engine_CUDNN;
#endif
  }
  if (engine == TanHParameter_Engine_CAFFE) {
    return new TanHLayer<Dtype>(param);
#ifdef USE_CUDNN
  } else if (engine == TanHParameter_Engine_CUDNN) {
    return new CuDNNTanHLayer<Dtype>(param);
#endif
  } else {
    LOG(FATAL) << "Layer " << param.name() << " has unknown engine.";
  }
}

// Get softmax layer according to engine.
template <typename Dtype>
Layer<Dtype>* GetSoftmaxLayer(const LayerParameter& param) {
  SoftmaxParameter_Engine engine = param.softmax_param().engine();
  if (engine == SoftmaxParameter_Engine_DEFAULT) {
    engine = SoftmaxParameter_Engine_CAFFE;
#ifdef USE_CUDNN
    engine = SoftmaxParameter_Engine_CUDNN;
#endif
  }
  if (engine == SoftmaxParameter_Engine_CAFFE) {
    return new SoftmaxLayer<Dtype>(param);
#ifdef USE_CUDNN
  } else if (engine == SoftmaxParameter_Engine_CUDNN) {
    return new CuDNNSoftmaxLayer<Dtype>(param);
#endif
  } else {
    LOG(FATAL) << "Layer " << param.name() << " has unknown engine.";
  }
}

// Layers that have a specific creator function.
REGISTER_LAYER_CREATOR(CONVOLUTION, GetConvolutionLayer);
REGISTER_LAYER_CREATOR(POOLING, GetPoolingLayer);
REGISTER_LAYER_CREATOR(RELU, GetReLULayer);
REGISTER_LAYER_CREATOR(SIGMOID, GetSigmoidLayer);
REGISTER_LAYER_CREATOR(SOFTMAX, GetSoftmaxLayer);
REGISTER_LAYER_CREATOR(TANH, GetTanHLayer);

// Layers that use their constructor as their default creator.
REGISTER_LAYER_CLASS(ACCURACY, AccuracyLayer);
REGISTER_LAYER_CLASS(ABSVAL, AbsValLayer);
REGISTER_LAYER_CLASS(ARGMAX, ArgMaxLayer);
REGISTER_LAYER_CLASS(BNLL, BNLLLayer);
REGISTER_LAYER_CLASS(CONCAT, ConcatLayer);
REGISTER_LAYER_CLASS(CONTRASTIVE_LOSS, ContrastiveLossLayer);
REGISTER_LAYER_CLASS(DATA, DataLayer);
REGISTER_LAYER_CLASS(DROPOUT, DropoutLayer);
REGISTER_LAYER_CLASS(DUMMY_DATA, DummyDataLayer);
REGISTER_LAYER_CLASS(EUCLIDEAN_LOSS, EuclideanLossLayer);
REGISTER_LAYER_CLASS(ELTWISE, EltwiseLayer);
REGISTER_LAYER_CLASS(EXP, ExpLayer);
REGISTER_LAYER_CLASS(FLATTEN, FlattenLayer);
REGISTER_LAYER_CLASS(HDF5_DATA, HDF5DataLayer);
REGISTER_LAYER_CLASS(HDF5_OUTPUT, HDF5OutputLayer);
REGISTER_LAYER_CLASS(HINGE_LOSS, HingeLossLayer);
REGISTER_LAYER_CLASS(IMAGE_DATA, ImageDataLayer);
REGISTER_LAYER_CLASS(IM2COL, Im2colLayer);
REGISTER_LAYER_CLASS(INFOGAIN_LOSS, InfogainLossLayer);
REGISTER_LAYER_CLASS(INNER_PRODUCT, InnerProductLayer);
REGISTER_LAYER_CLASS(LRN, LRNLayer);
REGISTER_LAYER_CLASS(MEMORY_DATA, MemoryDataLayer);
REGISTER_LAYER_CLASS(MVN, MVNLayer);
REGISTER_LAYER_CLASS(MULTINOMIAL_LOGISTIC_LOSS, MultinomialLogisticLossLayer);
REGISTER_LAYER_CLASS(POWER, PowerLayer);
REGISTER_LAYER_CLASS(SILENCE, SilenceLayer);
REGISTER_LAYER_CLASS(SIGMOID_CROSS_ENTROPY_LOSS, SigmoidCrossEntropyLossLayer);
REGISTER_LAYER_CLASS(SLICE, SliceLayer);
REGISTER_LAYER_CLASS(SOFTMAX_LOSS, SoftmaxWithLossLayer);
REGISTER_LAYER_CLASS(SPLIT, SplitLayer);
REGISTER_LAYER_CLASS(THRESHOLD, ThresholdLayer);
REGISTER_LAYER_CLASS(WINDOW_DATA, WindowDataLayer);

}  // namespace caffe
<commit_msg>Missing param.pad condition for CUDNN pooling<commit_after>#include <string>

#include "caffe/layer.hpp"
#include "caffe/layer_factory.hpp"
#include "caffe/proto/caffe.pb.h"
#include "caffe/vision_layers.hpp"

namespace caffe {

// GetLayer() defines the overall layer factory. The Get*Layer() functions
// define factories for layers with multiple computational engines.

// Get convolution layer according to engine.
template <typename Dtype>
Layer<Dtype>* GetConvolutionLayer(
    const LayerParameter& param) {
  ConvolutionParameter_Engine engine = param.convolution_param().engine();
  if (engine == ConvolutionParameter_Engine_DEFAULT) {
    engine = ConvolutionParameter_Engine_CAFFE;
#ifdef USE_CUDNN
    engine = ConvolutionParameter_Engine_CUDNN;
#endif
  }
  if (engine == ConvolutionParameter_Engine_CAFFE) {
    return new ConvolutionLayer<Dtype>(param);
#ifdef USE_CUDNN
  } else if (engine == ConvolutionParameter_Engine_CUDNN) {
    return new CuDNNConvolutionLayer<Dtype>(param);
#endif
  } else {
    LOG(FATAL) << "Layer " << param.name() << " has unknown engine.";
  }
}

// Get pooling layer according to engine.
template <typename Dtype>
Layer<Dtype>* GetPoolingLayer(const LayerParameter& param) {
  PoolingParameter_Engine engine = param.pooling_param().engine();
  if (engine == PoolingParameter_Engine_DEFAULT) {
    engine = PoolingParameter_Engine_CAFFE;
#ifdef USE_CUDNN
    engine = PoolingParameter_Engine_CUDNN;
#endif
  }
  if (engine == PoolingParameter_Engine_CAFFE) {
    return new PoolingLayer<Dtype>(param);
#ifdef USE_CUDNN
  } else if (engine == PoolingParameter_Engine_CUDNN) {
    PoolingParameter p_param = param.pooling_param();
    if (p_param.pad() || p_param.pad_h() || p_param.pad_w() ||
        param.top_size() > 1) {
      LOG(INFO) << "CUDNN does not support padding or multiple tops. "
                << "Using Caffe's own pooling layer.";
      return new PoolingLayer<Dtype>(param);
    }
    return new CuDNNPoolingLayer<Dtype>(param);
#endif
  } else {
    LOG(FATAL) << "Layer " << param.name() << " has unknown engine.";
  }
}

// Get relu layer according to engine.
template <typename Dtype>
Layer<Dtype>* GetReLULayer(const LayerParameter& param) {
  ReLUParameter_Engine engine = param.relu_param().engine();
  if (engine == ReLUParameter_Engine_DEFAULT) {
    engine = ReLUParameter_Engine_CAFFE;
#ifdef USE_CUDNN
    engine = ReLUParameter_Engine_CUDNN;
#endif
  }
  if (engine == ReLUParameter_Engine_CAFFE) {
    return new ReLULayer<Dtype>(param);
#ifdef USE_CUDNN
  } else if (engine == ReLUParameter_Engine_CUDNN) {
    return new CuDNNReLULayer<Dtype>(param);
#endif
  } else {
    LOG(FATAL) << "Layer " << param.name() << " has unknown engine.";
  }
}

// Get sigmoid layer according to engine.
template <typename Dtype>
Layer<Dtype>* GetSigmoidLayer(const LayerParameter& param) {
  SigmoidParameter_Engine engine = param.sigmoid_param().engine();
  if (engine == SigmoidParameter_Engine_DEFAULT) {
    engine = SigmoidParameter_Engine_CAFFE;
#ifdef USE_CUDNN
    engine = SigmoidParameter_Engine_CUDNN;
#endif
  }
  if (engine == SigmoidParameter_Engine_CAFFE) {
    return new SigmoidLayer<Dtype>(param);
#ifdef USE_CUDNN
  } else if (engine == SigmoidParameter_Engine_CUDNN) {
    return new CuDNNSigmoidLayer<Dtype>(param);
#endif
  } else {
    LOG(FATAL) << "Layer " << param.name() << " has unknown engine.";
  }
}

// Get tanh layer according to engine.
template <typename Dtype>
Layer<Dtype>* GetTanHLayer(const LayerParameter& param) {
  TanHParameter_Engine engine = param.tanh_param().engine();
  if (engine == TanHParameter_Engine_DEFAULT) {
    engine = TanHParameter_Engine_CAFFE;
#ifdef USE_CUDNN
    engine = TanHParameter_Engine_CUDNN;
#endif
  }
  if (engine == TanHParameter_Engine_CAFFE) {
    return new TanHLayer<Dtype>(param);
#ifdef USE_CUDNN
  } else if (engine == TanHParameter_Engine_CUDNN) {
    return new CuDNNTanHLayer<Dtype>(param);
#endif
  } else {
    LOG(FATAL) << "Layer " << param.name() << " has unknown engine.";
  }
}

// Get softmax layer according to engine.
template <typename Dtype>
Layer<Dtype>* GetSoftmaxLayer(const LayerParameter& param) {
  SoftmaxParameter_Engine engine = param.softmax_param().engine();
  if (engine == SoftmaxParameter_Engine_DEFAULT) {
    engine = SoftmaxParameter_Engine_CAFFE;
#ifdef USE_CUDNN
    engine = SoftmaxParameter_Engine_CUDNN;
#endif
  }
  if (engine == SoftmaxParameter_Engine_CAFFE) {
    return new SoftmaxLayer<Dtype>(param);
#ifdef USE_CUDNN
  } else if (engine == SoftmaxParameter_Engine_CUDNN) {
    return new CuDNNSoftmaxLayer<Dtype>(param);
#endif
  } else {
    LOG(FATAL) << "Layer " << param.name() << " has unknown engine.";
  }
}

// Layers that have a specific creator function.
REGISTER_LAYER_CREATOR(CONVOLUTION, GetConvolutionLayer);
REGISTER_LAYER_CREATOR(POOLING, GetPoolingLayer);
REGISTER_LAYER_CREATOR(RELU, GetReLULayer);
REGISTER_LAYER_CREATOR(SIGMOID, GetSigmoidLayer);
REGISTER_LAYER_CREATOR(SOFTMAX, GetSoftmaxLayer);
REGISTER_LAYER_CREATOR(TANH, GetTanHLayer);

// Layers that use their constructor as their default creator.
REGISTER_LAYER_CLASS(ACCURACY, AccuracyLayer);
REGISTER_LAYER_CLASS(ABSVAL, AbsValLayer);
REGISTER_LAYER_CLASS(ARGMAX, ArgMaxLayer);
REGISTER_LAYER_CLASS(BNLL, BNLLLayer);
REGISTER_LAYER_CLASS(CONCAT, ConcatLayer);
REGISTER_LAYER_CLASS(CONTRASTIVE_LOSS, ContrastiveLossLayer);
REGISTER_LAYER_CLASS(DATA, DataLayer);
REGISTER_LAYER_CLASS(DROPOUT, DropoutLayer);
REGISTER_LAYER_CLASS(DUMMY_DATA, DummyDataLayer);
REGISTER_LAYER_CLASS(EUCLIDEAN_LOSS, EuclideanLossLayer);
REGISTER_LAYER_CLASS(ELTWISE, EltwiseLayer);
REGISTER_LAYER_CLASS(EXP, ExpLayer);
REGISTER_LAYER_CLASS(FLATTEN, FlattenLayer);
REGISTER_LAYER_CLASS(HDF5_DATA, HDF5DataLayer);
REGISTER_LAYER_CLASS(HDF5_OUTPUT, HDF5OutputLayer);
REGISTER_LAYER_CLASS(HINGE_LOSS, HingeLossLayer);
REGISTER_LAYER_CLASS(IMAGE_DATA, ImageDataLayer);
REGISTER_LAYER_CLASS(IM2COL, Im2colLayer);
REGISTER_LAYER_CLASS(INFOGAIN_LOSS, InfogainLossLayer);
REGISTER_LAYER_CLASS(INNER_PRODUCT, InnerProductLayer);
REGISTER_LAYER_CLASS(LRN, LRNLayer);
REGISTER_LAYER_CLASS(MEMORY_DATA, MemoryDataLayer);
REGISTER_LAYER_CLASS(MVN, MVNLayer);
REGISTER_LAYER_CLASS(MULTINOMIAL_LOGISTIC_LOSS, MultinomialLogisticLossLayer);
REGISTER_LAYER_CLASS(POWER, PowerLayer);
REGISTER_LAYER_CLASS(SILENCE, SilenceLayer);
REGISTER_LAYER_CLASS(SIGMOID_CROSS_ENTROPY_LOSS, SigmoidCrossEntropyLossLayer);
REGISTER_LAYER_CLASS(SLICE, SliceLayer);
REGISTER_LAYER_CLASS(SOFTMAX_LOSS, SoftmaxWithLossLayer);
REGISTER_LAYER_CLASS(SPLIT, SplitLayer);
REGISTER_LAYER_CLASS(THRESHOLD, ThresholdLayer);
REGISTER_LAYER_CLASS(WINDOW_DATA, WindowDataLayer);

}  // namespace caffe
<|endoftext|>


<commit_before>/******************************************************************************\

          This file is part of the C! library.  A.K.A the cbang library.

                Copyright (c) 2003-2019, Cauldron Development LLC
                   Copyright (c) 2003-2017, Stanford University
                               All rights reserved.

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

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

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

        In addition, BSD licensing may be granted on a case by case basis
        by written permission from at least one of the copyright holders.
           You may request written permission by emailing the authors.

                  For information regarding this software email:
                                 Joseph Coffland
                          joseph@cauldrondevelopment.com

\******************************************************************************/

#include "Context.h"

#include <cbang/js/JSInterrupted.h>

using namespace cb;
using namespace cb::gv8;
using namespace std;

Context::Context(v8::Isolate *iso) : context(v8::Context::New(iso)) {}

Value Context::eval(const InputSource &src) {
  v8::EscapableHandleScope handleScope(Value::getIso());
  Context::Scope ctxScope(*this);

  // Get script origin
  v8::Local<v8::String> origin;
  string filename = src.getName();
  if (!filename.empty()) origin = Value::createString(filename);
  v8::ScriptOrigin sOrigin(origin);

  // Get script source
  auto source = Value::createString(src.toString());

  // Compile
  v8::TryCatch tryCatch(Value::getIso());
  auto script = v8::Script::Compile(context, source, &sOrigin);
  if (tryCatch.HasCaught()) translateException(tryCatch, false);

  // Execute
  auto ret = script.ToLocalChecked()->Run(context);
  if (tryCatch.HasCaught()) translateException(tryCatch, true);

  // Return result
  return handleScope.Escape(ret.ToLocalChecked());
}

void Context::translateException(const v8::TryCatch &tryCatch, bool useStack) {
  v8::HandleScope handleScope(Value::getIso());

  if (useStack && !tryCatch.StackTrace(context).IsEmpty())
    throw Exception(Value(tryCatch.StackTrace(context)).toString());

  if (tryCatch.Exception()->IsNull()) throw cb::js::JSInterrupted();

  string msg = Value(tryCatch.Exception()).toString();

  v8::Handle<v8::Message> message = tryCatch.Message();
  if (message.IsEmpty()) throw Exception(msg);

  string filename = Value(message->GetScriptResourceName()).toString();
  int line = message->GetLineNumber(context).FromJust();
  int col = message->GetStartColumn(context).FromJust();

  throw Exception(msg, FileLocation(filename, line, col));
}
<commit_msg>Support V8 version 10. re:#17<commit_after>/******************************************************************************\

          This file is part of the C! library.  A.K.A the cbang library.

                Copyright (c) 2003-2019, Cauldron Development LLC
                   Copyright (c) 2003-2017, Stanford University
                               All rights reserved.

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

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

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

        In addition, BSD licensing may be granted on a case by case basis
        by written permission from at least one of the copyright holders.
           You may request written permission by emailing the authors.

                  For information regarding this software email:
                                 Joseph Coffland
                          joseph@cauldrondevelopment.com

\******************************************************************************/

#include "Context.h"

#include <cbang/js/JSInterrupted.h>

using namespace cb;
using namespace cb::gv8;
using namespace std;

Context::Context(v8::Isolate *iso) : context(v8::Context::New(iso)) {}

Value Context::eval(const InputSource &src) {
  v8::EscapableHandleScope handleScope(Value::getIso());
  Context::Scope ctxScope(*this);

  // Get script origin
  v8::Local<v8::String> origin;
  string filename = src.getName();
  if (!filename.empty()) origin = Value::createString(filename);

#if V8_MAJOR_VERSION < 10
  v8::ScriptOrigin sOrigin(origin);
#else
  v8::ScriptOrigin sOrigin(Value::getIso(), origin);
#endif

  // Get script source
  auto source = Value::createString(src.toString());

  // Compile
  v8::TryCatch tryCatch(Value::getIso());
  auto script = v8::Script::Compile(context, source, &sOrigin);
  if (tryCatch.HasCaught()) translateException(tryCatch, false);

  // Execute
  auto ret = script.ToLocalChecked()->Run(context);
  if (tryCatch.HasCaught()) translateException(tryCatch, true);

  // Return result
  return handleScope.Escape(ret.ToLocalChecked());
}

void Context::translateException(const v8::TryCatch &tryCatch, bool useStack) {
  v8::HandleScope handleScope(Value::getIso());

  if (useStack && !tryCatch.StackTrace(context).IsEmpty())
    throw Exception(Value(tryCatch.StackTrace(context)).toString());

  if (tryCatch.Exception()->IsNull()) throw cb::js::JSInterrupted();

  string msg = Value(tryCatch.Exception()).toString();

  v8::Handle<v8::Message> message = tryCatch.Message();
  if (message.IsEmpty()) throw Exception(msg);

  string filename = Value(message->GetScriptResourceName()).toString();
  int line = message->GetLineNumber(context).FromJust();
  int col = message->GetStartColumn(context).FromJust();

  throw Exception(msg, FileLocation(filename, line, col));
}
<|endoftext|>


<commit_before>#include "crop.hpp"
#include "draw.hpp"
using namespace std;
using namespace cv;

namespace cp
{
	void cropCenter(InputArray src, OutputArray crop, const int window_size)
	{
		Mat s = src.getMat();
		cropZoom(src, crop, Point(s.cols / 2, s.rows / 2), window_size);
	}

	void cropZoom(InputArray src, OutputArray crop_zoom, const Rect roi, const int zoom_factor)
	{
		const int w = roi.width;
		const int h = roi.height;
		Mat bb;
		copyMakeBorder(src, bb, h, h, w, w, BORDER_CONSTANT, 0);
		Mat cropimage;
		bb(Rect(roi.x + w, roi.y + h, roi.width, roi.height)).copyTo(cropimage);

		resize(cropimage, crop_zoom, Size(zoom_factor*w, zoom_factor*h), 0, 0, INTER_NEAREST);
	}

	void cropZoom(InputArray src, OutputArray crop_zoom, const Point center, const int window_size, const int zoom_factor)
	{
		Rect roi = Rect(center.x - window_size / 2, center.y - window_size / 2, window_size, window_size);
		cropZoom(src, crop_zoom, roi, zoom_factor);
	}

	void cropZoomWithBoundingBox(InputArray src, OutputArray crop_zoom, const Rect roi, const int zoom_factor, const Scalar color, const int thickness)
	{
		const int w = roi.width;
		const int h = roi.height;
		Mat bb;
		copyMakeBorder(src, bb, h, h, w, w, BORDER_CONSTANT, 0);
		Mat cropimage;
		bb(Rect(roi.x + w, roi.y + h, roi.width, roi.height)).copyTo(cropimage);
		rectangle(cropimage, Rect(0, 0, w, h), color, thickness);

		resize(cropimage, crop_zoom, Size(zoom_factor*w, zoom_factor*h), 0, 0, INTER_NEAREST);
	}

	void cropZoomWithBoundingBox(InputArray src, OutputArray crop_zoom, const Point center, const int window_size, const int zoom_factor, const Scalar color, const int thickness)
	{
		Rect roi = Rect(center.x - window_size / 2, center.y - window_size / 2, window_size, window_size);
		cropZoomWithBoundingBox(src, crop_zoom, roi, zoom_factor, color, thickness);
	}

	void cropZoomWithSrcMarkAndBoundingBox(InputArray src, OutputArray crop_zoom, OutputArray src_mark, const Rect roi, const int zoom_factor, const Scalar color, const int thickness)
	{
		Mat temp;
		src.copyTo(temp);
		rectangle(temp, roi, color, thickness);
		temp.copyTo(src_mark);

		cropZoomWithBoundingBox(src, crop_zoom, roi, zoom_factor, color, thickness);
	}

	void cropZoomWithSrcMarkAndBoundingBox(InputArray src, OutputArray crop_zoom, OutputArray src_mark, const Point center, const int window_size, const int zoom_factor, const Scalar color, const int thickness)
	{
		Rect roi = Rect(center.x - window_size / 2, center.y - window_size / 2, window_size, window_size);
		cropZoomWithSrcMarkAndBoundingBox(src, crop_zoom, src_mark, roi, zoom_factor, color, thickness);
	}

	struct MouseParameterGUICropZoom
	{
		cv::Rect pt;
		std::string wname;
	};

	void onMouseGUICropZoom(int events, int x, int y, int flags, void *param)
	{
		MouseParameterGUICropZoom* retp = (MouseParameterGUICropZoom*)param;
		//if(events==CV_EVENT_LBUTTONDOWN)
		if (flags & EVENT_FLAG_LBUTTON)
		{
			retp->pt.x = max(0, min(retp->pt.width - 1, x));
			retp->pt.y = max(0, min(retp->pt.height - 1, y));

			setTrackbarPos("zoom_x", retp->wname, x);
			setTrackbarPos("zoom_y", retp->wname, y);
		}
	}

	cv::Mat guiCropZoom(InputArray src, Rect& dest_roi, int& dest_zoom_factor, const Scalar color, const int thickness, const bool isWait, const string wname)
	{
		const int zoom_factor_max = 32;

		const int width = src.size().width;
		const int height = src.size().height;

		static MouseParameterGUICropZoom param
		{
			Rect(width / 2, height / 2, width, height),
			wname
		};

		namedWindow(wname);
		setMouseCallback(wname, onMouseGUICropZoom, (void*)&param);

		static int zoom_show_option = 0; createTrackbar("zoom_show_op", wname, &zoom_show_option, 1);
		static int zoom_position = 0; createTrackbar("zoom_position", wname, &zoom_position, 4);
		createTrackbar("zoom_x", wname, &param.pt.x, width - 1);
		createTrackbar("zoom_y", wname, &param.pt.y, height - 1);
		static int zoom_count = 0;
		static int zoom_window = 40; createTrackbar("zoom_window", wname, &zoom_window, min(width, height) - 1);
		static int zoom_factor = 8; createTrackbar("zoom_factor", wname, &zoom_factor, zoom_factor_max);
		static int thick = thickness; createTrackbar("thickness", wname, &thick, 10);
		Mat show;
		Mat crop_resize;
		Mat input = src.getMat();

		int key = 0;
		displayOverlay(wname, "s: save, p: change position, ?: help", 5000);

		bool isScale = false;
		if (input.depth() == CV_32F)
		{
			double minv, maxv;
			cv::minMaxLoc(input, &minv, &maxv);
			if (maxv > 1)isScale = true;
		}
		while (key != 'q')
		{
			if(isScale) input.convertTo(show, CV_8U, 255);
			else input.copyTo(show);

			zoom_factor = max(zoom_factor, 1);

			if (zoom_show_option == 0)
			{
				cropZoomWithSrcMarkAndBoundingBox(input, crop_resize, show, Point(param.pt.x, param.pt.y), zoom_window, zoom_factor, color, thick);
			}
			else if (zoom_show_option == 1)
			{
				cropZoom(input, crop_resize, Point(param.pt.x, param.pt.y), zoom_window, zoom_factor);
			}

			imshow(wname + "_image", crop_resize);

			if (crop_resize.cols < width&&crop_resize.rows < height)
			{
				if (zoom_position == 1) crop_resize.copyTo(show(Rect(0, 0, crop_resize.size().width, crop_resize.size().height)));
				else if (zoom_position == 2) crop_resize.copyTo(show(Rect(show.cols - 1 - crop_resize.size().width, 0, crop_resize.size().width, crop_resize.size().height)));
				else if (zoom_position == 3) crop_resize.copyTo(show(Rect(show.cols - 1 - crop_resize.size().width, show.rows - 1 - crop_resize.size().height, crop_resize.size().width, crop_resize.size().height)));
				else if (zoom_position == 4) crop_resize.copyTo(show(Rect(0, show.rows - 1 - crop_resize.size().height, crop_resize.size().width, crop_resize.size().height)));
			}

			imshow(wname, show);
			if (!isWait) break;
			key = waitKey(1);
			if (key == 'i')
			{
				param.pt.y = max(param.pt.y - 1, 0);
				setTrackbarPos("zoom_y", wname, param.pt.x);
			}
			if (key == 'j')
			{
				param.pt.x = max(param.pt.x - 1, 0);
				setTrackbarPos("zoom_x", wname, param.pt.x);
			}
			if (key == 'k')
			{
				param.pt.x = min(param.pt.y + 1, height - 1);
				setTrackbarPos("zoom_y", wname, param.pt.y);
			}
			if (key == 'l')
			{
				param.pt.x = min(param.pt.x + 1, width - 1);
				setTrackbarPos("zoom_x", wname, param.pt.x);
			}
			if (key == 'z')
			{
				zoom_factor = min(zoom_factor + 1, zoom_factor_max);
				setTrackbarPos("zoom_factor", wname, zoom_factor);
			}
			if (key == 'x')
			{
				zoom_factor = max(zoom_factor - 1, 1);
				setTrackbarPos("zoom_factor", wname, zoom_factor);
			}
			if (key == 'p')
			{
				zoom_position++;
				zoom_position = (zoom_position > 4) ? 0 : zoom_position;
				setTrackbarPos("zoom_position", wname, zoom_position);
			}
			if (key == 's')
			{
				imwrite(wname + to_string(zoom_count) + "_mark.png", show);
				imwrite(wname + to_string(zoom_count) + ".png", crop_resize);
				zoom_count++;
			}
			if (key == '?')
			{
				cout << "i,j,k,l: move x, y, like vim" << endl;
				cout << "z: zoom factor++" << endl;
				cout << "x: zoom factor--" << endl;
				cout << "p: change position of zoomed image" << endl;
				cout << "s: save image" << endl;
				cout << "q: quit" << endl;
			}
		}

		if (isWait) destroyWindow(wname);
		return crop_resize;
	}

	cv::Mat guiCropZoom(InputArray src, const Scalar color, const int thickness, const bool isWait, const string wname)
	{
		Rect roi;
		int zf;
		return guiCropZoom(src, roi, zf, color, thickness, isWait, wname);
	}
}<commit_msg>Update crop.cpp<commit_after>#include "crop.hpp"
#include "draw.hpp"
using namespace std;
using namespace cv;

namespace cp
{
	void cropCenter(InputArray src, OutputArray crop, const int window_size)
	{
		Mat s = src.getMat();
		cropZoom(src, crop, Point(s.cols / 2, s.rows / 2), window_size);
	}

	void cropZoom(InputArray src, OutputArray crop_zoom, const Rect roi, const int zoom_factor)
	{
		const int w = roi.width;
		const int h = roi.height;
		Mat bb;
		copyMakeBorder(src, bb, h, h, w, w, BORDER_CONSTANT, 0);
		Mat cropimage;
		bb(Rect(roi.x + w, roi.y + h, roi.width, roi.height)).copyTo(cropimage);

		resize(cropimage, crop_zoom, Size(zoom_factor * w, zoom_factor * h), 0, 0, INTER_NEAREST);
	}

	void cropZoom(InputArray src, OutputArray crop_zoom, const Point center, const int window_size, const int zoom_factor)
	{
		Rect roi = Rect(center.x - window_size / 2, center.y - window_size / 2, window_size, window_size);
		cropZoom(src, crop_zoom, roi, zoom_factor);
	}

	void cropZoomWithBoundingBox(InputArray src, OutputArray crop_zoom, const Rect roi, const int zoom_factor, const Scalar color, const int thickness)
	{
		const int w = roi.width;
		const int h = roi.height;
		Mat bb;
		copyMakeBorder(src, bb, h, h, w, w, BORDER_CONSTANT, 0);
		Mat cropimage;
		bb(Rect(roi.x + w, roi.y + h, roi.width, roi.height)).copyTo(cropimage);
		rectangle(cropimage, Rect(0, 0, w, h), color, thickness);

		resize(cropimage, crop_zoom, Size(zoom_factor * w, zoom_factor * h), 0, 0, INTER_NEAREST);
	}

	void cropZoomWithBoundingBox(InputArray src, OutputArray crop_zoom, const Point center, const int window_size, const int zoom_factor, const Scalar color, const int thickness)
	{
		Rect roi = Rect(center.x - window_size / 2, center.y - window_size / 2, window_size, window_size);
		cropZoomWithBoundingBox(src, crop_zoom, roi, zoom_factor, color, thickness);
	}

	void cropZoomWithSrcMarkAndBoundingBox(InputArray src, OutputArray crop_zoom, OutputArray src_mark, const Rect roi, const int zoom_factor, const Scalar color, const int thickness)
	{
		Mat temp;
		src.copyTo(temp);
		rectangle(temp, roi, color, thickness);
		temp.copyTo(src_mark);

		cropZoomWithBoundingBox(src, crop_zoom, roi, zoom_factor, color, thickness);
	}

	void cropZoomWithSrcMarkAndBoundingBox(InputArray src, OutputArray crop_zoom, OutputArray src_mark, const Point center, const int window_size, const int zoom_factor, const Scalar color, const int thickness)
	{
		Rect roi = Rect(center.x - window_size / 2, center.y - window_size / 2, window_size, window_size);
		cropZoomWithSrcMarkAndBoundingBox(src, crop_zoom, src_mark, roi, zoom_factor, color, thickness);
	}

	struct MouseParameterGUICropZoom
	{
		cv::Rect pt;
		std::string wname;
	};

	void onMouseGUICropZoom(int events, int x, int y, int flags, void* param)
	{
		MouseParameterGUICropZoom* retp = (MouseParameterGUICropZoom*)param;
		//if(events==CV_EVENT_LBUTTONDOWN)
		if (flags & EVENT_FLAG_LBUTTON)
		{
			retp->pt.x = max(0, min(retp->pt.width - 1, x));
			retp->pt.y = max(0, min(retp->pt.height - 1, y));

			setTrackbarPos("zoom_x", retp->wname, x);
			setTrackbarPos("zoom_y", retp->wname, y);
		}
	}

	cv::Mat guiCropZoom(InputArray src, Rect& dest_roi, int& dest_zoom_factor, const Scalar color, const int thickness, const bool isWait, const string wname)
	{
		const int zoom_factor_max = 32;

		const int width = src.size().width;
		const int height = src.size().height;

		string trackbarname = "parameters";
		if (src.size().height < 1024)trackbarname = wname;
		else namedWindow(trackbarname);
		static MouseParameterGUICropZoom param
		{
			Rect(width / 2, height / 2, width, height),
			trackbarname
		};

		namedWindow(wname);
		setMouseCallback(wname, onMouseGUICropZoom, (void*)&param);

		static int zoom_show_option = 0;
		static int zoom_position = 0;
		static int zoom_count = 0;
		static int zoom_window = 40;
		static int zoom_factor = 8;
		static int thick = thickness;
		createTrackbar("zoom_show_op", trackbarname, &zoom_show_option, 1);
		createTrackbar("zoom_position", trackbarname, &zoom_position, 4);
		createTrackbar("zoom_x", trackbarname, &param.pt.x, width - 1);
		createTrackbar("zoom_y", trackbarname, &param.pt.y, height - 1);
		createTrackbar("zoom_window", trackbarname, &zoom_window, min(width, height) - 1);
		createTrackbar("zoom_factor", trackbarname, &zoom_factor, zoom_factor_max);
		createTrackbar("thickness", trackbarname, &thick, 10);

		Mat show;
		Mat crop_resize;
		Mat input = src.getMat();

		int key = 0;
		displayOverlay(wname, "s: save, p: change position, ?: help", 5000);

		bool isScale = false;
		if (input.depth() == CV_32F)
		{
			double minv, maxv;
			cv::minMaxLoc(input, &minv, &maxv);
			if (maxv > 1)isScale = true;
		}
		while (key != 'q')
		{
			if (isScale) input.convertTo(show, CV_8U, 255);
			else input.copyTo(show);

			zoom_factor = max(zoom_factor, 1);

			if (zoom_show_option == 0)
			{
				cropZoomWithSrcMarkAndBoundingBox(input, crop_resize, show, Point(param.pt.x, param.pt.y), zoom_window, zoom_factor, color, thick);
			}
			else if (zoom_show_option == 1)
			{
				cropZoom(input, crop_resize, Point(param.pt.x, param.pt.y), zoom_window, zoom_factor);
			}

			imshow(wname + "_image", crop_resize);

			if (crop_resize.cols < width && crop_resize.rows < height)
			{
				if (zoom_position == 1) crop_resize.copyTo(show(Rect(0, 0, crop_resize.size().width, crop_resize.size().height)));
				else if (zoom_position == 2) crop_resize.copyTo(show(Rect(show.cols - 1 - crop_resize.size().width, 0, crop_resize.size().width, crop_resize.size().height)));
				else if (zoom_position == 3) crop_resize.copyTo(show(Rect(show.cols - 1 - crop_resize.size().width, show.rows - 1 - crop_resize.size().height, crop_resize.size().width, crop_resize.size().height)));
				else if (zoom_position == 4) crop_resize.copyTo(show(Rect(0, show.rows - 1 - crop_resize.size().height, crop_resize.size().width, crop_resize.size().height)));
			}

			imshow(wname, show);
			if (!isWait) break;
			key = waitKey(1);
			if (key == 'i')
			{
				param.pt.y = max(param.pt.y - 1, 0);
				setTrackbarPos("zoom_y", wname, param.pt.x);
			}
			if (key == 'j')
			{
				param.pt.x = max(param.pt.x - 1, 0);
				setTrackbarPos("zoom_x", wname, param.pt.x);
			}
			if (key == 'k')
			{
				param.pt.x = min(param.pt.y + 1, height - 1);
				setTrackbarPos("zoom_y", wname, param.pt.y);
			}
			if (key == 'l')
			{
				param.pt.x = min(param.pt.x + 1, width - 1);
				setTrackbarPos("zoom_x", wname, param.pt.x);
			}
			if (key == 'z')
			{
				zoom_factor = min(zoom_factor + 1, zoom_factor_max);
				setTrackbarPos("zoom_factor", wname, zoom_factor);
			}
			if (key == 'x')
			{
				zoom_factor = max(zoom_factor - 1, 1);
				setTrackbarPos("zoom_factor", wname, zoom_factor);
			}
			if (key == 'p')
			{
				zoom_position++;
				zoom_position = (zoom_position > 4) ? 0 : zoom_position;
				setTrackbarPos("zoom_position", wname, zoom_position);
			}
			if (key == 's')
			{
				imwrite(wname + to_string(zoom_count) + "_mark.png", show);
				imwrite(wname + to_string(zoom_count) + ".png", crop_resize);
				zoom_count++;
			}
			if (key == '?')
			{
				cout << "i,j,k,l: move x, y, like vim" << endl;
				cout << "z: zoom factor++" << endl;
				cout << "x: zoom factor--" << endl;
				cout << "p: change position of zoomed image" << endl;
				cout << "s: save image" << endl;
				cout << "q: quit" << endl;
			}
		}

		if (isWait)
		{
			destroyWindow(wname);
			destroyWindow(trackbarname);
		}
		return crop_resize;
	}

	cv::Mat guiCropZoom(InputArray src, const Scalar color, const int thickness, const bool isWait, const string wname)
	{
		Rect roi;
		int zf;
		return guiCropZoom(src, roi, zf, color, thickness, isWait, wname);
	}
}<|endoftext|>