<commit_before>/*******************************************************************************
 *
 * MIT License
 *
 * Copyright (c) 2017 Advanced Micro Devices, 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 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.
 *
 *******************************************************************************/
#include "test.hpp"
#include <array>
#include <iostream>
#include <iterator>
#include <limits>
#include <memory>
#include <miopen/convolution.hpp>
#include <miopen/miopen.h>
#include <miopen/tensor.hpp>
#include <miopen/tensor_ops.hpp>
#include <utility>

#include "driver.hpp"
#include "get_handle.hpp"
#include "tensor_holder.hpp"
#include "verify.hpp"

#define MIO_OPS_DEBUG 0

template <class T>
struct tensor_ops_base
{
    tensor<T> a;
    tensor<T> b;
    tensor<T> c;

    void fail(float = 0)
    {
        std::cout << "A tensor: " << a.desc.ToString() << std::endl;
        std::cout << "B tensor: " << b.desc.ToString() << std::endl;
        std::cout << "C tensor: " << a.desc.ToString() << std::endl;
    }
};

template <class T>
struct verify_tensor_ops : tensor_ops_base<T>
{
    using tensor_ops_base<T>::a;
    using tensor_ops_base<T>::b;
    using tensor_ops_base<T>::c;

    int Aoffset;
    int Boffset;
    int Coffset;

    float alpha;
    float beta;

    verify_tensor_ops(const tensor<T>& pa,
                      const tensor<T>& pb,
                      const tensor<T>& pc,
                      std::vector<size_t>& offsets,
                      float palpha = 1,
                      float pbeta  = 1)
    {
        a = pa;
        b = pb;
        c = pc;

        Aoffset = offsets[0];
        Boffset = offsets[1];
        Coffset = offsets[2];

        alpha = palpha;
        beta  = pbeta;
    }

    // verify_tensor_ops(const tensor<T>& pa, const tensor<T>& pb, const tensor<T>& pc, const
    // std::vector<T>& dims)
    //{
    // a = pa(dims);
    // b = pb(dims);
    // c = pc(dims);
    //}

    T add_elem(T aelem, T belem) { return aelem + belem; }
    T mul_elem(T aelem, T belem) { return aelem * belem; }

    void tensor_for_loop(const tensor<T>& aten,
                         const tensor<T>& bten,
                         tensor<T>& cten,
                         const std::vector<size_t>& a_dims,
                         const std::vector<size_t>& b_dims,
                         float palpha,
                         float pbeta,
                         int recurr_aoffset,
                         int recurr_boffset,
                         int recurr_coffset,
                         int dim,
                         int AtenOffset,
                         int BtenOffset,
                         int CtenOffset)
    {

        int astride = aten.desc.GetStrides()[dim];
        int bstride = bten.desc.GetStrides()[dim];
        int cstride = cten.desc.GetStrides()[dim];

        // printf("cstride: %d\n", cstride);

        for(int idx = 0; idx < a_dims[dim]; idx++)
        {
            size_t aindex = recurr_aoffset + astride * idx;
            size_t cindex = recurr_coffset + cstride * idx;
            size_t bindex =
                (b_dims[dim] == a_dims[dim]) ? recurr_boffset + bstride * idx : recurr_boffset;

            // if((bindex < bten.desc.GetElementSize()) && (dim == a_dims.size() - 1))
            if(dim == (a_dims.size() - 1))
            {
#if(MIO_OPS_DEBUG)
                printf("c[%lu](%f) = a[%lu](%f) + b[%lu](%f)\n",
                       cindex + CtenOffset,
                       cten[cindex + CtenOffset],
                       aindex + AtenOffset,
                       aten[aindex + AtenOffset],
                       bindex + Boffset,
                       bten[bindex + Boffset]);
#endif
                cten[cindex + CtenOffset] =
                    add_elem(aten[aindex + AtenOffset], bten[bindex + BtenOffset]) * palpha +
                    pbeta * cten[cindex + Coffset];
            }
            if(dim < (a_dims.size() - 1))
            {

                tensor_for_loop(aten,
                                bten,
                                cten,
                                a_dims,
                                b_dims,
                                palpha,
                                pbeta,
                                aindex,
                                bindex,
                                cindex,
                                dim + 1,
                                AtenOffset,
                                BtenOffset,
                                CtenOffset);
            }
        }
        return;
    }

    tensor<T> cpu()
    {
        std::fill(c.begin(), c.end(), 1);
        auto clens    = c.desc.GetLengths();
        auto blens    = b.desc.GetLengths();
        auto bstrides = b.desc.GetStrides();
        auto cstrides = c.desc.GetStrides();

        // float alpha = -1, beta = 1;
        tensor_for_loop(a, b, c, clens, blens, alpha, beta, 0, 0, 0, 0, Aoffset, Boffset, Coffset);

#if(MIO_OPS_DEBUG)
        for(int i = 0; i < c.desc.GetElementSize(); i++)
            printf("CPU_C[%d]: %f\n", i, c.data[i]);
#endif
        return c;
    }

    tensor<T> gpu()
    {
        auto&& handle = get_handle();

        // return c;
        std::fill(c.begin(), c.end(), 1);

        auto c_dev = handle.Write(c.data);
        auto a_dev = handle.Write(a.data);
        auto b_dev = handle.Write(b.data);

        // float alpha1 = -1, alpha2 = 1, beta = 1;

        miopen::OpTensor(handle,
                         miopenTensorOpAdd,
                         // miopenTensorOpMul,
                         &alpha,
                         a.desc,
                         a_dev.get(),
                         NULL,
                         b.desc,
                         b_dev.get(),
                         &beta,
                         c.desc,
                         c_dev.get(),
                         Aoffset,
                         Boffset,
                         Coffset);

        c.data = handle.Read<T>(c_dev, c.data.size());

#if(MIO_OPS_DEBUG)
        handle.Finish();
        auto clens    = c.desc.GetLengths();
        auto cstrides = c.desc.GetStrides();
        for(int i = 0; i < c.desc.GetElementSize(); i++)
            printf("GPU_C[%d]: %f\n", i, c.data[i]);
#endif
        return c;
    }

    void fail(float = 0)
    {
        std::cout << "TensorOp: " << std::endl;
        this->tensor_ops_base<T>::fail();
    }
};

template <class T>
struct tensor_ops_driver : test_driver
{

    tensor<T> super_a;
    tensor<T> super_b;
    tensor<T> super_c;

    // tensor<T> a;
    // tensor<T> b;
    // tensor<T> c;

    tensor_ops_driver()
    {

        add(super_a, "super_a", generate_tensor(get_super_tensor(), {40, 10, 8, 20, 4}));
        add(super_b, "super_b", generate_tensor(get_super_tensor(), {40, 10, 8, 20, 4}));
        add(super_c, "super_c", generate_tensor(get_super_tensor(), {40, 10, 8, 20, 4}));
    }

    std::set<std::vector<int>> get_super_tensor()
    {
        std::vector<std::vector<int>> a_dims{
            {40, 10, 8, 20, 4},
        };

        return (std::set<std::vector<int>>(a_dims.begin(), a_dims.end()));
    }

    std::vector<tensor<T>> get_subtensors()
    {
        std::vector<tensor<T>> tensorList;

        unsigned int num_tensor_per_dims_size = 8;

        std::vector<std::vector<int>> lens{
            {32, 8, 8, 16, 4},
            {32, 4, 4, 8, 2},
            {16, 8, 4, 16, 2},
            {16, 2, 8, 4, 4},
            {8, 2, 8, 4, 4},
            {8, 8, 8, 4, 4},
            {4, 2, 4, 8, 2},
            {1, 8, 4, 8, 2}, // 5d
            {8, 1, 16, 4},
            {4, 2, 8, 2},
            {8, 4, 16, 2},
            {2, 8, 4, 4},
            {2, 2, 8, 4},
            {8, 8, 4, 4},
            {1, 4, 8, 2},
            {1, 1, 8, 2}, // 4d
            {8, 16, 4},
            {4, 8, 2},
            {4, 16, 2},
            {8, 1, 4},
            {8, 2, 4},
            {8, 4, 4},
            {4, 8, 2},
            {1, 8, 2}, // 3d
            {16, 4},
            {8, 2},
            {16, 2},
            {4, 4},
            {2, 4},
            {4, 1},
            {8, 2},
            {1, 4}, // 2d
        };

        std::vector<std::vector<int>> strides{
            {6400, 640, 80, 4, 1}, {640, 80, 4, 1}, {80, 4, 1}, {4, 1},
        };

        for(int i = 0; i < lens.size(); i++)
        {
            tensorList.push_back(
                make_tensor<T, int>(super_a, lens[i], strides[i / num_tensor_per_dims_size]));
        }

        return tensorList;
    }

    void run()
    {
        std::vector<tensor<T>> aTensorList = get_subtensors();
        std::vector<tensor<T>> bTensorList = get_subtensors();
        std::vector<tensor<T>> cTensorList = get_subtensors();

        std::vector<std::vector<size_t>> offsetList   = {{32, 16, 1}, {16, 32, 1}};
        std::vector<std::vector<float>> alphaBetaList = {
            {1, 1}, {-1, 1}, {0, 0}, {-1.5, 0.5}};

        for(int i = 0; i < aTensorList.size(); i++)
            if(aTensorList[i].desc.GetSize() == bTensorList[i].desc.GetSize())
            {
                for(int j = 0; j < offsetList.size(); j++)
                {
                    for(int k = 0; k < alphaBetaList.size(); k++)
                        verify(verify_tensor_ops<T>{aTensorList[i],
                                                    bTensorList[i],
                                                    cTensorList[i],
                                                    offsetList[j],
                                                    alphaBetaList[k][0],
                                                    alphaBetaList[k][1]});
                }
            }
    }
};

int main(int argc, const char* argv[]) { test_drive<tensor_ops_driver<float>>(argc, argv); }
<commit_msg>formatting fix<commit_after>/*******************************************************************************
 *
 * MIT License
 *
 * Copyright (c) 2017 Advanced Micro Devices, 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 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.
 *
 *******************************************************************************/
#include "test.hpp"
#include <array>
#include <iostream>
#include <iterator>
#include <limits>
#include <memory>
#include <miopen/convolution.hpp>
#include <miopen/miopen.h>
#include <miopen/tensor.hpp>
#include <miopen/tensor_ops.hpp>
#include <utility>

#include "driver.hpp"
#include "get_handle.hpp"
#include "tensor_holder.hpp"
#include "verify.hpp"

#define MIO_OPS_DEBUG 0

template <class T>
struct tensor_ops_base
{
    tensor<T> a;
    tensor<T> b;
    tensor<T> c;

    void fail(float = 0)
    {
        std::cout << "A tensor: " << a.desc.ToString() << std::endl;
        std::cout << "B tensor: " << b.desc.ToString() << std::endl;
        std::cout << "C tensor: " << a.desc.ToString() << std::endl;
    }
};

template <class T>
struct verify_tensor_ops : tensor_ops_base<T>
{
    using tensor_ops_base<T>::a;
    using tensor_ops_base<T>::b;
    using tensor_ops_base<T>::c;

    int Aoffset;
    int Boffset;
    int Coffset;

    float alpha;
    float beta;

    verify_tensor_ops(const tensor<T>& pa,
                      const tensor<T>& pb,
                      const tensor<T>& pc,
                      std::vector<size_t>& offsets,
                      float palpha = 1,
                      float pbeta  = 1)
    {
        a = pa;
        b = pb;
        c = pc;

        Aoffset = offsets[0];
        Boffset = offsets[1];
        Coffset = offsets[2];

        alpha = palpha;
        beta  = pbeta;
    }

    // verify_tensor_ops(const tensor<T>& pa, const tensor<T>& pb, const tensor<T>& pc, const
    // std::vector<T>& dims)
    //{
    // a = pa(dims);
    // b = pb(dims);
    // c = pc(dims);
    //}

    T add_elem(T aelem, T belem) { return aelem + belem; }
    T mul_elem(T aelem, T belem) { return aelem * belem; }

