<commit_before>#define SIMDEE_NEED_SSE 1
#include <simdee/simdee.hpp>

#include "catch.hpp"
#include <type_traits>

using B = sd::sseb;
const B::storage_t dataAB{ B::scalar_t::T, B::scalar_t::F, B::scalar_t::T, B::scalar_t::T };
const B::storage_t dataBB{ B::scalar_t::F, B::scalar_t::T, B::scalar_t::F, B::scalar_t::T };

using U = sd::sseu;
const U::storage_t dataAU{ 1753029375U, 1117080442U, 3817141237U, 3761735248U };
const U::storage_t dataBU{ 1679702461U, 2102346647U, 480083363U, 3761735248U };

using not_B = sd::expr::deferred_lognot<B>;
using not_U = sd::expr::deferred_bitnot<U>;

TEST_CASE("deferred_not types", "[deferred_not]") {
    REQUIRE((std::is_same<B::vector_t, not_B::vector_t>::value));
    REQUIRE((std::is_same<B::scalar_t, not_B::scalar_t>::value));
    REQUIRE((std::is_same<B::mask_t, not_B::mask_t>::value));
    REQUIRE((std::is_same<B::storage_t, not_B::storage_t>::value));
    REQUIRE((std::is_same<B::binary_op_t, not_B::binary_op_t>::value));
    REQUIRE((std::size_t(B::width) == not_B::width));

    REQUIRE((std::is_same<U::vector_t, not_U::vector_t>::value));
    REQUIRE((std::is_same<U::scalar_t, not_U::scalar_t>::value));
    REQUIRE((std::is_same<U::mask_t, not_U::mask_t>::value));
    REQUIRE((std::is_same<U::storage_t, not_U::storage_t>::value));
    REQUIRE((std::is_same<U::binary_op_t, not_U::binary_op_t>::value));
    REQUIRE((std::size_t(U::width) == not_U::width));
}

TEST_CASE("deferred_not bool arithmetic", "[deferred_not]") {
    const B ba = !dataAB;
    const not_B nba(dataAB);
    SECTION("unary") {
        SECTION("log not") {
            REQUIRE(all(ba == nba));
            REQUIRE(all(!ba == !nba));
            REQUIRE(all(ba == !!nba));
            REQUIRE(all(!!ba == nba));
            REQUIRE(all(!!ba == !!nba));
            REQUIRE(all(!!!ba == !!!nba));
        }
        SECTION("any, all") {
            const B zero = sd::zero();
            const B allb = sd::all_bits();
            const not_B nzero(B(!zero));
            const not_B nallb(B(!allb));
            REQUIRE(any(ba) == any(nba));
            REQUIRE(all(ba) == all(nba));
            REQUIRE(any(zero) == any(nzero));
            REQUIRE(all(zero) == all(nzero));
            REQUIRE(any(allb) == any(nallb));
            REQUIRE(all(allb) == all(nallb));
        }
    }
    SECTION("binary") {
        const B bb = !dataBB;
        const not_B nbb(dataBB);
        SECTION("log and") {
            B expect = ba && bb;
            REQUIRE(all((ba && nbb) == expect));
            REQUIRE(all((nba && bb) == expect));
            REQUIRE(all((nba && nbb) == expect));
        }
        SECTION("log or") {
            B expect = ba || bb;
            REQUIRE(all((ba || nbb) == expect));
            REQUIRE(all((nba || bb) == expect));
            REQUIRE(all((nba || nbb) == expect));
        }
        SECTION("log andnot") {
            B expect = andnot(ba, bb);
            REQUIRE(all(andnot(ba, nbb) == expect));
            REQUIRE(all(andnot(nba, bb) == expect));
            REQUIRE(all(andnot(nba, nbb) == expect));
        }
    }
}

TEST_CASE("deferred_not uint arithmetic", "[deferred_not]") {
    const U ua = ~dataAU;
    const not_U nua(dataAU);
    SECTION("unary") {
        SECTION("bit not") {
            REQUIRE(all(ua == nua));
            REQUIRE(all(~ua == ~nua));
            REQUIRE(all(ua == ~~nua));
            REQUIRE(all(~~ua == nua));
            REQUIRE(all(~~ua == ~~nua));
            REQUIRE(all(~~~ua == ~~~nua));
        }
    }
    SECTION("binary") {
        const U ub = ~dataBU;
        const not_U nub(dataBU);
        SECTION("bit and") {
            U expect = ua & ub;
            REQUIRE(all((ua & nub) == expect));
            REQUIRE(all((nua & ub) == expect));
            REQUIRE(all((nua & nub) == expect));
        }
        SECTION("bit or") {
            U expect = ua | ub;
            REQUIRE(all((ua | nub) == expect));
            REQUIRE(all((nua | ub) == expect));
            REQUIRE(all((nua | nub) == expect));
        }
        SECTION("bit xor") {
            U expect = ua ^ ub;
            REQUIRE(all((ua ^ nub) == expect));
            REQUIRE(all((nua ^ ub) == expect));
            REQUIRE(all((nua ^ nub) == expect));
        }
        SECTION("bit andnot") {
            U expect = andnot(ua, ub);
            REQUIRE(all(andnot(ua, nub) == expect));
            REQUIRE(all(andnot(nua, ub) == expect));
            REQUIRE(all(andnot(nua, nub) == expect));
        }
    }
}

TEST_CASE("deferred_not methods", "[deferred_not]") {
    const B ba = !dataAB;
    const not_B nba(dataAB);
    SECTION("eval") {
        auto res_ua = ba.eval();
        auto res_nua = nba.eval();
        REQUIRE((std::is_same<decltype(res_ua), decltype(res_nua)>::value));
        REQUIRE(all(res_ua == res_nua));
    }
    SECTION("data") {
        REQUIRE(all(B(ba.data()) == B(nba.data())));
    }
    SECTION("store") {
        SECTION("aligned") {
            B::storage_t res_ua{}, res_nua{};
            ba.aligned_store(res_ua.data());
            nba.aligned_store(res_nua.data());
            REQUIRE((res_ua == res_nua));
        }
        SECTION("unaligned") {
            B::storage_t res_ua{}, res_nua{};
            ba.unaligned_store(res_ua.data());
            nba.unaligned_store(res_nua.data());
            REQUIRE((res_ua == res_nua));
        }
        SECTION("interleaved") {
            B::storage_t res_ua[3]{}, res_nua[3]{};
            ba.interleaved_store(res_ua[0].data(), 3);
            nba.interleaved_store(res_nua[0].data(), 3);
            REQUIRE((res_ua[0] == res_nua[0]));
            REQUIRE((res_ua[1] == res_nua[1]));
            REQUIRE((res_ua[2] == res_nua[2]));
        }
    }
    SECTION("reduce") {
        auto res_ba = ba.reduce([](B a, B b) { return a && b; }).first_element();
        auto res_nba = nba.reduce([](B a, B b) { return a && b; }).first_element();
        REQUIRE(res_ba == res_nba);
    }
    SECTION("mask") {
        auto res_ba = ba.mask();
        auto res_nba = nba.mask();
        REQUIRE(res_ba == res_nba);
    }
    SECTION("first_element") {
        auto res_ba = ba.first_element();
        auto res_nba = nba.first_element();
        REQUIRE(res_ba == res_nba);
    }
}
<commit_msg>Suppress GCC logical not applied to one side warnings<commit_after>#define SIMDEE_NEED_SSE 1
#include <simdee/simdee.hpp>

#include "catch.hpp"
#include <type_traits>

using B = sd::sseb;
const B::storage_t dataAB{ B::scalar_t::T, B::scalar_t::F, B::scalar_t::T, B::scalar_t::T };
const B::storage_t dataBB{ B::scalar_t::F, B::scalar_t::T, B::scalar_t::F, B::scalar_t::T };

using U = sd::sseu;
const U::storage_t dataAU{ 1753029375U, 1117080442U, 3817141237U, 3761735248U };
const U::storage_t dataBU{ 1679702461U, 2102346647U, 480083363U, 3761735248U };

using not_B = sd::expr::deferred_lognot<B>;
using not_U = sd::expr::deferred_bitnot<U>;

TEST_CASE("deferred_not types", "[deferred_not]") {
    REQUIRE((std::is_same<B::vector_t, not_B::vector_t>::value));
    REQUIRE((std::is_same<B::scalar_t, not_B::scalar_t>::value));
    REQUIRE((std::is_same<B::mask_t, not_B::mask_t>::value));
    REQUIRE((std::is_same<B::storage_t, not_B::storage_t>::value));
    REQUIRE((std::is_same<B::binary_op_t, not_B::binary_op_t>::value));
    REQUIRE((std::size_t(B::width) == not_B::width));

    REQUIRE((std::is_same<U::vector_t, not_U::vector_t>::value));
    REQUIRE((std::is_same<U::scalar_t, not_U::scalar_t>::value));
    REQUIRE((std::is_same<U::mask_t, not_U::mask_t>::value));
    REQUIRE((std::is_same<U::storage_t, not_U::storage_t>::value));
    REQUIRE((std::is_same<U::binary_op_t, not_U::binary_op_t>::value));
    REQUIRE((std::size_t(U::width) == not_U::width));
}

TEST_CASE("deferred_not bool arithmetic", "[deferred_not]") {
    const B ba = !dataAB;
    const not_B nba(dataAB);
    SECTION("unary") {
        SECTION("log not") {
            REQUIRE(all((ba) == (nba)));
            REQUIRE(all((!ba) == (!nba)));
            REQUIRE(all((ba) == (!!nba)));
            REQUIRE(all((!!ba) == nba));
            REQUIRE(all((!!ba) == (!!nba)));
            REQUIRE(all((!!!ba) == (!!!nba)));
        }
        SECTION("any, all") {
            const B zero = sd::zero();
            const B allb = sd::all_bits();
            const not_B nzero(B(!zero));
            const not_B nallb(B(!allb));
            REQUIRE(any(ba) == any(nba));
            REQUIRE(all(ba) == all(nba));
            REQUIRE(any(zero) == any(nzero));
            REQUIRE(all(zero) == all(nzero));
            REQUIRE(any(allb) == any(nallb));
            REQUIRE(all(allb) == all(nallb));
        }
    }
    SECTION("binary") {
        const B bb = !dataBB;
        const not_B nbb(dataBB);
        SECTION("log and") {
            B expect = ba && bb;
            REQUIRE(all((ba && nbb) == expect));
            REQUIRE(all((nba && bb) == expect));
            REQUIRE(all((nba && nbb) == expect));
        }
        SECTION("log or") {
            B expect = ba || bb;
            REQUIRE(all((ba || nbb) == expect));
            REQUIRE(all((nba || bb) == expect));
            REQUIRE(all((nba || nbb) == expect));
        }
        SECTION("log andnot") {
            B expect = andnot(ba, bb);
            REQUIRE(all(andnot(ba, nbb) == expect));
            REQUIRE(all(andnot(nba, bb) == expect));
            REQUIRE(all(andnot(nba, nbb) == expect));
        }
    }
}

TEST_CASE("deferred_not uint arithmetic", "[deferred_not]") {
    const U ua = ~dataAU;
    const not_U nua(dataAU);
    SECTION("unary") {
        SECTION("bit not") {
            REQUIRE(all(ua == nua));
            REQUIRE(all(~ua == ~nua));
            REQUIRE(all(ua == ~~nua));
            REQUIRE(all(~~ua == nua));
            REQUIRE(all(~~ua == ~~nua));
            REQUIRE(all(~~~ua == ~~~nua));
        }
    }
    SECTION("binary") {
        const U ub = ~dataBU;
        const not_U nub(dataBU);
        SECTION("bit and") {
            U expect = ua & ub;
            REQUIRE(all((ua & nub) == expect));
            REQUIRE(all((nua & ub) == expect));
            REQUIRE(all((nua & nub) == expect));
        }
        SECTION("bit or") {
            U expect = ua | ub;
            REQUIRE(all((ua | nub) == expect));
            REQUIRE(all((nua | ub) == expect));
            REQUIRE(all((nua | nub) == expect));
        }
        SECTION("bit xor") {
            U expect = ua ^ ub;
            REQUIRE(all((ua ^ nub) == expect));
            REQUIRE(all((nua ^ ub) == expect));
            REQUIRE(all((nua ^ nub) == expect));
        }
        SECTION("bit andnot") {
            U expect = andnot(ua, ub);
            REQUIRE(all(andnot(ua, nub) == expect));
            REQUIRE(all(andnot(nua, ub) == expect));
            REQUIRE(all(andnot(nua, nub) == expect));
        }
    }
}

