text:
#include <cstdint>
#include <string>
#include <vector>

#include <boost/test/unit_test.hpp>

#include "shiguredo/mp4/box/co64.hpp"
#include "shiguredo/mp4/box/stco.hpp"
#include "shiguredo/mp4/box/stsc.hpp"
#include "shiguredo/mp4/box/stts.hpp"
#include "shiguredo/mp4/track/track.hpp"

BOOST_AUTO_TEST_SUITE(track)

struct MakeSttsEntriesTestCase {
  const std::vector<std::uint32_t> sample_duraitons;
  const std::vector<shiguredo::mp4::box::SttsEntry> entries;
};

MakeSttsEntriesTestCase make_stts_entries_test_cases[] = {
    {
        {10, 10, 10},
        {shiguredo::mp4::box::SttsEntry({.sample_count = 3, .sample_duration = 10})},
    },
    {
        {10, 5, 10},
        {shiguredo::mp4::box::SttsEntry({.sample_count = 1, .sample_duration = 10}),
         shiguredo::mp4::box::SttsEntry({.sample_count = 1, .sample_duration = 5}),
         shiguredo::mp4::box::SttsEntry({.sample_count = 1, .sample_duration = 10})},
    },
    {
        {10, 10, 5},
        {
            shiguredo::mp4::box::SttsEntry({.sample_count = 2, .sample_duration = 10}),
            shiguredo::mp4::box::SttsEntry({.sample_count = 1, .sample_duration = 5}),
        },
    },
    {
        {},
        {},
    },
};

BOOST_AUTO_TEST_CASE(make_stts_entries) {
  BOOST_TEST_MESSAGE("make_stts_entries");
  for (const auto& tc : make_stts_entries_test_cases) {
    std::vector<shiguredo::mp4::box::SttsEntry> entries;
    shiguredo::mp4::track::make_stts_entries(&entries, tc.sample_duraitons);
    BOOST_REQUIRE_EQUAL_COLLECTIONS(std::begin(tc.entries), std::end(tc.entries), std::begin(entries),
                                    std::end(entries));
  }
}

struct MakeStscEntriesTestCase {
  const std::vector<shiguredo::mp4::track::ChunkInfo> chunk_offsets;
  const std::vector<shiguredo::mp4::box::StscEntry> entries;
};

MakeStscEntriesTestCase make_stsc_entries_test_cases[] = {
    {{
         shiguredo::mp4::track::ChunkInfo{.number_of_samples = 10},
         shiguredo::mp4::track::ChunkInfo{.number_of_samples = 10},
     },
     {
         shiguredo::mp4::box::StscEntry({.first_chunk = 1, .samples_per_chunk = 10}),
     }},
    {{
         shiguredo::mp4::track::ChunkInfo{.number_of_samples = 10},
         shiguredo::mp4::track::ChunkInfo{.number_of_samples = 5},
         shiguredo::mp4::track::ChunkInfo{.number_of_samples = 10},
     },
     {
         shiguredo::mp4::box::StscEntry({.first_chunk = 1, .samples_per_chunk = 10}),
         shiguredo::mp4::box::StscEntry({.first_chunk = 2, .samples_per_chunk = 5}),
         shiguredo::mp4::box::StscEntry({.first_chunk = 3, .samples_per_chunk = 10}),
     }},
    {{
         shiguredo::mp4::track::ChunkInfo{.number_of_samples = 10},
         shiguredo::mp4::track::ChunkInfo{.number_of_samples = 10},
         shiguredo::mp4::track::ChunkInfo{.number_of_samples = 5},
     },
     {
         shiguredo::mp4::box::StscEntry({.first_chunk = 1, .samples_per_chunk = 10}),
         shiguredo::mp4::box::StscEntry({.first_chunk = 3, .samples_per_chunk = 5}),
     }},
    {
        {},
        {},
    },
};

BOOST_AUTO_TEST_CASE(make_stsc_entries) {
  BOOST_TEST_MESSAGE("make_stsc_entries");
  for (const auto& tc : make_stsc_entries_test_cases) {
    std::vector<shiguredo::mp4::box::StscEntry> entries;
    shiguredo::mp4::track::make_stsc_entries(&entries, tc.chunk_offsets);
    BOOST_REQUIRE_EQUAL_COLLECTIONS(std::begin(tc.entries), std::end(tc.entries), std::begin(entries),
                                    std::end(entries));
  }
}

struct MakeOffsetBoxTestCase {
  const std::vector<shiguredo::mp4::track::ChunkInfo> chunk_offsets;
  const bool use_co64;
  shiguredo::mp4::Box* box;
};

MakeOffsetBoxTestCase make_offset_box_test_cases[] = {
    {
        {},
        false,
        new shiguredo::mp4::box::Stco({.chunk_offsets = {}}),
    },
    {
        {
            shiguredo::mp4::track::ChunkInfo{.offset = 10},
            shiguredo::mp4::track::ChunkInfo{.offset = 15},
            shiguredo::mp4::track::ChunkInfo{.offset = 20},
        },
        false,
        new shiguredo::mp4::box::Stco({.chunk_offsets = {10, 15, 20}}),
    },
    {
        {
            shiguredo::mp4::track::ChunkInfo{.offset = 10},
            shiguredo::mp4::track::ChunkInfo{.offset = 15},
            shiguredo::mp4::track::ChunkInfo{.offset = 0xffffffff},
        },
        false,
        new shiguredo::mp4::box::Stco({.chunk_offsets = {10, 15, 0xffffffff}}),
    },
    {
        {
            shiguredo::mp4::track::ChunkInfo{.offset = 10},
            shiguredo::mp4::track::ChunkInfo{.offset = 15},
            shiguredo::mp4::track::ChunkInfo{.offset = 0x100000000},
        },
        true,
        new shiguredo::mp4::box::Co64({.chunk_offsets = {10, 15, 0x100000000}}),
    },
};

BOOST_AUTO_TEST_CASE(make_offset_box) {
  BOOST_TEST_MESSAGE("make_offset_box");
  for (const auto& tc : make_offset_box_test_cases) {
    const auto box = shiguredo::mp4::track::make_offset_box(tc.chunk_offsets);
    if (tc.use_co64) {
      const shiguredo::mp4::box::Co64* expected = dynamic_cast<shiguredo::mp4::box::Co64*>(tc.box);
      const shiguredo::mp4::box::Co64* actual = dynamic_cast<shiguredo::mp4::box::Co64*>(box);
      BOOST_REQUIRE(expected != nullptr);
      BOOST_REQUIRE(actual != nullptr);
      BOOST_REQUIRE_EQUAL(*expected, *actual);
    } else {
      const shiguredo::mp4::box::Stco* expected = dynamic_cast<shiguredo::mp4::box::Stco*>(tc.box);
      const shiguredo::mp4::box::Stco* actual = dynamic_cast<shiguredo::mp4::box::Stco*>(box);
      BOOST_REQUIRE(expected != nullptr);
      BOOST_REQUIRE(actual != nullptr);
      BOOST_REQUIRE_EQUAL(*expected, *actual);
    }
    delete tc.box;
    delete box;
  }
}

BOOST_AUTO_TEST_SUITE_END()


text:
// Copyright (C) 2020 T. Zachary Laine
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#include <boost/text/transcode_iterator.hpp>
#include <boost/text/transcode_algorithm.hpp>

#ifndef NO_ICU
#include <unicode/unistr.h>
U_NAMESPACE_USE
#endif

#include <benchmark/benchmark.h>

#include <algorithm>
#include <fstream>
#include <iostream>

std::string file_slurp(std::string filename)
{
    std::string retval;
    std::ifstream ifs(filename);
    while (ifs) {
        char const c = ifs.get();
        retval += c;
    }
    return retval;
}

std::string get_utf8_text()
{
    std::string retval = file_slurp("portuguese_wiki.txt") +
                         file_slurp("korean_wiki.txt") +
                         file_slurp("chinese_wiki.txt") +
                         file_slurp("hindi_wiki_in_russian.txt") +
                         file_slurp("perf/portuguese_wiki.txt") +
                         file_slurp("perf/korean_wiki.txt") +
                         file_slurp("perf/chinese_wiki.txt") +
                         file_slurp("perf/hindi_wiki_in_russian.txt") +
                         file_slurp("../perf/portuguese_wiki.txt") +
                         file_slurp("../perf/korean_wiki.txt") +
                         file_slurp("../perf/chinese_wiki.txt") +
                         file_slurp("../perf/hindi_wiki_in_russian.txt");
    return retval;
}

std::string const utf8_text = get_utf8_text();

using namespace boost;

#ifndef NO_ICU
void BM_8_to_16_algorithm_icu(benchmark::State & state)
{
    while (state.KeepRunning()) {
        UnicodeString str;
        benchmark::DoNotOptimize(str.fromUTF8(utf8_text.c_str()));
        benchmark::ClobberMemory();
    }
}
#endif

void BM_8_to_16_algorithm_no_alloc(benchmark::State & state)
{
    std::vector<uint16_t> utf16_result(utf8_text.size());
    while (state.KeepRunning()) {
        auto out = text::transcode_to_utf16(utf8_text, utf16_result.begin());
        (void)out;
        benchmark::ClobberMemory();
    }
}

void BM_8_to_16_algorithm_no_simd_no_alloc(benchmark::State & state)
{
    std::vector<uint16_t> utf16_result(utf8_text.size());
    while (state.KeepRunning()) {
        auto out = text::detail::transcode_utf_8_to_16<false>(
            utf8_text.begin(),
            utf8_text.end(),
            -1,
            utf16_result.begin(),
            std::input_iterator_tag{});
        (void)out;
        benchmark::ClobberMemory();
    }
}