    void tensor_for_loop(const tensor<T>& aten,
                         const tensor<T>& bten,
                         tensor<T>& cten,
                         const std::vector<size_t>& a_dims,
                         const std::vector<size_t>& b_dims,
                         float palpha,
                         float pbeta,
                         int recurr_aoffset,
                         int recurr_boffset,
                         int recurr_coffset,
                         int dim,
                         int AtenOffset,
                         int BtenOffset,
                         int CtenOffset)
    {

        int astride = aten.desc.GetStrides()[dim];
        int bstride = bten.desc.GetStrides()[dim];
        int cstride = cten.desc.GetStrides()[dim];

        // printf("cstride: %d\n", cstride);

        for(int idx = 0; idx < a_dims[dim]; idx++)
        {
            size_t aindex = recurr_aoffset + astride * idx;
            size_t cindex = recurr_coffset + cstride * idx;
            size_t bindex =
                (b_dims[dim] == a_dims[dim]) ? recurr_boffset + bstride * idx : recurr_boffset;

            // if((bindex < bten.desc.GetElementSize()) && (dim == a_dims.size() - 1))
            if(dim == (a_dims.size() - 1))
            {
#if(MIO_OPS_DEBUG)
                printf("c[%lu](%f) = a[%lu](%f) + b[%lu](%f)\n",
                       cindex + CtenOffset,
                       cten[cindex + CtenOffset],
                       aindex + AtenOffset,
                       aten[aindex + AtenOffset],
                       bindex + Boffset,
                       bten[bindex + Boffset]);
#endif
                cten[cindex + CtenOffset] =
                    add_elem(aten[aindex + AtenOffset], bten[bindex + BtenOffset]) * palpha +
                    pbeta * cten[cindex + Coffset];
            }
            if(dim < (a_dims.size() - 1))
            {

                tensor_for_loop(aten,
                                bten,
                                cten,
                                a_dims,
                                b_dims,
                                palpha,
                                pbeta,
                                aindex,
                                bindex,
                                cindex,
                                dim + 1,
                                AtenOffset,
                                BtenOffset,
                                CtenOffset);
            }
        }
        return;
    }

    tensor<T> cpu()
    {
        std::fill(c.begin(), c.end(), 1);
        auto clens    = c.desc.GetLengths();
        auto blens    = b.desc.GetLengths();
        auto bstrides = b.desc.GetStrides();
        auto cstrides = c.desc.GetStrides();

        // float alpha = -1, beta = 1;
        tensor_for_loop(a, b, c, clens, blens, alpha, beta, 0, 0, 0, 0, Aoffset, Boffset, Coffset);

#if(MIO_OPS_DEBUG)
        for(int i = 0; i < c.desc.GetElementSize(); i++)
            printf("CPU_C[%d]: %f\n", i, c.data[i]);
#endif
        return c;
    }

    tensor<T> gpu()
    {
        auto&& handle = get_handle();

        // return c;
        std::fill(c.begin(), c.end(), 1);

        auto c_dev = handle.Write(c.data);
        auto a_dev = handle.Write(a.data);
        auto b_dev = handle.Write(b.data);

        // float alpha1 = -1, alpha2 = 1, beta = 1;

        miopen::OpTensor(handle,
                         miopenTensorOpAdd,
                         // miopenTensorOpMul,
                         &alpha,
                         a.desc,
                         a_dev.get(),
                         NULL,
                         b.desc,
                         b_dev.get(),
                         &beta,
                         c.desc,
                         c_dev.get(),
                         Aoffset,
                         Boffset,
                         Coffset);

        c.data = handle.Read<T>(c_dev, c.data.size());

#if(MIO_OPS_DEBUG)
        handle.Finish();
        auto clens    = c.desc.GetLengths();
        auto cstrides = c.desc.GetStrides();
        for(int i = 0; i < c.desc.GetElementSize(); i++)
            printf("GPU_C[%d]: %f\n", i, c.data[i]);
#endif
        return c;
    }

    void fail(float = 0)
    {
        std::cout << "TensorOp: " << std::endl;
        this->tensor_ops_base<T>::fail();
    }
};

template <class T>
struct tensor_ops_driver : test_driver
{

    tensor<T> super_a;
    tensor<T> super_b;
    tensor<T> super_c;

    // tensor<T> a;
    // tensor<T> b;
    // tensor<T> c;

    tensor_ops_driver()
    {

        add(super_a, "super_a", generate_tensor(get_super_tensor(), {40, 10, 8, 20, 4}));
        add(super_b, "super_b", generate_tensor(get_super_tensor(), {40, 10, 8, 20, 4}));
        add(super_c, "super_c", generate_tensor(get_super_tensor(), {40, 10, 8, 20, 4}));
    }

    std::set<std::vector<int>> get_super_tensor()
    {
        std::vector<std::vector<int>> a_dims{
            {40, 10, 8, 20, 4},
        };

        return (std::set<std::vector<int>>(a_dims.begin(), a_dims.end()));
    }

    std::vector<tensor<T>> get_subtensors()
    {
        std::vector<tensor<T>> tensorList;

        unsigned int num_tensor_per_dims_size = 8;

        std::vector<std::vector<int>> lens{
            {32, 8, 8, 16, 4},
            {32, 4, 4, 8, 2},
            {16, 8, 4, 16, 2},
            {16, 2, 8, 4, 4},
            {8, 2, 8, 4, 4},
            {8, 8, 8, 4, 4},
            {4, 2, 4, 8, 2},
            {1, 8, 4, 8, 2}, // 5d
            {8, 1, 16, 4},
            {4, 2, 8, 2},
            {8, 4, 16, 2},
            {2, 8, 4, 4},
            {2, 2, 8, 4},
            {8, 8, 4, 4},
            {1, 4, 8, 2},
            {1, 1, 8, 2}, // 4d
            {8, 16, 4},
            {4, 8, 2},
            {4, 16, 2},
            {8, 1, 4},
            {8, 2, 4},
            {8, 4, 4},
            {4, 8, 2},
            {1, 8, 2}, // 3d
            {16, 4},
            {8, 2},
            {16, 2},
            {4, 4},
            {2, 4},
            {4, 1},
            {8, 2},
            {1, 4}, // 2d
        };

        std::vector<std::vector<int>> strides{
            {6400, 640, 80, 4, 1}, {640, 80, 4, 1}, {80, 4, 1}, {4, 1},
        };

        for(int i = 0; i < lens.size(); i++)
        {
            tensorList.push_back(
                make_tensor<T, int>(super_a, lens[i], strides[i / num_tensor_per_dims_size]));
        }

        return tensorList;
    }

    void run()
    {
        std::vector<tensor<T>> aTensorList = get_subtensors();
        std::vector<tensor<T>> bTensorList = get_subtensors();
        std::vector<tensor<T>> cTensorList = get_subtensors();

        std::vector<std::vector<size_t>> offsetList   = {{32, 16, 1}, {16, 32, 1}};
        std::vector<std::vector<float>> alphaBetaList = {{1, 1}, {-1, 1}, {0, 0}, {-1.5, 0.5}};

        for(int i = 0; i < aTensorList.size(); i++)
            if(aTensorList[i].desc.GetSize() == bTensorList[i].desc.GetSize())
            {
                for(int j = 0; j < offsetList.size(); j++)
                {
                    for(int k = 0; k < alphaBetaList.size(); k++)
                        verify(verify_tensor_ops<T>{aTensorList[i],
                                                    bTensorList[i],
                                                    cTensorList[i],
                                                    offsetList[j],
                                                    alphaBetaList[k][0],
                                                    alphaBetaList[k][1]});
                }
            }
    }
};

int main(int argc, const char* argv[]) { test_drive<tensor_ops_driver<float>>(argc, argv); }
<|endoftext|>


<commit_before>#include <gtest/gtest.h>
#include "simple_graph/list_graph.hpp"
#include "simple_graph/astar.hpp"

namespace {

using simple_graph::vertex_index_t;

class ListGraphUndirectedTest : public ::testing::Test {
protected:
    simple_graph::ListGraph<false, std::pair<float, float>, float> g;
};

static float dist(const simple_graph::ListGraph<false, std::pair<float, float>, float> &g,
        vertex_index_t c, vertex_index_t r)
{
    const auto &cdata = g.vertex(c).data();
    const auto &rdata = g.vertex(r).data();
    float xdiff = rdata.first - cdata.first;
    float ydiff = rdata.second - cdata.second;
    return std::sqrt(std::pow(xdiff, 2) + std::pow(ydiff, 2));
}

TEST_F(ListGraphUndirectedTest, test_astar_long)
{
    g.add_vertex(simple_graph::Vertex<std::pair<float, float>>(0, std::make_pair(0.0f, 0.0f)));
    g.add_vertex(simple_graph::Vertex<std::pair<float, float>>(1, std::make_pair(1.0f, 1.0f)));
    g.add_vertex(simple_graph::Vertex<std::pair<float, float>>(2, std::make_pair(2.0f, 2.0f)));
    g.add_vertex(simple_graph::Vertex<std::pair<float, float>>(3, std::make_pair(5.0f, 5.0f)));
    g.add_vertex(simple_graph::Vertex<std::pair<float, float>>(4, std::make_pair(7.5f, 7.5f)));
    g.add_vertex(simple_graph::Vertex<std::pair<float, float>>(5, std::make_pair(3.0f, 1.0f)));
    g.add_vertex(simple_graph::Vertex<std::pair<float, float>>(6, std::make_pair(10.0f, 1.0f)));
    g.add_vertex(simple_graph::Vertex<std::pair<float, float>>(7, std::make_pair(10.0f, 10.0f)));

    EXPECT_EQ(8, g.vertex_num());

    g.add_edge(simple_graph::Edge<float>(0, 1, dist(g, 0, 1)));
    g.add_edge(simple_graph::Edge<float>(1, 2, dist(g, 1, 2)));
    g.add_edge(simple_graph::Edge<float>(2, 3, dist(g, 2, 3)));
    g.add_edge(simple_graph::Edge<float>(3, 4, dist(g, 3, 4)));
    g.add_edge(simple_graph::Edge<float>(4, 7, dist(g, 4, 7)));
    g.add_edge(simple_graph::Edge<float>(0, 5, dist(g, 0, 5)));
    g.add_edge(simple_graph::Edge<float>(5, 6, dist(g, 5, 6)));
    g.add_edge(simple_graph::Edge<float>(6, 7, dist(g, 6, 7)));

    std::vector<vertex_index_t> path;
    std::function<float(vertex_index_t, vertex_index_t)> heuristic = [=](vertex_index_t c, vertex_index_t r) {
        return dist(g, c, r);
    };
    EXPECT_EQ(true, astar(g, 0, 7, heuristic, &path));
    EXPECT_EQ(6, path.size());
    EXPECT_EQ(0, path[0]);
    EXPECT_EQ(1, path[1]);
    EXPECT_EQ(4, path[4]);
}

TEST_F(ListGraphUndirectedTest, test_astar_short)
{
    g.add_vertex(simple_graph::Vertex<std::pair<float, float>>(0, std::make_pair(0.0f, 0.0f)));
    g.add_vertex(simple_graph::Vertex<std::pair<float, float>>(1, std::make_pair(1.0f, 1.0f)));
    g.add_vertex(simple_graph::Vertex<std::pair<float, float>>(2, std::make_pair(2.0f, 2.0f)));
    g.add_vertex(simple_graph::Vertex<std::pair<float, float>>(3, std::make_pair(5.0f, 5.0f)));
    g.add_vertex(simple_graph::Vertex<std::pair<float, float>>(4, std::make_pair(15.0f, 15.0f)));
    g.add_vertex(simple_graph::Vertex<std::pair<float, float>>(5, std::make_pair(3.0f, 1.0f)));
    g.add_vertex(simple_graph::Vertex<std::pair<float, float>>(6, std::make_pair(10.0f, 1.0f)));
    g.add_vertex(simple_graph::Vertex<std::pair<float, float>>(7, std::make_pair(10.0f, 10.0f)));

    EXPECT_EQ(8, g.vertex_num());

    g.add_edge(simple_graph::Edge<float>(0, 1, dist(g, 0, 1)));
    g.add_edge(simple_graph::Edge<float>(1, 2, dist(g, 1, 2)));
    g.add_edge(simple_graph::Edge<float>(2, 3, dist(g, 2, 3)));
    g.add_edge(simple_graph::Edge<float>(3, 4, dist(g, 3, 4)));
    g.add_edge(simple_graph::Edge<float>(4, 7, dist(g, 4, 7)));
    g.add_edge(simple_graph::Edge<float>(0, 5, dist(g, 0, 5)));
    g.add_edge(simple_graph::Edge<float>(5, 6, dist(g, 5, 6)));
    g.add_edge(simple_graph::Edge<float>(6, 7, dist(g, 6, 7)));

    std::vector<vertex_index_t> path;
    std::function<float(vertex_index_t, vertex_index_t)> heuristic = [=](vertex_index_t c, vertex_index_t r) {
        return dist(g, c, r);
    };
    EXPECT_EQ(true, astar(g, 0, 7, heuristic, &path));
    EXPECT_EQ(4, path.size());
    EXPECT_EQ(5, path[1]);
    EXPECT_EQ(6, path[2]);
}

}  // namespace