TEST_CASE("deferred_not methods", "[deferred_not]") {
    const B ba = !dataAB;
    const not_B nba(dataAB);
    SECTION("eval") {
        auto res_ua = ba.eval();
        auto res_nua = nba.eval();
        REQUIRE((std::is_same<decltype(res_ua), decltype(res_nua)>::value));
        REQUIRE(all(res_ua == res_nua));
    }
    SECTION("data") {
        REQUIRE(all(B(ba.data()) == B(nba.data())));
    }
    SECTION("store") {
        SECTION("aligned") {
            B::storage_t res_ua{}, res_nua{};
            ba.aligned_store(res_ua.data());
            nba.aligned_store(res_nua.data());
            REQUIRE((res_ua == res_nua));
        }
        SECTION("unaligned") {
            B::storage_t res_ua{}, res_nua{};
            ba.unaligned_store(res_ua.data());
            nba.unaligned_store(res_nua.data());
            REQUIRE((res_ua == res_nua));
        }
        SECTION("interleaved") {
            B::storage_t res_ua[3]{}, res_nua[3]{};
            ba.interleaved_store(res_ua[0].data(), 3);
            nba.interleaved_store(res_nua[0].data(), 3);
            REQUIRE((res_ua[0] == res_nua[0]));
            REQUIRE((res_ua[1] == res_nua[1]));
            REQUIRE((res_ua[2] == res_nua[2]));
        }
    }
    SECTION("reduce") {
        auto res_ba = ba.reduce([](B a, B b) { return a && b; }).first_element();
        auto res_nba = nba.reduce([](B a, B b) { return a && b; }).first_element();
        REQUIRE(res_ba == res_nba);
    }
    SECTION("mask") {
        auto res_ba = ba.mask();
        auto res_nba = nba.mask();
        REQUIRE(res_ba == res_nba);
    }
    SECTION("first_element") {
        auto res_ba = ba.first_element();
        auto res_nba = nba.first_element();
        REQUIRE(res_ba == res_nba);
    }
}
<|endoftext|>


<commit_before>/*
 * Copyright 2008 Blanton Black
 *
 * 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.
 */

/**
 * @file main.cpp
 * @brief main implementation
 */

#include <gas/fsio.h>

#include <stdio.h>
#include <fcntl.h>

#include <string>
#include <iostream>

using namespace std;

int test_main (int argc, char **argv);

#if HAVE_QT4
int xml2gas_main (int argc, char **argv);
int qtedit_main (int argc, char **argv);
#endif

int gas2c (int argc, char **argv);

void print_gas_file (string fname)
{
    FILE* fs;
    GASchunk *c = NULL;

    fs = fopen(fname.c_str(), "r");
    if (fs == NULL) {
        fprintf(stderr, "file not found");
        return;
    }
    while (!feof(fs)) {
        gas_read_fs(fs, &c);
        gas_print(c);
        gas_destroy(c);
        c = NULL;
    }
    fclose(fs);
}

void die (string msg)
{
    cerr << msg << endl;
    exit(1);
}

int main (int argc, char **argv)
{
    if (argc < 2) {
        die("invalid usage: command not given");
    }

    string cmd = argv[1];
    if (cmd == "print") {
        if (argc != 3) {
            die("file not given");
        }
        print_gas_file(argv[2]);
    } else if (cmd == "test") {
        test_main(argc-1, &argv[1]);
#if HAVE_QT4
    } else if (cmd == "xml2gas") {
        xml2gas_main(argc-1, &argv[1]);
    } else if (cmd == "edit") {
        qtedit_main(argc-1, &argv[1]);
#endif
    } else if (cmd == "gas2c") {
        gas2c(argc-1, &argv[1]);
    } else {
        die("invalid command");
    }
    return 0;
}

// vim: sw=4 fdm=marker
<commit_msg>gascan print enhancements<commit_after>/*
 * Copyright 2008 Blanton Black
 *
 * 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.
 */

/**
 * @file main.cpp
 * @brief main implementation
 */

#include <gas/fsio.h>

#include <stdio.h>
#include <fcntl.h>

#include <string>
#include <iostream>

using namespace std;

int test_main (int argc, char **argv);

#if HAVE_QT4
int xml2gas_main (int argc, char **argv);
int qtedit_main (int argc, char **argv);
#endif

int gas2c (int argc, char **argv);

void print_gas_file (string fname)
{
    FILE* fs;
    GASchunk *c = NULL;
    GASresult result;

    if (fname == "-") {
        fs = stdin;
    } else {
        fs = fopen(fname.c_str(), "r");
    }
    if (fs == NULL) {
        fprintf(stderr, "file not found");
        return;
    }
    while (!feof(fs)) {
        result = gas_read_fs(fs, &c);
        if (result != GAS_OK) {
            if (result != GAS_ERR_FILE_EOF) {
                // only print error if not eof
                fprintf(stderr, "gascan detected error while reading: %s\n",
                        gas_error_string(result));
            }
            if (c != NULL) {
                gas_destroy(c);
            }
            continue;
        }

        result = gas_print(c);
        if (result != GAS_OK) {
            fprintf(stderr, "gascan detected error while printing: %s\n",
                    gas_error_string(result));
        }

        gas_destroy(c);
        if (result != GAS_OK) {
            fprintf(stderr, "gascan detected error while destroying: %s\n",
                    gas_error_string(result));
        }

        c = NULL;
    }

    fclose(fs);
}

void die (string msg)
{
    cerr << msg << endl;
    exit(1);
}

int main (int argc, char **argv)
{
    if (argc < 2) {
        die("invalid usage: command not given");
    }

    string cmd = argv[1];
    if (cmd == "print") {
        if (argc == 2) {
            print_gas_file("-");
        } else {
            for (int i = 2; i < argc; i++) {
                if (argc > 3) {
                    printf("*** %s\n", argv[i]);
                }
                print_gas_file(argv[i]);
                if (argc > 3) {
                    printf("\n");
                }
            }
        }
    } else if (cmd == "test") {
        test_main(argc-1, &argv[1]);
#if HAVE_QT4
    } else if (cmd == "xml2gas") {
        xml2gas_main(argc-1, &argv[1]);
    } else if (cmd == "edit") {
        qtedit_main(argc-1, &argv[1]);
#endif
    } else if (cmd == "gas2c") {
        gas2c(argc-1, &argv[1]);
    } else {
        die("invalid command");
    }
    return 0;
}

// vim: sw=4 fdm=marker
<|endoftext|>


<commit_before>#ifndef MAP_HPP
#define MAP_HPP

#include <lua.hpp>
#include <string>
#include <iostream>
#include <memory>
#include <fabric/gameobjectHandler.hpp>
#include <Windows.h>
#include <vector>
#include <fabric/gameobject.hpp>

namespace fabric {

	class Map {
	public:

		int open();
		int close();
		Map(std::string fileName);
		~Map();

	private:
		int pushToTop(std::string name, lua_State* L);
		int pushToTop(std::string name, lua_State* L, bool __first);
		lua_State* L;
	};

}
#endif<commit_msg>Map::Open() now takes the map file<commit_after>#ifndef MAP_HPP
#define MAP_HPP

#include <lua.hpp>
#include <string>
#include <iostream>
#include <memory>
#include <fabric/gameobjectHandler.hpp>
#include <Windows.h>
#include <vector>
#include <fabric/gameobject.hpp>

namespace fabric {

	class Map {
	public:

		int open(std::string fileName);
		int close();
		Map();
		~Map();

	private:
		int pushToTop(std::string name, lua_State* L);
		int pushToTop(std::string name, lua_State* L, bool __first);
		lua_State* L;
	};

}
#endif<|endoftext|>


<commit_before>// Copyright 2012-2013 Samplecount S.L.
//
// 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 METHCLA_AUDIO_HPP_INCLUDED
#define METHCLA_AUDIO_HPP_INCLUDED

#include <cstdint>
#include <methcla/common.h>
#include <methcla/engine.h>

namespace Methcla { namespace Audio
{
    typedef uint32_t Epoch;
    typedef Methcla_AudioSample sample_t;

    class TimeInterface
    {
        virtual Methcla_Time currentTime() const = 0;
    };

    template <typename A, typename B> void deinterleave(A* const* dst, const B* src, size_t numChannels, size_t numFrames)
    {
        for (size_t c=0; c < numChannels; c++)
        {
            for (size_t i=0; i < numFrames; i++)
            {
                dst[c][i] = src[i*numChannels+c];
            }
        }
    }

    template <typename A, typename B> void interleave(A* dst, const B* const* src, size_t numChannels, size_t numFrames)
    {
        for (size_t c=0; c < numChannels; c++)
        {
            for (size_t i=0; i < numFrames; i++)
            {
                dst[i*numChannels+c] = src[c][i];
            }
        }
    }
} }

#endif // METHCLA_AUDIO_HPP_INCLUDED
<commit_msg>Add interleave template that scales the input before storing<commit_after>// Copyright 2012-2013 Samplecount S.L.
//
// 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 METHCLA_AUDIO_HPP_INCLUDED
#define METHCLA_AUDIO_HPP_INCLUDED

#include <cstdint>
#include <methcla/common.h>
#include <methcla/engine.h>

namespace Methcla { namespace Audio
{
    typedef uint32_t Epoch;
    typedef Methcla_AudioSample sample_t;

    class TimeInterface
    {
        virtual Methcla_Time currentTime() const = 0;
    };

    template <typename A, typename B> void deinterleave(A* const* dst, const B* src, size_t numChannels, size_t numFrames)
    {
        for (size_t c=0; c < numChannels; c++)
        {
            for (size_t i=0; i < numFrames; i++)
            {
                dst[c][i] = src[i*numChannels+c];
            }
        }
    }

    template <typename A, typename B> void interleave(A* dst, const B* const* src, size_t numChannels, size_t numFrames)
    {
        for (size_t c=0; c < numChannels; c++)
        {
            for (size_t i=0; i < numFrames; i++)
            {
                dst[i*numChannels+c] = src[c][i];
            }
        }
    }

    template <typename A, typename B> void interleave(A* dst, const B* const* src, B scale, size_t numChannels, size_t numFrames)
    {
        for (size_t c=0; c < numChannels; c++)
        {
            for (size_t i=0; i < numFrames; i++)
            {
                dst[i*numChannels+c] = static_cast<A>(scale * src[c][i]);
            }
        }
    }
} }

#endif // METHCLA_AUDIO_HPP_INCLUDED
<|endoftext|>