void BM_8_to_16_algorithm_no_alloc_pointer(benchmark::State & state)
{
    std::vector<uint16_t> utf16_result(utf8_text.size());
    while (state.KeepRunning()) {
        auto out = text::transcode_to_utf16(
            &*utf8_text.begin(), &*utf8_text.end(), &*utf16_result.begin());
        (void)out;
        benchmark::ClobberMemory();
    }
}

void BM_8_to_16_algorithm_prealloc(benchmark::State & state)
{
    while (state.KeepRunning()) {
        std::vector<uint16_t> utf16_result(utf8_text.size());
        auto out = text::transcode_to_utf16(utf8_text, utf16_result.begin());
        utf16_result.resize(out - utf16_result.begin());
        benchmark::ClobberMemory();
    }
}

void BM_8_to_16_algorithm_no_simd_prealloc(benchmark::State & state)
{
    while (state.KeepRunning()) {
        std::vector<uint16_t> utf16_result(utf8_text.size());
        auto out = text::detail::transcode_utf_8_to_16<false>(
                       utf8_text.begin(),
                       utf8_text.end(),
                       -1,
                       utf16_result.begin(),
                       std::input_iterator_tag{})
                       .out;
        utf16_result.resize(out - utf16_result.begin());
        benchmark::ClobberMemory();
    }
}

void BM_8_to_16_algorithm_prealloc_pointer(benchmark::State & state)
{
    while (state.KeepRunning()) {
        std::vector<uint16_t> utf16_result(utf8_text.size());
        auto out = text::transcode_to_utf16(
            &*utf8_text.begin(),
            &*utf8_text.begin() + utf8_text.size(),
            &*utf16_result.begin());
        utf16_result.resize(out - &*utf16_result.begin());
        benchmark::ClobberMemory();
    }
}

void BM_8_to_16_algorithm_no_simd_prealloc_pointer(benchmark::State & state)
{
    while (state.KeepRunning()) {
        std::vector<uint16_t> utf16_result(utf8_text.size());
        auto out = text::detail::transcode_utf_8_to_16<false>(
                       &*utf8_text.begin(),
                       &*utf8_text.begin() + utf8_text.size(),
                       -1,
                       &*utf16_result.begin(),
                       std::input_iterator_tag{})
                       .out;
        utf16_result.resize(out - &*utf16_result.begin());
        benchmark::ClobberMemory();
    }
}

void BM_8_to_16_iterator_prealloc(benchmark::State & state)
{
    while (state.KeepRunning()) {
        std::vector<uint16_t> utf16_result(utf8_text.size());
        auto out = std::copy(
            text::utf16_iterator(
                utf8_text.begin(), utf8_text.begin(), utf8_text.end()),
            text::utf16_iterator(
                utf8_text.begin(), utf8_text.end(), utf8_text.end()),
            utf16_result.begin());
        utf16_result.resize(out - utf16_result.begin());
        benchmark::ClobberMemory();
    }
}

void BM_8_to_16_algorithm(benchmark::State & state)
{
    while (state.KeepRunning()) {
        std::vector<uint16_t> utf16_result;
        text::transcode_to_utf16(utf8_text, std::back_inserter(utf16_result));
        benchmark::ClobberMemory();
    }
}

void BM_8_to_16_algorithm_no_simd(benchmark::State & state)
{
    while (state.KeepRunning()) {
        std::vector<uint16_t> utf16_result;
        text::detail::transcode_utf_8_to_16<false>(
            utf8_text.begin(),
            utf8_text.end(),
            -1,
            std::back_inserter(utf16_result),
            std::input_iterator_tag{})
            .out;
        benchmark::ClobberMemory();
    }
}

void BM_8_to_16_iterator(benchmark::State & state)
{
    while (state.KeepRunning()) {
        std::vector<uint16_t> utf16_result;
        std::copy(
            text::utf16_iterator(
                utf8_text.begin(), utf8_text.begin(), utf8_text.end()),
            text::utf16_iterator(
                utf8_text.begin(), utf8_text.end(), utf8_text.end()),
            std::back_inserter(utf16_result));
        benchmark::ClobberMemory();
    }
}

void BM_8_to_32_algorithm_no_alloc(benchmark::State & state)
{
    std::vector<uint16_t> utf16_result(utf8_text.size());
    while (state.KeepRunning()) {
        auto out = text::transcode_to_utf32(utf8_text, utf16_result.begin());
        (void)out;
        benchmark::ClobberMemory();
    }
}

void BM_8_to_32_algorithm_no_simd_no_alloc(benchmark::State & state)
{
    std::vector<uint16_t> utf16_result(utf8_text.size());
    while (state.KeepRunning()) {
        auto out = text::detail::transcode_utf_8_to_32<false>(
                       utf8_text.begin(),
                       utf8_text.end(),
                       -1,
                       utf16_result.begin(),
                       std::input_iterator_tag{})
                       .out;
        (void)out;
        benchmark::ClobberMemory();
    }
}

void BM_8_to_32_algorithm_no_alloc_pointer(benchmark::State & state)
{
    std::vector<uint16_t> utf16_result(utf8_text.size());
    while (state.KeepRunning()) {
        auto out = text::transcode_to_utf32(
            &*utf8_text.begin(), &*utf8_text.end(), &*utf16_result.begin());
        (void)out;
        benchmark::ClobberMemory();
    }
}

void BM_8_to_32_algorithm_prealloc(benchmark::State & state)
{
    while (state.KeepRunning()) {
        std::vector<uint32_t> utf32_result(utf8_text.size());
        auto out = text::transcode_to_utf32(utf8_text, utf32_result.begin());
        utf32_result.resize(out - utf32_result.begin());
        benchmark::ClobberMemory();
    }
}

void BM_8_to_32_algorithm_no_simd_prealloc(benchmark::State & state)
{
    while (state.KeepRunning()) {
        std::vector<uint32_t> utf32_result(utf8_text.size());
        auto out = text::detail::transcode_utf_8_to_32<false>(
                       utf8_text.begin(),
                       utf8_text.end(),
                       -1,
                       utf32_result.begin(),
                       std::input_iterator_tag{})
                       .out;
        utf32_result.resize(out - utf32_result.begin());
        benchmark::ClobberMemory();
    }
}

void BM_8_to_32_algorithm_prealloc_pointer(benchmark::State & state)
{
    while (state.KeepRunning()) {
        std::vector<uint32_t> utf32_result(utf8_text.size());
        auto out = text::transcode_to_utf32(
            &*utf8_text.begin(),
            &*utf8_text.begin() + utf8_text.size(),
            &*utf32_result.begin());
        utf32_result.resize(out - &*utf32_result.begin());
        benchmark::ClobberMemory();
    }
}

void BM_8_to_32_algorithm_no_simd_prealloc_pointer(benchmark::State & state)
{
    while (state.KeepRunning()) {
        std::vector<uint32_t> utf32_result(utf8_text.size());
        auto out = text::detail::transcode_utf_8_to_32<false>(
                       &*utf8_text.begin(),
                       &*utf8_text.begin() + utf8_text.size(),
                       -1,
                       &*utf32_result.begin(),
                       std::input_iterator_tag{})
                       .out;
        utf32_result.resize(out - &*utf32_result.begin());
        benchmark::ClobberMemory();
    }
}

void BM_8_to_32_iterator_prealloc(benchmark::State & state)
{
    while (state.KeepRunning()) {
        std::vector<uint32_t> utf32_result(utf8_text.size());
        auto out = std::copy(
            text::utf32_iterator(
                utf8_text.begin(), utf8_text.begin(), utf8_text.end()),
            text::utf32_iterator(
                utf8_text.begin(), utf8_text.end(), utf8_text.end()),
            utf32_result.begin());
        utf32_result.resize(out - utf32_result.begin());
        benchmark::ClobberMemory();
    }
}

void BM_8_to_32_algorithm(benchmark::State & state)
{
    while (state.KeepRunning()) {
        std::vector<uint32_t> utf32_result;
        text::transcode_to_utf32(utf8_text, std::back_inserter(utf32_result));
        benchmark::ClobberMemory();
    }
}

void BM_8_to_32_algorithm_no_simd(benchmark::State & state)
{
    while (state.KeepRunning()) {
        std::vector<uint32_t> utf32_result;
        text::detail::transcode_utf_8_to_32<false>(
            utf8_text.begin(),
            utf8_text.end(),
            -1,
            std::back_inserter(utf32_result),
            std::input_iterator_tag{})
            .out;
        benchmark::ClobberMemory();
    }
}

void BM_8_to_32_iterator(benchmark::State & state)
{
    while (state.KeepRunning()) {
        std::vector<uint32_t> utf32_result;
        std::copy(
            text::utf32_iterator(
                utf8_text.begin(), utf8_text.begin(), utf8_text.end()),
            text::utf32_iterator(
                utf8_text.begin(), utf8_text.end(), utf8_text.end()),
            std::back_inserter(utf32_result));
        benchmark::ClobberMemory();
    }
}