int main(int argc, char **argv)
{
    ::testing::InitGoogleTest(&argc, argv);
    return RUN_ALL_TESTS();
}
<commit_msg>Add "no path" test for A* algorithm<commit_after>#include <gtest/gtest.h>
#include "simple_graph/list_graph.hpp"
#include "simple_graph/astar.hpp"

namespace {

using simple_graph::vertex_index_t;

class ListGraphUndirectedTest : public ::testing::Test {
protected:
    simple_graph::ListGraph<false, std::pair<float, float>, float> g;
};

static float dist(const simple_graph::ListGraph<false, std::pair<float, float>, float> &g,
        vertex_index_t c, vertex_index_t r)
{
    const auto &cdata = g.vertex(c).data();
    const auto &rdata = g.vertex(r).data();
    float xdiff = rdata.first - cdata.first;
    float ydiff = rdata.second - cdata.second;
    return std::sqrt(std::pow(xdiff, 2) + std::pow(ydiff, 2));
}

TEST_F(ListGraphUndirectedTest, test_astar_long)
{
    g.add_vertex(simple_graph::Vertex<std::pair<float, float>>(0, std::make_pair(0.0f, 0.0f)));
    g.add_vertex(simple_graph::Vertex<std::pair<float, float>>(1, std::make_pair(1.0f, 1.0f)));
    g.add_vertex(simple_graph::Vertex<std::pair<float, float>>(2, std::make_pair(2.0f, 2.0f)));
    g.add_vertex(simple_graph::Vertex<std::pair<float, float>>(3, std::make_pair(5.0f, 5.0f)));
    g.add_vertex(simple_graph::Vertex<std::pair<float, float>>(4, std::make_pair(7.5f, 7.5f)));
    g.add_vertex(simple_graph::Vertex<std::pair<float, float>>(5, std::make_pair(3.0f, 1.0f)));
    g.add_vertex(simple_graph::Vertex<std::pair<float, float>>(6, std::make_pair(10.0f, 1.0f)));
    g.add_vertex(simple_graph::Vertex<std::pair<float, float>>(7, std::make_pair(10.0f, 10.0f)));

    EXPECT_EQ(8, g.vertex_num());

    g.add_edge(simple_graph::Edge<float>(0, 1, dist(g, 0, 1)));
    g.add_edge(simple_graph::Edge<float>(1, 2, dist(g, 1, 2)));
    g.add_edge(simple_graph::Edge<float>(2, 3, dist(g, 2, 3)));
    g.add_edge(simple_graph::Edge<float>(3, 4, dist(g, 3, 4)));
    g.add_edge(simple_graph::Edge<float>(4, 7, dist(g, 4, 7)));
    g.add_edge(simple_graph::Edge<float>(0, 5, dist(g, 0, 5)));
    g.add_edge(simple_graph::Edge<float>(5, 6, dist(g, 5, 6)));
    g.add_edge(simple_graph::Edge<float>(6, 7, dist(g, 6, 7)));

    std::vector<vertex_index_t> path;
    std::function<float(vertex_index_t, vertex_index_t)> heuristic = [=](vertex_index_t c, vertex_index_t r) {
        return dist(g, c, r);
    };
    EXPECT_EQ(true, astar(g, 0, 7, heuristic, &path));
    EXPECT_EQ(6, path.size());
    EXPECT_EQ(0, path[0]);
    EXPECT_EQ(1, path[1]);
    EXPECT_EQ(4, path[4]);
}

TEST_F(ListGraphUndirectedTest, test_astar_short)
{
    g.add_vertex(simple_graph::Vertex<std::pair<float, float>>(0, std::make_pair(0.0f, 0.0f)));
    g.add_vertex(simple_graph::Vertex<std::pair<float, float>>(1, std::make_pair(1.0f, 1.0f)));
    g.add_vertex(simple_graph::Vertex<std::pair<float, float>>(2, std::make_pair(2.0f, 2.0f)));
    g.add_vertex(simple_graph::Vertex<std::pair<float, float>>(3, std::make_pair(5.0f, 5.0f)));
    g.add_vertex(simple_graph::Vertex<std::pair<float, float>>(4, std::make_pair(15.0f, 15.0f)));
    g.add_vertex(simple_graph::Vertex<std::pair<float, float>>(5, std::make_pair(3.0f, 1.0f)));
    g.add_vertex(simple_graph::Vertex<std::pair<float, float>>(6, std::make_pair(10.0f, 1.0f)));
    g.add_vertex(simple_graph::Vertex<std::pair<float, float>>(7, std::make_pair(10.0f, 10.0f)));

    EXPECT_EQ(8, g.vertex_num());

    g.add_edge(simple_graph::Edge<float>(0, 1, dist(g, 0, 1)));
    g.add_edge(simple_graph::Edge<float>(1, 2, dist(g, 1, 2)));
    g.add_edge(simple_graph::Edge<float>(2, 3, dist(g, 2, 3)));
    g.add_edge(simple_graph::Edge<float>(3, 4, dist(g, 3, 4)));
    g.add_edge(simple_graph::Edge<float>(4, 7, dist(g, 4, 7)));
    g.add_edge(simple_graph::Edge<float>(0, 5, dist(g, 0, 5)));
    g.add_edge(simple_graph::Edge<float>(5, 6, dist(g, 5, 6)));
    g.add_edge(simple_graph::Edge<float>(6, 7, dist(g, 6, 7)));

    std::vector<vertex_index_t> path;
    std::function<float(vertex_index_t, vertex_index_t)> heuristic = [=](vertex_index_t c, vertex_index_t r) {
        return dist(g, c, r);
    };
    EXPECT_EQ(true, astar(g, 0, 7, heuristic, &path));
    EXPECT_EQ(4, path.size());
    EXPECT_EQ(5, path[1]);
    EXPECT_EQ(6, path[2]);
}

TEST_F(ListGraphUndirectedTest, test_astar_no_path)
{
    g.add_vertex(simple_graph::Vertex<std::pair<float, float>>(0, std::make_pair(0.0f, 0.0f)));
    g.add_vertex(simple_graph::Vertex<std::pair<float, float>>(1, std::make_pair(1.0f, 1.0f)));
    g.add_vertex(simple_graph::Vertex<std::pair<float, float>>(2, std::make_pair(2.0f, 2.0f)));
    g.add_vertex(simple_graph::Vertex<std::pair<float, float>>(3, std::make_pair(5.0f, 5.0f)));

    ASSERT_EQ(4, g.vertex_num());

    g.add_edge(simple_graph::Edge<float>(0, 1, dist(g, 0, 1)));
    g.add_edge(simple_graph::Edge<float>(2, 3, dist(g, 2, 3)));

    std::vector<vertex_index_t> path;
    std::function<float(vertex_index_t, vertex_index_t)> heuristic = [=](vertex_index_t c, vertex_index_t r) {
        return dist(g, c, r);
    };
    EXPECT_EQ(false, astar(g, 0, 3, heuristic, &path));
    EXPECT_EQ(0, path.size());
}

}  // namespace

int main(int argc, char **argv)
{
    ::testing::InitGoogleTest(&argc, argv);
    return RUN_ALL_TESTS();
}
<|endoftext|>


<commit_before>#define BOOST_TEST_MODULE TestCuFFT

#include "libraries/cufft/cufft_helper.hpp"
#include <boost/test/included/unit_test.hpp> // Single-header usage variant
#include <iostream>

using namespace gearshifft::CuFFT;

BOOST_AUTO_TEST_CASE( Device )
{
  int nr=0;

  try {
    CHECK_CUDA( cudaGetDeviceCount(&nr) );
    for( auto i=0; i<nr; ++i ) {
      CHECK_CUDA( cudaSetDevice(i) );
      CHECK_CUDA( cudaDeviceReset() );
    }
  }catch(const std::runtime_error& e){
    BOOST_FAIL("CUDA Error: " << e.what());
  }
  BOOST_CHECK( true );
}

BOOST_AUTO_TEST_CASE( CuFFT_Single )
{
  cufftComplex* data = nullptr;
  cufftComplex* data_transform = nullptr;
  cufftHandle plan = 0;
  CHECK_CUDA( cudaSetDevice(0) );
  std::vector< std::array<size_t, 1> > vec_extents;
  std::array<size_t, 1> e0 = {{128}};
  std::array<size_t, 1> e1 = {{125}};
  std::array<size_t, 1> e2 = {{169}};
  std::array<size_t, 1> e3 = {{170}};
  vec_extents.push_back( e0 );
  vec_extents.push_back( e1 );
  vec_extents.push_back( e2 );
  vec_extents.push_back( e3 );

  for( auto extents : vec_extents ) {
    size_t data_size = extents[0]*sizeof(cufftComplex);
    size_t data_transform_size = extents[0]*sizeof(cufftComplex);

    try {
      CHECK_CUDA( cudaMalloc(&data, data_size));
      CHECK_CUDA( cudaMalloc(&data_transform, data_transform_size));

      CHECK_CUDA( cufftPlan1d(&plan, extents[0], CUFFT_C2C, 1));

      CHECK_CUDA( cufftExecC2C(plan, data, data_transform, CUFFT_FORWARD));
      CHECK_CUDA( cufftExecC2C(plan, data_transform, data, CUFFT_INVERSE));

      CHECK_CUDA( cudaFree(data) );
      CHECK_CUDA( cudaFree(data_transform) );
      CHECK_CUDA( cufftDestroy(plan) );
      plan = 0;
    }catch(std::runtime_error& e){
      // cleanup #1
      CHECK_CUDA( cudaFree(data) );
      CHECK_CUDA( cudaFree(data_transform) );
      if(plan) {
        CHECK_CUDA( cufftDestroy(plan) );
        plan=0;
      }
      BOOST_ERROR("Error for nx="<<extents[0]<<": "<<e.what());
    }
  }
  CHECK_CUDA( cudaDeviceReset() );
  BOOST_CHECK( true );

}

BOOST_AUTO_TEST_CASE( CuFFT_Double )
{
  cufftDoubleComplex* data = nullptr;
  cufftDoubleComplex* data_transform = nullptr;
  cufftHandle plan = 0;
  CHECK_CUDA( cudaSetDevice(0) );
  std::vector< std::array<size_t, 1> > vec_extents;
  std::array<size_t, 1> e0 = {{128}};
  std::array<size_t, 1> e1 = {{125}};
  std::array<size_t, 1> e2 = {{169}};
  std::array<size_t, 1> e3 = {{170}};
  vec_extents.push_back( e0 );
  vec_extents.push_back( e1 );
  vec_extents.push_back( e2 );
  vec_extents.push_back( e3 );

  for( auto extents : vec_extents ) {
    size_t data_size = extents[0]*sizeof(cufftDoubleComplex);
    size_t data_transform_size = extents[0]*sizeof(cufftDoubleComplex);

    try {
      CHECK_CUDA( cudaMalloc(&data, data_size));
      CHECK_CUDA( cudaMalloc(&data_transform, data_transform_size));

      CHECK_CUDA( cufftPlan1d(&plan, extents[0], CUFFT_Z2Z, 1));

      CHECK_CUDA( cufftExecZ2Z(plan, data, data_transform, CUFFT_FORWARD));
      CHECK_CUDA( cufftExecZ2Z(plan, data_transform, data, CUFFT_INVERSE));

      CHECK_CUDA( cudaFree(data) );
      CHECK_CUDA( cudaFree(data_transform) );
      CHECK_CUDA( cufftDestroy(plan) );
      plan = 0;
    }catch(std::runtime_error& e){
      // cleanup #1
      CHECK_CUDA( cudaFree(data) );
      CHECK_CUDA( cudaFree(data_transform) );
      if(plan) {
        CHECK_CUDA( cufftDestroy(plan) );
        plan=0;
      }
      BOOST_ERROR("Error for nx="<<extents[0]<<": "<<e.what());
    }
  }
  CHECK_CUDA( cudaDeviceReset() );
  BOOST_CHECK( true );
}
<commit_msg>test/test_cufft.cpp: added std::array header<commit_after>#define BOOST_TEST_MODULE TestCuFFT

#include "libraries/cufft/cufft_helper.hpp"
#include <boost/test/included/unit_test.hpp> // Single-header usage variant
#include <array>
#include <iostream>

using namespace gearshifft::CuFFT;

BOOST_AUTO_TEST_CASE( Device )
{
  int nr=0;

  try {
    CHECK_CUDA( cudaGetDeviceCount(&nr) );
    for( auto i=0; i<nr; ++i ) {
      CHECK_CUDA( cudaSetDevice(i) );
      CHECK_CUDA( cudaDeviceReset() );
    }
  }catch(const std::runtime_error& e){
    BOOST_FAIL("CUDA Error: " << e.what());
  }
  BOOST_CHECK( true );
}