<commit_before>/*
The MIT License(MIT)

Copyright(c) 2015 Dennis Wandschura

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 <vxLib/RawInput.h>
#include <vxLib/Allocator/LinearAllocator.h>
#include <Windows.h>

namespace vx
{
	Keyboard RawInput::s_keyboard{};
	Mouse RawInput::s_mouse{};
	vx::array<KeyEvent, LinearAllocator> RawInput::s_keyEvents{};
	Input::KeyEventCallback RawInput::s_keyEventPressedCallback{ nullptr };
	Input::KeyEventCallback RawInput::s_keyEventReleasedCallback{ nullptr };

	struct InputHandler
	{
		static void handleKeyboard(const RAWKEYBOARD &rawKeyboard, Keyboard* keyboard, vx::array<KeyEvent, LinearAllocator>* keyEvents)
		{
			auto flag = rawKeyboard.Flags;
			auto key = rawKeyboard.VKey;

			if (flag == RI_KEY_MAKE)
			{
				keyboard->m_keys[key] = 1;
				keyEvents->push_back(KeyEvent(key, KeyEvent::Pressed));
			}
			// key up
			else if (flag == RI_KEY_BREAK)
			{
				keyboard->m_keys[key] = 0;
				keyEvents->push_back(KeyEvent(key, KeyEvent::Released));
			}
		}

		static void handleMouse(const RAWMOUSE &rawMouse, Mouse* mouse)
		{
			if (rawMouse.usFlags == MOUSE_MOVE_RELATIVE)
			{
				mouse->m_relative.x = rawMouse.lLastX;
				mouse->m_relative.y = rawMouse.lLastY;

				mouse->m_position.x += rawMouse.lLastX;
				mouse->m_position.y += rawMouse.lLastY;
			}
		}
	};

	RawInput::RawInput()
	{
	}

	RawInput::~RawInput()
	{
		s_keyEvents.clear();
	}

	bool RawInput::initialize(void* window, LinearAllocator* allocator, u32 maxEventCount)
	{
		RAWINPUTDEVICE rid[2];

		// keyboard
		rid[0].usUsagePage = 0x01;
		rid[0].usUsage = 0x06;
		rid[0].dwFlags = 0;
		rid[0].hwndTarget = (HWND)window;

		// mouse
		rid[1].usUsagePage = 0x01;
		rid[1].usUsage = 0x02;
		rid[1].dwFlags = RIDEV_NOLEGACY;
		rid[1].hwndTarget = (HWND)window;

		if (RegisterRawInputDevices(rid, 2, sizeof(rid[0])) == FALSE)
		{
			//GetLastError();
			return false;
		}

		s_mouse.m_position.x = 0;
		s_mouse.m_position.y = 0;
		s_mouse.m_relative.x = 0;
		s_mouse.m_relative.y = 0;

		vx::array <KeyEvent, LinearAllocator> evtArray(allocator, maxEventCount);
		s_keyEvents.swap(evtArray);

		return true;
	}

	void RawInput::shutdown()
	{
		s_keyEvents.clear();
	}

	void RawInput::update(LPARAM lparam)
	{
		UINT dwSize;
		// get size of structure
		GetRawInputData((HRAWINPUT)lparam, RID_INPUT, NULL, &dwSize, sizeof(RAWINPUTHEADER));

		const auto bufferSize = 64u;

		assert(dwSize <= bufferSize);

		BYTE buffer[bufferSize];

		// get input
		if (GetRawInputData((HRAWINPUT)lparam, RID_INPUT, buffer, &dwSize, sizeof(RAWINPUTHEADER)) != dwSize)
		{
			OutputDebugString(TEXT("GetRawInputData does not return correct size !\n"));
			return;
		}

		auto *raw = (RAWINPUT*)buffer;

		if (raw->header.dwType == RIM_TYPEKEYBOARD)
		{
			InputHandler::handleKeyboard(raw->data.keyboard, &s_keyboard, &s_keyEvents);
		}
		else if (raw->header.dwType == RIM_TYPEMOUSE)
		{
			// handle mouse input
			InputHandler::handleMouse(raw->data.mouse, &s_mouse);
		}
	}

	void RawInput::beginFrame()
	{
		// reset relative mouse movement
		s_mouse.m_relative.x = 0;
		s_mouse.m_relative.y = 0;
	}

	void RawInput::endFrame()
	{
		for (auto &it : s_keyEvents)
		{
			switch (it.evt)
			{
			case KeyEvent::Pressed:
			{
				if (s_keyEventPressedCallback)
					s_keyEventPressedCallback(it.key);
			}break;
			case KeyEvent::Released:
			{
				if (s_keyEventReleasedCallback)
					s_keyEventReleasedCallback(it.key);
			}break;
			}
		}

		s_keyEvents.clear();
	}

	u8 RawInput::isKeyPressed(u16 keyCode)
	{
		return s_keyboard.m_keys[keyCode];
	}

	void RawInput::getKeyboard(Keyboard &keyboard)
	{
		keyboard = s_keyboard;
	}

	Mouse RawInput::getMouse()
	{
		return s_mouse;
	}

	void RawInput::setCallbackKeyPressed(Input::KeyEventCallback callback)
	{
		s_keyEventPressedCallback = callback;
	}

	void RawInput::setCallbackKeyReleased(Input::KeyEventCallback callback)
	{
		s_keyEventReleasedCallback = callback;
	}
}<commit_msg>fix memory leak<commit_after>/*
The MIT License(MIT)

Copyright(c) 2015 Dennis Wandschura

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 <vxLib/RawInput.h>
#include <vxLib/Allocator/LinearAllocator.h>
#include <Windows.h>

namespace vx
{
	Keyboard RawInput::s_keyboard{};
	Mouse RawInput::s_mouse{};
	vx::array<KeyEvent, LinearAllocator> RawInput::s_keyEvents{};
	Input::KeyEventCallback RawInput::s_keyEventPressedCallback{ nullptr };
	Input::KeyEventCallback RawInput::s_keyEventReleasedCallback{ nullptr };

	struct InputHandler
	{
		static void handleKeyboard(const RAWKEYBOARD &rawKeyboard, Keyboard* keyboard, vx::array<KeyEvent, LinearAllocator>* keyEvents)
		{
			auto flag = rawKeyboard.Flags;
			auto key = rawKeyboard.VKey;

			if (flag == RI_KEY_MAKE)
			{
				keyboard->m_keys[key] = 1;
				keyEvents->push_back(KeyEvent(key, KeyEvent::Pressed));
			}
			// key up
			else if (flag == RI_KEY_BREAK)
			{
				keyboard->m_keys[key] = 0;
				keyEvents->push_back(KeyEvent(key, KeyEvent::Released));
			}
		}

		static void handleMouse(const RAWMOUSE &rawMouse, Mouse* mouse)
		{
			if (rawMouse.usFlags == MOUSE_MOVE_RELATIVE)
			{
				mouse->m_relative.x = rawMouse.lLastX;
				mouse->m_relative.y = rawMouse.lLastY;

				mouse->m_position.x += rawMouse.lLastX;
				mouse->m_position.y += rawMouse.lLastY;
			}
		}
	};

	RawInput::RawInput()
	{
	}

	RawInput::~RawInput()
	{
		s_keyEvents.clear();
	}

	bool RawInput::initialize(void* window, LinearAllocator* allocator, u32 maxEventCount)
	{
		RAWINPUTDEVICE rid[2];

		// keyboard
		rid[0].usUsagePage = 0x01;
		rid[0].usUsage = 0x06;
		rid[0].dwFlags = 0;
		rid[0].hwndTarget = (HWND)window;

		// mouse
		rid[1].usUsagePage = 0x01;
		rid[1].usUsage = 0x02;
		rid[1].dwFlags = RIDEV_NOLEGACY;
		rid[1].hwndTarget = (HWND)window;

		if (RegisterRawInputDevices(rid, 2, sizeof(rid[0])) == FALSE)
		{
			//GetLastError();
			return false;
		}

		s_mouse.m_position.x = 0;
		s_mouse.m_position.y = 0;
		s_mouse.m_relative.x = 0;
		s_mouse.m_relative.y = 0;

		vx::array <KeyEvent, LinearAllocator> evtArray(allocator, maxEventCount);
		s_keyEvents.swap(evtArray);

		return true;
	}

	void RawInput::shutdown()
	{
		s_keyEvents.release();
	}

	void RawInput::update(LPARAM lparam)
	{
		UINT dwSize;
		// get size of structure
		GetRawInputData((HRAWINPUT)lparam, RID_INPUT, NULL, &dwSize, sizeof(RAWINPUTHEADER));

		const auto bufferSize = 64u;

		assert(dwSize <= bufferSize);

		BYTE buffer[bufferSize];

		// get input
		if (GetRawInputData((HRAWINPUT)lparam, RID_INPUT, buffer, &dwSize, sizeof(RAWINPUTHEADER)) != dwSize)
		{
			OutputDebugString(TEXT("GetRawInputData does not return correct size !\n"));
			return;
		}

		auto *raw = (RAWINPUT*)buffer;

		if (raw->header.dwType == RIM_TYPEKEYBOARD)
		{
			InputHandler::handleKeyboard(raw->data.keyboard, &s_keyboard, &s_keyEvents);
		}
		else if (raw->header.dwType == RIM_TYPEMOUSE)
		{
			// handle mouse input
			InputHandler::handleMouse(raw->data.mouse, &s_mouse);
		}
	}

	void RawInput::beginFrame()
	{
		// reset relative mouse movement
		s_mouse.m_relative.x = 0;
		s_mouse.m_relative.y = 0;
	}

	void RawInput::endFrame()
	{
		for (auto &it : s_keyEvents)
		{
			switch (it.evt)
			{
			case KeyEvent::Pressed:
			{
				if (s_keyEventPressedCallback)
					s_keyEventPressedCallback(it.key);
			}break;
			case KeyEvent::Released:
			{
				if (s_keyEventReleasedCallback)
					s_keyEventReleasedCallback(it.key);
			}break;
			}
		}

		s_keyEvents.clear();
	}

	u8 RawInput::isKeyPressed(u16 keyCode)
	{
		return s_keyboard.m_keys[keyCode];
	}

	void RawInput::getKeyboard(Keyboard &keyboard)
	{
		keyboard = s_keyboard;
	}

	Mouse RawInput::getMouse()
	{
		return s_mouse;
	}

	void RawInput::setCallbackKeyPressed(Input::KeyEventCallback callback)
	{
		s_keyEventPressedCallback = callback;
	}

	void RawInput::setCallbackKeyReleased(Input::KeyEventCallback callback)
	{
		s_keyEventReleasedCallback = callback;
	}
}<|endoftext|>


<commit_before>//winFile.hpp
#ifndef osFile_HPP
	#define osFile_HPP

	#include <string>
	#include <iostream>

	#ifdef _WIN32
		#include <windows.h>
	#elif __APPLE__
		#include <limits.h>
		#include <unistd.h>
	#elif __linux__
		#include <limits.h>
		#include <unistd.h>
	#endif
	static std::string ExePath()
	{
		#ifdef _WIN32
	    	char buffer[MAX_PATH];
	    	GetModuleFileName( NULL, buffer, MAX_PATH );
	    	std::string::size_type pos = string( buffer ).find_last_of( "\\/" );
	    	return std::string( buffer ).substr( 0, pos);
	    #elif __APPLE__
	    	std::cout << "DEBUG:: On OSX" << std::endl;
			char result[ PATH_MAX ];
			ssize_t count = readlink( "/proc/self/exe", result, PATH_MAX );
			return std::string( result, (count > 0) ? count : 0 );
	    #elif __linux__
			char result[ PATH_MAX ];
		 	ssize_t count = readlink( "/proc/self/exe", result, PATH_MAX );
		 	return std::string( result, (count > 0) ? count : 0 );
	    #endif
	}

#endif<commit_msg>forgot std<commit_after>//winFile.hpp
#ifndef osFile_HPP
	#define osFile_HPP

	#include <string>
	#include <iostream>

	#ifdef _WIN32
		#include <windows.h>
	#elif __APPLE__
		#include <limits.h>
		#include <unistd.h>
	#elif __linux__
		#include <limits.h>
		#include <unistd.h>
	#endif
	static std::string ExePath()
	{
		#ifdef _WIN32
	    	char buffer[MAX_PATH];
	    	GetModuleFileName( NULL, buffer, MAX_PATH );
	    	std::string::size_type pos = std::string( buffer ).find_last_of( "\\/" );
	    	return std::string( buffer ).substr( 0, pos);
	    #elif __APPLE__
	    	std::cout << "DEBUG:: On OSX" << std::endl;
			char result[ PATH_MAX ];
			ssize_t count = readlink( "/proc/self/exe", result, PATH_MAX );
			return std::string( result, (count > 0) ? count : 0 );
	    #elif __linux__
			char result[ PATH_MAX ];
		 	ssize_t count = readlink( "/proc/self/exe", result, PATH_MAX );
		 	return std::string( result, (count > 0) ? count : 0 );
	    #endif
	}

#endif<|endoftext|>


<commit_before>//
//  ADSREnvelope.cpp
//  AudioKit Core
//
//  Created by Shane Dunne, revision history on Github.
//  Copyright © 2018 AudioKit. All rights reserved.
//
#include "ADSREnvelope.hpp"

#include <cmath>

namespace AudioKitCore
{

    ADSREnvelopeParameters::ADSREnvelopeParameters()
        : sampleRateHz(44100.0f) // a guess, will be overridden later by a call to init(,,,,)
    {
        init(0.0f, 0.0f, 1.0f, 0.0f);
    }

    void ADSREnvelopeParameters::init(float attackSeconds, float decaySeconds, float susFraction, float releaseSeconds)
    {
        attackSamples = attackSeconds * sampleRateHz;
        decaySamples = decaySeconds * sampleRateHz;
        sustainFraction = susFraction;
        releaseSamples = releaseSeconds * sampleRateHz;
    }

    void ADSREnvelopeParameters::init(float newSampleRateHz, float attackSeconds, float decaySeconds, float susFraction, float releaseSeconds)
    {
        sampleRateHz = newSampleRateHz;
        init(attackSeconds, decaySeconds, susFraction, releaseSeconds);
    }

    void ADSREnvelopeParameters::updateSampleRate(float newSampleRateHz)
    {
        float scaleFactor = newSampleRateHz / sampleRateHz;
        sampleRateHz = newSampleRateHz;
        attackSamples *= scaleFactor;
        decaySamples *= scaleFactor;
        releaseSamples *= scaleFactor;
    }

    void ADSREnvelope::init(CurvatureType curvatureType)
    {
        int silenceSamples = int(0.01 * pParameters->sampleRateHz);     // always 10 mSec
        int attackSamples = int(pParameters->attackSamples);
        int decaySamples = int(pParameters->decaySamples);
        double sustainFraction = double(pParameters->sustainFraction);
        int releaseSamples = int(pParameters->releaseSamples);

        envDesc.clear();
        envDesc.push_back({ 0.0, 0.0, 0.0, -1 });               // kIdle: 0 forever
        envDesc.push_back({ 1.0, 0.0, 0.0, silenceSamples });   // kSilence in 10 mSec

        if (curvatureType == kAnalogLike)
        {
            envDesc.push_back({ 0.0, 1.0, exp(-1.5), attackSamples });                  // kAttack
            envDesc.push_back({ 1.0, sustainFraction, exp(-4.95), decaySamples });      // kDecay
            envDesc.push_back({ sustainFraction, sustainFraction, 0.0, -1 });           // kSustain
            envDesc.push_back({ sustainFraction, 0.0, exp(-4.95), releaseSamples });    // kRelease
        }
        else if (curvatureType == kLinearInDb)
        {
            envDesc.push_back({ 0.0, 1.0, 0.99999, attackSamples });                    // kAttack
            envDesc.push_back({ 1.0, sustainFraction, exp(-11.05), decaySamples });     // kDecay
            envDesc.push_back({ sustainFraction, sustainFraction, 0.0, -1 });           // kSustain
            envDesc.push_back({ sustainFraction, 0.0, exp(-11.05), releaseSamples });   // kRelease
        }
        else
        {
            envDesc.push_back({ 0.0, 1.0, 0.0, attackSamples });                        // kAttack
            envDesc.push_back({ 1.0, sustainFraction, 0.0, decaySamples });             // kDecay
            envDesc.push_back({ sustainFraction, sustainFraction, 0.0, -1 });           // kSustain
            envDesc.push_back({ sustainFraction, 0.0, 0.0, releaseSamples });           // kRelease
        }

        env.reset(&envDesc);
    }

    void ADSREnvelope::updateParams()
    {
        if (envDesc.size() < 6) return;
        double sustainFraction = double(pParameters->sustainFraction);

        envDesc[kAttack].lengthSamples = int(pParameters->attackSamples);
        envDesc[kDecay].finalValue = sustainFraction;
        envDesc[kDecay].lengthSamples = int(pParameters->decaySamples);
        envDesc[kSustain].initialValue = envDesc[kSustain].finalValue = sustainFraction;
        envDesc[kRelease].initialValue = sustainFraction;
        envDesc[kRelease].lengthSamples = int(pParameters->releaseSamples);
    }

    void ADSREnvelope::start()
    {
        env.advanceToSegment(kAttack);
    }

    void ADSREnvelope::restart()
    {
        env.advanceToSegment(kSilence);
    }

    void ADSREnvelope::release()
    {
        env.advanceToSegment(kRelease);
    }

    void ADSREnvelope::reset()
    {
        env.reset(&envDesc);
    }

}
<commit_msg>adapt adsrenvelope to new envelope mechanism<commit_after>//
//  ADSREnvelope.cpp
//  AudioKit Core
//
//  Created by Shane Dunne, revision history on Github.
//  Copyright © 2018 AudioKit. All rights reserved.
//
#include "ADSREnvelope.hpp"

#include <cmath>

namespace AudioKitCore
{

    ADSREnvelopeParameters::ADSREnvelopeParameters()
        : sampleRateHz(44100.0f) // a guess, will be overridden later by a call to init(,,,,)
    {
        init(0.0f, 0.0f, 1.0f, 0.0f);
    }

    void ADSREnvelopeParameters::init(float attackSeconds, float decaySeconds, float susFraction, float releaseSeconds)
    {
        attackSamples = attackSeconds * sampleRateHz;
        decaySamples = decaySeconds * sampleRateHz;
        sustainFraction = susFraction;
        releaseSamples = releaseSeconds * sampleRateHz;
    }

    void ADSREnvelopeParameters::init(float newSampleRateHz, float attackSeconds, float decaySeconds, float susFraction, float releaseSeconds)
    {
        sampleRateHz = newSampleRateHz;
        init(attackSeconds, decaySeconds, susFraction, releaseSeconds);
    }

    void ADSREnvelopeParameters::updateSampleRate(float newSampleRateHz)
    {
        float scaleFactor = newSampleRateHz / sampleRateHz;
        sampleRateHz = newSampleRateHz;
        attackSamples *= scaleFactor;
        decaySamples *= scaleFactor;
        releaseSamples *= scaleFactor;
    }

    void ADSREnvelope::init(CurvatureType curvatureType)
    {
        int silenceSamples = int(0.01 * pParameters->sampleRateHz);     // always 10 mSec
        int attackSamples = int(pParameters->attackSamples);
        int decaySamples = int(pParameters->decaySamples);
        double sustainFraction = double(pParameters->sustainFraction);
        int releaseSamples = int(pParameters->releaseSamples);

        envDesc.clear();
        envDesc.push_back({ 0.0, 0.0, 0.0, -1 });               // kIdle: 0 forever
        envDesc.push_back({ 1.0, 0.0, 0.0, silenceSamples });   // kSilence in 10 mSec

        if (curvatureType == kAnalogLike)
        {
            envDesc.push_back({ 0.0, 1.0, exp(-1.5), attackSamples });                  // kAttack
            envDesc.push_back({ 1.0, sustainFraction, exp(-4.95), decaySamples });      // kDecay
            envDesc.push_back({ sustainFraction, sustainFraction, 0.0, -1 });           // kSustain
            envDesc.push_back({ sustainFraction, 0.0, exp(-4.95), releaseSamples });    // kRelease
        }
        else if (curvatureType == kLinearInDb)
        {
            envDesc.push_back({ 0.0, 1.0, 0.99999, attackSamples });                    // kAttack
            envDesc.push_back({ 1.0, sustainFraction, exp(-11.05), decaySamples });     // kDecay
            envDesc.push_back({ sustainFraction, sustainFraction, 0.0, -1 });           // kSustain
            envDesc.push_back({ sustainFraction, 0.0, exp(-11.05), releaseSamples });   // kRelease
        }
        else
        {
            envDesc.push_back({ 0.0, 1.0, 0.0, attackSamples });                        // kAttack
            envDesc.push_back({ 1.0, sustainFraction, 0.0, decaySamples });             // kDecay
            envDesc.push_back({ sustainFraction, sustainFraction, 0.0, -1 });           // kSustain
            envDesc.push_back({ sustainFraction, 0.0, 0.0, releaseSamples });           // kRelease
        }

        env.reset(&envDesc);
    }

    void ADSREnvelope::updateParams()
    {
        if (envDesc.size() < 6) return;
        double sustainFraction = double(pParameters->sustainFraction);

        envDesc[kAttack].lengthSamples = int(pParameters->attackSamples);
        envDesc[kDecay].finalValue = sustainFraction;
        envDesc[kDecay].lengthSamples = int(pParameters->decaySamples);
        envDesc[kSustain].initialValue = envDesc[kSustain].finalValue = sustainFraction;
        envDesc[kRelease].initialValue = sustainFraction;
        envDesc[kRelease].lengthSamples = int(pParameters->releaseSamples);
    }

    void ADSREnvelope::start()
    {
        env.startAtSegment(kAttack);
    }

    void ADSREnvelope::restart()
    {
        env.advanceToSegment(kSilence);
    }

    void ADSREnvelope::release()
    {
        envDesc[kRelease].initialValue = env.getValue();
        env.advanceToSegment(kRelease);
    }

    void ADSREnvelope::reset()
    {
        env.reset(&envDesc);
    }

}
<|endoftext|>


<commit_before>/**
 * @file allknn_main.cpp
 * @author Ryan Curtin
 *
 * Implementation of the AllkNN executable.  Allows some number of standard
 * options.
 */