#ifndef NO_ICU
BENCHMARK(BM_8_to_16_algorithm_icu);
#endif
BENCHMARK(BM_8_to_16_algorithm_no_alloc);
BENCHMARK(BM_8_to_16_algorithm_no_simd_no_alloc);
BENCHMARK(BM_8_to_16_algorithm_no_alloc_pointer);
BENCHMARK(BM_8_to_16_algorithm_prealloc);
BENCHMARK(BM_8_to_16_algorithm_no_simd_prealloc);
BENCHMARK(BM_8_to_16_algorithm_prealloc_pointer);
BENCHMARK(BM_8_to_16_algorithm_no_simd_prealloc_pointer);
BENCHMARK(BM_8_to_16_iterator_prealloc);
BENCHMARK(BM_8_to_16_algorithm);
BENCHMARK(BM_8_to_16_algorithm_no_simd);
BENCHMARK(BM_8_to_16_iterator);

BENCHMARK(BM_8_to_32_algorithm_no_alloc);
BENCHMARK(BM_8_to_32_algorithm_no_simd_no_alloc);
BENCHMARK(BM_8_to_32_algorithm_no_alloc_pointer);
BENCHMARK(BM_8_to_32_algorithm_prealloc);
BENCHMARK(BM_8_to_32_algorithm_no_simd_prealloc);
BENCHMARK(BM_8_to_32_algorithm_prealloc_pointer);
BENCHMARK(BM_8_to_32_algorithm_no_simd_prealloc_pointer);
BENCHMARK(BM_8_to_32_iterator_prealloc);
BENCHMARK(BM_8_to_32_algorithm);
BENCHMARK(BM_8_to_32_algorithm_no_simd);
BENCHMARK(BM_8_to_32_iterator);

BENCHMARK_MAIN()

ext: cpp

max_stars_repo_name: Ryan-rsm-McKenzie/text

max_issues_repo_name: Ryan-rsm-McKenzie/text

max_forks_repo_name: Ryan-rsm-McKenzie/text


text:
/********************************************************************************
 * Copyright 2009 The Robotics Group, The Maersk Mc-Kinney Moller Institute,
 * Faculty of Engineering, University of Southern Denmark
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 ********************************************************************************/

#ifndef RWSIM_DYNAMICS_DYNAMICWORKCELL_HPP_
#define RWSIM_DYNAMICS_DYNAMICWORKCELL_HPP_

#include "Body.hpp"
#include "Constraint.hpp"
#include "ContactDataMap.hpp"
#include "DynamicDevice.hpp"
#include "MaterialDataMap.hpp"

#include <rw/core/Event.hpp>
#include <rw/core/PropertyMap.hpp>
#include <rw/core/Ptr.hpp>
#include <rw/models/WorkCell.hpp>
#include <rwlibs/simulation/SimulatedController.hpp>
#include <rwlibs/simulation/SimulatedSensor.hpp>

#include <boost/any.hpp>
#include <map>
#include <vector>
namespace rwsim { namespace dynamics {
    //! @addtogroup rwsim_dynamics
    //! @{
    /**
     * @brief the WorkCellDimension describe a center and the box halflengths of
     * the space that the WorkCell expands.
     *
     */
    struct WorkCellDimension
    {
      public:
        /**
         * @brief Constructor.
         * @param c [in] center.
         * @param box [in] the halflengths of the workspace.
         */
        WorkCellDimension (const rw::math::Vector3D<>& c, const rw::math::Vector3D<>& box) :
            center (c), boxDim (box)
        {}
        //! @brief The center of the workspace.
        rw::math::Vector3D<> center;
        //! @brief The halftlengths of the workspace.
        rw::math::Vector3D<> boxDim;
    };

    /**
     * @brief the DynamicWorkcell class is a container class for dynamic
     * information/data in a workcell, much like WorkCell is a container
     * class for the kinematic information/data in a workcell
     *
     * The dynamic description includes:
     * - Body: severel different forms of bodies that may be constrained by rules
     * - Constraint: constraining the bodies to move in a specific way relative to each other
     * - Controllers: severel controllers that in some way control/influence the bodies
     * - Sensors: bodies that have tactile sensing capability
     *
     */
    class DynamicWorkCell
    {
      public:
        //! @brief Type for the collection of bodies.
        typedef std::vector< Body::Ptr > BodyList;
        //! @brief Type for the collection of constraints.
        typedef std::vector< Constraint::Ptr > ConstraintList;
        //! @brief Type for the collection of devices.
        typedef std::vector< DynamicDevice::Ptr > DeviceList;
        //! @brief Type for the collection of simulated controllers.
        typedef std::vector< rwlibs::simulation::SimulatedController::Ptr > ControllerList;
        //! @brief Type for the collection of simulated sensors.
        typedef std::vector< rwlibs::simulation::SimulatedSensor::Ptr > SensorList;
        //! @brief Smart pointer type for DynamicWorkCell.
        typedef rw::core::Ptr< DynamicWorkCell > Ptr;
        //! @brief Smart pointer type for const DynamicWorkCell.
        typedef rw::core::Ptr< const DynamicWorkCell > CPtr;

        /**
         * @brief Constructor
         * @param workcell [in] a smart pointer to the rw::models::WorkCell
         */
        DynamicWorkCell (rw::models::WorkCell::Ptr workcell);

        /**
         * @brief Constructor
         * @param workcell [in] a smart pointer to the rw::models::WorkCell
         * @param bodies [in] a list of bodies.
         * @param allbodies [in] a list of bodies.
         * @param constraints [in] a list of constraints.
         * @param devices [in] a list of devices.
         * @param controllers [in] a list of controllers.
         */
        DynamicWorkCell (rw::models::WorkCell::Ptr workcell, const BodyList& bodies,
                         const BodyList& allbodies, const ConstraintList& constraints,
                         const DeviceList& devices, const ControllerList& controllers);

        /**
         * @brief destructor
         */
        virtual ~DynamicWorkCell ();

        /**
         * @brief gets a list of all bodies in the dynamic workcell
         */
        const BodyList& getBodies () const { return _allbodies; };

        /**
         * @brief find a specific body with name \b name
         * @param name [in] name of body
         * @return body if found, NULL otherwise
         */
        Body::Ptr findBody (const std::string& name) const;

        /**
         * @brief find a specific body with name \b name and type \b T
         * @param name [in] name of body
         * @return body if found, NULL otherwise
         */
        template< class T > rw::core::Ptr< T > findBody (const std::string& name) const
        {
            Body::Ptr body = findBody (name);
            if (body == NULL)
                return NULL;
            return body.cast< T > ();
        }

        /**
         * @brief find all bodies with type \b T
         * @return list of all bodies of type \b T
         */
        template< class T > std::vector< rw::core::Ptr< T > > findBodies () const
        {
            std::vector< rw::core::Ptr< T > > bodies;
            for (const Body::Ptr b : _allbodies) {
                if (rw::core::Ptr< T > tb = b.cast< T > ()) {
                    bodies.push_back (tb);
                }
            }
            return bodies;
        }

        /**
         * @brief Add a constraint to the dynamic workcell.
         * @param constraint [in] a smart pointer to the constraint to add.
         */
        void addConstraint (Constraint::Ptr constraint);

        /**
         * @brief gets a list of all constraints in the dynamic workcell
         */
        const ConstraintList& getConstraints () const { return _constraints; }

        /**
         * @brief find a specific constraint with name \b name
         * @param name [in] name of constraint
         * @return constraint if found, NULL otherwise
         */
        Constraint::Ptr findConstraint (const std::string& name) const;

        /**
         * @brief gets a list of all dynamic devices in the dynamic workcell
         * @return a list of dynamic devices.
         */
        const DeviceList& getDynamicDevices () const { return _devices; };

        /**
         * @brief add a device to the dynamic workcell
         * @param device [in] a device
         */
        void addDevice (DynamicDevice::Ptr device)
        {
            device->registerIn (_workcell->getStateStructure ());
            _devices.push_back (device);
            _changedEvent.fire (DeviceAddedEvent, boost::any (device));
        };

        /**
         * @brief find a dynamic device of name \b name
         * @param name [in] name of device
         * @return a device with name \b name or null
         */
        DynamicDevice::Ptr findDevice (const std::string& name) const;

        /**
         * @brief find a specific device with name \b name and type \b T
         * @param name [in] name of body
         * @return body if found, NULL otherwise
         */
        template< class T > rw::core::Ptr< T > findDevice (const std::string& name) const
        {
            DynamicDevice::Ptr dev = findDevice (name);
            if (dev == NULL)
                return NULL;
            return dev.cast< T > ();
        }

        /**
         * @brief gets a list of all controllers in the dynamic workcell
         */
        const ControllerList& getControllers () const { return _controllers; }

        /**
         * @brief get the list of sensors
         */
        const SensorList& getSensors () const { return _sensors; };

        /**
         * @brief add a sensor to the dynamic workcell
         * @param sensor [in] a simulated sensor
         */
        void addSensor (rwlibs::simulation::SimulatedSensor::Ptr sensor);

        /**
         * @brief find a sensor
         * @param name [in] the sensor
         * @return
         */
        rwlibs::simulation::SimulatedSensor::Ptr findSensor (const std::string& name) const;

        /**
         * @brief find a sensor of a specific type.
         * @param name [in] name of sensor
         * @return
         */
        template< class T > rw::core::Ptr< T > findSensor (const std::string& name) const
        {
            rwlibs::simulation::SimulatedSensor::Ptr sensor = findSensor (name);
            if (sensor == NULL)
                return NULL;
            return sensor.cast< T > ();
        }

        /**
         * @brief adds a body to the dynamic workcell.
         *
         * Notice that this will change the length of the default
         * State.
         */
        void addBody (Body::Ptr body);