BOOST_AUTO_TEST_CASE( CuFFT_Single )
{
  cufftComplex* data = nullptr;
  cufftComplex* data_transform = nullptr;
  cufftHandle plan = 0;
  CHECK_CUDA( cudaSetDevice(0) );
  std::vector< std::array<size_t, 1> > vec_extents;
  std::array<size_t, 1> e0 = {{128}};
  std::array<size_t, 1> e1 = {{125}};
  std::array<size_t, 1> e2 = {{169}};
  std::array<size_t, 1> e3 = {{170}};
  vec_extents.push_back( e0 );
  vec_extents.push_back( e1 );
  vec_extents.push_back( e2 );
  vec_extents.push_back( e3 );

  for( auto extents : vec_extents ) {
    size_t data_size = extents[0]*sizeof(cufftComplex);
    size_t data_transform_size = extents[0]*sizeof(cufftComplex);

    try {
      CHECK_CUDA( cudaMalloc(&data, data_size));
      CHECK_CUDA( cudaMalloc(&data_transform, data_transform_size));

      CHECK_CUDA( cufftPlan1d(&plan, extents[0], CUFFT_C2C, 1));

      CHECK_CUDA( cufftExecC2C(plan, data, data_transform, CUFFT_FORWARD));
      CHECK_CUDA( cufftExecC2C(plan, data_transform, data, CUFFT_INVERSE));

      CHECK_CUDA( cudaFree(data) );
      CHECK_CUDA( cudaFree(data_transform) );
      CHECK_CUDA( cufftDestroy(plan) );
      plan = 0;
    }catch(std::runtime_error& e){
      // cleanup #1
      CHECK_CUDA( cudaFree(data) );
      CHECK_CUDA( cudaFree(data_transform) );
      if(plan) {
        CHECK_CUDA( cufftDestroy(plan) );
        plan=0;
      }
      BOOST_ERROR("Error for nx="<<extents[0]<<": "<<e.what());
    }
  }
  CHECK_CUDA( cudaDeviceReset() );
  BOOST_CHECK( true );

}

BOOST_AUTO_TEST_CASE( CuFFT_Double )
{
  cufftDoubleComplex* data = nullptr;
  cufftDoubleComplex* data_transform = nullptr;
  cufftHandle plan = 0;
  CHECK_CUDA( cudaSetDevice(0) );
  std::vector< std::array<size_t, 1> > vec_extents;
  std::array<size_t, 1> e0 = {{128}};
  std::array<size_t, 1> e1 = {{125}};
  std::array<size_t, 1> e2 = {{169}};
  std::array<size_t, 1> e3 = {{170}};
  vec_extents.push_back( e0 );
  vec_extents.push_back( e1 );
  vec_extents.push_back( e2 );
  vec_extents.push_back( e3 );

  for( auto extents : vec_extents ) {
    size_t data_size = extents[0]*sizeof(cufftDoubleComplex);
    size_t data_transform_size = extents[0]*sizeof(cufftDoubleComplex);

    try {
      CHECK_CUDA( cudaMalloc(&data, data_size));
      CHECK_CUDA( cudaMalloc(&data_transform, data_transform_size));

      CHECK_CUDA( cufftPlan1d(&plan, extents[0], CUFFT_Z2Z, 1));

      CHECK_CUDA( cufftExecZ2Z(plan, data, data_transform, CUFFT_FORWARD));
      CHECK_CUDA( cufftExecZ2Z(plan, data_transform, data, CUFFT_INVERSE));

      CHECK_CUDA( cudaFree(data) );
      CHECK_CUDA( cudaFree(data_transform) );
      CHECK_CUDA( cufftDestroy(plan) );
      plan = 0;
    }catch(std::runtime_error& e){
      // cleanup #1
      CHECK_CUDA( cudaFree(data) );
      CHECK_CUDA( cudaFree(data_transform) );
      if(plan) {
        CHECK_CUDA( cufftDestroy(plan) );
        plan=0;
      }
      BOOST_ERROR("Error for nx="<<extents[0]<<": "<<e.what());
    }
  }
  CHECK_CUDA( cudaDeviceReset() );
  BOOST_CHECK( true );
}
<|endoftext|>


<commit_before>// For conditions of distribution and use, see copyright notice in license.txt

/**
 *  @file InventoryAsset.cpp
 *  @brief A class representing asset in inventory.
 */

#include "
#include "StableHeaders.h"
#include "InventoryAsset.h"
#include "InventoryFolder.h"

namespace Inventory
{

InventoryAsset::InventoryAsset(const QString &id, const QString &asset_reference,const QString &name, InventoryFolder *parent) :
    AbstractInventoryItem(id, name, parent), itemType_(AbstractInventoryItem::Type_Asset), assetReference_(asset_reference),
    libraryAsset_(false)
{
}

// virtual
InventoryAsset::~InventoryAsset()
{
}

bool InventoryAsset::IsDescendentOf(AbstractInventoryItem *searchFolder)
{
    forever
    {
        AbstractInventoryItem *parent = GetParent();
        if (parent)
        {
            if (parent == searchFolder)
                return true;
            else
                return parent->IsDescendentOf(searchFolder);
        }

        return false;
    }
}

/*
int InventoryAsset::ColumnCount() const
{
    return itemData_.count();
}

int InventoryAsset::Row() const
{
    if (GetParent())
        return GetParent()->Children().indexOf(const_cast<InventoryAsset *>(this));

    return 0;
}
*/

}
<commit_msg>Remove accidentally added "include ""<commit_after>// For conditions of distribution and use, see copyright notice in license.txt

/**
 *  @file InventoryAsset.cpp
 *  @brief A class representing asset in inventory.
 */

#include "StableHeaders.h"
#include "InventoryAsset.h"
#include "InventoryFolder.h"

namespace Inventory
{

InventoryAsset::InventoryAsset(const QString &id, const QString &asset_reference,const QString &name, InventoryFolder *parent) :
    AbstractInventoryItem(id, name, parent), itemType_(AbstractInventoryItem::Type_Asset), assetReference_(asset_reference),
    libraryAsset_(false)
{
}

// virtual
InventoryAsset::~InventoryAsset()
{
}

bool InventoryAsset::IsDescendentOf(AbstractInventoryItem *searchFolder)
{
    forever
    {
        AbstractInventoryItem *parent = GetParent();
        if (parent)
        {
            if (parent == searchFolder)
                return true;
            else
                return parent->IsDescendentOf(searchFolder);
        }

        return false;
    }
}

/*
int InventoryAsset::ColumnCount() const
{
    return itemData_.count();
}

int InventoryAsset::Row() const
{
    if (GetParent())
        return GetParent()->Children().indexOf(const_cast<InventoryAsset *>(this));

    return 0;
}
*/

}
<|endoftext|>


<commit_before>#include "libtorrent/session.hpp"
#include "libtorrent/session_settings.hpp"
#include "libtorrent/hasher.hpp"
#include <boost/thread.hpp>
#include <boost/tuple/tuple.hpp>
#include <boost/filesystem/operations.hpp>

#include "test.hpp"
#include "setup_transfer.hpp"

using boost::filesystem::remove_all;

void test_swarm()
{
	using namespace libtorrent;

	session ses1(fingerprint("LT", 0, 1, 0, 0), std::make_pair(48000, 49000));
	session ses2(fingerprint("LT", 0, 1, 0, 0), std::make_pair(49000, 50000));
	session ses3(fingerprint("LT", 0, 1, 0, 0), std::make_pair(50000, 51000));

	// this is to avoid everything finish from a single peer
	// immediately. To make the swarm actually connect all
	// three peers before finishing.
	float rate_limit = 40000;
	ses1.set_upload_rate_limit(int(rate_limit));
	ses2.set_download_rate_limit(int(rate_limit));
	ses3.set_download_rate_limit(int(rate_limit));
	ses2.set_upload_rate_limit(int(rate_limit / 2));
	ses3.set_upload_rate_limit(int(rate_limit / 2));

	session_settings settings;
	settings.allow_multiple_connections_per_ip = true;
	ses1.set_settings(settings);
	ses2.set_settings(settings);
	ses3.set_settings(settings);

#ifndef TORRENT_DISABLE_ENCRYPTION
	pe_settings pes;
	pes.out_enc_policy = pe_settings::disabled;
	pes.in_enc_policy = pe_settings::disabled;
	ses1.set_pe_settings(pes);
	ses2.set_pe_settings(pes);
	ses3.set_pe_settings(pes);
#endif

	torrent_handle tor1;
	torrent_handle tor2;
	torrent_handle tor3;

	boost::tie(tor1, tor2, tor3) = setup_transfer(&ses1, &ses2, &ses3, true, false);

	float sum_dl_rate2 = 0.f;
	float sum_dl_rate3 = 0.f;
	int count_dl_rates2 = 0;
	int count_dl_rates3 = 0;

	for (int i = 0; i < 65; ++i)
	{
		std::auto_ptr<alert> a;
		a = ses1.pop_alert();
		if (a.get())
			std::cerr << "ses1: " << a->msg() << "\n";

		a = ses2.pop_alert();
		if (a.get())
			std::cerr << "ses2: " << a->msg() << "\n";

		a = ses3.pop_alert();
		if (a.get())
			std::cerr << "ses3: " << a->msg() << "\n";

		torrent_status st1 = tor1.status();
		torrent_status st2 = tor2.status();
		torrent_status st3 = tor3.status();

		if (st2.progress < 1.f && st2.progress > 0.3f)
		{
			sum_dl_rate2 += st2.download_payload_rate;
			++count_dl_rates2;
		}
		if (st3.progress < 1.f && st3.progress > 0.3f)
		{
			sum_dl_rate3 += st3.download_rate;
			++count_dl_rates3;
		}

		std::cerr
			<< "\033[33m" << int(st1.upload_payload_rate / 1000.f) << "kB/s: "
			<< "\033[32m" << int(st2.download_payload_rate / 1000.f) << "kB/s "
			<< "\033[31m" << int(st2.upload_payload_rate / 1000.f) << "kB/s "
			<< "\033[0m" << int(st2.progress * 100) << "% - "
			<< "\033[32m" << int(st3.download_payload_rate / 1000.f) << "kB/s "
			<< "\033[31m" << int(st3.upload_payload_rate / 1000.f) << "kB/s "
			<< "\033[0m" << int(st3.progress * 100) << "% "
			<< std::endl;

		if (tor2.is_seed() && tor3.is_seed()) break;
		test_sleep(1000);
	}

	TEST_CHECK(tor2.is_seed());
	TEST_CHECK(tor3.is_seed());

	float average2 = sum_dl_rate2 / float(count_dl_rates2);
	float average3 = sum_dl_rate3 / float(count_dl_rates3);

	std::cerr << "average rate: " << (average2 / 1000.f) << "kB/s - "
		<< (average3 / 1000.f) << "kB/s" << std::endl;

	TEST_CHECK(std::fabs(average2 - float(rate_limit)) < 3000.f);
	TEST_CHECK(std::fabs(average3 - float(rate_limit)) < 3000.f);
	if (tor2.is_seed() && tor3.is_seed()) std::cerr << "done\n";
}

int test_main()
{
	using namespace libtorrent;
	using namespace boost::filesystem;

	// in case the previous run was terminated
	try { remove_all("./tmp1"); } catch (std::exception&) {}
	try { remove_all("./tmp2"); } catch (std::exception&) {}
	try { remove_all("./tmp3"); } catch (std::exception&) {}

	test_swarm();

	remove_all("./tmp1");
	remove_all("./tmp2");
	remove_all("./tmp3");

	return 0;
}

<commit_msg>more output in test_swarm<commit_after>#include "libtorrent/session.hpp"
#include "libtorrent/session_settings.hpp"
#include "libtorrent/hasher.hpp"
#include <boost/thread.hpp>
#include <boost/tuple/tuple.hpp>
#include <boost/filesystem/operations.hpp>

#include "test.hpp"
#include "setup_transfer.hpp"

using boost::filesystem::remove_all;