#include <mlpack/core.hpp>

#include <string>
#include <fstream>
#include <iostream>

#include "neighbor_search.hpp"

using namespace std;
using namespace mlpack;
using namespace mlpack::neighbor;
using namespace mlpack::tree;

// Information about the program itself.
PROGRAM_INFO("All K-Nearest-Neighbors",
    "This program will calculate the all k-nearest-neighbors of a set of "
    "points. You may specify a separate set of reference points and query "
    "points, or just a reference set which will be used as both the reference "
    "and query set."
    "\n\n"
    "For example, the following will calculate the 5 nearest neighbors of each"
    "point in 'input.csv' and store the distances in 'distances.csv' and the "
    "neighbors in the file 'neighbors.csv':"
    "\n\n"
    "$ allknn --k=5 --reference_file=input.csv --distances_file=distances.csv\n"
    "  --neighbors_file=neighbors.csv"
    "\n\n"
    "The output files are organized such that row i and column j in the "
    "neighbors output file corresponds to the index of the point in the "
    "reference set which is the i'th nearest neighbor from the point in the "
    "query set with index j.  Row i and column j in the distances output file "
    "corresponds to the distance between those two points.");

// Define our input parameters that this program will take.
PARAM_STRING_REQ("reference_file", "File containing the reference dataset.",
    "r");
PARAM_STRING_REQ("distances_file", "File to output distances into.", "d");
PARAM_STRING_REQ("neighbors_file", "File to output neighbors into.", "n");

PARAM_INT_REQ("k", "Number of furthest neighbors to find.", "k");

PARAM_STRING("query_file", "File containing query points (optional).", "q", "");

PARAM_INT("leaf_size", "Leaf size for tree building.", "l", 20);
PARAM_FLAG("naive", "If true, O(n^2) naive mode is used for computation.", "N");
PARAM_FLAG("single_mode", "If true, single-tree search is used (as opposed to "
    "dual-tree search.", "s");