        /**
         * @brief adds a body controller to the dynamic workcell.
         *
         * Notice that this will change the length of the default
         * State.
         */
        void addController (rwlibs::simulation::SimulatedController::Ptr manipulator)
        {
            // TODO: change STATE and WorkCell accordingly
            if (!manipulator->getControllerModel ()->isRegistered ())
                _workcell->add (manipulator->getControllerModel ());
            if (!manipulator->isRegistered ())
                manipulator->registerIn (_workcell->getStateStructure ());

            _controllers.push_back (manipulator);
            _changedEvent.fire (ControllerAddedEvent, boost::any (manipulator));
        }

        /**
         * @brief Find a simulated controller.
         * @param name [in] name of the controller.
         * @return the simulated controller if found, NULL otherwise.
         */
        rwlibs::simulation::SimulatedController::Ptr findController (const std::string& name) const;

        /**
         * @brief Find a simulated controller.
         * @param name [in] name of the controller.
         * @return the simulated controller if found, NULL otherwise.
         */
        template< class T > rw::core::Ptr< T > findController (const std::string& name) const
        {
            rwlibs::simulation::SimulatedController::Ptr controller = findController (name);
            if (controller == NULL)
                return NULL;
            return controller.cast< T > ();
        }

        /**
         * @brief gets the static contact data information
         */
        ContactDataMap& getContactData () { return _contactDataMap; }

        /**
         * @brief Get the static contact data information.
         * @return a reference to a constant rwsim::dynamics::ContactDataMap.
         */
        const ContactDataMap& getContactData () const { return _contactDataMap; }

        /**
         * @brief gets the material data information, like friction
         * properties
         */
        MaterialDataMap& getMaterialData () { return _matDataMap; }

        /**
         * @brief Get the material data information, like friction.
         * @return a reference to a constant rwsim::dynamics::ContactDataMap.
         */
        const MaterialDataMap& getMaterialData () const { return _matDataMap; }

        /**
         * @brief gets the body associated with frame f if any.
         */
        Body::Ptr getBody (rw::kinematics::Frame* f);

        /**
         * @brief gets the default kinematic workcell
         */
        rw::models::WorkCell::Ptr getWorkcell () const { return _workcell; };

        /**
         * @brief the collision margin describe how close
         */
        double getCollisionMargin () { return _collisionMargin; }

        /**
         * @brief Set the collision margin.
         * @param margin [in] the new margin.
         */
        void setCollisionMargin (double margin) { _collisionMargin = margin; }

        /**
         * @brief Get dimensions of workspace.
         * @return the dimensions.
         */
        WorkCellDimension getWorldDimension () { return _worldDimension; }

        /**
         * @brief tests if a body is part of a device
         * @param body [in] the body to test for.
         * @return true if body is part of the device.
         */
        bool inDevice (rw::core::Ptr< const Body > body) const;

        /**
         * @brief Set the gravity in this dynamic workcell
         * @return gravity
         */
        void setGravity (const rw::math::Vector3D<>& grav)
        {
            _gravity = grav;
            _changedEvent.fire (GravityChangedEvent, boost::any (grav));
        }

        /**
         * @brief get the gravity in this dynamic workcell
         * @return gravity
         */
        const rw::math::Vector3D<>& getGravity () const { return _gravity; }

        /**
         * @brief get the settings and properties for the physics engine
         * @return propertymap
         */
        rw::core::PropertyMap& getEngineSettings () { return _engineSettings; }

        /**
         * @brief Get the settings and properties for the physics engine.
         * @return a reference to a constant PropertyMap.
         */
        const rw::core::PropertyMap& getEngineSettings () const { return _engineSettings; }

        //! @brief Types of events a DynamicWorkCell can emit.
        typedef enum {
            GravityChangedEvent,     //!< If the gravity is changed.
            ConstraintAddedEvent,    //!< When a constraint is added.
            BodyAddedEvent,          //!< When a body is added.
            DeviceAddedEvent,        //!< When a device is added.
            ControllerAddedEvent,    //!< When a controller is added.
            SensorAddedEvent         //!< When a sensor is added.
        } DWCEventType;

        //! @brief Type for an event listener.
        typedef boost::function< void (DWCEventType, boost::any) > DWCChangedListener;
        //! @brief Type for the event.
        typedef rw::core::Event< DWCChangedListener, DWCEventType, boost::any > DWCChangedEvent;

        /**
         * @brief Returns StateChangeEvent needed for subscribing and firing the event.
         * @return Reference to the StateChangedEvent
         */
        DWCChangedEvent& changedEvent () { return _changedEvent; }

      private:
        DWCChangedEvent _changedEvent;
        // the workcell
        rw::models::WorkCell::Ptr _workcell;
        // length of nr of bodies
        BodyList _bodies;
        BodyList _allbodies;
        ConstraintList _constraints;
        DeviceList _devices;
        // list of controllers in the workcell
        ControllerList _controllers;

        double _collisionMargin;
        WorkCellDimension _worldDimension;
        rw::math::Vector3D<> _gravity;

        // list of sensors
        SensorList _sensors;

        // deprecated
        std::map< rw::kinematics::Frame*, Body::Ptr > _frameToBody;

        MaterialDataMap _matDataMap;
        ContactDataMap _contactDataMap;

        rw::core::PropertyMap _engineSettings;
    };
    //! @}
}}    // namespace rwsim::dynamics

#endif /*DYNAMICWORKCELL_HPP_*/

ext: hpp


text:
#include <memory>
#include <mutex>
#include <optional>
#include <string_view>
#include <unordered_set>

#include <boost/json/value.hpp>
namespace json = boost::json;
#include "json_diff.hpp"
#include <boost/json/serialize.hpp>

#include <libtorrent/config.hpp>

#include "handlers.hpp"
#include "http_websocket.hpp"
#include "log.hpp"

namespace btd {

httpCaller::
httpCaller(std::shared_ptr<sheath> const& shth,
	std::string ui_dir)
	 : shth_(shth)
	 , ui_root_(ui_dir)
{}

const std::optional<http::response<string_body>>
httpCaller::
sbCall(http::request<string_body> const& req)
{
	if (req.target().find("/api/") == std::string_view::npos) return std::nullopt;
	auto uri = req.target().substr(4);
	if (req.method() == verb::get && uri == "/session"sv) return handleSessionInfo(req);
	if (req.method() == verb::get && uri == "/session/stats"sv) return handleSessionStats(req);
	if (req.method() == verb::get && uri == "/sync/stats"sv) return handleSyncStats(req);
	if (uri == "/torrents"sv) return handleTorrents(req);

    if (uri.find("/torrent/") == 0) return handleTorrent(req, 13); // len(/api/torrent/) == 13

    if (req.method() == verb::put && uri == "/session/toggle"sv)
        return handleSessionToggle(req);

    // TODO: more routes
    return std::nullopt;
}

http::response<string_body>
httpCaller::
handleSessionInfo(http::request<string_body> const& req)
{
    return make_resp<string_body>(req, json::serialize(shth_->getSessionInfo()), ctJSON);
}

http::response<string_body>
httpCaller::
handleSessionStats(http::request<string_body> const& req)
{
	return make_resp<string_body>(req, json::serialize(shth_->getSessionStats()), ctJSON);
}

http::response<string_body>
httpCaller::
handleSessionToggle(http::request<string_body> const& req)
{
    json::object ret({{"isPaused", shth_->toggle_pause_resume()}});
    return make_resp<string_body>(req, json::serialize(ret), ctJSON);
}

http::response<string_body>
httpCaller::
handleSyncStats(http::request<string_body> const& req)
{
	return make_resp<string_body>(req, json::serialize(shth_->getSyncStats()), ctJSON);
}

http::response<string_body>
httpCaller::
handleTorrents(http::request<string_body> const& req) // get or post
{
    if (req.method() == verb::get) {
        return make_resp<string_body>(req, json::serialize(shth_->get_torrents()), ctJSON);
    }

	if (req.method() == verb::post) {
		PLOGD_(WebLog) << "posted " << req.find(http::field::content_length)->value() << " bytes\n";
		std::string dir(shth_->dir_store.string());
		auto savePath = req.find("x-save-path");
		if (savePath != req.end()) {
			dir = savePath->value();
		}
        if (req[http::field::content_type] == ctTorrent) {
            if (shth_->add_torrent(req.body().data(), req.body().size(), dir)) {
                return make_resp_204(req);
            }
            return make_resp_500(req, "failed to add with metainfo");
        }

        if (shth_->add_magnet(req.body())) { return make_resp_204(req); }
        return make_resp_500(req, "failed to add with magnet");
	}

	return make_resp_400(req, "Unsupported method");
}

// handle a torrent with GET or POST or DELETE
http::response<string_body>
httpCaller::
handleTorrent(http::request<string_body> const& req, size_t const offset)
{
	// len(/api/torrent/{info_hash}/{act}?) >= 4 + 9 + 40
	const std::string s(req.target().data(), req.target().size());
	const size_t ih_size = 40;
	const size_t min_size = offset+ih_size;
	if (s.size() < min_size) return make_resp_404(req);

	lt::sha1_hash ih;
	if (!from_hex(ih, s.substr(offset, ih_size)))
	{
		return make_resp_400(req, "invalid hash string");
	}
	if (req.method() == verb::head)
	{
		if (shth_->exists(ih))
		{
			return make_resp_204(req);
		}
		return make_resp_404(req);
	}
	std::string act = "";
	if (s.size() > min_size + 1)
	{
		act = s.substr(min_size + 1);
	}
	if (req.method() == verb::get)
	{
		auto flag = sheath::query_basic;
		if ("peers" == act) flag = sheath::query_peers;
		else if ("files" == act) flag = sheath::query_files;
		auto jv = shth_->get_torrent(ih, flag);
		if (jv.is_null()) { return make_resp_404(req); }
		return make_resp<string_body>(req, json::serialize(jv), ctJSON);
	}
	if (req.method() == verb::delete_)
	{
		shth_->drop_torrent(ih, ("yes" == act || "with_data" == act));
		return make_resp_204(req);
	}
    if (req.method() == verb::put) {

        if ("toggle" == act || "pause" == act)
            shth_->pause_resume_torrent(ih);

        else if ("start" == act || "resume" == act)
            shth_->resume_torrent(ih);

        return make_resp_204(req);
    }

    return make_resp_400(req, "Unsupported method");
}

void
httpCaller::
join(websocket_session* wss)
{
    std::lock_guard<std::mutex> lock(mutex_);
    sessions_.insert(wss);
    sync_ver ++;
    auto qid = wss->qid();
    if (qid.empty()) qid = n2hex(randNum(1000, 9999));
    if (curr_stats.is_null()) curr_stats = getSyncStats();
    json::value jv({
        {"version", sync_ver.load()}
        ,{"id", qid}
        ,{"body", curr_stats}
    });
    PLOGD_(WebLog) << "ws joinning " << sync_ver.load();
    wss->send(std::make_shared<std::string const>(json::serialize(jv)));
}

void
httpCaller::
leave(websocket_session* wss)
{
    std::lock_guard<std::mutex> lock(mutex_);
    sessions_.erase(wss);
    PLOGD_(WebLog) << "ws leaved";
}

// Broadcast a message to all websocket client sessions
void
httpCaller::
broadcast(std::string message)
{
    // Put the message in a shared pointer so we can re-use it for each client
    auto const ss = std::make_shared<std::string const>(std::move(message));

    // Make a local list of all the weak pointers representing
    // the sessions, so we can do the actual sending without
    // holding the mutex:
    std::vector<std::weak_ptr<websocket_session>> vws;
    {
        std::lock_guard<std::mutex> lock(mutex_);
        vws.reserve(sessions_.size());
        for(auto p : sessions_)
            vws.emplace_back(p->weak_from_this());
    }

    // For each session in our local list, try to acquire a strong
    // pointer. If successful, then send the message on that session.
    for(auto const& wp : vws)
        if(auto sp = wp.lock())
            sp->send(ss);
}

void
httpCaller::
closeWS()
{
    std::lock_guard<std::mutex> lock(mutex_);
	for(auto p : sessions_)
		p->close("close by caller");
}

json::value
httpCaller::
getSyncStats()
{
	return shth_->getSyncStats();
}

void
httpCaller::
doLoop()
{
    if (sessions_.empty())
    {
    	std::this_thread::sleep_for(std::chrono::seconds(20));
    	return;
    }
    std::this_thread::sleep_for(std::chrono::seconds(1));
    sync_ver ++;
    curr_stats = shth_->getSyncStats();
    json::value jv({
        {"version", sync_ver.load()}
        ,{"delta", true}
        ,{"body", json_diff(prev_stats, curr_stats)}
    });
    broadcast(json::serialize(jv));
    // std::clog << sync_ver.load() << " ";
	prev_stats = curr_stats;

}

} // namespace btd