void test_swarm()
{
	using namespace libtorrent;

	session ses1(fingerprint("LT", 0, 1, 0, 0), std::make_pair(48000, 49000));
	session ses2(fingerprint("LT", 0, 1, 0, 0), std::make_pair(49000, 50000));
	session ses3(fingerprint("LT", 0, 1, 0, 0), std::make_pair(50000, 51000));

	// this is to avoid everything finish from a single peer
	// immediately. To make the swarm actually connect all
	// three peers before finishing.
	float rate_limit = 40000;
	ses1.set_upload_rate_limit(int(rate_limit));
	ses2.set_download_rate_limit(int(rate_limit));
	ses3.set_download_rate_limit(int(rate_limit));
	ses2.set_upload_rate_limit(int(rate_limit / 2));
	ses3.set_upload_rate_limit(int(rate_limit / 2));

	session_settings settings;
	settings.allow_multiple_connections_per_ip = true;
	ses1.set_settings(settings);
	ses2.set_settings(settings);
	ses3.set_settings(settings);

#ifndef TORRENT_DISABLE_ENCRYPTION
	pe_settings pes;
	pes.out_enc_policy = pe_settings::disabled;
	pes.in_enc_policy = pe_settings::disabled;
	ses1.set_pe_settings(pes);
	ses2.set_pe_settings(pes);
	ses3.set_pe_settings(pes);
#endif

	torrent_handle tor1;
	torrent_handle tor2;
	torrent_handle tor3;

	boost::tie(tor1, tor2, tor3) = setup_transfer(&ses1, &ses2, &ses3, true, false);

	float sum_dl_rate2 = 0.f;
	float sum_dl_rate3 = 0.f;
	int count_dl_rates2 = 0;
	int count_dl_rates3 = 0;

	for (int i = 0; i < 65; ++i)
	{
		std::auto_ptr<alert> a;
		a = ses1.pop_alert();
		if (a.get())
			std::cerr << "ses1: " << a->msg() << "\n";

		a = ses2.pop_alert();
		if (a.get())
			std::cerr << "ses2: " << a->msg() << "\n";

		a = ses3.pop_alert();
		if (a.get())
			std::cerr << "ses3: " << a->msg() << "\n";

		torrent_status st1 = tor1.status();
		torrent_status st2 = tor2.status();
		torrent_status st3 = tor3.status();

		if (st2.progress < 1.f && st2.progress > 0.3f)
		{
			sum_dl_rate2 += st2.download_payload_rate;
			++count_dl_rates2;
		}
		if (st3.progress < 1.f && st3.progress > 0.3f)
		{
			sum_dl_rate3 += st3.download_rate;
			++count_dl_rates3;
		}

		std::cerr
			<< "\033[33m" << int(st1.upload_payload_rate / 1000.f) << "kB/s "
			<< st1.num_peers << ": "
			<< "\033[32m" << int(st2.download_payload_rate / 1000.f) << "kB/s "
			<< "\033[31m" << int(st2.upload_payload_rate / 1000.f) << "kB/s "
			<< "\033[0m" << int(st2.progress * 100) << "% "
			<< st2.num_peers << " - "
			<< "\033[32m" << int(st3.download_payload_rate / 1000.f) << "kB/s "
			<< "\033[31m" << int(st3.upload_payload_rate / 1000.f) << "kB/s "
			<< "\033[0m" << int(st3.progress * 100) << "% "
			<< st3.num_peers
			<< std::endl;

		if (tor2.is_seed() && tor3.is_seed()) break;
		test_sleep(1000);
	}

	TEST_CHECK(tor2.is_seed());
	TEST_CHECK(tor3.is_seed());

	float average2 = sum_dl_rate2 / float(count_dl_rates2);
	float average3 = sum_dl_rate3 / float(count_dl_rates3);

	std::cerr << "average rate: " << (average2 / 1000.f) << "kB/s - "
		<< (average3 / 1000.f) << "kB/s" << std::endl;

	TEST_CHECK(std::fabs(average2 - float(rate_limit)) < 3000.f);
	TEST_CHECK(std::fabs(average3 - float(rate_limit)) < 3000.f);
	if (tor2.is_seed() && tor3.is_seed()) std::cerr << "done\n";
}

int test_main()
{
	using namespace libtorrent;
	using namespace boost::filesystem;

	// in case the previous run was terminated
	try { remove_all("./tmp1"); } catch (std::exception&) {}
	try { remove_all("./tmp2"); } catch (std::exception&) {}
	try { remove_all("./tmp3"); } catch (std::exception&) {}

	test_swarm();

	remove_all("./tmp1");
	remove_all("./tmp2");
	remove_all("./tmp3");

	return 0;
}

<|endoftext|>


<commit_before>// thiefControl.cpp : Defines the entry point for the DLL application.
//

#include "bzfsAPI.h"

BZ_GET_PLUGIN_VERSION

class ThiefControl : public bz_EventHandler
{
public:
  ThiefControl() {} ;
  virtual ~ThiefControl() {};
  virtual void process( bz_EventData *eventData );
};

ThiefControl thiefHandler;

BZF_PLUGIN_CALL int bz_Load ( const char* /*commandLine*/ )
{
  bz_debugMessage(4,"thiefControl plugin loaded");
  bz_registerEvent(bz_eFlagTransferredEvent, &thiefHandler);
  return 0;
}

BZF_PLUGIN_CALL int bz_Unload ( void )
{
  bz_removeEvent(bz_eFlagTransferredEvent, &thiefHandler);
  bz_debugMessage(4,"thiefControl plugin unloaded");
  return 0;
}

void ThiefControl::process( bz_EventData *eventData )
{
  bz_FlagTransferredEventData_V1 *data = (bz_FlagTransferredEventData_V1 *) eventData;
  const std::string noStealMsg = "Flag dropped. Don't steal from teammates!";

  if(!data)
    return;

  if(data->eventType != bz_eFlagTransferredEvent)
    return;

  bz_BasePlayerRecord *playerFrom = bz_getPlayerByIndex(data->fromPlayerID);
  bz_BasePlayerRecord *playerTo = bz_getPlayerByIndex(data->toPlayerID);

  if(!playerFrom || !playerTo) {
    bz_freePlayerRecord(playerFrom);
    bz_freePlayerRecord(playerTo);
    return;
  }

  switch(bz_getGameType()) {

    case eTeamFFAGame:
    {
      if(playerTo->team == playerFrom->team &&
	 playerTo->team != eRogueTeam) {

	data->action = data->DropThief;
	bz_sendTextMessage(BZ_SERVER, data->toPlayerID, noStealMsg.c_str());

      }

    }
      break;

    case eClassicCTFGame:
    {

      // Allow teammates to steal team flags
      // This will allow someone to steal a team flag in order
      // to possibly capture it faster.
      bool allowTransfer = false;

      if(playerTo->team == playerFrom->team &&
	 playerTo->team != eRogueTeam) {

	std::string flagT = data->flagType;

	// Allow theft of team flags only
	allowTransfer = (flagT == "R*" || flagT == "G*" || flagT == "B*" || flagT == "P*");

	if(!allowTransfer) {
	  data->action = data->DropThief;
	  bz_sendTextMessage(BZ_SERVER, data->toPlayerID, noStealMsg.c_str());
	}
      }
    }
      break;

    case eOpenFFAGame:
    {
    }
      break;

    case eRabbitGame:
    {
      if(playerTo->team == playerFrom->team) {

	data->action = data->DropThief;
	bz_sendTextMessage(BZ_SERVER, data->toPlayerID, noStealMsg.c_str());
      }
    }
      break;

    default:
      break;

  }

  bz_freePlayerRecord(playerTo);
  bz_freePlayerRecord(playerFrom);
}

// Local Variables: ***
// mode:C++ ***
// tab-width: 8 ***
// c-basic-offset: 2 ***
// indent-tabs-mode: t ***
// End: ***
// ex: shiftwidth=2 tabstop=8
<commit_msg>Do not call functions with NULL pointers<commit_after>// thiefControl.cpp : Defines the entry point for the DLL application.
//

#include "bzfsAPI.h"

BZ_GET_PLUGIN_VERSION

class ThiefControl : public bz_EventHandler
{
public:
  ThiefControl() {} ;
  virtual ~ThiefControl() {};
  virtual void process( bz_EventData *eventData );
};

ThiefControl thiefHandler;

BZF_PLUGIN_CALL int bz_Load ( const char* /*commandLine*/ )
{
  bz_debugMessage(4,"thiefControl plugin loaded");
  bz_registerEvent(bz_eFlagTransferredEvent, &thiefHandler);
  return 0;
}

BZF_PLUGIN_CALL int bz_Unload ( void )
{
  bz_removeEvent(bz_eFlagTransferredEvent, &thiefHandler);
  bz_debugMessage(4,"thiefControl plugin unloaded");
  return 0;
}

void ThiefControl::process( bz_EventData *eventData )
{
  bz_FlagTransferredEventData_V1 *data = (bz_FlagTransferredEventData_V1 *) eventData;
  const std::string noStealMsg = "Flag dropped. Don't steal from teammates!";

  if(!data)
    return;

  if(data->eventType != bz_eFlagTransferredEvent)
    return;

  bz_BasePlayerRecord *playerFrom = bz_getPlayerByIndex(data->fromPlayerID);

  if (!playerFrom)
    return;

  bz_BasePlayerRecord *playerTo = bz_getPlayerByIndex(data->toPlayerID);

  if(!playerTo) {
    bz_freePlayerRecord(playerFrom);
    return;
  }

  switch(bz_getGameType()) {

    case eTeamFFAGame:
    {
      if(playerTo->team == playerFrom->team &&
	 playerTo->team != eRogueTeam) {

	data->action = data->DropThief;
	bz_sendTextMessage(BZ_SERVER, data->toPlayerID, noStealMsg.c_str());

      }

    }
      break;

    case eClassicCTFGame:
    {

      // Allow teammates to steal team flags
      // This will allow someone to steal a team flag in order
      // to possibly capture it faster.
      bool allowTransfer = false;

      if(playerTo->team == playerFrom->team &&
	 playerTo->team != eRogueTeam) {

	std::string flagT = data->flagType;

	// Allow theft of team flags only
	allowTransfer = (flagT == "R*" || flagT == "G*" || flagT == "B*" || flagT == "P*");

	if(!allowTransfer) {
	  data->action = data->DropThief;
	  bz_sendTextMessage(BZ_SERVER, data->toPlayerID, noStealMsg.c_str());
	}
      }
    }
      break;

    case eOpenFFAGame:
    {
    }
      break;

    case eRabbitGame:
    {
      if(playerTo->team == playerFrom->team) {

	data->action = data->DropThief;
	bz_sendTextMessage(BZ_SERVER, data->toPlayerID, noStealMsg.c_str());
      }
    }
      break;

    default:
      break;

  }

  bz_freePlayerRecord(playerTo);
  bz_freePlayerRecord(playerFrom);
}

// Local Variables: ***
// mode:C++ ***
// tab-width: 8 ***
// c-basic-offset: 2 ***
// indent-tabs-mode: t ***
// End: ***
// ex: shiftwidth=2 tabstop=8
<|endoftext|>


<commit_before>// mapnik
#include "mapnik3x_compatibility.hpp"
#include <mapnik/map.hpp>
#include <mapnik/layer.hpp>
#include <mapnik/image_util.hpp>
#include <mapnik/graphics.hpp>
#include <mapnik/agg_renderer.hpp>
#include <mapnik/save_map.hpp>
#include <mapnik/map.hpp>
#include <mapnik/feature.hpp>
#include <mapnik/feature_factory.hpp>
#include <mapnik/unicode.hpp>
#include <mapnik/geometry.hpp>
#include <mapnik/datasource.hpp>
#include <mapnik/load_map.hpp>
#include <mapnik/memory_datasource.hpp>

// boost
#include MAPNIK_SHARED_INCLUDE
#include MAPNIK_MAKE_SHARED_INCLUDE

#include <string>

MAPNIK_SHARED_PTR<mapnik::memory_datasource> build_ds(double x,double y) {
    mapnik::context_ptr ctx = MAPNIK_MAKE_SHARED<mapnik::context_type>();
    ctx->push("name");
    mapnik::feature_ptr feature(mapnik::feature_factory::create(ctx,1));
    mapnik::transcoder tr("utf-8");
    UnicodeString ustr = tr.transcode("null island");
    feature->put("name",ustr);
    mapnik::geometry_type * pt = new mapnik::geometry_type(MAPNIK_POINT);
    pt->move_to(x,y);
    feature->add_geometry(pt);
    MAPNIK_SHARED_PTR<mapnik::memory_datasource> ds = MAPNIK_MAKE_SHARED<mapnik::memory_datasource>();
    ds->push(feature);
    return ds;
}
<commit_msg>put string directly as rvalue to avoid copy with c++11<commit_after>// mapnik
#include "mapnik3x_compatibility.hpp"
#include <mapnik/map.hpp>
#include <mapnik/layer.hpp>
#include <mapnik/image_util.hpp>
#include <mapnik/graphics.hpp>
#include <mapnik/agg_renderer.hpp>
#include <mapnik/save_map.hpp>
#include <mapnik/map.hpp>
#include <mapnik/feature.hpp>
#include <mapnik/feature_factory.hpp>
#include <mapnik/unicode.hpp>
#include <mapnik/geometry.hpp>
#include <mapnik/datasource.hpp>
#include <mapnik/load_map.hpp>
#include <mapnik/memory_datasource.hpp>