int main(int argc, char *argv[])
{
  // Give CLI the command line parameters the user passed in.
  CLI::ParseCommandLine(argc, argv);

  // Get all the parameters.
  string referenceFile = CLI::GetParam<string>("reference_file");

  string distancesFile = CLI::GetParam<string>("distances_file");
  string neighborsFile = CLI::GetParam<string>("neighbors_file");

  int lsInt = CLI::GetParam<int>("leaf_size");

  size_t k = CLI::GetParam<int>("k");

  bool naive = CLI::HasParam("naive");
  bool singleMode = CLI::HasParam("single_mode");

  arma::mat referenceData;
  arma::mat queryData; // So it doesn't go out of scope.
  data::Load(referenceFile.c_str(), referenceData, true);

  Log::Info << "Loaded reference data from '" << referenceFile << "' ("
      << referenceData.n_rows << " x " << referenceData.n_cols << ")." << endl;

  // Sanity check on k value: must be greater than 0, must be less than the
  // number of reference points.
  if ((k <= 0) || (k >= referenceData.n_cols))
  {
    Log::Fatal << "Invalid k: " << k << "; must be greater than 0 and less ";
    Log::Fatal << "than the number of reference points (";
    Log::Fatal << referenceData.n_cols << ")." << endl;
  }

  // Sanity check on leaf size.
  if (lsInt < 0)
  {
    Log::Fatal << "Invalid leaf size: " << lsInt << ".  Must be greater "
        "than or equal to 0." << endl;
  }
  size_t leafSize = lsInt;

  // Naive mode overrides single mode.
  if (singleMode && naive)
  {
    Log::Warn << "--single_mode ignored because --naive is present." << endl;
  }

  if (naive)
    leafSize = referenceData.n_cols;

  arma::Mat<size_t> neighbors;
  arma::mat distances;

  // Because we may construct it differently, we need a pointer.
  AllkNN* allknn = NULL;

  // Mappings for when we build the tree.
  std::vector<size_t> oldFromNewRefs;

  // Build trees by hand, so we can save memory: if we pass a tree to
  // NeighborSearch, it does not copy the matrix.
  Log::Info << "Building reference tree..." << endl;
  Timer::Start("tree_building");

  BinarySpaceTree<bound::HRectBound<2>, QueryStat<NearestNeighborSort> >
      refTree(referenceData, oldFromNewRefs, leafSize);
  BinarySpaceTree<bound::HRectBound<2>, QueryStat<NearestNeighborSort> >*
      queryTree = NULL; // Empty for now.

  Timer::Stop("tree_building");

  std::vector<size_t> oldFromNewQueries;

  if (CLI::GetParam<string>("query_file") != "")
  {
    string queryFile = CLI::GetParam<string>("query_file");

    data::Load(queryFile.c_str(), queryData, true);

    if (naive && leafSize < queryData.n_cols)
      leafSize = queryData.n_cols;

    Log::Info << "Loaded query data from '" << queryFile << "' ("
        << queryData.n_rows << " x " << queryData.n_cols << ")." << endl;

    Log::Info << "Building query tree..." << endl;

    // Build trees by hand, so we can save memory: if we pass a tree to
    // NeighborSearch, it does not copy the matrix.
    Timer::Start("tree_building");

    queryTree = new BinarySpaceTree<bound::HRectBound<2>,
        QueryStat<NearestNeighborSort> >(queryData, oldFromNewQueries,
        leafSize);

    Timer::Stop("tree_building");

    allknn = new AllkNN(&refTree, queryTree, referenceData, queryData,
        singleMode);

    Log::Info << "Tree built." << endl;
  }
  else
  {
    allknn = new AllkNN(&refTree, referenceData, singleMode);

    Log::Info << "Trees built." << endl;
  }

  Log::Info << "Computing " << k << " nearest neighbors..." << endl;
  allknn->Search(k, neighbors, distances);

  Log::Info << "Neighbors computed." << endl;

  // We have to map back to the original indices from before the tree
  // construction.
  Log::Info << "Re-mapping indices..." << endl;

  arma::mat distancesOut(distances.n_rows, distances.n_cols);
  arma::Mat<size_t> neighborsOut(neighbors.n_rows, neighbors.n_cols);

  // Do the actual remapping.
  if (CLI::GetParam<string>("query_file") != "")
  {
    for (size_t i = 0; i < distances.n_cols; ++i)
    {
      // Map distances (copy a column).
      distancesOut.col(oldFromNewQueries[i]) = distances.col(i);

      // Map indices of neighbors.
      for (size_t j = 0; j < distances.n_rows; ++j)
      {
        neighborsOut(j, oldFromNewQueries[i]) = oldFromNewRefs[neighbors(j, i)];
      }
    }
  }
  else
  {
    for (size_t i = 0; i < distances.n_cols; ++i)
    {
      // Map distances (copy a column).
      distancesOut.col(oldFromNewRefs[i]) = distances.col(i);

      // Map indices of neighbors.
      for (size_t j = 0; j < distances.n_rows; ++j)
      {
        neighborsOut(j, oldFromNewRefs[i]) = oldFromNewRefs[neighbors(j, i)];
      }
    }
  }

  // Clean up.
  if (queryTree)
    delete queryTree;

  // Save output.
  data::Save(distancesFile, distancesOut);
  data::Save(neighborsFile, neighborsOut);

  delete allknn;
}
<commit_msg>Add an option to use cover trees.<commit_after>/**
 * @file allknn_main.cpp
 * @author Ryan Curtin
 *
 * Implementation of the AllkNN executable.  Allows some number of standard
 * options.
 */
#include <mlpack/core.hpp>
#include <mlpack/core/tree/cover_tree.hpp>

#include <string>
#include <fstream>
#include <iostream>

#include "neighbor_search.hpp"

using namespace std;
using namespace mlpack;
using namespace mlpack::neighbor;
using namespace mlpack::tree;

// Information about the program itself.
PROGRAM_INFO("All K-Nearest-Neighbors",
    "This program will calculate the all k-nearest-neighbors of a set of "
    "points. You may specify a separate set of reference points and query "
    "points, or just a reference set which will be used as both the reference "
    "and query set."
    "\n\n"
    "For example, the following will calculate the 5 nearest neighbors of each"
    "point in 'input.csv' and store the distances in 'distances.csv' and the "
    "neighbors in the file 'neighbors.csv':"
    "\n\n"
    "$ allknn --k=5 --reference_file=input.csv --distances_file=distances.csv\n"
    "  --neighbors_file=neighbors.csv"
    "\n\n"
    "The output files are organized such that row i and column j in the "
    "neighbors output file corresponds to the index of the point in the "
    "reference set which is the i'th nearest neighbor from the point in the "
    "query set with index j.  Row i and column j in the distances output file "
    "corresponds to the distance between those two points.");

// Define our input parameters that this program will take.
PARAM_STRING_REQ("reference_file", "File containing the reference dataset.",
    "r");
PARAM_STRING_REQ("distances_file", "File to output distances into.", "d");
PARAM_STRING_REQ("neighbors_file", "File to output neighbors into.", "n");

PARAM_INT_REQ("k", "Number of furthest neighbors to find.", "k");

PARAM_STRING("query_file", "File containing query points (optional).", "q", "");

PARAM_INT("leaf_size", "Leaf size for tree building.", "l", 20);
PARAM_FLAG("naive", "If true, O(n^2) naive mode is used for computation.", "N");
PARAM_FLAG("single_mode", "If true, single-tree search is used (as opposed to "
    "dual-tree search.", "s");
PARAM_FLAG("cover_tree", "If true, use cover trees to perform the search.",
    "c");

int main(int argc, char *argv[])
{
  // Give CLI the command line parameters the user passed in.
  CLI::ParseCommandLine(argc, argv);

  // Get all the parameters.
  string referenceFile = CLI::GetParam<string>("reference_file");

  string distancesFile = CLI::GetParam<string>("distances_file");
  string neighborsFile = CLI::GetParam<string>("neighbors_file");

  int lsInt = CLI::GetParam<int>("leaf_size");

  size_t k = CLI::GetParam<int>("k");

  bool naive = CLI::HasParam("naive");
  bool singleMode = CLI::HasParam("single_mode");

  arma::mat referenceData;
  arma::mat queryData; // So it doesn't go out of scope.
  data::Load(referenceFile.c_str(), referenceData, true);

  Log::Info << "Loaded reference data from '" << referenceFile << "' ("
      << referenceData.n_rows << " x " << referenceData.n_cols << ")." << endl;

  // Sanity check on k value: must be greater than 0, must be less than the
  // number of reference points.
  if ((k <= 0) || (k >= referenceData.n_cols))
  {
    Log::Fatal << "Invalid k: " << k << "; must be greater than 0 and less ";
    Log::Fatal << "than the number of reference points (";
    Log::Fatal << referenceData.n_cols << ")." << endl;
  }

  // Sanity check on leaf size.
  if (lsInt < 0)
  {
    Log::Fatal << "Invalid leaf size: " << lsInt << ".  Must be greater "
        "than or equal to 0." << endl;
  }
  size_t leafSize = lsInt;

  // Naive mode overrides single mode.
  if (singleMode && naive)
  {
    Log::Warn << "--single_mode ignored because --naive is present." << endl;
  }

  if (naive)
    leafSize = referenceData.n_cols;

  arma::Mat<size_t> neighbors;
  arma::mat distances;

  if (!CLI::HasParam("cover_tree"))
  {
    // Because we may construct it differently, we need a pointer.
    AllkNN* allknn = NULL;

    // Mappings for when we build the tree.
    std::vector<size_t> oldFromNewRefs;

    // Build trees by hand, so we can save memory: if we pass a tree to
    // NeighborSearch, it does not copy the matrix.
    Log::Info << "Building reference tree..." << endl;
    Timer::Start("tree_building");

    BinarySpaceTree<bound::HRectBound<2>, QueryStat<NearestNeighborSort> >
      refTree(referenceData, oldFromNewRefs, leafSize);
    BinarySpaceTree<bound::HRectBound<2>, QueryStat<NearestNeighborSort> >*
      queryTree = NULL; // Empty for now.

    Timer::Stop("tree_building");

    std::vector<size_t> oldFromNewQueries;

    if (CLI::GetParam<string>("query_file") != "")
    {
      string queryFile = CLI::GetParam<string>("query_file");

      data::Load(queryFile.c_str(), queryData, true);

      if (naive && leafSize < queryData.n_cols)
        leafSize = queryData.n_cols;

      Log::Info << "Loaded query data from '" << queryFile << "' ("
        << queryData.n_rows << " x " << queryData.n_cols << ")." << endl;

      Log::Info << "Building query tree..." << endl;

      // Build trees by hand, so we can save memory: if we pass a tree to
      // NeighborSearch, it does not copy the matrix.
      Timer::Start("tree_building");

      queryTree = new BinarySpaceTree<bound::HRectBound<2>,
                QueryStat<NearestNeighborSort> >(queryData, oldFromNewQueries,
                    leafSize);

      Timer::Stop("tree_building");

      allknn = new AllkNN(&refTree, queryTree, referenceData, queryData,
          singleMode);

      Log::Info << "Tree built." << endl;
    }
    else
    {
      allknn = new AllkNN(&refTree, referenceData, singleMode);

      Log::Info << "Trees built." << endl;
    }

    arma::mat distancesOut;
    arma::Mat<size_t> neighborsOut;

    Log::Info << "Computing " << k << " nearest neighbors..." << endl;
    allknn->Search(k, neighborsOut, distancesOut);

    Log::Info << "Neighbors computed." << endl;

    // We have to map back to the original indices from before the tree
    // construction.
    Log::Info << "Re-mapping indices..." << endl;

    neighbors.set_size(neighborsOut.n_rows, neighborsOut.n_cols);
    distances.set_size(distancesOut.n_rows, distancesOut.n_cols);

    // Do the actual remapping.
    if (CLI::GetParam<string>("query_file") != "")
    {
      for (size_t i = 0; i < distancesOut.n_cols; ++i)
      {
        // Map distances (copy a column).
        distances.col(oldFromNewQueries[i]) = distancesOut.col(i);

        // Map indices of neighbors.
        for (size_t j = 0; j < distancesOut.n_rows; ++j)
        {
          neighbors(j, oldFromNewQueries[i]) =
              oldFromNewRefs[neighborsOut(j, i)];
        }
      }
    }
    else
    {
      for (size_t i = 0; i < distancesOut.n_cols; ++i)
      {
        // Map distances (copy a column).
        distances.col(oldFromNewRefs[i]) = distancesOut.col(i);

        // Map indices of neighbors.
        for (size_t j = 0; j < distancesOut.n_rows; ++j)
        {
          neighbors(j, oldFromNewRefs[i]) = oldFromNewRefs[neighborsOut(j, i)];
        }
      }
    }

    // Clean up.
    if (queryTree)
      delete queryTree;

    delete allknn;
  }
  else // Cover trees.
  {
    // Build our reference tree.
    Log::Info << "Building reference tree..." << endl;
    Timer::Start("tree_building");
    CoverTree<metric::LMetric<2>, tree::FirstPointIsRoot,
        QueryStat<NearestNeighborSort> > referenceTree(referenceData);
    CoverTree<metric::LMetric<2>, tree::FirstPointIsRoot,
        QueryStat<NearestNeighborSort> >* queryTree = NULL;
    Timer::Stop("tree_building");

    NeighborSearch<NearestNeighborSort, metric::LMetric<2>,
        CoverTree<metric::LMetric<2>, tree::FirstPointIsRoot,
        QueryStat<NearestNeighborSort> > >* allknn = NULL;

    // See if we have query data.
    if (CLI::HasParam("query_file"))
    {
      string queryFile = CLI::GetParam<string>("query_file");

      data::Load(queryFile, queryData, true);

      // Build query tree.
      Log::Info << "Building query tree..." << endl;
      Timer::Start("tree_building");
      queryTree = new CoverTree<metric::LMetric<2>, tree::FirstPointIsRoot,
          QueryStat<NearestNeighborSort> >(queryData);
      Timer::Stop("tree_building");

      allknn = new NeighborSearch<NearestNeighborSort, metric::LMetric<2>,
          CoverTree<metric::LMetric<2>, tree::FirstPointIsRoot,
          QueryStat<NearestNeighborSort> > >(&referenceTree, queryTree,
          referenceData, queryData, true);
    }
    else
    {
      allknn = new NeighborSearch<NearestNeighborSort, metric::LMetric<2>,
          CoverTree<metric::LMetric<2>, tree::FirstPointIsRoot,
          QueryStat<NearestNeighborSort> > >(&referenceTree, referenceData,
          true);
    }

    Log::Info << "Computing " << k << " nearest neighbors..." << endl;
    allknn->Search(k, neighbors, distances);

    Log::Info << "Neighbors computed." << endl;

    delete allknn;

    if (queryTree)
      delete queryTree;
  }

  // Save output.
  data::Save(distancesFile, distances);
  data::Save(neighborsFile, neighbors);
}
<|endoftext|>