max_stars_repo_name: liut/kedge

max_issues_repo_name: liut/kedge

max_forks_repo_name: liut/kedge


text:
// Copyright (c) 2019 Graphcore Ltd. All rights reserved.

#ifndef popnn_RnnUtil_hpp
#define popnn_RnnUtil_hpp

#include <boost/optional.hpp>
#include <cassert>
#include <cstdint>
#include <poplibs_support/Compiler.hpp>
#include <poplibs_support/gcd.hpp>
#include <poplin/ConvUtil.hpp>
#include <poplin/Convolution.hpp>
#include <poplin/MatMul.hpp>
#include <popnn/NonLinearity.hpp>
#include <popops/DynamicSlice.hpp>
#include <popops/ElementWise.hpp>
#include <popops/Rearrange.hpp>
#include <popops/Reduce.hpp>
#include <popops/ScaledAdd.hpp>
#include <popops/Zero.hpp>
#include <poputil/DebugInfo.hpp>
#include <poputil/OptionParsing.hpp>
#include <poputil/TileMapping.hpp>
#include <poputil/Util.hpp>
#include <poputil/VarStructure.hpp>
#include <poputil/VertexTemplates.hpp>

namespace popnn {
namespace Rnn {

// Flatten a 3D tensor to a 2D tensor such that the innermost dimension is the
// product of outputs(or inputs) and units
inline poplar::Tensor flattenUnits(const poplar::Tensor &t) {
  return t.dimShuffle({1, 0, 2}).reshape({t.dim(1), t.dim(0) * t.dim(2)});
}

// unflatten a 2D tensor which has units flattened in it's innermost dimension.
// The resultant 3D tensor view has the unit dimension as the outermost
// dimension
inline poplar::Tensor unflattenUnits(const poplar::Tensor &t, size_t num_unit) {
  return t.reshape({t.dim(0), num_unit, t.dim(1) / num_unit})
      .dimShuffle({1, 0, 2});
}

// Given a tensor of rank 2 that is laid out in memory such that groups of
// elements in the outermost dimension are contiguous try to rearrange it
// so groups of elements in the innermost dimension are contiguous.
// Returns either the original tensor or a copy of the original tensor
// with the same shape but a updated memory layout.
inline poplar::Tensor tryGroupedPartialTranspose(
    poplar::Graph &graph, poplar::Tensor t, unsigned desiredGrouping,
    poplar::program::Sequence &prog, const poplar::DebugNameAndId &dnai) {
  unsigned outerSize = t.dim(0);
  unsigned innerSize = t.dim(1);
  if (innerSize % desiredGrouping) {
    desiredGrouping = gcd(innerSize, desiredGrouping);
  }
  if (desiredGrouping == 1) {
    return t;
  }
  const auto outerGrouping =
      poputil::detectInnermostGrouping(graph, t.transpose());
  if (outerGrouping == 1) {
    return t;
  }
  auto groupedView = t.reshape({outerSize / outerGrouping, outerGrouping,
                                innerSize / desiredGrouping, desiredGrouping})
                         .dimShuffle({0, 2, 3, 1});
  auto cs = graph.addComputeSet({dnai, "groupedPartialTranspose"});
  auto partiallyTransposed =
      popops::rearrange::partialTranspose(graph, groupedView, cs, {dnai});
  prog.add(poplar::program::Execute(cs, {dnai}));
  return partiallyTransposed.dimShuffle({0, 2, 1, 3})
      .reshape({outerSize, innerSize});
}

/// Create a tensor with dimensions [sequenceLength, numGrains, grainSize]
/// that satisfies the following properties:
/// - Grains are never split across tiles.
/// - The tile mapping and layout is identical for each sub-tensor in the
///   sequence.
/// - The elements on a tile form a single contigous region where the
///   sequenceLength the outer dimension.
/// These properties make the tensor well suited for use with dynamic
/// slice / dynamic update
inline poplar::Tensor
createDynamicSliceTensor(poplar::Graph &graph, poplar::Type dataType,
                         unsigned sequenceLength, unsigned numGrains,
                         unsigned grainSize,
                         const poplar::DebugNameAndId &dnai) {
  const auto &target = graph.getTarget();
  const auto numTiles = target.getNumTiles();
  const auto grainsPerTile = (numGrains + numTiles - 1) / numTiles;
  const auto numUsedTiles = (numGrains + grainsPerTile - 1) / grainsPerTile;
  const auto grainsOnLastTile = numGrains - (numUsedTiles - 1) * grainsPerTile;
  auto tExcludingLast = graph.addVariable(
      dataType, {numUsedTiles - 1, sequenceLength, grainsPerTile, grainSize},
      {dnai});
  auto tLast = graph.addVariable(
      dataType, {sequenceLength, grainsOnLastTile, grainSize}, {dnai});
  for (unsigned tile = 0; tile != numTiles; ++tile) {
    unsigned usedTileIndex = tile * numUsedTiles / numTiles;
    if (usedTileIndex != (tile + 1) * numUsedTiles / numTiles) {
      if (usedTileIndex + 1 == numUsedTiles) {
        graph.setTileMapping(tLast, tile);
      } else {
        graph.setTileMapping(tExcludingLast[usedTileIndex], tile);
      }
    }
  }
  return concat(tExcludingLast.dimRoll(0, 1).flatten(1, 3), tLast, 1);
}

} // namespace Rnn
} // namespace popnn

#endif // #ifndef popnn_RnnUtil_hpp


text:
/*
 * Copyright (c) 2013 Juniper Networks, Inc. All rights reserved.
 */

#include "base/os.h"
#include "testing/gunit.h"
#include <boost/assign.hpp>

#include <sys/socket.h>
#include <netinet/if_ether.h>
#include <base/logging.h>