// boost
#include MAPNIK_SHARED_INCLUDE
#include MAPNIK_MAKE_SHARED_INCLUDE

#include <string>

MAPNIK_SHARED_PTR<mapnik::memory_datasource> build_ds(double x,double y) {
    mapnik::context_ptr ctx = MAPNIK_MAKE_SHARED<mapnik::context_type>();
    ctx->push("name");
    mapnik::feature_ptr feature(mapnik::feature_factory::create(ctx,1));
    mapnik::transcoder tr("utf-8");
    feature->put("name",tr.transcode("null island"));
    mapnik::geometry_type * pt = new mapnik::geometry_type(MAPNIK_POINT);
    pt->move_to(x,y);
    feature->add_geometry(pt);
    MAPNIK_SHARED_PTR<mapnik::memory_datasource> ds = MAPNIK_MAKE_SHARED<mapnik::memory_datasource>();
    ds->push(feature);
    return ds;
}
<|endoftext|>


<commit_before>/***************************************************************************
* Copyright (c) 2016, Johan Mabille and Sylvain Corlay                     *
*                                                                          *
* Distributed under the terms of the BSD 3-Clause License.                 *
*                                                                          *
* The full license is in the file LICENSE, distributed with this software. *
****************************************************************************/

#include "gtest/gtest.h"
#include "xtensor/xarray.hpp"
#include "xtensor/xmath.hpp"

namespace xt
{
    using std::size_t;
    using shape_type = std::vector<size_t>;

    /**********************
     * Basic operations
     **********************/

    TEST(xmath, abs)
    {
        shape_type shape = {3, 2};
        xarray<double> a(shape, 4.5);
        EXPECT_EQ(abs(a)(0, 0), std::abs(a(0, 0)));
    }

    TEST(xmath, fabs)
    {
        shape_type shape = {3, 2};
        xarray<double> a(shape, 4.5);
        EXPECT_EQ(fabs(a)(0, 0), std::fabs(a(0, 0)));
    }

    TEST(xmath, fmod)
    {
        shape_type shape = {3, 2};
        xarray<double> a(shape, 4.5);
        xarray<double> b(shape, 1.3);
        EXPECT_EQ(fmod(a, b)(0, 0), std::fmod(a(0, 0), b(0, 0)));

        double sb = 1.2;
        EXPECT_EQ(fmod(a, sb)(0, 0), std::fmod(a(0, 0), sb));

        double sa = 4.6;
        EXPECT_EQ(fmod(sa, b)(0, 0), std::fmod(sa, b(0, 0)));
    }

    TEST(xmath, remainder)
    {
        shape_type shape = {3, 2};
        xarray<double> a(shape, 4.5);
        xarray<double> b(shape, 1.3);
        EXPECT_EQ(remainder(a, b)(0, 0), std::remainder(a(0, 0), b(0, 0)));

        double sb = 1.2;
        EXPECT_EQ(remainder(a, sb)(0, 0), std::remainder(a(0, 0), sb));

        double sa = 4.6;
        EXPECT_EQ(remainder(sa, b)(0, 0), std::remainder(sa, b(0, 0)));
    }

    TEST(xmath, fma)
    {
        shape_type shape = {3, 2};
        xarray<double> a(shape, 4.5);
        xarray<double> b(shape, 1.3);
        xarray<double> c(shape, 2.6);
        EXPECT_EQ(fma(a, b, c)(0, 0), std::fma(a(0, 0), b(0, 0), c(0, 0)));

        double sb = 1.2;
        EXPECT_EQ(fma(a, sb, c)(0, 0), std::fma(a(0, 0), sb, c(0, 0)));

        double sa = 4.6;
        EXPECT_EQ(fma(sa, b, c)(0, 0), std::fma(sa, b(0, 0), c(0, 0)));

        EXPECT_EQ(fma(sa, sb, c)(0, 0), std::fma(sa, sb, c(0, 0)));
    }

    TEST(xmath, fmax)
    {
        shape_type shape = {3, 2};
        xarray<double> a(shape, 4.5);
        xarray<double> b(shape, 1.3);
        EXPECT_EQ(fmax(a, b)(0, 0), std::fmax(a(0, 0), b(0, 0)));

        double sb = 1.2;
        EXPECT_EQ(fmax(a, sb)(0, 0), std::fmax(a(0, 0), sb));

        double sa = 4.6;
        EXPECT_EQ(fmax(sa, b)(0, 0), std::fmax(sa, b(0, 0)));
    }

    TEST(xmath, fmin)
    {
        shape_type shape = {3, 2};
        xarray<double> a(shape, 4.5);
        xarray<double> b(shape, 1.3);
        EXPECT_EQ(fmin(a, b)(0, 0), std::fmin(a(0, 0), b(0, 0)));

        double sb = 1.2;
        EXPECT_EQ(fmin(a, sb)(0, 0), std::fmin(a(0, 0), sb));

        double sa = 4.6;
        EXPECT_EQ(fmin(sa, b)(0, 0), std::fmin(sa, b(0, 0)));
    }

    TEST(xmath, fdim)
    {
        shape_type shape = {3, 2};
        xarray<double> a(shape, 4.5);
        xarray<double> b(shape, 1.3);
        EXPECT_EQ(fdim(a, b)(0, 0), std::fdim(a(0, 0), b(0, 0)));

        double sb = 1.2;
        EXPECT_EQ(fdim(a, sb)(0, 0), std::fdim(a(0, 0), sb));

        double sa = 4.6;
        EXPECT_EQ(fdim(sa, b)(0, 0), std::fdim(sa, b(0, 0)));
    }

    /***************************
     * Exponential functions
     ***************************/

    TEST(xmath, exp)
    {
        shape_type shape = {3, 2};
        xarray<double> a(shape, 3.7);
        EXPECT_EQ(exp(a)(0, 0), std::exp(a(0, 0)));
    }

    TEST(xmath, exp2)
    {
        shape_type shape = {3, 2};
        xarray<double> a(shape, 3.7);
        EXPECT_EQ(exp2(a)(0, 0), std::exp2(a(0, 0)));
    }

    TEST(xmath, expm1)
    {
        shape_type shape = {3, 2};
        xarray<double> a(shape, 3.7);
        EXPECT_EQ(expm1(a)(0, 0), std::expm1(a(0, 0)));
    }

    TEST(xmath, log)
    {
        shape_type shape = {3, 2};
        xarray<double> a(shape, 3.7);
        EXPECT_EQ(log(a)(0, 0), std::log(a(0, 0)));
    }

    TEST(xmath, log2)
    {
        shape_type shape = {3, 2};
        xarray<double> a(shape, 3.7);
        EXPECT_EQ(log2(a)(0, 0), std::log2(a(0, 0)));
    }

    TEST(xmath, log1p)
    {
        shape_type shape = {3, 2};
        xarray<double> a(shape, 3.7);
        EXPECT_EQ(log1p(a)(0, 0), std::log1p(a(0, 0)));
    }

    /*********************
     * Power functions
     *********************/

    TEST(xmath, pow)
    {
        shape_type shape = {3, 2};
        xarray<double> a(shape, 4.5);
        xarray<double> b(shape, 1.3);
        EXPECT_EQ(pow(a, b)(0, 0), std::pow(a(0, 0), b(0, 0)));

        double sb = 1.2;
        EXPECT_EQ(pow(a, sb)(0, 0), std::pow(a(0, 0), sb));

        double sa = 4.6;
        EXPECT_EQ(pow(sa, b)(0, 0), std::pow(sa, b(0, 0)));
    }

    TEST(xmath, sqrt)
    {
        shape_type shape = {3, 2};
        xarray<double> a(shape, 3.7);
        EXPECT_EQ(sqrt(a)(0, 0), std::sqrt(a(0, 0)));
    }

    TEST(xmath, cbrt)
    {
        shape_type shape = {3, 2};
        xarray<double> a(shape, 3.7);
        EXPECT_EQ(cbrt(a)(0, 0), std::cbrt(a(0, 0)));
    }

    TEST(xmath, hypot)
    {
        shape_type shape = {3, 2};
        xarray<double> a(shape, 4.5);
        xarray<double> b(shape, 1.3);
        EXPECT_EQ(hypot(a, b)(0, 0), std::hypot(a(0, 0), b(0, 0)));

        double sb = 1.2;
        EXPECT_EQ(hypot(a, sb)(0, 0), std::hypot(a(0, 0), sb));

        double sa = 4.6;
        EXPECT_EQ(hypot(sa, b)(0, 0), std::hypot(sa, b(0, 0)));
    }

    /*****************************
     * Trigonometric functions
     *****************************/

    TEST(xmath, sin)
    {
        shape_type shape = {3, 2};
        xarray<double> a(shape, 3.7);
        EXPECT_EQ(sin(a)(0, 0), std::sin(a(0, 0)));
    }

    TEST(xmath, cos)
    {
        shape_type shape = {3, 2};
        xarray<double> a(shape, 3.7);
        EXPECT_EQ(cos(a)(0, 0), std::cos(a(0, 0)));
    }

    TEST(xmath, tan)
    {
        shape_type shape = {3, 2};
        xarray<double> a(shape, 3.7);
        EXPECT_EQ(tan(a)(0, 0), std::tan(a(0, 0)));
    }

    TEST(xmath, asin)
    {
        shape_type shape = {3, 2};
        xarray<double> a(shape, 0.7);
        EXPECT_EQ(asin(a)(0, 0), std::asin(a(0, 0)));
    }

    TEST(xmath, acos)
    {
        shape_type shape = {3, 2};
        xarray<double> a(shape, 0.7);
        EXPECT_EQ(acos(a)(0, 0), std::acos(a(0, 0)));
    }

    TEST(xmath, atan)
    {
        shape_type shape = {3, 2};
        xarray<double> a(shape, 3.7);
        EXPECT_EQ(atan(a)(0, 0), std::atan(a(0, 0)));
    }

    TEST(xmath, atan2)
    {
        shape_type shape = {3, 2};
        xarray<double> a(shape, 4.5);
        xarray<double> b(shape, 1.3);
        EXPECT_EQ(atan2(a, b)(0, 0), std::atan2(a(0, 0), b(0, 0)));

        double sb = 1.2;
        EXPECT_EQ(atan2(a, sb)(0, 0), std::atan2(a(0, 0), sb));

        double sa = 4.6;
        EXPECT_EQ(atan2(sa, b)(0, 0), std::atan2(sa, b(0, 0)));
    }

    /**************************
     * Hyperbolic functions
     **************************/

    TEST(xmath, sinh)
    {
        shape_type shape = {3, 2};
        xarray<double> a(shape, 3.7);
        EXPECT_EQ(sinh(a)(0, 0), std::sinh(a(0, 0)));
    }

    TEST(xmath, cosh)
    {
        shape_type shape = {3, 2};
        xarray<double> a(shape, 3.7);
        EXPECT_EQ(cosh(a)(0, 0), std::cosh(a(0, 0)));
    }

    TEST(xmath, tanh)
    {
        shape_type shape = {3, 2};
        xarray<double> a(shape, 3.7);
        EXPECT_EQ(tanh(a)(0, 0), std::tanh(a(0, 0)));
    }

    TEST(xmath, asinh)
    {
        shape_type shape = {3, 2};
        xarray<double> a(shape, 0.7);
        EXPECT_EQ(asinh(a)(0, 0), std::asinh(a(0, 0)));
    }

    TEST(xmath, acosh)
    {
        shape_type shape = {3, 2};
        xarray<double> a(shape, 1.7);
        EXPECT_EQ(acosh(a)(0, 0), std::acosh(a(0, 0)));
    }

    TEST(xmath, atanh)
    {
        shape_type shape = {3, 2};
        xarray<double> a(shape, 0.7);
        EXPECT_EQ(atanh(a)(0, 0), std::atanh(a(0, 0)));
    }

    /*******************************
     * Error and gamma functions
     *******************************/

    TEST(xmath, erf)
    {
        shape_type shape = {3, 2};
        xarray<double> a(shape, 0.7);
        EXPECT_EQ(erf(a)(0, 0), std::erf(a(0, 0)));
    }

    TEST(xmath, erfc)
    {
        shape_type shape = {3, 2};
        xarray<double> a(shape, 0.7);
        EXPECT_EQ(erfc(a)(0, 0), std::erfc(a(0, 0)));
    }