<commit_before>/**
 * @file
 *      exercise_03_05_part_a.cpp
 * @author
 *      Henrik Samuelsson, henrik.somuelsson(at)gmail.com
 */
#include <iostream>
#include <string>

using std::cin;
using std::cout;
using std::string;

int main() {
    string temp, result;
    while(cin >> temp) {
        result.append(temp);
    }
    cout << result;
    return 0;
}<commit_msg>Committing exercise 3.5 part 1.<commit_after>/**
 * @file
 *      exercise_03_05_part_a.cpp
 * @author
 *      Henrik Samuelsson, henrik.somuelsson(at)gmail.com
 */
#include <iostream>
#include <string>

using std::cin;
using std::cout;
using std::string;

int main() {
    string temp, result;
    while(cin >> temp) {
        result.append(temp);
    }
    cout << result;
    return 0;
}
<|endoftext|>


<commit_before>#ifndef VEXCL_FFT_KERNELS_HPP
#define VEXCL_FFT_KERNELS_HPP

/*
The MIT License

Copyright (c) 2012 Denis Demidov <ddemidov@ksu.ru>

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.
*/

/**
 * \file   kernels.hpp
 * \author Pascal Germroth <pascal@ensieve.org>
 * \brief  Kernel generator for FFT.
 */

// OpenCL FFT kernels, original by Eric Bainville

namespace vex {
namespace fft {

struct kernel_call {
    cl::Kernel kernel;
    cl::NDRange global, local;
    kernel_call(cl::Kernel k, cl::NDRange g, cl::NDRange l) : kernel(k), global(g), local(l) {}
};

/// Return the greatest k = 2^m <= n
static int pow2_floor(int n) {
    if(n == 0) return 0;
    for(size_t m = 0 ; ; m++)
        if((1 << (m + 1)) > n)
            return 1 << m;
}

// return the `s` most significant bits from an integer in reverse.
// <http://graphics.stanford.edu/~seander/bithacks.html#BitReverseObvious>
template <class T>
T bit_reverse(T v, size_t s = sizeof(T) * CHAR_BIT) {
    T r = v & 1;
    s--;
    for(v >>= 1 ; v ; v >>= 1) {
        r <<= 1;
        r |= v & 1;
        s--;
    }
    return r << s;
}

// calculate log2(2^k) = k.
template <class T>
T log2(T n) {
    int k = 0;
    if(n <= 0) throw std::logic_error("not a positive power of 2.");
    while(n != 1) {
        if(n & 1) throw std::logic_error("not a power of 2.");
        n >>= 1;
        k++;
    }
    return k;
}

// generates "(vfrom,vfrom+1,...,vto)"
void param_list(std::ostringstream &o, size_t from, size_t to) {
    o << '(';
    for(size_t i = from ; i != to ; i++) {
        if(i != from) o << ',';
        o << 'v' << i;
    } o << ')';
}

template <class T>
void in_place_dft(std::ostringstream &o, bool invert, size_t radix) {
    // inline DFT macro.
    if(radix == 2) {
        o << R"(#define DFT2(v0,v1) { \
                real2_t tmp = v0 - v1; \
                v0 += v1; \
                v1 = tmp; \
            }
        )";
    } else {
        const size_t half_radix = radix / 2;
        // parameters
        o << "#define DFT" << radix;
        param_list(o, 0, radix);
        o << '{';
        // leaves
        for(size_t i = 0 ; i < half_radix ; i++) {
            o << "DFT2(v" << i << ",v" << (i + half_radix) << ");";
            if(i != 0) {
                const size_t j = i + half_radix;
                if(2 * i == half_radix) {
                    o << 'v' << j << "=twiddle_1_2(v" << j << ");";
                } else {
                    T factor = (invert ? 1 : -1) * (T)M_PI * i / half_radix;
                    typename cl::vector_of<T,2>::type twiddle =
                        {{std::cos(factor), std::sin(factor)}};
                    o << 'v' << j << "=mul(v" << j << ',' << std::setprecision(25) << twiddle << ");";
                }
            }
        }
        // next stage
        o << "DFT" << half_radix; param_list(o, 0, half_radix); o << ';';
        o << "DFT" << half_radix ; param_list(o, half_radix, radix); o << ';';
        o << "}\n";
    }
}

template <class T>
void kernel_radix(std::ostringstream &o, bool invert, size_t radix, size_t p) {
    for(size_t r = radix ; r >= 2 ; r /= 2)
        in_place_dft<T>(o, invert, r);

    // kernel.
    o << "__kernel void radix(__global const real2_t *x, __global real2_t *y) {";
    o << "const size_t threads = get_global_size(0);"
        << "const size_t i = get_global_id(0);"
        << "const size_t k = i & " << (p - 1) << ";" // index in input sequence, in 0..P-1
        << "const size_t j = ((i - k) * " << radix << ") + k;" // output index
        << "const size_t batch_offset = get_global_id(1) * threads * " << radix << ';'
        << "x += i + batch_offset; y += j + batch_offset;"
        << "real_t alpha = -FFT_PI / " << (p * radix / 2) << " * k;";

    // read
    o << "real2_t v0 = x[0];";
    for(size_t i = 1 ; i < radix ; i++)
        o << "real2_t v" << i << "=twiddle(x[" << i << "* threads]," << i << ",alpha);";
    // inplace DFT
    o << "DFT" << radix; param_list(o, 0, radix); o << ';';
    // write back
    for(size_t i = 0 ; i < radix ; i++) {
        size_t j = bit_reverse(i, log2(radix));
        o << "y[" << (i * p) << "]=v" << j << ';';
    }
    o << "}\n";
}

template <class T>
void kernel_common(std::ostringstream &o) {
    if(std::is_same<T, cl_double>::value) {
        o << standard_kernel_header;
        o << "typedef double real_t; typedef double2 real2_t;\n";
        o << "#define FFT_PI M_PI\n";
    } else {
        o << "typedef float real_t; typedef float2 real2_t;\n";
        o << "#define FFT_PI M_PI_F\n";
    }
}

template <class T>
kernel_call radix_kernel(cl::CommandQueue &queue, size_t n, size_t batch, bool invert, size_t radix, size_t p, cl::Buffer in, cl::Buffer out) {
    std::ostringstream o;
    kernel_common<T>(o);

    // Return A*B (complex multiplication)
    o << R"(
        real2_t mul(real2_t a, real2_t b) {
            return (real2_t)(a.x * b.x - a.y * b.y, a.x * b.y + a.y * b.x);
        }
    )";

    // A * exp(k * alpha * I) == cos(k * alpha) + I * sin(k * alpha)
    o << "real2_t twiddle(real2_t a, int k, real_t alpha) {"
        << "real_t cs, sn;"
        << "sn = sincos(" << (invert ? '-' : ' ') << "k * alpha, &cs);"
        << "return mul(a, (real2_t)(cs, sn));"
        << "}";

    // real(twiddle) = 0
    o << "real2_t twiddle_1_2(real2_t a){"
        << "return (real2_t)(" << (invert ? "-a.y, a.x" : "a.y, -a.x") << ");}\n";

    // kernels.
    kernel_radix<T>(o, invert, radix, p);

    auto program = build_sources(qctx(queue), o.str());
    cl::Kernel kernel(program, "radix");
    kernel.setArg(0, in);
    kernel.setArg(1, out);

    const size_t m = n / radix;
    size_t wg = pow2_floor(std::min(m,
        (size_t)kernel_workgroup_size(kernel, qdev(queue))));

    return kernel_call(kernel, cl::NDRange(m, batch), cl::NDRange(wg, 1));
}

template <class T>
kernel_call transpose_kernel(cl::CommandQueue &queue, size_t width, size_t height, cl::Buffer in, cl::Buffer out) {
    std::ostringstream o;
    kernel_common<T>(o);

    // determine max block size to fit into __local memory.
    size_t block_size = 128;
    const auto local_size = qdev(queue).getInfo<CL_DEVICE_LOCAL_MEM_SIZE>();
    while(block_size * block_size * sizeof(T) * 2 > local_size) block_size /= 2;
    block_size /= 2;

    // from NVIDIA SDK.
    o << "__kernel void transpose("
        "__global const real2_t *input, __global real2_t *output) {"
        "const size_t "
        "global_x = get_global_id(0), global_y = get_global_id(1),"
        "local_x = get_local_id(0), local_y = get_local_id(1),"
        "group_x = get_group_id(0), group_y = get_group_id(1),"
        "width =" << width << ", height = " << height << ", block_size = " << block_size << ","
        "target_x = local_y + group_y * block_size,"
        "target_y = local_x + group_x * block_size;"
        // local memory
        "__local real2_t block[" << (block_size * block_size) << "];"
        // copy from input to local memory
        "block[local_x + local_y * block_size] = input[global_x + global_y * width];"
        // wait until the whole block is filled
        "barrier(CLK_LOCAL_MEM_FENCE);"
        // transpose local block to target
        "output[target_x + target_y * height] = block[local_x + local_y * block_size];"
        "}";

    auto program = build_sources(qctx(queue), o.str());
    cl::Kernel kernel(program, "transpose");
    kernel.setArg(0, in);
    kernel.setArg(1, out);

    return kernel_call(kernel, cl::NDRange(width, height),
        cl::NDRange(std::min(width, block_size), std::min(height, block_size)));
}

} // namespace fft
} // namespace vex

#endif
<commit_msg>Number of threads known at kernel compile time<commit_after>#ifndef VEXCL_FFT_KERNELS_HPP
#define VEXCL_FFT_KERNELS_HPP

/*
The MIT License

Copyright (c) 2012 Denis Demidov <ddemidov@ksu.ru>

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.
*/

/**
 * \file   kernels.hpp
 * \author Pascal Germroth <pascal@ensieve.org>
 * \brief  Kernel generator for FFT.
 */

// OpenCL FFT kernels, original by Eric Bainville