#include <io/event_manager.h>
#include <cmn/agent_cmn.h>
#include <oper/operdb_init.h>
#include <controller/controller_init.h>
#include <controller/controller_vrf_export.h>
#include <pkt/pkt_init.h>
#include <services/services_init.h>
#include <vrouter/ksync/ksync_init.h>
#include <oper/vrf.h>
#include <oper/mirror_table.h>
#include <pugixml/pugixml.hpp>
#include <services/icmpv6_proto.h>
#include <vr_interface.h>
#include <test/pkt_gen.h>
#include <test/test_cmn_util.h>
#include "vr_types.h"
#include "xmpp/test/xmpp_test_util.h"
#include <services/services_sandesh.h>
#include "oper/path_preference.h"
#include "services/ndp_entry.h"
#include "mac_learning/mac_learning_proto.h"
#include "mac_learning/mac_learning_mgmt.h"
#include "mac_learning/mac_learning_init.h"

using namespace std;
using namespace boost::assign;
using namespace boost::posix_time;

struct PortInfo input1[] = {
    {"vnet1", 1, "8.1.1.1", "00:00:00:01:01:01", 1, 1, "fd11::2"},
    {"vnet2", 2, "8.1.1.2", "00:00:01:01:01:02", 1, 1, "fd11::3"}
};

IpamInfo ipam_info[] = {
    {"fd11::", 120, "fd11::1"},
};

MacAddress src_mac(0x00, 0x01, 0x02, 0x03, 0x04, 0x05);
MacAddress dest_mac(0x00, 0x01, 0x02, 0x03, 0x04, 0x05);

class MacIp6LearningHCTest : public ::testing::Test {
protected:
    MacIp6LearningHCTest() {
        disable_na = false;
        TestPkt0Interface *tap = (TestPkt0Interface *)
                    (Agent::GetInstance()->pkt()->control_interface());
        tap->RegisterCallback(
                boost::bind(&MacIp6LearningHCTest::Pkt0IntfReceiveIPv6NS, this, _1, _2));
   }

    uint32_t Sum(uint16_t *ptr, std::size_t len, uint32_t sum) {
        while (len > 1) {
            sum += *ptr++;
            len -= 2;
            if (sum & 0x80000000)
                sum = (sum & 0xFFFF) + (sum >> 16);
        }

        if (len > 0)
            sum += *(uint8_t *)ptr;

        return sum;
    }

    uint16_t Csum(uint16_t *ptr, std::size_t len, uint32_t sum) {
        sum = Sum(ptr, len, sum);

        while (sum >> 16)
            sum = (sum & 0xFFFF) + (sum >> 16);

        return ~sum;
    }

    void SendND(short ifindex, short vrf, uint8_t *sip, uint8_t *tip,
                bool ns = true, bool solicit = false) {
        int len = ICMP_PKT_SIZE;
        uint8_t *ptr(new uint8_t[len]);
        uint8_t *buf  = ptr;
        memset(buf, 0, len);

        struct ether_header *eth = (struct ether_header *)buf;
        eth->ether_dhost[5] = 1;
        eth->ether_shost[5] = 2;
        eth->ether_type = htons(0x800);

        agent_hdr *agent = (agent_hdr *)(eth + 1);
        agent->hdr_ifindex = htons(ifindex);
        agent->hdr_vrf = htons(vrf);
        agent->hdr_cmd = htons(AgentHdr::TRAP_RESOLVE);

        eth = (struct ether_header *) (agent + 1);
        dest_mac.ToArray(eth->ether_dhost, sizeof(eth->ether_dhost));
        src_mac.ToArray(eth->ether_shost, sizeof(eth->ether_shost));
        eth->ether_type = htons(ETHERTYPE_IPV6);

        ip6_hdr *ip6 = (ip6_hdr *) (eth + 1);
        ip6->ip6_flow = htonl(0x60000000); // version 6, TC and Flow set to 0
        ip6->ip6_plen = htons(64);
        ip6->ip6_nxt = IPPROTO_ICMPV6;
        ip6->ip6_hlim = 16;
        memcpy(ip6->ip6_src.s6_addr, sip, 16);

        uint8_t *icmp;
        if (ns) {
            nd_neighbor_solicit *ns = (nd_neighbor_solicit *) (ip6 + 1);
            ns->nd_ns_type = ND_NEIGHBOR_SOLICIT;
            ns->nd_ns_code = 0;
            ns->nd_ns_reserved = 0;
            memcpy(ns->nd_ns_target.s6_addr, tip, 16);
            uint16_t offset = sizeof(nd_neighbor_solicit);
            dest_mac.ToArray(((uint8_t *)ns) + offset, sizeof(eth->ether_dhost));
        } else {
            nd_neighbor_advert *na = (nd_neighbor_advert *) (ip6 + 1);
            na->nd_na_type = ND_NEIGHBOR_ADVERT;
            na->nd_na_code = 0;
            na->nd_na_flags_reserved = ND_NA_FLAG_OVERRIDE;
            if (solicit)
                na->nd_na_flags_reserved = ND_NA_FLAG_SOLICITED;
            memcpy(na->nd_na_target.s6_addr, tip, 16);
            uint16_t offset = sizeof(nd_neighbor_advert);
            nd_opt_hdr *opt = (nd_opt_hdr *) (((uint8_t *)na) + offset);
            opt->nd_opt_type = ND_OPT_TARGET_LINKADDR;
            opt->nd_opt_len = 1;
            offset += sizeof(nd_opt_hdr);
            dest_mac.ToArray(((uint8_t *)na) + offset, sizeof(eth->ether_dhost));
        }
        uint32_t plen = htonl((uint32_t)64);
        uint32_t next = htonl((uint32_t)IPPROTO_ICMPV6);
        uint32_t pseudo = 0;
        pseudo = Sum((uint16_t *)sip, 16, 0);
        pseudo = Sum((uint16_t *)&plen, 4, pseudo);
        pseudo = Sum((uint16_t *)&next, 4, pseudo);
        if (ns) {
            nd_neighbor_solicit *icmp = (nd_neighbor_solicit *)(ip6 + 1);
            icmp->nd_ns_cksum = Csum((uint16_t *)icmp, 64, pseudo);
        } else {
            nd_neighbor_advert *icmp = (nd_neighbor_advert *)(ip6 + 1);
            icmp->nd_na_cksum = Csum((uint16_t *)icmp, 64, pseudo);
        }

        TestPkt0Interface *tap = (TestPkt0Interface *)
                (Agent::GetInstance()->pkt()->control_interface());
        tap->TxPacket(ptr, len);
    }

    void SendNA(short ifindex, short vrf, uint8_t *sip, uint8_t *tip,
                bool solicit = false) {
        return SendND(ifindex, vrf, sip, tip, false, solicit);
    }

    virtual void SetUp() {
        agent_ = Agent::GetInstance();
        CreateV6VmportEnv(input1, 2);
        client->WaitForIdle();
        EXPECT_TRUE(VmPortActive(1));
        EXPECT_TRUE(VmPortActive(2));
        AddIPAM("vn1", ipam_info, 1);
        client->WaitForIdle();
    }

    virtual void TearDown() {
        DeleteVmportEnv(input1, 2, true, 0, NULL, NULL, true, true);
        client->WaitForIdle();
        DelIPAM("vn1");
        client->WaitForIdle();
        EXPECT_TRUE(VrfGet("vrf1", true) == NULL);
    }

    void Pkt0IntfReceiveIPv6NS(uint8_t *buf, std::size_t len) {
        #define IP6_ICMPV6TYPE  58
        struct ether_header *eth = (struct ether_header *)buf;
        agent_hdr *agent = (agent_hdr *)(eth + 1);
        eth = (struct ether_header *) (agent + 1);
        if (ntohs(eth->ether_type) == ETHERTYPE_IPV6) {
            struct ip6_hdr *ip6 = (struct ip6_hdr *) (eth + 1);
            if (ip6->ip6_nxt == IP6_ICMPV6TYPE) {
                nd_neighbor_solicit *nshdr = (nd_neighbor_solicit *) (ip6 + 1);
                if (nshdr->nd_ns_hdr.icmp6_type == ND_NEIGHBOR_SOLICIT) {
                    if(!disable_na){
                    // Sending NA from interface instead of using multicast addr
                    uint8_t target[16] = {0xfd, 0x11, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0};
                    target[15] = ip6->ip6_dst.s6_addr[15];
                    SendNA(ntohs(agent->hdr_ifindex), ntohs(agent->hdr_vrf),
                      ip6->ip6_src.s6_addr, target, true);
                    }
                }
            }
        }
    }
    bool disable_na;
    Agent *agent_;
};

void TxL2Packet(int ifindex, const char *smac, const char *dmac,
                const char *sip, const char *dip,
                int proto, int vrf,
                uint16_t sport, uint16_t dport) {
    PktGen *pkt = new PktGen();

    pkt->AddEthHdr("00:00:00:00:00:01", "00:00:00:00:00:02", 0x800);
    pkt->AddAgentHdr(ifindex, AgentHdr::TRAP_MAC_IP_LEARNING, 0,  vrf) ;
    pkt->AddEthHdr(dmac, smac, ETHERTYPE_IPV6);
    pkt->AddIp6Hdr(sip, dip, proto);
    if (proto == IPPROTO_ICMPV6) {
        pkt->AddIcmp6Hdr();
    } else if (proto == IPPROTO_UDP) {
        pkt->AddUdpHdr(sport, dport, 64);
    }
    uint8_t *ptr(new uint8_t[pkt->GetBuffLen()]);
    memcpy(ptr, pkt->GetBuff(), pkt->GetBuffLen());
    client->agent_init()->pkt0()->ProcessFlowPacket(ptr, pkt->GetBuffLen(),
            pkt->GetBuffLen());
    delete pkt;
}