    TEST(xmath, tgamma)
    {
        shape_type shape = {3, 2};
        xarray<double> a(shape, 0.7);
        EXPECT_EQ(tgamma(a)(0, 0), std::tgamma(a(0, 0)));
    }

    TEST(xmath, lgamma)
    {
        shape_type shape = {3, 2};
        xarray<double> a(shape, 0.7);
        EXPECT_EQ(lgamma(a)(0, 0), std::lgamma(a(0, 0)));
    }

}

<commit_msg>disambiguate fma call in test_xmath<commit_after>/***************************************************************************
* Copyright (c) 2016, Johan Mabille and Sylvain Corlay                     *
*                                                                          *
* Distributed under the terms of the BSD 3-Clause License.                 *
*                                                                          *
* The full license is in the file LICENSE, distributed with this software. *
****************************************************************************/

#include "gtest/gtest.h"
#include "xtensor/xarray.hpp"
#include "xtensor/xmath.hpp"

namespace xt
{
    using std::size_t;
    using shape_type = std::vector<size_t>;

    /**********************
     * Basic operations
     **********************/

    TEST(xmath, abs)
    {
        shape_type shape = {3, 2};
        xarray<double> a(shape, 4.5);
        EXPECT_EQ(abs(a)(0, 0), std::abs(a(0, 0)));
    }

    TEST(xmath, fabs)
    {
        shape_type shape = {3, 2};
        xarray<double> a(shape, 4.5);
        EXPECT_EQ(fabs(a)(0, 0), std::fabs(a(0, 0)));
    }

    TEST(xmath, fmod)
    {
        shape_type shape = {3, 2};
        xarray<double> a(shape, 4.5);
        xarray<double> b(shape, 1.3);
        EXPECT_EQ(fmod(a, b)(0, 0), std::fmod(a(0, 0), b(0, 0)));

        double sb = 1.2;
        EXPECT_EQ(fmod(a, sb)(0, 0), std::fmod(a(0, 0), sb));

        double sa = 4.6;
        EXPECT_EQ(fmod(sa, b)(0, 0), std::fmod(sa, b(0, 0)));
    }

    TEST(xmath, remainder)
    {
        shape_type shape = {3, 2};
        xarray<double> a(shape, 4.5);
        xarray<double> b(shape, 1.3);
        EXPECT_EQ(remainder(a, b)(0, 0), std::remainder(a(0, 0), b(0, 0)));

        double sb = 1.2;
        EXPECT_EQ(remainder(a, sb)(0, 0), std::remainder(a(0, 0), sb));

        double sa = 4.6;
        EXPECT_EQ(remainder(sa, b)(0, 0), std::remainder(sa, b(0, 0)));
    }

    TEST(xmath, fma)
    {
        shape_type shape = {3, 2};
        xarray<double> a(shape, 4.5);
        xarray<double> b(shape, 1.3);
        xarray<double> c(shape, 2.6);
        EXPECT_EQ(xt::fma(a, b, c)(0, 0), std::fma(a(0, 0), b(0, 0), c(0, 0)));

        double sb = 1.2;
        EXPECT_EQ(xt::fma(a, sb, c)(0, 0), std::fma(a(0, 0), sb, c(0, 0)));

        double sa = 4.6;
        EXPECT_EQ(xt::fma(sa, b, c)(0, 0), std::fma(sa, b(0, 0), c(0, 0)));

        EXPECT_EQ(xt::fma(sa, sb, c)(0, 0), std::fma(sa, sb, c(0, 0)));
    }

    TEST(xmath, fmax)
    {
        shape_type shape = {3, 2};
        xarray<double> a(shape, 4.5);
        xarray<double> b(shape, 1.3);
        EXPECT_EQ(fmax(a, b)(0, 0), std::fmax(a(0, 0), b(0, 0)));

        double sb = 1.2;
        EXPECT_EQ(fmax(a, sb)(0, 0), std::fmax(a(0, 0), sb));

        double sa = 4.6;
        EXPECT_EQ(fmax(sa, b)(0, 0), std::fmax(sa, b(0, 0)));
    }

    TEST(xmath, fmin)
    {
        shape_type shape = {3, 2};
        xarray<double> a(shape, 4.5);
        xarray<double> b(shape, 1.3);
        EXPECT_EQ(fmin(a, b)(0, 0), std::fmin(a(0, 0), b(0, 0)));

        double sb = 1.2;
        EXPECT_EQ(fmin(a, sb)(0, 0), std::fmin(a(0, 0), sb));

        double sa = 4.6;
        EXPECT_EQ(fmin(sa, b)(0, 0), std::fmin(sa, b(0, 0)));
    }

    TEST(xmath, fdim)
    {
        shape_type shape = {3, 2};
        xarray<double> a(shape, 4.5);
        xarray<double> b(shape, 1.3);
        EXPECT_EQ(fdim(a, b)(0, 0), std::fdim(a(0, 0), b(0, 0)));

        double sb = 1.2;
        EXPECT_EQ(fdim(a, sb)(0, 0), std::fdim(a(0, 0), sb));

        double sa = 4.6;
        EXPECT_EQ(fdim(sa, b)(0, 0), std::fdim(sa, b(0, 0)));
    }

    /***************************
     * Exponential functions
     ***************************/

    TEST(xmath, exp)
    {
        shape_type shape = {3, 2};
        xarray<double> a(shape, 3.7);
        EXPECT_EQ(exp(a)(0, 0), std::exp(a(0, 0)));
    }

    TEST(xmath, exp2)
    {
        shape_type shape = {3, 2};
        xarray<double> a(shape, 3.7);
        EXPECT_EQ(exp2(a)(0, 0), std::exp2(a(0, 0)));
    }

    TEST(xmath, expm1)
    {
        shape_type shape = {3, 2};
        xarray<double> a(shape, 3.7);
        EXPECT_EQ(expm1(a)(0, 0), std::expm1(a(0, 0)));
    }

    TEST(xmath, log)
    {
        shape_type shape = {3, 2};
        xarray<double> a(shape, 3.7);
        EXPECT_EQ(log(a)(0, 0), std::log(a(0, 0)));
    }

    TEST(xmath, log2)
    {
        shape_type shape = {3, 2};
        xarray<double> a(shape, 3.7);
        EXPECT_EQ(log2(a)(0, 0), std::log2(a(0, 0)));
    }

    TEST(xmath, log1p)
    {
        shape_type shape = {3, 2};
        xarray<double> a(shape, 3.7);
        EXPECT_EQ(log1p(a)(0, 0), std::log1p(a(0, 0)));
    }

    /*********************
     * Power functions
     *********************/

    TEST(xmath, pow)
    {
        shape_type shape = {3, 2};
        xarray<double> a(shape, 4.5);
        xarray<double> b(shape, 1.3);
        EXPECT_EQ(pow(a, b)(0, 0), std::pow(a(0, 0), b(0, 0)));

        double sb = 1.2;
        EXPECT_EQ(pow(a, sb)(0, 0), std::pow(a(0, 0), sb));

        double sa = 4.6;
        EXPECT_EQ(pow(sa, b)(0, 0), std::pow(sa, b(0, 0)));
    }

    TEST(xmath, sqrt)
    {
        shape_type shape = {3, 2};
        xarray<double> a(shape, 3.7);
        EXPECT_EQ(sqrt(a)(0, 0), std::sqrt(a(0, 0)));
    }

    TEST(xmath, cbrt)
    {
        shape_type shape = {3, 2};
        xarray<double> a(shape, 3.7);
        EXPECT_EQ(cbrt(a)(0, 0), std::cbrt(a(0, 0)));
    }

    TEST(xmath, hypot)
    {
        shape_type shape = {3, 2};
        xarray<double> a(shape, 4.5);
        xarray<double> b(shape, 1.3);
        EXPECT_EQ(hypot(a, b)(0, 0), std::hypot(a(0, 0), b(0, 0)));

        double sb = 1.2;
        EXPECT_EQ(hypot(a, sb)(0, 0), std::hypot(a(0, 0), sb));

        double sa = 4.6;
        EXPECT_EQ(hypot(sa, b)(0, 0), std::hypot(sa, b(0, 0)));
    }

    /*****************************
     * Trigonometric functions
     *****************************/

    TEST(xmath, sin)
    {
        shape_type shape = {3, 2};
        xarray<double> a(shape, 3.7);
        EXPECT_EQ(sin(a)(0, 0), std::sin(a(0, 0)));
    }

    TEST(xmath, cos)
    {
        shape_type shape = {3, 2};
        xarray<double> a(shape, 3.7);
        EXPECT_EQ(cos(a)(0, 0), std::cos(a(0, 0)));
    }

    TEST(xmath, tan)
    {
        shape_type shape = {3, 2};
        xarray<double> a(shape, 3.7);
        EXPECT_EQ(tan(a)(0, 0), std::tan(a(0, 0)));
    }

    TEST(xmath, asin)
    {
        shape_type shape = {3, 2};
        xarray<double> a(shape, 0.7);
        EXPECT_EQ(asin(a)(0, 0), std::asin(a(0, 0)));
    }

    TEST(xmath, acos)
    {
        shape_type shape = {3, 2};
        xarray<double> a(shape, 0.7);
        EXPECT_EQ(acos(a)(0, 0), std::acos(a(0, 0)));
    }

    TEST(xmath, atan)
    {
        shape_type shape = {3, 2};
        xarray<double> a(shape, 3.7);
        EXPECT_EQ(atan(a)(0, 0), std::atan(a(0, 0)));
    }

    TEST(xmath, atan2)
    {
        shape_type shape = {3, 2};
        xarray<double> a(shape, 4.5);
        xarray<double> b(shape, 1.3);
        EXPECT_EQ(atan2(a, b)(0, 0), std::atan2(a(0, 0), b(0, 0)));

        double sb = 1.2;
        EXPECT_EQ(atan2(a, sb)(0, 0), std::atan2(a(0, 0), sb));

        double sa = 4.6;
        EXPECT_EQ(atan2(sa, b)(0, 0), std::atan2(sa, b(0, 0)));
    }

    /**************************
     * Hyperbolic functions
     **************************/

    TEST(xmath, sinh)
    {
        shape_type shape = {3, 2};
        xarray<double> a(shape, 3.7);
        EXPECT_EQ(sinh(a)(0, 0), std::sinh(a(0, 0)));
    }

    TEST(xmath, cosh)
    {
        shape_type shape = {3, 2};
        xarray<double> a(shape, 3.7);
        EXPECT_EQ(cosh(a)(0, 0), std::cosh(a(0, 0)));
    }

    TEST(xmath, tanh)
    {
        shape_type shape = {3, 2};
        xarray<double> a(shape, 3.7);
        EXPECT_EQ(tanh(a)(0, 0), std::tanh(a(0, 0)));
    }

    TEST(xmath, asinh)
    {
        shape_type shape = {3, 2};
        xarray<double> a(shape, 0.7);
        EXPECT_EQ(asinh(a)(0, 0), std::asinh(a(0, 0)));
    }

    TEST(xmath, acosh)
    {
        shape_type shape = {3, 2};
        xarray<double> a(shape, 1.7);
        EXPECT_EQ(acosh(a)(0, 0), std::acosh(a(0, 0)));
    }

    TEST(xmath, atanh)
    {
        shape_type shape = {3, 2};
        xarray<double> a(shape, 0.7);
        EXPECT_EQ(atanh(a)(0, 0), std::atanh(a(0, 0)));
    }

    /*******************************
     * Error and gamma functions
     *******************************/

    TEST(xmath, erf)
    {
        shape_type shape = {3, 2};
        xarray<double> a(shape, 0.7);
        EXPECT_EQ(erf(a)(0, 0), std::erf(a(0, 0)));
    }

    TEST(xmath, erfc)
    {
        shape_type shape = {3, 2};
        xarray<double> a(shape, 0.7);
        EXPECT_EQ(erfc(a)(0, 0), std::erfc(a(0, 0)));
    }

    TEST(xmath, tgamma)
    {
        shape_type shape = {3, 2};
        xarray<double> a(shape, 0.7);
        EXPECT_EQ(tgamma(a)(0, 0), std::tgamma(a(0, 0)));
    }

    TEST(xmath, lgamma)
    {
        shape_type shape = {3, 2};
        xarray<double> a(shape, 0.7);
        EXPECT_EQ(lgamma(a)(0, 0), std::lgamma(a(0, 0)));
    }

}

<|endoftext|>


<commit_before>// Copyright (c) 2012, Susumu Yata
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice,
//    this list of conditions and the following disclaimer.
// 2. Redistributions in binary form must reproduce the above copyright notice,
//    this list of conditions and the following disclaimer in the documentation
//    and/or other materials provided with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
// THE POSSIBILITY OF SUCH DAMAGE.