namespace vex {
namespace fft {

struct kernel_call {
    cl::Kernel kernel;
    cl::NDRange global, local;
    kernel_call(cl::Kernel k, cl::NDRange g, cl::NDRange l) : kernel(k), global(g), local(l) {}
};

/// Return the greatest k = 2^m <= n
static int pow2_floor(int n) {
    if(n == 0) return 0;
    for(size_t m = 0 ; ; m++)
        if((1 << (m + 1)) > n)
            return 1 << m;
}

// return the `s` most significant bits from an integer in reverse.
// <http://graphics.stanford.edu/~seander/bithacks.html#BitReverseObvious>
template <class T>
T bit_reverse(T v, size_t s = sizeof(T) * CHAR_BIT) {
    T r = v & 1;
    s--;
    for(v >>= 1 ; v ; v >>= 1) {
        r <<= 1;
        r |= v & 1;
        s--;
    }
    return r << s;
}

// calculate log2(2^k) = k.
template <class T>
T log2(T n) {
    int k = 0;
    if(n <= 0) throw std::logic_error("not a positive power of 2.");
    while(n != 1) {
        if(n & 1) throw std::logic_error("not a power of 2.");
        n >>= 1;
        k++;
    }
    return k;
}

// generates "(vfrom,vfrom+1,...,vto)"
void param_list(std::ostringstream &o, size_t from, size_t to) {
    o << '(';
    for(size_t i = from ; i != to ; i++) {
        if(i != from) o << ',';
        o << 'v' << i;
    } o << ')';
}

template <class T>
void in_place_dft(std::ostringstream &o, bool invert, size_t radix) {
    // inline DFT macro.
    if(radix == 2) {
        o << R"(#define DFT2(v0,v1) { \
                real2_t tmp = v0 - v1; \
                v0 += v1; \
                v1 = tmp; \
            }
        )";
    } else {
        const size_t half_radix = radix / 2;
        // parameters
        o << "#define DFT" << radix;
        param_list(o, 0, radix);
        o << '{';
        // leaves
        for(size_t i = 0 ; i < half_radix ; i++) {
            o << "DFT2(v" << i << ",v" << (i + half_radix) << ");";
            if(i != 0) {
                const size_t j = i + half_radix;
                if(2 * i == half_radix) {
                    o << 'v' << j << "=twiddle_1_2(v" << j << ");";
                } else {
                    T factor = (invert ? 1 : -1) * (T)M_PI * i / half_radix;
                    typename cl::vector_of<T,2>::type twiddle =
                        {{std::cos(factor), std::sin(factor)}};
                    o << 'v' << j << "=mul(v" << j << ',' << std::setprecision(25) << twiddle << ");";
                }
            }
        }
        // next stage
        o << "DFT" << half_radix; param_list(o, 0, half_radix); o << ';';
        o << "DFT" << half_radix ; param_list(o, half_radix, radix); o << ';';
        o << "}\n";
    }
}

template <class T>
void kernel_radix(std::ostringstream &o, bool invert, size_t radix, size_t p, size_t threads) {
    for(size_t r = radix ; r >= 2 ; r /= 2)
        in_place_dft<T>(o, invert, r);

    // kernel.
    o << "__kernel void radix(__global const real2_t *x, __global real2_t *y) {";
    o << "const size_t i = get_global_id(0);"
        << "const size_t k = i & " << (p - 1) << ";" // index in input sequence, in 0..P-1
        << "const size_t j = ((i - k) * " << radix << ") + k;" // output index
        << "const size_t batch_offset = get_global_id(1) * " << (threads * radix) << ';'
        << "x += i + batch_offset; y += j + batch_offset;"
        << "real_t alpha = -FFT_PI / " << (p * radix / 2) << " * k;";

    // read
    o << "real2_t v0 = x[0];";
    for(size_t i = 1 ; i < radix ; i++)
        o << "real2_t v" << i << "=twiddle(x[" << (i * threads) << "]," << i << ",alpha);";
    // inplace DFT
    o << "DFT" << radix; param_list(o, 0, radix); o << ';';
    // write back
    for(size_t i = 0 ; i < radix ; i++) {
        size_t j = bit_reverse(i, log2(radix));
        o << "y[" << (i * p) << "]=v" << j << ';';
    }
    o << "}\n";
}

template <class T>
void kernel_common(std::ostringstream &o) {
    if(std::is_same<T, cl_double>::value) {
        o << standard_kernel_header;
        o << "typedef double real_t; typedef double2 real2_t;\n";
        o << "#define FFT_PI M_PI\n";
    } else {
        o << "typedef float real_t; typedef float2 real2_t;\n";
        o << "#define FFT_PI M_PI_F\n";
    }
}

template <class T>
kernel_call radix_kernel(cl::CommandQueue &queue, size_t n, size_t batch, bool invert, size_t radix, size_t p, cl::Buffer in, cl::Buffer out) {
    std::ostringstream o;
    kernel_common<T>(o);

    // Return A*B (complex multiplication)
    o << R"(
        real2_t mul(real2_t a, real2_t b) {
            return (real2_t)(a.x * b.x - a.y * b.y, a.x * b.y + a.y * b.x);
        }
    )";

    // A * exp(k * alpha * I) == cos(k * alpha) + I * sin(k * alpha)
    o << "real2_t twiddle(real2_t a, int k, real_t alpha) {"
        << "real_t cs, sn;"
        << "sn = sincos(" << (invert ? '-' : ' ') << "k * alpha, &cs);"
        << "return mul(a, (real2_t)(cs, sn));"
        << "}";

    // real(twiddle) = 0
    o << "real2_t twiddle_1_2(real2_t a){"
        << "return (real2_t)(" << (invert ? "-a.y, a.x" : "a.y, -a.x") << ");}\n";

    const size_t m = n / radix;
    kernel_radix<T>(o, invert, radix, p, m);

    auto program = build_sources(qctx(queue), o.str());
    cl::Kernel kernel(program, "radix");
    kernel.setArg(0, in);
    kernel.setArg(1, out);

    size_t wg = pow2_floor(std::min(m,
        (size_t)kernel_workgroup_size(kernel, qdev(queue))));

    return kernel_call(kernel, cl::NDRange(m, batch), cl::NDRange(wg, 1));
}

template <class T>
kernel_call transpose_kernel(cl::CommandQueue &queue, size_t width, size_t height, cl::Buffer in, cl::Buffer out) {
    std::ostringstream o;
    kernel_common<T>(o);

    // determine max block size to fit into __local memory.
    size_t block_size = 128;
    const auto local_size = qdev(queue).getInfo<CL_DEVICE_LOCAL_MEM_SIZE>();
    while(block_size * block_size * sizeof(T) * 2 > local_size) block_size /= 2;
    block_size /= 2;

    // from NVIDIA SDK.
    o << "__kernel void transpose("
        "__global const real2_t *input, __global real2_t *output) {"
        "const size_t "
        "global_x = get_global_id(0), global_y = get_global_id(1),"
        "local_x = get_local_id(0), local_y = get_local_id(1),"
        "group_x = get_group_id(0), group_y = get_group_id(1),"
        "width =" << width << ", height = " << height << ", block_size = " << block_size << ","
        "target_x = local_y + group_y * block_size,"
        "target_y = local_x + group_x * block_size;"
        // local memory
        "__local real2_t block[" << (block_size * block_size) << "];"
        // copy from input to local memory
        "block[local_x + local_y * block_size] = input[global_x + global_y * width];"
        // wait until the whole block is filled
        "barrier(CLK_LOCAL_MEM_FENCE);"
        // transpose local block to target
        "output[target_x + target_y * height] = block[local_x + local_y * block_size];"
        "}";

    auto program = build_sources(qctx(queue), o.str());
    cl::Kernel kernel(program, "transpose");
    kernel.setArg(0, in);
    kernel.setArg(1, out);

    return kernel_call(kernel, cl::NDRange(width, height),
        cl::NDRange(std::min(width, block_size), std::min(height, block_size)));
}

} // namespace fft
} // namespace vex