TEST_F(MacIp6LearningHCTest, NSTest1) {
    const VmInterface *intf = static_cast<const VmInterface *>(VmPortGet(1));
    MacAddress smac = intf->vm_mac();
    TxL2Packet(intf->id(), smac.ToString().c_str(), "00:00:00:33:22:11",
               "fd11::5", "fd11::1", 58, intf->vrf()->vrf_id(), 1, 1);
    client->WaitForIdle();
    boost::system::error_code error_code;
    Ip6Address sip = Ip6Address::from_string("fd11::5", error_code);
    EXPECT_TRUE(EvpnRouteGet("vrf1", smac, IpAddress(), 0) != NULL);
    EXPECT_TRUE(EvpnRouteGet("vrf1", smac, AddressFromString("fd11::5", &error_code), 0) != NULL);
    EXPECT_TRUE(L2RouteGet("vrf1", smac) != NULL);
    EXPECT_TRUE(RouteGetV6("vrf1", sip, 128) != NULL);
    sleep(20);
    EXPECT_TRUE(EvpnRouteGet("vrf1", smac, AddressFromString("fd11::5", &error_code), 0) != NULL);
    EXPECT_TRUE(EvpnRouteGet("vrf1", smac, IpAddress(), 0) != NULL);
}

TEST_F(MacIp6LearningHCTest, NSTest2) {
    disable_na = true;
    const VmInterface *intf = static_cast<const VmInterface *>(VmPortGet(1));
    MacAddress smac = intf->vm_mac();
    TxL2Packet(intf->id(), smac.ToString().c_str(), "00:00:00:33:22:11",
               "fd11::5", "fd11::1", 58, intf->vrf()->vrf_id(), 1, 1);
    client->WaitForIdle();
    boost::system::error_code error_code;
    Ip6Address sip = Ip6Address::from_string("fd11::5", error_code);
    EXPECT_TRUE(EvpnRouteGet("vrf1", smac, IpAddress(), 0) != NULL);
    EXPECT_TRUE(EvpnRouteGet("vrf1", smac, AddressFromString("fd11::5", &error_code), 0) != NULL);
    EXPECT_TRUE(L2RouteGet("vrf1", smac) != NULL);
    EXPECT_TRUE(RouteGetV6("vrf1", sip, 128) != NULL);
    sleep(20);
    EXPECT_TRUE(EvpnRouteGet("vrf1", smac, AddressFromString("fd11::5", &error_code), 0) == NULL);
    EXPECT_TRUE(EvpnRouteGet("vrf1", smac, IpAddress(), 0) != NULL);
}

// Create BFD Health and attach to the virtual-network
// Modify the health check
// Health check parameters should reflect in MAC IP learning entry
TEST_F(MacIp6LearningHCTest, BfdTest1) {
    const VmInterface *intf = static_cast<const VmInterface *>(VmPortGet(1));
    TxL2Packet(intf->id(), intf->vm_mac().ToString().c_str(), "00:00:00:11:22:31",
                "fd11::5", "fd11::1", 58, intf->vrf()->vrf_id(), 1, 1);
    client->WaitForIdle();

    intf = static_cast<const VmInterface *>(VmPortGet(2));
    TxL2Packet(intf->id(), intf->vm_mac().ToString().c_str(), "00:00:00:11:22:30",
                "fd11::1", "fd11::5", 58, intf->vrf()->vrf_id(), 1, 1);
    client->WaitForIdle();

    boost::system::error_code ec;

    AddVnHealthCheckService("HC-1", 1, 1, 1, 3, true, NULL, 0);
    AddLink("virtual-network", "vn1",
            "service-health-check", "HC-1");
    client->WaitForIdle();

    AddVnHealthCheckService("HC-1", 1, 1, 1, 3, true, NULL, 0);
    client->WaitForIdle();

    AddVnHealthCheckService("HC-1", 1, 2, 5, 3, true, NULL, 0);
    client->WaitForIdle();

    IpAddress ip = IpAddress(Ip6Address::from_string("fd11::5", ec));
    MacIpLearningKey key(GetVrfId("vrf1"), ip);
    MacIpLearningEntry *entry = agent_->mac_learning_proto()->
                GetMacIpLearningTable()->Find(key);
    EXPECT_TRUE(entry != NULL);
    EXPECT_TRUE(entry->HcService() != NULL);
    EXPECT_TRUE(entry->HcService()->name() == "HC-1");
    EXPECT_TRUE(entry->HcInstance() != NULL);

    ip = IpAddress(Ip6Address::from_string("fd11::1", ec));
    MacIpLearningKey key1(GetVrfId("vrf1"), ip);
    entry = agent_->mac_learning_proto()->
                GetMacIpLearningTable()->Find(key1);
    EXPECT_TRUE(entry != NULL);

    DelLink("virtual-network", "vn1",
            "service-health-check", "HC-1");
    client->WaitForIdle();
    DelHealthCheckService("HC-1");
    client->WaitForIdle();
}

// Create and attach BFD health check to VN
// Modify HC to take varying ip address (toggle from ALL)
TEST_F(MacIp6LearningHCTest, BfdTest2) {

    const VmInterface *intf = static_cast<const VmInterface *>(VmPortGet(1));
    boost::system::error_code ec;

    intf = static_cast<const VmInterface *>(VmPortGet(2));
    TxL2Packet(intf->id(), intf->vm_mac().ToString().c_str(), "00:00:00:11:22:30",
                "fd11::5", "fd11::1", 58, intf->vrf()->vrf_id(), 1, 1);
    client->WaitForIdle();

    AddVnHealthCheckService("HC-1", 1, 1, 1, 3, true, NULL, 0);
    AddLink("virtual-network", "vn1",
            "service-health-check", "HC-1");
    client->WaitForIdle();

    IpStr ip_list[2] = {"fd11::5", "fd11::1"};
    AddVnHealthCheckService("HC-1", 1, 1, 1, 3, false, ip_list, 2);
    client->WaitForIdle();

    IpStr ip_list1[3] = {"fd11::5", "fd11::1", "fd11::6"};
    AddVnHealthCheckService("HC-1", 1, 1, 1, 3, false, ip_list1, 3);
    client->WaitForIdle();

    IpAddress ip = IpAddress(Ip6Address::from_string("fd11::5", ec));
    MacIpLearningKey key(GetVrfId("vrf1"), ip);
    MacIpLearningEntry *entry = agent_->mac_learning_proto()->
                GetMacIpLearningTable()->Find(key);
    EXPECT_TRUE(entry != NULL);
    EXPECT_TRUE(entry->HcService() != NULL);
    EXPECT_TRUE(entry->HcService()->name() == "HC-1");
    EXPECT_TRUE(entry->HcInstance() != NULL);

    sleep(3);

    entry = agent_->mac_learning_proto()->
                GetMacIpLearningTable()->Find(key);
    EXPECT_TRUE(entry != NULL);

    DelLink("virtual-network", "vn1",
            "service-health-check", "HC-1");
    client->WaitForIdle();
    DelHealthCheckService("HC-1");
    client->WaitForIdle();
}

// Attach BFD HC and detach BFD HC and check in MAC IP learning entry
TEST_F(MacIp6LearningHCTest, BfdTest3) {

    boost::system::error_code ec;

    const VmInterface *intf = static_cast<const VmInterface *>(VmPortGet(1));
    TxL2Packet(intf->id(), intf->vm_mac().ToString().c_str(), "00:00:00:11:22:30",
               "fd11::5", "fd11::1", 58, intf->vrf()->vrf_id(), 1, 1);
    client->WaitForIdle();

    AddVnHealthCheckService("HC-1", 1, 1, 1, 3, true, NULL, 0);
    AddLink("virtual-network", "vn1",
            "service-health-check", "HC-1");
    client->WaitForIdle();

    IpAddress ip = IpAddress(Ip6Address::from_string("fd11::5", ec));
    MacIpLearningKey key(GetVrfId("vrf1"), ip);
    MacIpLearningEntry *entry = agent_->mac_learning_proto()->
                GetMacIpLearningTable()->Find(key);
    EXPECT_TRUE(entry != NULL);
    EXPECT_TRUE(entry->HcService() != NULL);
    EXPECT_TRUE(entry->HcService()->name() == "HC-1");
    EXPECT_TRUE(entry->HcInstance() != NULL);

    DelHealthCheckService("HC-1");
    client->WaitForIdle();
    DelLink("virtual-network", "vn1",
            "service-health-check", "HC-1");
    client->WaitForIdle();

    ip = IpAddress(Ip6Address::from_string("fd11::5", ec));
    MacIpLearningKey key2(GetVrfId("vrf1"), ip);
    entry = agent_->mac_learning_proto()->
                GetMacIpLearningTable()->Find(key2);
    EXPECT_TRUE(entry != NULL);
    EXPECT_TRUE(entry->HcService() == NULL);
    EXPECT_TRUE(entry->HcInstance() == NULL);
}