#include <algorithm>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <iomanip>
#include <iostream>
#include <set>
#include <string>
#include <thread>
#include <vector>

#include <madoka/sketch.h>
#include <madoka/random.h>

namespace {

const std::size_t NUM_KEYS       = 1 << 17;
const std::size_t MIN_KEY_LENGTH = 1;
const std::size_t MAX_KEY_LENGTH = 16;

void generate_keys(std::vector<std::string> *keys,
                   std::vector<madoka::UInt64> *freqs,
                   std::vector<std::size_t> *ids) {
  madoka::Random random;

  std::set<std::string> unique_keys;
  std::string key;
  while (unique_keys.size() < NUM_KEYS) {
    const std::size_t key_length = MIN_KEY_LENGTH +
        (random() % (MAX_KEY_LENGTH - MIN_KEY_LENGTH + 1));
    key.resize(key_length);
    for (std::size_t j = 0; j < key_length; ++j) {
      key[j] = 'A' + (random() % 26);
    }
    unique_keys.insert(key);
  }
  std::vector<std::string>(unique_keys.begin(), unique_keys.end()).swap(*keys);

  for (std::size_t i = 0; i < NUM_KEYS; ++i) {
    const std::size_t freq = NUM_KEYS / (i + 1);
    freqs->push_back(freq);
    for (std::size_t j = 0; j < freq; ++j) {
      ids->push_back(i);
    }
  }
  std::random_shuffle(ids->begin(), ids->end(), random);
}

void do_approx_count(madoka::UInt64 count,
                     madoka::UInt64 *approx, madoka::Random *random) {
  for (madoka::UInt64 i = 0; i < count; ++i) {
    *approx = madoka::Approx::inc(*approx, random);
  }
}

void test_approx() {
  std::cout << "info: Approx: catastrophic" << std::endl;

  std::cout.setf(std::ios::fixed);

  for (madoka::UInt64 count = 1 << 20; count <= (1 << 24); count <<= 1) {
    std::cout << "info: " << std::setw(8) << count << ':' << std::flush;
    for (int num_threads = 1; num_threads <= 8; ++num_threads) {
      madoka::UInt64 approx = 0;
      madoka::Random random;

      std::vector<std::thread> threads;
      for (int i = 0; i < num_threads; ++i) {
        threads.push_back(std::thread(do_approx_count, count / num_threads,
                                      &approx, &random));
      }

      for (std::size_t i = 0; i < threads.size(); ++i) {
        threads[i].join();
      }

      const madoka::UInt64 value = madoka::Approx::decode(approx);
      std::cout << ' ' << std::setw(5) << std::setprecision(3)
                << (static_cast<double>(value) / count) << std::flush;
    }
    std::cout << std::endl;
  }
}

void do_sketch_count(const std::vector<std::string> &keys,
                     std::vector<std::size_t>::const_iterator begin,
                     std::vector<std::size_t>::const_iterator end,
                     madoka::Sketch *sketch) {
  for (std::vector<std::size_t>::const_iterator it = begin; it != end; ++it) {
    sketch->inc(keys[*it].c_str(), keys[*it].length());
  }
}

void test_sketch() {
  std::vector<std::string> keys;
  std::vector<madoka::UInt64> freqs;
  std::vector<std::size_t> ids;
  generate_keys(&keys, &freqs, &ids);

  MADOKA_THROW_IF(keys.size() != NUM_KEYS);
  MADOKA_THROW_IF(freqs.size() != NUM_KEYS);

  std::cout << "info: Sketch: Zipf distribution: "
            << "#keys = " << keys.size()
            << ", #queries = " << ids.size() << std::endl;

  std::cout.setf(std::ios::fixed);

  madoka::Random random;
  for (madoka::UInt64 width = keys.size() / 4;
       width <= keys.size() * 4; width *= 2) {
    std::cout << "info: " << std::setw(6) << width << ':' << std::flush;
    for (int num_threads = 1; num_threads <= 8; ++num_threads) {
      madoka::Sketch sketch;
      sketch.create(width);

      std::vector<std::thread> threads;
      for (int i = 0; i < num_threads; ++i) {
        const auto begin = ids.begin() + (ids.size() / num_threads) * i;
        const auto end = ids.begin() + (ids.size() / num_threads) * (i + 1);
        threads.push_back(std::thread(do_sketch_count, keys, begin, end,
                                      &sketch));
      }

      for (std::size_t i = 0; i < threads.size(); ++i) {
        threads[i].join();
      }

      madoka::UInt64 diff = 0;
      for (std::size_t i = 0; i < keys.size(); ++i) {
        const madoka::UInt64 freq =
            sketch.get(keys[i].c_str(), keys[i].length());
        diff += std::llabs(freq - freqs[i]);
      }
      std::cout << ' ' << std::setw(6) << std::setprecision(3)
                << (100.0 * diff / ids.size()) << '%' << std::flush;
    }
    std::cout << std::endl;
  }
}

}  // namespace

int main() try {
  test_approx();
  test_sketch();

  return 0;
} catch (const madoka::Exception &ex) {
  std::cerr << "error: " << ex.what() << std::endl;
  return 1;
}
<commit_msg>added a benchmark of merge().<commit_after>// Copyright (c) 2012, Susumu Yata
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice,
//    this list of conditions and the following disclaimer.
// 2. Redistributions in binary form must reproduce the above copyright notice,
//    this list of conditions and the following disclaimer in the documentation
//    and/or other materials provided with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
// THE POSSIBILITY OF SUCH DAMAGE.

#include <algorithm>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <iomanip>
#include <iostream>
#include <set>
#include <string>
#include <thread>
#include <vector>

#include <madoka/sketch.h>
#include <madoka/random.h>

namespace {

const std::size_t NUM_KEYS       = 1 << 17;
const std::size_t MIN_KEY_LENGTH = 1;
const std::size_t MAX_KEY_LENGTH = 16;

void generate_keys(std::vector<std::string> *keys,
                   std::vector<madoka::UInt64> *freqs,
                   std::vector<std::size_t> *ids) {
  madoka::Random random;

  std::set<std::string> unique_keys;
  std::string key;
  while (unique_keys.size() < NUM_KEYS) {
    const std::size_t key_length = MIN_KEY_LENGTH +
        (random() % (MAX_KEY_LENGTH - MIN_KEY_LENGTH + 1));
    key.resize(key_length);
    for (std::size_t j = 0; j < key_length; ++j) {
      key[j] = 'A' + (random() % 26);
    }
    unique_keys.insert(key);
  }
  std::vector<std::string>(unique_keys.begin(), unique_keys.end()).swap(*keys);

  for (std::size_t i = 0; i < NUM_KEYS; ++i) {
    const std::size_t freq = NUM_KEYS / (i + 1);
    freqs->push_back(freq);
    for (std::size_t j = 0; j < freq; ++j) {
      ids->push_back(i);
    }
  }
  std::random_shuffle(ids->begin(), ids->end(), random);
}

void do_approx_count(madoka::UInt64 count,
                     madoka::UInt64 *approx, madoka::Random *random) {
  for (madoka::UInt64 i = 0; i < count; ++i) {
    *approx = madoka::Approx::inc(*approx, random);
  }
}

void test_approx() {
  std::cout << "info: Approx: catastrophic" << std::endl;

  std::cout.setf(std::ios::fixed);

  for (madoka::UInt64 count = 1 << 20; count <= (1 << 24); count <<= 1) {
    std::cout << "info: " << std::setw(8) << count << ':' << std::flush;
    for (int num_threads = 1; num_threads <= 8; ++num_threads) {
      madoka::UInt64 approx = 0;
      madoka::Random random;

      std::vector<std::thread> threads;
      for (int i = 0; i < num_threads; ++i) {
        threads.push_back(std::thread(do_approx_count, count / num_threads,
                                      &approx, &random));
      }

      for (std::size_t i = 0; i < threads.size(); ++i) {
        threads[i].join();
      }

      const madoka::UInt64 value = madoka::Approx::decode(approx);
      std::cout << ' ' << std::setw(5) << std::setprecision(3)
                << (static_cast<double>(value) / count) << std::flush;
    }
    std::cout << std::endl;
  }
}

void do_sketch_count(const std::vector<std::string> &keys,
                     std::vector<std::size_t>::const_iterator begin,
                     std::vector<std::size_t>::const_iterator end,
                     madoka::Sketch *sketch) {
  for (std::vector<std::size_t>::const_iterator it = begin; it != end; ++it) {
    sketch->inc(keys[*it].c_str(), keys[*it].length());
  }
}

void test_sketch() {
  std::vector<std::string> keys;
  std::vector<madoka::UInt64> freqs;
  std::vector<std::size_t> ids;
  generate_keys(&keys, &freqs, &ids);

  MADOKA_THROW_IF(keys.size() != NUM_KEYS);
  MADOKA_THROW_IF(freqs.size() != NUM_KEYS);

  std::cout << "info: Sketch: Zipf distribution: "
            << "#keys = " << keys.size()
            << ", #queries = " << ids.size() << std::endl;

  std::cout.setf(std::ios::fixed);

  madoka::Random random;
  for (madoka::UInt64 width = keys.size() / 4;
       width <= keys.size() * 4; width *= 2) {
    std::cout << "info: " << std::setw(6) << width << ':' << std::flush;
    for (int num_threads = 1; num_threads <= 8; ++num_threads) {
      madoka::Sketch sketch;
      sketch.create(width);

      std::vector<std::thread> threads;
      for (int i = 0; i < num_threads; ++i) {
        const auto begin = ids.begin() + (ids.size() / num_threads) * i;
        const auto end = ids.begin() + (ids.size() / num_threads) * (i + 1);
        threads.push_back(std::thread(do_sketch_count, keys, begin, end,
                                      &sketch));
      }

      for (int i = 0; i < num_threads; ++i) {
        threads[i].join();
      }

      madoka::UInt64 diff = 0;
      for (std::size_t i = 0; i < keys.size(); ++i) {
        const madoka::UInt64 freq =
            sketch.get(keys[i].c_str(), keys[i].length());
        diff += std::llabs(freq - freqs[i]);
      }
      std::cout << ' ' << std::setw(6) << std::setprecision(3)
                << (100.0 * diff / ids.size()) << '%' << std::flush;
    }
    std::cout << std::endl;
  }
}

void test_merge() {
  std::vector<std::string> keys;
  std::vector<madoka::UInt64> freqs;
  std::vector<std::size_t> ids;
  generate_keys(&keys, &freqs, &ids);

  MADOKA_THROW_IF(keys.size() != NUM_KEYS);
  MADOKA_THROW_IF(freqs.size() != NUM_KEYS);

  std::cout << "info: Sketch (merge): Zipf distribution: "
            << "#keys = " << keys.size()
            << ", #queries = " << ids.size() << std::endl;

  std::cout.setf(std::ios::fixed);

  madoka::Random random;
  for (madoka::UInt64 width = keys.size() / 4;
       width <= keys.size() * 4; width *= 2) {
    std::cout << "info: " << std::setw(6) << width << ':' << std::flush;
    for (int num_threads = 1; num_threads <= 8; ++num_threads) {
      madoka::Sketch * const sketches = new madoka::Sketch[num_threads];
      for (int i = 0; i < num_threads; ++i) {
        sketches[i].create(width);
      }

      std::vector<std::thread> threads;
      for (int i = 0; i < num_threads; ++i) {
        const auto begin = ids.begin() + (ids.size() / num_threads) * i;
        const auto end = ids.begin() + (ids.size() / num_threads) * (i + 1);
        threads.push_back(std::thread(do_sketch_count, keys, begin, end,
                                      &sketches[i]));
      }

      for (int i = 0; i < num_threads; ++i) {
        threads[i].join();
      }

      for (int i = 1; i < num_threads; ++i) {
        sketches[0].merge(sketches[i]);
      }

      madoka::UInt64 diff = 0;
      for (std::size_t i = 0; i < keys.size(); ++i) {
        const madoka::UInt64 freq =
            sketches[0].get(keys[i].c_str(), keys[i].length());
        diff += std::llabs(freq - freqs[i]);
      }
      std::cout << ' ' << std::setw(6) << std::setprecision(3)
                << (100.0 * diff / ids.size()) << '%' << std::flush;

      delete [] sketches;
    }
    std::cout << std::endl;
  }
}

}  // namespace

int main() try {
  test_approx();
  test_sketch();
  test_merge();

  return 0;
} catch (const madoka::Exception &ex) {
  std::cerr << "error: " << ex.what() << std::endl;
  return 1;
}
<|endoftext|>