#endif
<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  $RCSfile: DataPoint.cxx,v $
 *
 *  $Revision: 1.2 $
 *
 *  last change: $Author: bm $ $Date: 2004-01-26 09:12:26 $
 *
 *  The Contents of this file are made available subject to the terms of
 *  either of the following licenses
 *
 *         - GNU Lesser General Public License Version 2.1
 *         - Sun Industry Standards Source License Version 1.1
 *
 *  Sun Microsystems Inc., October, 2000
 *
 *  GNU Lesser General Public License Version 2.1
 *  =============================================
 *  Copyright 2000 by Sun Microsystems, Inc.
 *  901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License version 2.1, as published by the Free Software Foundation.
 *
 *  This library is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *  Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this library; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *  MA  02111-1307  USA
 *
 *
 *  Sun Industry Standards Source License Version 1.1
 *  =================================================
 *  The contents of this file are subject to the Sun Industry Standards
 *  Source License Version 1.1 (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.openoffice.org/license.html.
 *
 *  Software provided under this License is provided on an "AS IS" basis,
 *  WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
 *  WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
 *  MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
 *  See the License for the specific provisions governing your rights and
 *  obligations concerning the Software.
 *
 *  The Initial Developer of the Original Code is: Sun Microsystems, Inc.
 *
 *  Copyright: 2003 by Sun Microsystems, Inc.
 *
 *  All Rights Reserved.
 *
 *  Contributor(s): _______________________________________
 *
 *
 ************************************************************************/
#include "DataPoint.hxx"
#include "DataPointProperties.hxx"
#include "CharacterProperties.hxx"
#include "UserDefinedProperties.hxx"
#include "PropertyHelper.hxx"
#include "macros.hxx"
#include "algohelper.hxx"

#ifndef _COM_SUN_STAR_BEANS_PROPERTYATTRIBUTE_HPP_
#include <com/sun/star/beans/PropertyAttribute.hpp>
#endif
#ifndef _COM_SUN_STAR_STYLE_XSTYLE_HPP_
#include <com/sun/star/style/XStyle.hpp>
#endif
#ifndef _COM_SUN_STAR_BEANS_XPROPERTYSET_HPP_
#include <com/sun/star/beans/XPropertySet.hpp>
#endif

#ifndef _COM_SUN_STAR_UNO_SEQUENCE_HXX_
#include <com/sun/star/uno/Sequence.hxx>
#endif

#include <algorithm>

using namespace ::com::sun::star;

using ::com::sun::star::uno::Reference;
using ::com::sun::star::beans::Property;
using ::osl::MutexGuard;

// ____________________________________________________________

namespace
{
const uno::Sequence< Property > & lcl_GetPropertySequence()
{
    static uno::Sequence< Property > aPropSeq;

    // /--
    ::osl::MutexGuard aGuard( ::osl::Mutex::getGlobalMutex() );
    if( 0 == aPropSeq.getLength() )
    {
        // get properties
        ::std::vector< ::com::sun::star::beans::Property > aProperties;
        ::chart::DataPointProperties::AddPropertiesToVector(
            aProperties, /* bIncludeStyleProperties = */ true );
        ::chart::CharacterProperties::AddPropertiesToVector(
            aProperties, /* bIncludeStyleProperties = */ true );
        ::chart::UserDefinedProperties::AddPropertiesToVector( aProperties );

        // and sort them for access via bsearch
        ::std::sort( aProperties.begin(), aProperties.end(),
                     ::chart::helper::PropertyNameLess() );

        // transfer result to static Sequence
        aPropSeq = ::chart::helper::VectorToSequence( aProperties );
    }

    return aPropSeq;
}
} // anonymous namespace

// ____________________________________________________________

namespace chart
{

DataPoint::DataPoint( ::osl::Mutex & _rMutex ) :
        ::property::OPropertySet( _rMutex ),
    m_rMutex( _rMutex )
{}

DataPoint::DataPoint( ::osl::Mutex & _rMutex,
                      const uno::Reference<
                          beans::XPropertySet > & rParentProperties ) :
        ::property::OPropertySet( _rMutex ),
    m_rMutex( _rMutex ),
    m_xParentProperties( rParentProperties )
{}

DataPoint::~DataPoint()
{}

// ____ XInterface ____
uno::Any SAL_CALL DataPoint::queryInterface(
    const uno::Type & rType )
    throw (uno::RuntimeException)
{
    // OPropertySet interfaces
    uno::Any aAny = ::property::OPropertySet::queryInterface( rType );
    if( aAny.hasValue() )
        return aAny;

    // OWeakObject interfaces
    return ::cppu::OWeakObject::queryInterface( rType );
}

void SAL_CALL DataPoint::acquire() throw ()
{
    ::cppu::OWeakObject::acquire();
}

void SAL_CALL DataPoint::release() throw ()
{
    ::cppu::OWeakObject::release();
}

// ____ OPropertySet ____
uno::Any DataPoint::GetDefaultValue( sal_Int32 nHandle ) const
    throw(beans::UnknownPropertyException)
{
    // the value set at the data series is the default
    uno::Reference< beans::XFastPropertySet > xFast( m_xParentProperties, uno::UNO_QUERY );
    OSL_ASSERT( xFast.is());
    return xFast->getFastPropertyValue( nHandle );
}

::cppu::IPropertyArrayHelper & SAL_CALL DataPoint::getInfoHelper()
{
    return getInfoHelperConst();
}

::cppu::IPropertyArrayHelper & SAL_CALL DataPoint::getInfoHelperConst() const
{
    static ::cppu::OPropertyArrayHelper aArrayHelper(
        lcl_GetPropertySequence(),
        /* bSorted = */ sal_True );

    return aArrayHelper;
}

// ____ XPropertySet ____
Reference< beans::XPropertySetInfo > SAL_CALL
    DataPoint::getPropertySetInfo()
    throw (uno::RuntimeException)
{
    static Reference< beans::XPropertySetInfo > xInfo;

    // /--
    ::osl::MutexGuard aGuard( ::osl::Mutex::getGlobalMutex() );
    if( !xInfo.is())
    {
        xInfo = ::cppu::OPropertySetHelper::createPropertySetInfo(
            getInfoHelper());
    }

    return xInfo;
    // \--
}

::osl::Mutex & DataPoint::GetMutex()
{
    return m_rMutex;
}

} //  namespace chart
<commit_msg>INTEGRATION: CWS ooo19126 (1.2.110); FILE MERGED 2005/09/05 18:43:03 rt 1.2.110.1: #i54170# Change license header: remove SISSL<commit_after>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: DataPoint.cxx,v $
 *
 *  $Revision: 1.3 $
 *
 *  last change: $Author: rt $ $Date: 2005-09-08 00:55:01 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/
#include "DataPoint.hxx"
#include "DataPointProperties.hxx"
#include "CharacterProperties.hxx"
#include "UserDefinedProperties.hxx"
#include "PropertyHelper.hxx"
#include "macros.hxx"
#include "algohelper.hxx"

#ifndef _COM_SUN_STAR_BEANS_PROPERTYATTRIBUTE_HPP_
#include <com/sun/star/beans/PropertyAttribute.hpp>
#endif
#ifndef _COM_SUN_STAR_STYLE_XSTYLE_HPP_
#include <com/sun/star/style/XStyle.hpp>
#endif
#ifndef _COM_SUN_STAR_BEANS_XPROPERTYSET_HPP_
#include <com/sun/star/beans/XPropertySet.hpp>
#endif

#ifndef _COM_SUN_STAR_UNO_SEQUENCE_HXX_
#include <com/sun/star/uno/Sequence.hxx>
#endif

#include <algorithm>

using namespace ::com::sun::star;

using ::com::sun::star::uno::Reference;
using ::com::sun::star::beans::Property;
using ::osl::MutexGuard;

// ____________________________________________________________

namespace
{
const uno::Sequence< Property > & lcl_GetPropertySequence()
{
    static uno::Sequence< Property > aPropSeq;

    // /--
    ::osl::MutexGuard aGuard( ::osl::Mutex::getGlobalMutex() );
    if( 0 == aPropSeq.getLength() )
    {
        // get properties
        ::std::vector< ::com::sun::star::beans::Property > aProperties;
        ::chart::DataPointProperties::AddPropertiesToVector(
            aProperties, /* bIncludeStyleProperties = */ true );
        ::chart::CharacterProperties::AddPropertiesToVector(
            aProperties, /* bIncludeStyleProperties = */ true );
        ::chart::UserDefinedProperties::AddPropertiesToVector( aProperties );

        // and sort them for access via bsearch
        ::std::sort( aProperties.begin(), aProperties.end(),
                     ::chart::helper::PropertyNameLess() );

        // transfer result to static Sequence
        aPropSeq = ::chart::helper::VectorToSequence( aProperties );
    }

    return aPropSeq;
}
} // anonymous namespace

// ____________________________________________________________

namespace chart
{

DataPoint::DataPoint( ::osl::Mutex & _rMutex ) :
        ::property::OPropertySet( _rMutex ),
    m_rMutex( _rMutex )
{}

DataPoint::DataPoint( ::osl::Mutex & _rMutex,
                      const uno::Reference<
                          beans::XPropertySet > & rParentProperties ) :
        ::property::OPropertySet( _rMutex ),
    m_rMutex( _rMutex ),
    m_xParentProperties( rParentProperties )
{}

DataPoint::~DataPoint()
{}

// ____ XInterface ____
uno::Any SAL_CALL DataPoint::queryInterface(
    const uno::Type & rType )
    throw (uno::RuntimeException)
{
    // OPropertySet interfaces
    uno::Any aAny = ::property::OPropertySet::queryInterface( rType );
    if( aAny.hasValue() )
        return aAny;

    // OWeakObject interfaces
    return ::cppu::OWeakObject::queryInterface( rType );
}

void SAL_CALL DataPoint::acquire() throw ()
{
    ::cppu::OWeakObject::acquire();
}

void SAL_CALL DataPoint::release() throw ()
{
    ::cppu::OWeakObject::release();
}

// ____ OPropertySet ____
uno::Any DataPoint::GetDefaultValue( sal_Int32 nHandle ) const
    throw(beans::UnknownPropertyException)
{
    // the value set at the data series is the default
    uno::Reference< beans::XFastPropertySet > xFast( m_xParentProperties, uno::UNO_QUERY );
    OSL_ASSERT( xFast.is());
    return xFast->getFastPropertyValue( nHandle );
}

::cppu::IPropertyArrayHelper & SAL_CALL DataPoint::getInfoHelper()
{
    return getInfoHelperConst();
}

::cppu::IPropertyArrayHelper & SAL_CALL DataPoint::getInfoHelperConst() const
{
    static ::cppu::OPropertyArrayHelper aArrayHelper(
        lcl_GetPropertySequence(),
        /* bSorted = */ sal_True );

    return aArrayHelper;
}

// ____ XPropertySet ____
Reference< beans::XPropertySetInfo > SAL_CALL
    DataPoint::getPropertySetInfo()
    throw (uno::RuntimeException)
{
    static Reference< beans::XPropertySetInfo > xInfo;

    // /--
    ::osl::MutexGuard aGuard( ::osl::Mutex::getGlobalMutex() );
    if( !xInfo.is())
    {
        xInfo = ::cppu::OPropertySetHelper::createPropertySetInfo(
            getInfoHelper());
    }

    return xInfo;
    // \--
}

::osl::Mutex & DataPoint::GetMutex()
{
    return m_rMutex;
}

} //  namespace chart
<|endoftext|>


<commit_before>#ifndef VPP_IMAGENd_HPP__
# define VPP_IMAGENd_HPP__

# include <vpp/imageNd.hh>
# include <vpp/boxNd.hh>
# include <vpp/copy.hh>

namespace vpp
{

  template <typename V, unsigned N>
  imageNd<V, N>::imageNd()
  {
  }

  template <typename V, unsigned N>
  imageNd<V, N>::imageNd(const std::initializer_list<int>& dims, vpp::border b)
  {
    allocate(dims, b);
  }

  template <typename V, unsigned N>
  imageNd<V, N>::imageNd(const std::vector<int>& dims, vpp::border b)
  {
    allocate(dims, b);
  }

  template <typename V, unsigned N>
  imageNd<V, N>::imageNd(int ncols, vpp::border b)
    : imageNd({ncols}, b)
  {
    static_assert(N == 1, "ImageNd constructor: bad dimension.");
  }

  template <typename V, unsigned N>
  imageNd<V, N>::imageNd(int nrows, int ncols, vpp::border b)
    : imageNd({nrows, ncols}, b)
  {
    static_assert(N == 2, "ImageNd constructor: bad dimension.");
  }

  template <typename V, unsigned N>
  imageNd<V, N>::imageNd(int nslices, int nrows, int ncols, vpp::border b)
    : imageNd({nslices, nrows, ncols}, b)
  {
    static_assert(N == 3, "ImageNd constructor: bad dimension.");
  }

  template <typename V, unsigned N>
  imageNd<V, N>::imageNd(std::vector<int> dims, vpp::border b, V* data, int pitch, bool own_data)
  {
    ptr_ = std::shared_ptr<imageNd_data<V, N>>(new imageNd_data<V, N>(),
                               delete_imageNd_data<imageNd_data<V, N>>);
    ptr_->data_ = data;
    ptr_->begin_ = ptr_->data_;
    ptr_->pitch_ = pitch;
    ptr_->own_data_ = own_data;
    ptr_->domain_.p1() = vint<N>::Zero();
    for (unsigned i = 0; i < N; i++)
      ptr_->domain_.p2()[i] = dims[i] - 1;

    ptr_->border_ = b.size();

    int size = ptr_->pitch_;
    for (int n = 0; n < N - 1; n++)
      size *= ptr_->domain_.size(n);

    ptr_->data_end_ = (V*)((char*) ptr_->data_ + size);
  }

  template <typename V, unsigned N>
  imageNd<V, N>::imageNd(const imageNd<V, N>&& other)
  {
    *this = other;
  }

  template <typename V, unsigned N>
  imageNd<V, N>& imageNd<V, N>::operator=(const imageNd<V, N>& other)
  {
    ptr_ = other.ptr_;
    return *this;
  }

  template <typename V, unsigned N>
  imageNd<V, N>::imageNd(const imageNd<V, N>& other)
  {
    *this = other;
  }

  template <typename V, unsigned N>
  imageNd<V, N>& imageNd<V, N>::operator=(const imageNd<V, N>&& other)
  {
    ptr_ = other.ptr_;
    return *this;
  }

  template <typename V, unsigned N>
  imageNd<V, N>::imageNd(const boxNd<N>& domain, vpp::border b)
  {
    std::vector<int> dims(N);

    for (int i = 0; i < int(N); i++)
      dims[i] = domain.size(i);

    allocate(dims, b);
  }

  template <typename V, unsigned N>
  imageNd<V, N>::~imageNd()
  {
    // The shared_ptr this_->ptr_ will destroy the data if needed.
  }

  template <typename V, unsigned N>
  void imageNd<V, N>::allocate(const std::vector<int>& dims, vpp::border b)
  {
    ptr_ = std::make_shared<imageNd_data<V, N>>();
    auto& d = *ptr_;
    d.own_data_ = true;
    d.border_ = b.size();
    d.pitch_ = (dims[N - 1] + b.size() * 2) * sizeof(V);
    int size = 1;
    for (int i = 0; i < N; i++)
      size *= (dims[i] + b.size() * 2);
    d.data_ = new V[size];
    d.data_end_ = d.data_ + size;

    d.domain_.p1() = vint<N>::Zero();
    for (unsigned i = 0; i < N; i++)
      d.domain_.p2()[i] = dims[i] - 1;

    vint<N> p = vint<N>::Ones() * b.size();
    d.begin_ = (V*)((char*)d.data_ + coords_to_offset(p));
  }

  template <typename V, unsigned N>
  int imageNd<V, N>::coords_to_index(const vint<N>& p) const
  {
    int idx = p[N-1];
    int ds = 1;
    for (int i = N - 2; i >= 0; i--)
    {
      ds *= ptr_->domain_.size(i + 1);
      idx += ds * p[i];
    }
    return idx;
  }

  template <typename V, unsigned N>
  int imageNd<V, N>::coords_to_offset(const vint<N>& p) const
  {
    int row_idx = p[N-2];
    int ds = 1;
    for (int i = N - 3; i >= 0; i--)
    {
      ds *= ptr_->domain_.size(i + 1);
      row_idx += ds * p[i];
    }
    return row_idx * ptr_->pitch_ + p[N - 1] * sizeof(V);
  }

  template <typename V, unsigned N>
  V&
  imageNd<V, N>::operator()(const vint<N>& p)
  {
    assert(domain_with_border().has(p));
    V* addr = (V*)((char*)ptr_->begin_ + coords_to_offset(p));
    assert(addr < ptr_->data_end_);
    return *addr;
  }

  template <typename V, unsigned N>
  const V&
  imageNd<V, N>::operator()(const vint<N>& p) const
  {
    assert(domain_with_border().has(p));
    const V* addr = (V*)((char*)ptr_->begin_ + coords_to_offset(p));
    assert(addr < ptr_->data_end_);
    return *addr;
  }

  template <typename V, unsigned N>
  V*
  imageNd<V, N>::address_of(const vint<N>& p)
  {
    return (V*)((char*)(ptr_->begin_) + coords_to_offset(p));
  }

  template <typename V, unsigned N>
  const V*
  imageNd<V, N>::address_of(const vint<N>& p) const
  {
    return (V*)((char*)(ptr_->begin_) + coords_to_offset(p));
  }

  template <typename V, unsigned N>
  int
  imageNd<V, N>::offset_of(const vint<N>& p) const
  {
    return coords_to_offset(p);
  }

  template <typename I>
  I clone(I img)
  {
    I n(img.domain(), img.border());
    copy(img, n);
    return n;
  }

  template <typename I>
  I clone_with_border(I img, vpp::border b)
  {
    I n(img.domain(), b);
    copy(img, n);
    return n;
  }

};

#endif
<commit_msg>Align imageNd rows to enable the use of aligned simd instruction.<commit_after><|endoftext|>