// Attach BFD HC, change IP address list to have learnt IP
// and then delete IP address from list for BFD HC
TEST_F(MacIp6LearningHCTest, BfdTest4) {

    boost::system::error_code ec;

    const VmInterface *intf = static_cast<const VmInterface *>(VmPortGet(1));
    TxL2Packet(intf->id(), intf->vm_mac().ToString().c_str(), "00:00:00:11:22:30",
                "fd11::5", "fd11::1", 58, intf->vrf()->vrf_id(), 1, 1);
    client->WaitForIdle();

    AddVnHealthCheckService("HC-1", 1, 1, 1, 3, true, NULL, 0);
    AddLink("virtual-network", "vn1",
            "service-health-check", "HC-1");
    client->WaitForIdle();

    IpStr ip_list[2] = {"fd11::5","fd11::1"};
    AddVnHealthCheckService("HC-1", 1, 1, 1, 3, false, ip_list, 2);
    client->WaitForIdle();

    IpAddress ip = IpAddress(Ip6Address::from_string("fd11::5", ec));
    MacIpLearningKey key(GetVrfId("vrf1"), ip);
    MacIpLearningEntry *entry = agent_->mac_learning_proto()->
                GetMacIpLearningTable()->Find(key);
    EXPECT_TRUE(entry != NULL);
    EXPECT_TRUE(entry->HcService() != NULL);
    EXPECT_TRUE(entry->HcService()->name() == "HC-1");
    EXPECT_TRUE(entry->HcInstance() != NULL);

    IpStr ip_list1[1] = {"fd11::1"};
    AddVnHealthCheckService("HC-1", 1, 1, 1, 3, false, ip_list1, 1);
    client->WaitForIdle();

    ip = IpAddress(Ip6Address::from_string("fd11::5", ec));
    MacIpLearningKey key2(GetVrfId("vrf1"), ip);
    entry = agent_->mac_learning_proto()->
                GetMacIpLearningTable()->Find(key2);
    EXPECT_TRUE(entry != NULL);
    EXPECT_TRUE(entry->HcService() == NULL);
    EXPECT_TRUE(entry->HcInstance() == NULL);

    DelLink("virtual-network", "vn1",
            "service-health-check", "HC-1");
    client->WaitForIdle();
    DelHealthCheckService("HC-1");
    client->WaitForIdle();
}

// Move IP to another interface and check for HC
TEST_F(MacIp6LearningHCTest, BfdTest5) {

    const VmInterface *intf = static_cast<const VmInterface *>(VmPortGet(1));

    boost::system::error_code ec;

    AddVnHealthCheckService("HC-1", 1, 1, 1, 3, true, NULL, 0);
    AddLink("virtual-network", "vn1",
            "service-health-check", "HC-1");
    client->WaitForIdle();

    TxL2Packet(intf->id(), intf->vm_mac().ToString().c_str(), "00:00:00:11:22:30",
               "fd11::5", "fd11::1", 58, intf->vrf()->vrf_id(), 1, 1);
    client->WaitForIdle();

    intf = static_cast<const VmInterface *>(VmPortGet(2));
    IpAddress ip = IpAddress(Ip6Address::from_string("fd11::5", ec));
    MacIpLearningKey key(GetVrfId("vrf1"), ip);
    MacIpLearningEntry *entry = agent_->mac_learning_proto()->
                GetMacIpLearningTable()->Find(key);
    EXPECT_TRUE(entry != NULL);
    EXPECT_TRUE(entry->HcService() != NULL);
    EXPECT_TRUE(entry->HcService()->name() == "HC-1");
    EXPECT_TRUE(entry->HcInstance() != NULL);

    sleep(3);

    intf = static_cast<const VmInterface *>(VmPortGet(2));
    MacAddress smac = intf->vm_mac();
    TxL2Packet(intf->id(), smac.ToString().c_str(), "00:00:00:11:22:30",
               "fd11::5", "fd11::1", 58, intf->vrf()->vrf_id(), 1, 1);
    client->WaitForIdle();

    entry = agent_->mac_learning_proto()->
                GetMacIpLearningTable()->Find(key);
    EXPECT_TRUE(entry != NULL);
    EXPECT_TRUE(entry->HcService() != NULL);
    EXPECT_TRUE(entry->HcService()->name() == "HC-1");
    EXPECT_TRUE(entry->HcInstance() != NULL);

    EXPECT_TRUE(EvpnRouteGet("vrf1", smac, IpAddress(), 0) != NULL);
    client->WaitForIdle();

    DelLink("virtual-network", "vn1",
            "service-health-check", "HC-1");
    client->WaitForIdle();
    DelHealthCheckService("HC-1");
    client->WaitForIdle();
}

// verify that mac-ip are not learnt once limit is reached on interface
TEST_F(MacIp6LearningHCTest, scale_test) {
    const VmInterface *intf = static_cast<const VmInterface *>(VmPortGet(1));
    MacAddress smac = intf->vm_mac();
    for ( int i = 1; i < VmInterface::kMaxMacIpLimit + 20; i++) {
        std::stringstream mac_str;
        std::stringstream ip_str;
        mac_str << "00:00:00:11:22:" << i+12;
        ip_str << "fd11::" << i+12;
        boost::system::error_code error_code;
        const string ip = ip_str.str();
        const string mac = mac_str.str();
        Ip6Address sip = Ip6Address::from_string(ip_str.str(), error_code);
        TxL2Packet(intf->id(), smac.ToString().c_str(), "00:00:00:33:22:11",
               sip.to_string().c_str(), "fd11::11", 58, intf->vrf()->vrf_id(), 1, 1);
        client->WaitForIdle();
        if ( i <= VmInterface::kMaxMacIpLimit) {
            EXPECT_TRUE(intf->learnt_mac_ip_list().list_.size()  == i);
            EXPECT_TRUE(EvpnRouteGet("vrf1", smac, IpAddress(), 0) != NULL);
            EXPECT_TRUE(EvpnRouteGet("vrf1", smac, sip, 0) != NULL);
            EXPECT_TRUE(L2RouteGet("vrf1", smac) != NULL);
            EXPECT_TRUE(RouteGetV6("vrf1", sip, 128) != NULL);
        } else {
            EXPECT_TRUE(intf->learnt_mac_ip_list().list_.size()
                    == VmInterface::kMaxMacIpLimit);
            EXPECT_TRUE(EvpnRouteGet("vrf1", smac, IpAddress(), 0) != NULL);
            EXPECT_TRUE(EvpnRouteGet("vrf1", smac, sip, 0) == NULL);
            EXPECT_TRUE(L2RouteGet("vrf1", smac) != NULL);
            EXPECT_TRUE(RouteGetV6("vrf1", sip, 128) == NULL);
        }
    }

}

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

    client = TestInit(init_file, ksync_init, true, true);
    usleep(100000);
    client->WaitForIdle();

    int ret = RUN_ALL_TESTS();
    usleep(100000);
    client->WaitForIdle();
    TestShutdown();
    delete client;
    return ret;
}

ext: cc

max_stars_repo_name: EWERK-DIGITAL/tf-controller

max_issues_repo_name: EWERK-DIGITAL/tf-controller

max_forks_repo_name: EWERK-DIGITAL/tf-controller


text:
#include "nca.hpp"

#include <cmath>
#include <cstdlib>
#include <fstream>
#include <iostream>
#include <vector>

#include <boost/tokenizer.hpp>

#include <Eigen/Core>

typedef boost::tokenizer< boost::escaped_list_separator<char> > CsvSplitter;

// Counts how many columns there are in the string
unsigned int csv_size(const std::string& s) {
    CsvSplitter tok(s);
    int size = -1;
    for(CsvSplitter::const_iterator t = tok.begin(); t != tok.end(); ++t) ++size;
    if(size <= 0) {
        std::cerr << "Error: No columns available" << std::endl;
        exit(1);
    }
    return size;
}

int main(int argc, char *argv[]) {
    if(argc < 5) {
        std::cerr << "usage: " << argv[0] << " csv_file label_index iterations learning_rate" << std::endl << std::endl;
        std::cerr << "\tcsv_file: the input file. It must be in csv format." << std::endl;
        std::cerr << "\tlabel_index: the index (starting from 0) of the class label on each line of the input file." << std::endl;
        std::cerr << "\titerations: how many iterations to run sgd. Make this at least 100000 for good results." << std::endl;
        std::cerr << "\tlearning_rate: how fast it learns. 0.01 or 0.001 is usually a good value." << std::endl;
        exit(1);
    }

    std::ifstream csv_file(argv[1]);
    int label_index = std::atoi(argv[2]);
    int iterations = std::atoi(argv[3]);
    double learning_rate = std::atof(argv[4]);

    // Input parsing
    std::vector<Eigen::VectorXd> input;
    std::vector<std::string> label;
    std::string s;

    int size = -1;
    while(std::getline(csv_file, s)) {
        if(size < 0) size = csv_size(s);

        CsvSplitter tok(s);
        Eigen::VectorXd x(size);
        int i = 0, pos = 0;
        for(CsvSplitter::const_iterator t = tok.begin(); t != tok.end(); ++t) {
            if(pos == label_index) {
                label.push_back(*t);
            } else {
                x[i] = std::atof(t->c_str());
                ++i;
            }
            ++pos;
        }

        input.push_back(x);
    }

    // Test
    Eigen::MatrixXd A = neighborhood_components_analysis(input, label, scaling_matrix(input), iterations, learning_rate);

    std::vector<Eigen::VectorXd> nca_input(scale(A, input));

    std::cout << A << std::endl << std::endl;

    std::cout << "Nearest neighbors on raw data:" << std::endl;
    nearest_neighbors(input, label);

    std::cout << std::endl << "Nearest neighbors on scaled data:" << std::endl;
    nearest_neighbors(scale(scaling_matrix(input), input), label);

    std::cout << std::endl << "Nearest neighbors on nca data:" << std::endl;
    nearest_neighbors(nca_input, label);

    return 0;
}

max_stars_repo_name: jhseu/nca

max_issues_repo_name: jhseu/nca

max_forks_repo_name: jhseu/nca