<commit_before>/** @example user_accelerometer_poses.cpp
 * Pose detection using accelerometers.
 */
#include <ESP.h>

ASCIISerialStream stream(0, 115200, 3);
GestureRecognitionPipeline pipeline;
Calibrator calibrator;
TcpOStream oStream("localhost", 5204, 3, "l", "r", " ");

MatrixDouble uprightData, upsideDownData;
bool haveUprightData = false, haveUpsideDownData = false;
double range;
vector<double> zeroGs(3);

vector<double> processAccelerometerData(vector<double> input)
{
    vector<double> result(3);

    for (int i = 0; i < 3; i++) {
        result[i] = (input[i] - zeroGs[i]) / range;
    }

    return result;
}

CalibrateResult calibrate(const MatrixDouble& data) {
    CalibrateResult result = CalibrateResult::SUCCESS;

    // Run checks on newly collected sample.

    // take average of X and Y acceleration as the zero G value
    double zG = (data.getMean()[0] + data.getMean()[1]) / 2;
    double oG = data.getMean()[2]; // use Z acceleration as one G value

    double r = abs(oG - zG);
    vector<double> stddev = data.getStdDev();

    if (stddev[0] / r > 0.05 ||
        stddev[1] / r > 0.05 ||
        stddev[2] / r > 0.05)
        result = CalibrateResult(CalibrateResult::WARNING,
            "Accelerometer seemed to be moving; consider recollecting the "
            "calibration sample.");

    if (abs(data.getMean()[0] - data.getMean()[1]) / r > 0.1)
        result = CalibrateResult(CalibrateResult::WARNING,
            "X and Y axes differ by " + std::to_string(
            abs(data.getMean()[0] - data.getMean()[1]) / r * 100) +
            " percent. Check that accelerometer is flat.");

    // If we have both samples, do the actual calibration.

    if (haveUprightData && haveUpsideDownData) {
        for (int i = 0; i < 3; i++) {
            zeroGs[i] =
                (uprightData.getMean()[i] + upsideDownData.getMean()[i]) / 2;
        }

        // use half the difference between the two z-axis values (-1 and +1)
        // as the range
        range = (uprightData.getMean()[2] - upsideDownData.getMean()[2]) / 2;
    }

    return result;
}

CalibrateResult uprightDataCollected(const MatrixDouble& data)
{
    uprightData = data;
    haveUprightData = true;
    return calibrate(data);
}

CalibrateResult upsideDownDataCollected(const MatrixDouble& data)
{
    upsideDownData = data;
    haveUpsideDownData = true;
    return calibrate(data);
}

double null_rej = 5.0;
bool always_pick_something = false;
bool send_repeated_predictions = false;
int timeout = 100;

void updateAlwaysPickSomething(bool new_val) {
    pipeline.getClassifier()->enableNullRejection(!new_val);
}

void updateVariability(double new_val) {
    pipeline.getClassifier()->setNullRejectionCoeff(new_val);
    pipeline.getClassifier()->recomputeNullRejectionThresholds();
}

void updateSendRepeatedPredictions(bool new_val) {
    if (new_val) {
        assert(pipeline.getNumPostProcessingModules() == 0);
        pipeline.addPostProcessingModule(ClassLabelTimeoutFilter(timeout));
    } else {
        assert(pipeline.getNumPostProcessingModules() == 1);
        pipeline.removePostProcessingModule(0);
    }
}

void updateTimeout(int new_val) {
    if (pipeline.getNumPostProcessingModules() > 0) {
        ClassLabelTimeoutFilter *filter =
            dynamic_cast<ClassLabelTimeoutFilter *>
                (pipeline.getPostProcessingModule(0));
        assert(filter != nullptr);
        filter->setTimeoutDuration(new_val);
    }

    // else do nothing, i.e. allow the user to adjust the timout parameter
    // even if it's not currently being used (because send_repeated_predictions
    // is false).
}

void setup()
{
    stream.setLabelsForAllDimensions({"x", "y", "z"});
    useInputStream(stream);
    useOutputStream(oStream);
    //useStream(stream);

    calibrator.setCalibrateFunction(processAccelerometerData);
    calibrator.addCalibrateProcess("Upright",
        "Rest accelerometer upright on flat surface.", uprightDataCollected);
    calibrator.addCalibrateProcess("Upside Down",
        "Rest accelerometer upside down on flat surface.", upsideDownDataCollected);
    useCalibrator(calibrator);

    pipeline.addFeatureExtractionModule(TimeDomainFeatures(10, 1, 3, false, true, true, false, false));
    pipeline.setClassifier(ANBC(false, !always_pick_something, null_rej)); // use scaling, use null rejection, null rejection parameter
    // null rejection parameter is multiplied by the standard deviation to determine
    // the rejection threshold. the higher the number, the looser the filter; the
    // lower the number, the tighter the filter.

    if (send_repeated_predictions)
        pipeline.addPostProcessingModule(ClassLabelTimeoutFilter(timeout));
    usePipeline(pipeline);

    registerTuneable(always_pick_something, "Always Pick Something",
        "Whether to always pick (predict) one of the classes of training data, "
        "even if it's not a very good match. If selected, 'Variability' will "
        "not be used.", updateAlwaysPickSomething);
    registerTuneable(null_rej, 1.0, 25.0, "Variability",
         "How different from the training data a new gesture can be and "
         "still be considered the same gesture. The higher the number, the more "
         "different it can be.", updateVariability);
    registerTuneable(send_repeated_predictions, "Send Repeated Predictions",
        "Whether to send repeated predictions while a pose is being held. If "
        "not selected, predictions will only be sent on transition from one "
        "pose to another.", updateSendRepeatedPredictions);
    registerTuneable(timeout, 1, 3000,
        "Timeout",
        "How long (in milliseconds) to wait after recognizing a class before "
        "recognizing a different one. Only used if 'Send Repeated Predictions' "
        "is selected.", updateTimeout);
}
<commit_msg>Don't hard-code serial port in accelerometer poses example.<commit_after>/** @example user_accelerometer_poses.cpp
 * Pose detection using accelerometers.
 */
#include <ESP.h>

ASCIISerialStream stream(115200, 3);
GestureRecognitionPipeline pipeline;
Calibrator calibrator;
TcpOStream oStream("localhost", 5204, 3, "l", "r", " ");

MatrixDouble uprightData, upsideDownData;
bool haveUprightData = false, haveUpsideDownData = false;
double range;
vector<double> zeroGs(3);

vector<double> processAccelerometerData(vector<double> input)
{
    vector<double> result(3);

    for (int i = 0; i < 3; i++) {
        result[i] = (input[i] - zeroGs[i]) / range;
    }

    return result;
}

CalibrateResult calibrate(const MatrixDouble& data) {
    CalibrateResult result = CalibrateResult::SUCCESS;

    // Run checks on newly collected sample.

    // take average of X and Y acceleration as the zero G value
    double zG = (data.getMean()[0] + data.getMean()[1]) / 2;
    double oG = data.getMean()[2]; // use Z acceleration as one G value

    double r = abs(oG - zG);
    vector<double> stddev = data.getStdDev();

    if (stddev[0] / r > 0.05 ||
        stddev[1] / r > 0.05 ||
        stddev[2] / r > 0.05)
        result = CalibrateResult(CalibrateResult::WARNING,
            "Accelerometer seemed to be moving; consider recollecting the "
            "calibration sample.");

    if (abs(data.getMean()[0] - data.getMean()[1]) / r > 0.1)
        result = CalibrateResult(CalibrateResult::WARNING,
            "X and Y axes differ by " + std::to_string(
            abs(data.getMean()[0] - data.getMean()[1]) / r * 100) +
            " percent. Check that accelerometer is flat.");

    // If we have both samples, do the actual calibration.

    if (haveUprightData && haveUpsideDownData) {
        for (int i = 0; i < 3; i++) {
            zeroGs[i] =
                (uprightData.getMean()[i] + upsideDownData.getMean()[i]) / 2;
        }

        // use half the difference between the two z-axis values (-1 and +1)
        // as the range
        range = (uprightData.getMean()[2] - upsideDownData.getMean()[2]) / 2;
    }

    return result;
}

CalibrateResult uprightDataCollected(const MatrixDouble& data)
{
    uprightData = data;
    haveUprightData = true;
    return calibrate(data);
}

CalibrateResult upsideDownDataCollected(const MatrixDouble& data)
{
    upsideDownData = data;
    haveUpsideDownData = true;
    return calibrate(data);
}

double null_rej = 5.0;
bool always_pick_something = false;
bool send_repeated_predictions = false;
int timeout = 100;

void updateAlwaysPickSomething(bool new_val) {
    pipeline.getClassifier()->enableNullRejection(!new_val);
}

void updateVariability(double new_val) {
    pipeline.getClassifier()->setNullRejectionCoeff(new_val);
    pipeline.getClassifier()->recomputeNullRejectionThresholds();
}

void updateSendRepeatedPredictions(bool new_val) {
    if (new_val) {
        assert(pipeline.getNumPostProcessingModules() == 0);
        pipeline.addPostProcessingModule(ClassLabelTimeoutFilter(timeout));
    } else {
        assert(pipeline.getNumPostProcessingModules() == 1);
        pipeline.removePostProcessingModule(0);
    }
}

void updateTimeout(int new_val) {
    if (pipeline.getNumPostProcessingModules() > 0) {
        ClassLabelTimeoutFilter *filter =
            dynamic_cast<ClassLabelTimeoutFilter *>
                (pipeline.getPostProcessingModule(0));
        assert(filter != nullptr);
        filter->setTimeoutDuration(new_val);
    }

    // else do nothing, i.e. allow the user to adjust the timout parameter
    // even if it's not currently being used (because send_repeated_predictions
    // is false).
}

void setup()
{
    stream.setLabelsForAllDimensions({"x", "y", "z"});
    useInputStream(stream);
    useOutputStream(oStream);
    //useStream(stream);

    calibrator.setCalibrateFunction(processAccelerometerData);
    calibrator.addCalibrateProcess("Upright",
        "Rest accelerometer upright on flat surface.", uprightDataCollected);
    calibrator.addCalibrateProcess("Upside Down",
        "Rest accelerometer upside down on flat surface.", upsideDownDataCollected);
    useCalibrator(calibrator);

    pipeline.addFeatureExtractionModule(TimeDomainFeatures(10, 1, 3, false, true, true, false, false));
    pipeline.setClassifier(ANBC(false, !always_pick_something, null_rej)); // use scaling, use null rejection, null rejection parameter
    // null rejection parameter is multiplied by the standard deviation to determine
    // the rejection threshold. the higher the number, the looser the filter; the
    // lower the number, the tighter the filter.

    if (send_repeated_predictions)
        pipeline.addPostProcessingModule(ClassLabelTimeoutFilter(timeout));
    usePipeline(pipeline);

    registerTuneable(always_pick_something, "Always Pick Something",
        "Whether to always pick (predict) one of the classes of training data, "
        "even if it's not a very good match. If selected, 'Variability' will "
        "not be used.", updateAlwaysPickSomething);
    registerTuneable(null_rej, 1.0, 25.0, "Variability",
         "How different from the training data a new gesture can be and "
         "still be considered the same gesture. The higher the number, the more "
         "different it can be.", updateVariability);
    registerTuneable(send_repeated_predictions, "Send Repeated Predictions",
        "Whether to send repeated predictions while a pose is being held. If "
        "not selected, predictions will only be sent on transition from one "
        "pose to another.", updateSendRepeatedPredictions);
    registerTuneable(timeout, 1, 3000,
        "Timeout",
        "How long (in milliseconds) to wait after recognizing a class before "
        "recognizing a different one. Only used if 'Send Repeated Predictions' "
        "is selected.", updateTimeout);
}
<|endoftext|>


<commit_before>// Copyright (c) 2011, Cornell University
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
//     * Redistributions of source code must retain the above copyright notice,
//       this list of conditions and the following disclaimer.
//     * Redistributions in binary form must reproduce the above copyright
//       notice, this list of conditions and the following disclaimer in the
//       documentation and/or other materials provided with the distribution.
//     * Neither the name of HyperDex nor the names of its contributors may be
//       used to endorse or promote products derived from this software without
//       specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.

#define __STDC_LIMIT_MACROS

// C
#include <cassert>
#include <cstdlib>
#include <ctime>

// HyperspaceHashing
#include "hashes_internal.h"
#include "hyperspacehashing/hashes.h"
#include "hyperspacehashing/mask.h"
#include "hyperspacehashing/prefix.h"
#include "hyperspacehashing/search.h"

using hyperspacehashing::hash_t;
using hyperspacehashing::EQUALITY;
using hyperspacehashing::NONE;
using namespace hyperspacehashing;

void
validate(const std::vector<hash_t> hf, const e::buffer& key, const std::vector<e::buffer>& value);

int
main(int, char* [])
{
    srand(time(NULL));

    for (size_t i = 0; i < 10; ++i)
    {
        uint32_t nums[5];

        for (int j = 0; j < 5; ++j)
        {
            nums[i] = static_cast<uint32_t>(rand());
        }

        for (size_t k = EQUALITY; k <= NONE; ++k)
        {
            std::vector<hash_t> hf(1);
            hf[0] = static_cast<hash_t>(k);

            std::vector<e::buffer> value;
            e::buffer key;
            key.pack() << nums[0];
            validate(hf, key, value);
            hf.push_back(NONE);
            value.push_back(e::buffer());

            for (size_t v1 = EQUALITY; v1 <= NONE; ++v1)
            {
                assert(hf.size() == 2);
                assert(value.size() == 1);
                hf[1] = static_cast<hash_t>(v1);
                value[0].pack() << nums[1];
                validate(hf, key, value);
                hf.push_back(NONE);
                value.push_back(e::buffer());

                for (size_t v2 = EQUALITY; v2 <= NONE; ++v2)
                {
                    assert(hf.size() == 3);
                    assert(value.size() == 2);
                    hf[2] = static_cast<hash_t>(v2);
                    value[1].pack() << nums[2];
                    validate(hf, key, value);
                    hf.push_back(NONE);
                    value.push_back(e::buffer());

                    for (size_t v3 = EQUALITY; v3 <= NONE; ++v3)
                    {
                        assert(hf.size() == 4);
                        assert(value.size() == 3);
                        hf[3] = static_cast<hash_t>(v3);
                        value[2].pack() << nums[3];
                        validate(hf, key, value);
                        hf.push_back(NONE);
                        value.push_back(e::buffer());

                        for (size_t v4 = EQUALITY; v4 <= NONE; ++v4)
                        {
                            assert(hf.size() == 5);
                            assert(value.size() == 4);
                            hf[4] = static_cast<hash_t>(v4);
                            value[3].pack() << nums[4];
                            validate(hf, key, value);
                        }

                        value.pop_back();
                        hf.pop_back();
                    }

                    value.pop_back();
                    hf.pop_back();
                }

                value.pop_back();
                hf.pop_back();
            }
        }
    }

    return EXIT_SUCCESS;
}

void
validate(const std::vector<hash_t> hf, const e::buffer& key, const std::vector<e::buffer>& value)
{
    prefix::hasher ph(hf);
    prefix::coordinate pc = ph.hash(key, value);
    //mask::hasher mh(hf);
    //mask::coordinate mc = mh.hash(key, value);

    // Do an equality search for each attribute
    for (size_t i = 0; i < value.size() + 1; ++i)
    {
        search s(value.size() + 1);

        if (i == 0)
        {
            s.equality_set(0, key);
        }
        else
        {
            s.equality_set(i, value[i - 1]);
        }

        prefix::search_coordinate psc = ph.hash(s);
        //mask::search_coordinate msc = mh.hash(s);
        assert(psc.matches(pc));
        //assert(msc.matches(mc));
        //assert(msc.matches(key, value));
    }

    // Do a range search for each attribute
    for (size_t i = 0; i < value.size() + 1; ++i)
    {
        search s(value.size() + 1);

        if (i == 0)
        {
            uint64_t num = lendian(key);
            s.range_set(0, num, num + 1);
        }
        else
        {
            uint64_t num = lendian(value[i - 1]);
            s.range_set(i, num, num + 1);
        }

        prefix::search_coordinate psc = ph.hash(s);
        //mask::search_coordinate msc = mh.hash(s);
        assert(psc.matches(pc));
        //assert(msc.matches(mc));
        //assert(msc.matches(key, value));
    }

    // Do an equality/range search for two attributes
    for (size_t i = 0; i < value.size() + 1; ++i)
    {
        for (size_t j = 0; j < value.size() + 1; ++j)
        {
            if (i == j)
            {
                continue;
            }

            search s(value.size() + 1);

            if (i == 0)
            {
                s.equality_set(0, key);
            }
            else
            {
                s.equality_set(i, value[i - 1]);
            }

            if (j == 0)
            {
                uint64_t num = lendian(key);
                s.range_set(0, num, num + 1);
            }
            else
            {
                uint64_t num = lendian(value[j - 1]);
                s.range_set(j, num, num + 1);
            }

            prefix::search_coordinate psc = ph.hash(s);
            //mask::search_coordinate msc = mh.hash(s);
            assert(psc.matches(pc));
            //assert(msc.matches(mc));
            //assert(msc.matches(key, value));
        }
    }
}
<commit_msg>Use the appropriate loop counter to index.<commit_after>// Copyright (c) 2011, Cornell University
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
//     * Redistributions of source code must retain the above copyright notice,
//       this list of conditions and the following disclaimer.
//     * Redistributions in binary form must reproduce the above copyright
//       notice, this list of conditions and the following disclaimer in the
//       documentation and/or other materials provided with the distribution.
//     * Neither the name of HyperDex nor the names of its contributors may be
//       used to endorse or promote products derived from this software without
//       specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.

#define __STDC_LIMIT_MACROS

// C
#include <cassert>
#include <cstdlib>
#include <ctime>

// HyperspaceHashing
#include "hashes_internal.h"
#include "hyperspacehashing/hashes.h"
#include "hyperspacehashing/mask.h"
#include "hyperspacehashing/prefix.h"
#include "hyperspacehashing/search.h"

using hyperspacehashing::hash_t;
using hyperspacehashing::EQUALITY;
using hyperspacehashing::NONE;
using namespace hyperspacehashing;

void
validate(const std::vector<hash_t> hf, const e::buffer& key, const std::vector<e::buffer>& value);

int
main(int, char* [])
{
    srand(time(NULL));

    for (size_t i = 0; i < 100; ++i)
    {
        uint32_t nums[5];

        for (int j = 0; j < 5; ++j)
        {
            nums[j] = static_cast<uint32_t>(rand());
        }

        for (size_t k = EQUALITY; k <= NONE; ++k)
        {
            std::vector<hash_t> hf(1);
            hf[0] = static_cast<hash_t>(k);

            std::vector<e::buffer> value;
            e::buffer key;
            key.pack() << nums[0];
            validate(hf, key, value);
            hf.push_back(NONE);
            value.push_back(e::buffer());

            for (size_t v1 = EQUALITY; v1 <= NONE; ++v1)
            {
                assert(hf.size() == 2);
                assert(value.size() == 1);
                hf[1] = static_cast<hash_t>(v1);
                value[0].pack() << nums[1];
                validate(hf, key, value);
                hf.push_back(NONE);
                value.push_back(e::buffer());

                for (size_t v2 = EQUALITY; v2 <= NONE; ++v2)
                {
                    assert(hf.size() == 3);
                    assert(value.size() == 2);
                    hf[2] = static_cast<hash_t>(v2);
                    value[1].pack() << nums[2];
                    validate(hf, key, value);
                    hf.push_back(NONE);
                    value.push_back(e::buffer());

                    for (size_t v3 = EQUALITY; v3 <= NONE; ++v3)
                    {
                        assert(hf.size() == 4);
                        assert(value.size() == 3);
                        hf[3] = static_cast<hash_t>(v3);
                        value[2].pack() << nums[3];
                        validate(hf, key, value);
                        hf.push_back(NONE);
                        value.push_back(e::buffer());

                        for (size_t v4 = EQUALITY; v4 <= NONE; ++v4)
                        {
                            assert(hf.size() == 5);
                            assert(value.size() == 4);
                            hf[4] = static_cast<hash_t>(v4);
                            value[3].pack() << nums[4];
                            validate(hf, key, value);
                        }

                        value.pop_back();
                        hf.pop_back();
                    }

                    value.pop_back();
                    hf.pop_back();
                }

                value.pop_back();
                hf.pop_back();
            }
        }
    }

    return EXIT_SUCCESS;
}

void
validate(const std::vector<hash_t> hf, const e::buffer& key, const std::vector<e::buffer>& value)
{
    prefix::hasher ph(hf);
    prefix::coordinate pc = ph.hash(key, value);
    //mask::hasher mh(hf);
    //mask::coordinate mc = mh.hash(key, value);

    // Do an equality search for each attribute
    for (size_t i = 0; i < value.size() + 1; ++i)
    {
        search s(value.size() + 1);

        if (i == 0)
        {
            s.equality_set(0, key);
        }
        else
        {
            s.equality_set(i, value[i - 1]);
        }

        prefix::search_coordinate psc = ph.hash(s);
        //mask::search_coordinate msc = mh.hash(s);
        assert(psc.matches(pc));
        //assert(msc.matches(mc));
        //assert(msc.matches(key, value));
    }

    // Do a range search for each attribute
    for (size_t i = 0; i < value.size() + 1; ++i)
    {
        search s(value.size() + 1);

        if (i == 0)
        {
            uint64_t num = lendian(key);
            s.range_set(0, num, num + 1);
        }
        else
        {
            uint64_t num = lendian(value[i - 1]);
            s.range_set(i, num, num + 1);
        }

        prefix::search_coordinate psc = ph.hash(s);
        //mask::search_coordinate msc = mh.hash(s);
        assert(psc.matches(pc));
        //assert(msc.matches(mc));
        //assert(msc.matches(key, value));
    }

    // Do an equality/range search for two attributes
    for (size_t i = 0; i < value.size() + 1; ++i)
    {
        for (size_t j = 0; j < value.size() + 1; ++j)
        {
            if (i == j)
            {
                continue;
            }

            search s(value.size() + 1);

            if (i == 0)
            {
                s.equality_set(0, key);
            }
            else
            {
                s.equality_set(i, value[i - 1]);
            }

            if (j == 0)
            {
                uint64_t num = lendian(key);
                s.range_set(0, num, num + 1);
            }
            else
            {
                uint64_t num = lendian(value[j - 1]);
                s.range_set(j, num, num + 1);
            }

            prefix::search_coordinate psc = ph.hash(s);
            //mask::search_coordinate msc = mh.hash(s);
            assert(psc.matches(pc));
            //assert(msc.matches(mc));
            //assert(msc.matches(key, value));
        }
    }
}
<|endoftext|>


<commit_before>#include <tiramisu/tiramisu.h>
#include <vector>
#include "configure.h"

using namespace tiramisu;

int main()
{
    init("densenet_block");

    // -------------------------------------------------------
    // Layer I
    // -------------------------------------------------------
    var x("x", 0, N), y("y", 0, N), z("z", 0, 4*GR), n("n", 0, BATCH_SIZE);
    var _y("_y", 0, N - 1);

    var x_pad("x", 0, N + 2), y_pad("y", 0, N + 2);
    var k_x("k_x", 0, K_X), k_y("k_y", 0, K_Y), fout("fout", 0, GR);

    var z_b("z_b", 0, Z_NB_BLOCKS), zz("zz", 0, Z_BLOCKING);
    var fout_b("fout_b", 0, FOUT_NB_BLOCKS), ffout("ffout", 0, FOUT_BLOCKING);

    input c_input("c_input", {n, z_b, y, x, zz}, p_float32);
    input bn_scale("bn_scale", {z_b, zz}, p_float32);
    input bn_shift("bn_shift", {z_b, zz}, p_float32);

    input conv_filter("conv_filter", {z_b, fout_b, k_y, k_x, ffout, zz}, p_float32);
    input conv_bias("conv_bias", {fout_b, ffout}, p_float32);

    // Batch normalization followed by ReLU
    // Compute the sum over the features dimension (z)
    computation input_sum_init("input_sum_init", {z_b, zz}, cast(p_float32, 0));
    computation input_sum(
        "input_sum",
        {n, z_b, y, x, zz},
        input_sum_init(z_b, zz) + c_input(n, z_b, y, x, zz)
    );

    // Compute the sum of squares over the features dimension (z)
    computation input_sum_squares_init("input_sum_squares_init", {z_b, zz}, cast(p_float32, 0));
    computation input_sum_squares(
        "input_sum_squares",
        {n, z_b, y, x, zz},
        input_sum_squares_init(z_b, zz) + c_input(n, z_b, y, x, zz) * c_input(n, z_b, y, x, zz)
    );

    computation input_mean(
        "input_mean",
        {z_b, zz},
        input_sum(BATCH_SIZE - 1, z_b, N - 1, N - 1, zz) / cast(p_float32, BATCH_SIZE*N*N)
    );

    computation input_sd(
        "input_sd",
        {z_b, zz},
        expr(
            o_sqrt,
            input_sum_squares(BATCH_SIZE - 1, z_b, N - 1, N - 1, zz) / cast(p_float32, BATCH_SIZE*N*N) - input_mean(z_b, zz) * input_mean(z_b, zz) + cast(p_float32, EPSILON)
        )
    );

    // Compute BN followed by ReLU
    std::vector<var> bn_relu_iter_vars = {n, z_b, y, x, zz};
    if (SCHEDULE_FUSION)
        bn_relu_iter_vars = {n, z_b, _y, x, zz};

    computation init_workspace("init_workspace", {n, z_b, y_pad, x_pad, zz}, cast(p_float32, 0));
    computation bn("bn", bn_relu_iter_vars, expr(p_float32));
    computation relu("relu", bn_relu_iter_vars, expr(p_float32));

    // These two computations are not scheduled when fusion is disabled
    computation bn_prelude("bn_prelude", {n, z_b, x, zz}, expr(p_float32), SCHEDULE_FUSION);
    computation relu_prelude("relu_prelude", {n, z_b, x, zz}, expr(p_float32), SCHEDULE_FUSION);

    if (!SCHEDULE_FUSION) {
        bn.set_expression(bn_scale(z_b, zz) * ((c_input(n, z_b, y, x, zz) - input_mean(z_b, zz)) / input_sd(z_b, zz)) + bn_shift(z_b, zz));
        relu.set_expression(
            expr(
                o_max,
                cast(p_float32, 0), bn(n, z_b, y, x, zz)
            )
        );
    }

    else {
        bn_prelude.set_expression(bn_scale(z_b, zz) * ((c_input(n, z_b, 0, x, zz) - input_mean(z_b, zz)) / input_sd(z_b, zz)) + bn_shift(z_b, zz));
        relu_prelude.set_expression(
            expr(
                o_max,
                cast(p_float32, 0), bn_prelude(n, z_b, x, zz)
            )
        );

        bn.set_expression(bn_scale(z_b, zz) * ((c_input(n, z_b, _y + 1, x, zz) - input_mean(z_b, zz)) / input_sd(z_b, zz)) + bn_shift(z_b, zz));
        relu.set_expression(
            expr(
                o_max,
                cast(p_float32, 0), bn(n, z_b, _y, x, zz)
            )
        );
    }

    view relu_padded("relu_padded", {n, z_b, y_pad, x_pad, zz}, p_float32);

    // Convolution computation
    std::vector<var> conv_iter_vars = {n, z_b, fout_b, y, x, k_y, k_x, ffout, zz};
    if (SCHEDULE_FUSION)
        conv_iter_vars = {n, z_b, fout_b, _y, x, k_y, k_x, ffout, zz};

    computation init_output("init_output", {n, fout_b, y, x, ffout}, conv_bias(fout_b, ffout));
    computation conv("conv", conv_iter_vars, expr(p_float32));

    // This operation is not scheduled when fusion is disabled
    computation conv_conclude(
        "conv_conclude",
        {n, z_b, fout_b, x, k_y, k_x, ffout, zz},
        expr(p_float32),
        SCHEDULE_FUSION
    );

    if (!SCHEDULE_FUSION)
        conv.set_expression(init_output(n, fout_b, y, x, ffout) + relu_padded(n, z_b, y + k_y, x + k_x, zz)*conv_filter(z_b, fout_b, k_y, k_x, ffout, zz));

    else {
        conv.set_expression(init_output(n, fout_b, _y, x, ffout) + relu_padded(n, z_b, _y + k_y, x + k_x, zz)*conv_filter(z_b, fout_b, k_y, k_x, ffout, zz));
        conv_conclude.set_expression(init_output(n, fout_b, N - 1, x, ffout) + relu_padded(n, z_b, N + k_y - 1, x + k_x, zz)*conv_filter(z_b, fout_b, k_y, k_x, ffout, zz));
    }

    // -------------------------------------------------------
    // Layer II
    // -------------------------------------------------------
    if (!SCHEDULE_FUSION) {
        init_output.then(input_sum_init, computation::root)
                   .then(input_sum_squares_init, zz)
                   .then(input_sum, computation::root)
                   .then(input_sum_squares, zz)
                   .then(input_mean, computation::root)
                   .then(input_sd, zz)
                   .then(init_workspace, computation::root)
                   .then(bn, z_b)
                   .then(relu, zz)
                   .then(conv, computation::root);

        input_sum.vectorize(zz, Z_BLOCKING);

        bn.tag_parallel_level(n);
        bn.vectorize(zz, Z_BLOCKING);

        //n, z_b, fout_b, y, x, k_y, k_x, ffout, z_b
        conv.interchange(x, k_y);
        conv.interchange(x, k_x);

        if (BLOCK_NUMBER >= 1) {
            conv.interchange(y, k_y);
            conv.interchange(y, k_x);
        }

        conv.tag_parallel_level(n);
        conv.vectorize(ffout, FOUT_BLOCKING);
    }

    else {
        conv.interchange(fout_b, _y);
        conv_conclude.interchange(fout_b, x);

        init_output.then(input_sum_init, computation::root)
                   .then(input_sum_squares_init, zz)
                   .then(input_sum, computation::root)
                   .then(input_sum_squares, zz)
                   .then(input_mean, computation::root)
                   .then(input_sd, zz)
                   .then(init_workspace, computation::root)
                   .then(bn_prelude, z_b)
                   .then(relu_prelude, z_b)
                   .then(bn, z_b)
                   .then(relu, zz)
                   .then(conv, _y)
                   .then(conv_conclude, z_b);

        input_sum.vectorize(zz, Z_BLOCKING);
        bn_prelude.vectorize(zz, Z_BLOCKING);
        bn.vectorize(zz, Z_BLOCKING);

        //n, z_b, y, fout_b, x, k_y, k_x, ffout, zz
        conv.interchange(x, k_y);
        conv.interchange(x, k_x);

        conv_conclude.interchange(x, k_y);
        conv_conclude.interchange(x, k_x);
        //n, z_b, y, fout_b, k_y, k_x, x, ffout, zz

        conv.tag_parallel_level(n);
        conv.vectorize(ffout, FOUT_BLOCKING);
        conv_conclude.vectorize(ffout, FOUT_BLOCKING);
    }

    // -------------------------------------------------------
    // Layer III
    // -------------------------------------------------------
    buffer output_buf("output_buf", {BATCH_SIZE, FOUT_NB_BLOCKS, N, N, FOUT_BLOCKING}, p_float32, a_output);

    buffer input_mean_buf("input_mean_buf", {Z_NB_BLOCKS, Z_BLOCKING}, p_float32, a_temporary);
    buffer input_sd_buf("input_sd_buf", {Z_NB_BLOCKS, Z_BLOCKING}, p_float32, a_temporary);

    // We use this buffer as a temporary buffer to store BN and ReLU results
    // This buffer is padded (its width and height are C_N + 2) so as to prepare it for convolution
    std::vector<expr> workspace_dim_sizes = {BATCH_SIZE, Z_NB_BLOCKS, N + 2, N + 2, Z_BLOCKING};

    // When fusion is enabled, we don't need the second dimension of workspace_buf.
    // This is because we consume all computed values of this buffer before moving
    // on to the next z_block.
    if (SCHEDULE_FUSION)
        workspace_dim_sizes = {BATCH_SIZE, N + 2, N + 2, Z_BLOCKING};

    buffer workspace_buf(
        "workspace_buf",
        workspace_dim_sizes,
        p_float32,
        a_temporary
    );

    if (!SCHEDULE_FUSION)
        init_workspace.store_in(&workspace_buf);
    else
        init_workspace.store_in(&workspace_buf, {n, y_pad, x_pad, zz});

    input_sum_init.store_in(&input_mean_buf);
    input_sum.store_in(&input_mean_buf, {z_b, zz});
    input_mean.store_in(&input_mean_buf);

    input_sum_squares_init.store_in(&input_sd_buf);
    input_sum_squares.store_in(&input_sd_buf, {z_b, zz});
    input_sd.store_in(&input_sd_buf);

    if (!SCHEDULE_FUSION) {
        // We shift the BN and ReLU computations, so as to avoid to
        // compute on the padding region of workspace_buf.
        bn.store_in(&workspace_buf, {n, z_b, y + 1, x + 1, zz});
        relu.store_in(&workspace_buf, {n, z_b, y + 1, x + 1, zz});
        relu_padded.store_in(&workspace_buf);

        init_output.store_in(&output_buf);
        conv.store_in(&output_buf, {n, fout_b, y, x, ffout});
    }

    else {
        // We shift the BN and ReLU computations, so as to avoid to
        // compute on the padding region of workspace_buf.
        bn_prelude.store_in(&workspace_buf, {n, 1, x + 1, zz});
        relu_prelude.store_in(&workspace_buf, {n, 1, x + 1, zz});

        bn.store_in(&workspace_buf, {n, _y + 2, x + 1, zz});
        relu.store_in(&workspace_buf, {n, _y + 2, x + 1, zz});

        relu_padded.store_in(&workspace_buf, {n, y_pad, x_pad, zz});

        init_output.store_in(&output_buf);
        conv.store_in(&output_buf, {n, fout_b, _y, x, ffout});
        conv_conclude.store_in(&output_buf, {n, fout_b, N - 1, x, ffout});
    }

    // -------------------------------------------------------
    // Code Generation
    // -------------------------------------------------------
    codegen({
        c_input.get_buffer(),
        bn_scale.get_buffer(),
        bn_shift.get_buffer(),
        conv_filter.get_buffer(),
        conv_bias.get_buffer(),
        &output_buf
    }, "densenet_block_tiramisu.o");

    return 0;
}
<commit_msg>DenseNet block : Fuse BN-ReLU with CONV<commit_after>#include <tiramisu/tiramisu.h>
#include <vector>
#include "configure.h"

using namespace tiramisu;

int main()
{
    init("densenet_block");

    // -------------------------------------------------------
    // Layer I
    // -------------------------------------------------------
    var x("x", 0, N), y("y", 0, N), z("z", 0, 4*GR), n("n", 0, BATCH_SIZE);
    var _y("_y", 0, N - 1);

    var x_pad("x", 0, N + 2), y_pad("y", 0, N + 2);
    var k_x("k_x", 0, K_X), k_y("k_y", 0, K_Y), fout("fout", 0, GR);

    var z_b("z_b", 0, Z_NB_BLOCKS), zz("zz", 0, Z_BLOCKING);
    var fout_b("fout_b", 0, FOUT_NB_BLOCKS), ffout("ffout", 0, FOUT_BLOCKING);

    input c_input("c_input", {n, z_b, y, x, zz}, p_float32);
    input bn_scale("bn_scale", {z_b, zz}, p_float32);
    input bn_shift("bn_shift", {z_b, zz}, p_float32);

    input conv_filter("conv_filter", {z_b, fout_b, k_y, k_x, ffout, zz}, p_float32);
    input conv_bias("conv_bias", {fout_b, ffout}, p_float32);

    // Batch normalization followed by ReLU
    // Compute the sum over the features dimension (z)
    computation input_sum_init("input_sum_init", {z_b, zz}, cast(p_float32, 0));
    computation input_sum(
        "input_sum",
        {n, z_b, y, x, zz},
        input_sum_init(z_b, zz) + c_input(n, z_b, y, x, zz)
    );

    // Compute the sum of squares over the features dimension (z)
    computation input_sum_squares_init("input_sum_squares_init", {z_b, zz}, cast(p_float32, 0));
    computation input_sum_squares(
        "input_sum_squares",
        {n, z_b, y, x, zz},
        input_sum_squares_init(z_b, zz) + c_input(n, z_b, y, x, zz) * c_input(n, z_b, y, x, zz)
    );

    computation input_mean(
        "input_mean",
        {z_b, zz},
        input_sum(BATCH_SIZE - 1, z_b, N - 1, N - 1, zz) / cast(p_float32, BATCH_SIZE*N*N)
    );

    computation input_sd(
        "input_sd",
        {z_b, zz},
        expr(
            o_sqrt,
            input_sum_squares(BATCH_SIZE - 1, z_b, N - 1, N - 1, zz) / cast(p_float32, BATCH_SIZE*N*N) - input_mean(z_b, zz) * input_mean(z_b, zz) + cast(p_float32, EPSILON)
        )
    );

    // Compute BN followed by ReLU
    std::vector<var> bn_relu_iter_vars = {n, z_b, y, x, zz};
    if (SCHEDULE_FUSION)
        bn_relu_iter_vars = {n, z_b, _y, x, zz};

    computation init_workspace("init_workspace", {n, z_b, y_pad, x_pad, zz}, cast(p_float32, 0));
    computation bn("bn", bn_relu_iter_vars, expr(p_float32));
    computation relu("relu", bn_relu_iter_vars, expr(p_float32));

    // These two computations are not scheduled when fusion is disabled
    computation bn_prelude("bn_prelude", {n, z_b, x, zz}, expr(p_float32), SCHEDULE_FUSION);
    computation relu_prelude("relu_prelude", {n, z_b, x, zz}, expr(p_float32), SCHEDULE_FUSION);

    if (!SCHEDULE_FUSION) {
        bn.set_expression(bn_scale(z_b, zz) * ((c_input(n, z_b, y, x, zz) - input_mean(z_b, zz)) / input_sd(z_b, zz)) + bn_shift(z_b, zz));
        relu.set_expression(
            expr(
                o_max,
                cast(p_float32, 0), bn(n, z_b, y, x, zz)
            )
        );
    }

    else {
        bn_prelude.set_expression(bn_scale(z_b, zz) * ((c_input(n, z_b, 0, x, zz) - input_mean(z_b, zz)) / input_sd(z_b, zz)) + bn_shift(z_b, zz));
        relu_prelude.set_expression(
            expr(
                o_max,
                cast(p_float32, 0), bn_prelude(n, z_b, x, zz)
            )
        );

        bn.set_expression(bn_scale(z_b, zz) * ((c_input(n, z_b, _y + 1, x, zz) - input_mean(z_b, zz)) / input_sd(z_b, zz)) + bn_shift(z_b, zz));
        relu.set_expression(
            expr(
                o_max,
                cast(p_float32, 0), bn(n, z_b, _y, x, zz)
            )
        );
    }

    view relu_padded("relu_padded", {n, z_b, y_pad, x_pad, zz}, p_float32);

    // Convolution computation
    std::vector<var> conv_iter_vars = {n, z_b, fout_b, y, x, k_y, k_x, ffout, zz};
    if (SCHEDULE_FUSION)
        conv_iter_vars = {n, z_b, fout_b, _y, x, k_y, k_x, ffout, zz};

    computation init_output("init_output", {n, fout_b, y, x, ffout}, conv_bias(fout_b, ffout));
    computation conv("conv", conv_iter_vars, expr(p_float32));

    // This operation is not scheduled when fusion is disabled
    computation conv_conclude(
        "conv_conclude",
        {n, z_b, fout_b, x, k_y, k_x, ffout, zz},
        expr(p_float32),
        SCHEDULE_FUSION
    );

    if (!SCHEDULE_FUSION)
        conv.set_expression(init_output(n, fout_b, y, x, ffout) + relu_padded(n, z_b, y + k_y, x + k_x, zz)*conv_filter(z_b, fout_b, k_y, k_x, ffout, zz));

    else {
        conv.set_expression(init_output(n, fout_b, _y, x, ffout) + relu_padded(n, z_b, _y + k_y, x + k_x, zz)*conv_filter(z_b, fout_b, k_y, k_x, ffout, zz));
        conv_conclude.set_expression(init_output(n, fout_b, N - 1, x, ffout) + relu_padded(n, z_b, N + k_y - 1, x + k_x, zz)*conv_filter(z_b, fout_b, k_y, k_x, ffout, zz));
    }

    // -------------------------------------------------------
    // Layer II
    // -------------------------------------------------------
    if (!SCHEDULE_FUSION) {
        init_output.then(input_sum_init, computation::root)
                   .then(input_sum_squares_init, zz)
                   .then(input_sum, computation::root)
                   .then(input_sum_squares, zz)
                   .then(input_mean, computation::root)
                   .then(input_sd, zz)
                   .then(init_workspace, computation::root)
                   .then(bn, z_b)
                   .then(relu, zz)
                   .then(conv, computation::root);

        input_sum.vectorize(zz, Z_BLOCKING);

        bn.tag_parallel_level(n);
        bn.vectorize(zz, Z_BLOCKING);

        //n, z_b, fout_b, y, x, k_y, k_x, ffout, z_b
        conv.interchange(x, k_y);
        conv.interchange(x, k_x);
        //n, z_b, fout_b, y, k_y, k_x, x, ffout, z_b

        if (BLOCK_NUMBER >= 1) {
            //n, z_b, fout_b, y, k_y, k_x, x, ffout, z_b
            conv.interchange(y, k_y);
            conv.interchange(y, k_x);
            //n, z_b, fout_b, k_y, k_x, y, x, ffout, z_b
        }

        conv.tag_parallel_level(n);
        conv.vectorize(ffout, FOUT_BLOCKING);
    }

    else {
        conv.interchange(fout_b, _y);
        conv_conclude.interchange(fout_b, x);

        init_output.then(input_sum_init, computation::root)
                   .then(input_sum_squares_init, zz)
                   .then(input_sum, computation::root)
                   .then(input_sum_squares, zz)
                   .then(input_mean, computation::root)
                   .then(input_sd, zz)
                   .then(init_workspace, computation::root)
                   .then(bn_prelude, z_b)
                   .then(relu_prelude, z_b)
                   .then(bn, z_b)
                   .then(relu, zz)
                   .then(conv, _y)
                   .then(conv_conclude, z_b);

        input_sum.vectorize(zz, Z_BLOCKING);
        bn_prelude.vectorize(zz, Z_BLOCKING);
        bn.vectorize(zz, Z_BLOCKING);

        //n, z_b, y, fout_b, x, k_y, k_x, ffout, zz
        conv.interchange(x, k_y);
        conv.interchange(x, k_x);

        conv_conclude.interchange(x, k_y);
        conv_conclude.interchange(x, k_x);
        //n, z_b, y, fout_b, k_y, k_x, x, ffout, zz

        conv.tag_parallel_level(n);
        conv.vectorize(ffout, FOUT_BLOCKING);
        conv_conclude.vectorize(ffout, FOUT_BLOCKING);
    }

    // -------------------------------------------------------
    // Layer III
    // -------------------------------------------------------
    buffer output_buf("output_buf", {BATCH_SIZE, FOUT_NB_BLOCKS, N, N, FOUT_BLOCKING}, p_float32, a_output);

    buffer input_mean_buf("input_mean_buf", {Z_NB_BLOCKS, Z_BLOCKING}, p_float32, a_temporary);
    buffer input_sd_buf("input_sd_buf", {Z_NB_BLOCKS, Z_BLOCKING}, p_float32, a_temporary);

    // We use this buffer as a temporary buffer to store BN and ReLU results
    // This buffer is padded (its width and height are C_N + 2) so as to prepare it for convolution
    std::vector<expr> workspace_dim_sizes = {BATCH_SIZE, Z_NB_BLOCKS, N + 2, N + 2, Z_BLOCKING};

    // When fusion is enabled, we don't need the second dimension of workspace_buf.
    // This is because we consume all computed values of this buffer before moving
    // on to the next z_block.
    if (SCHEDULE_FUSION)
        workspace_dim_sizes = {BATCH_SIZE, N + 2, N + 2, Z_BLOCKING};

    buffer workspace_buf(
        "workspace_buf",
        workspace_dim_sizes,
        p_float32,
        a_temporary
    );

    if (!SCHEDULE_FUSION)
        init_workspace.store_in(&workspace_buf);
    else
        init_workspace.store_in(&workspace_buf, {n, y_pad, x_pad, zz});

    input_sum_init.store_in(&input_mean_buf);
    input_sum.store_in(&input_mean_buf, {z_b, zz});
    input_mean.store_in(&input_mean_buf);

    input_sum_squares_init.store_in(&input_sd_buf);
    input_sum_squares.store_in(&input_sd_buf, {z_b, zz});
    input_sd.store_in(&input_sd_buf);

    if (!SCHEDULE_FUSION) {
        // We shift the BN and ReLU computations, so as to avoid to
        // compute on the padding region of workspace_buf.
        bn.store_in(&workspace_buf, {n, z_b, y + 1, x + 1, zz});
        relu.store_in(&workspace_buf, {n, z_b, y + 1, x + 1, zz});
        relu_padded.store_in(&workspace_buf);

        init_output.store_in(&output_buf);
        conv.store_in(&output_buf, {n, fout_b, y, x, ffout});
    }

    else {
        // We shift the BN and ReLU computations, so as to avoid to
        // compute on the padding region of workspace_buf.
        bn_prelude.store_in(&workspace_buf, {n, 1, x + 1, zz});
        relu_prelude.store_in(&workspace_buf, {n, 1, x + 1, zz});

        bn.store_in(&workspace_buf, {n, _y + 2, x + 1, zz});
        relu.store_in(&workspace_buf, {n, _y + 2, x + 1, zz});

        relu_padded.store_in(&workspace_buf, {n, y_pad, x_pad, zz});

        init_output.store_in(&output_buf);
        conv.store_in(&output_buf, {n, fout_b, _y, x, ffout});
        conv_conclude.store_in(&output_buf, {n, fout_b, N - 1, x, ffout});
    }

    // -------------------------------------------------------
    // Code Generation
    // -------------------------------------------------------
    codegen({
        c_input.get_buffer(),
        bn_scale.get_buffer(),
        bn_shift.get_buffer(),
        conv_filter.get_buffer(),
        conv_bias.get_buffer(),
        &output_buf
    }, "densenet_block_tiramisu.o");

    return 0;
}
<|endoftext|>


<commit_before>/*
   Copyright (C) 2013 Samsung Electronics

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

   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
   Library General Public License for more details.

   You should have received a copy of the GNU Library General Public License
   along with this library; see the file COPYING.LIB.  If not, write to
   the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
   Boston, MA 02110-1301, USA.
*/

#include "eweb_view.h"
#include "selection_controller_efl.h"
#include "selection_handle_efl.h"
#include "selection_box_efl.h"
#include "selection_magnifier_efl.h"

namespace content {

static bool IsRectEmpty(const gfx::Rect& rect) {
  if (rect.x() == 0 && rect.y() == 0 && rect.height() == 0 && rect.width() == 0) {
    LOG(INFO) << "SelectionControllerEfl:IsRectEmpty : true";
    return true;
  }
  return false;
}

SelectionControllerEfl::SelectionControllerEfl(EWebView* parent_view)
    :  parent_view_(parent_view),
       mouse_press_(false),
       long_mouse_press_(false),
       scrolling_(false),
       selection_data_(new SelectionBoxEfl(parent_view)),
       start_handle_(new SelectionHandleEfl(this, SelectionHandleEfl::HANDLE_TYPE_LEFT, parent_view->evas_object())),
       end_handle_(new SelectionHandleEfl(this, SelectionHandleEfl::HANDLE_TYPE_RIGHT, parent_view->evas_object())),
       input_handle_(new SelectionHandleEfl(this, SelectionHandleEfl::HANDLE_TYPE_INPUT, parent_view->evas_object())),
       magnifier_(new SelectionMagnifierEfl(this)) {
  evas_object_event_callback_add(parent_view_->evas_object(), EVAS_CALLBACK_MOVE, &EvasParentViewMoveCallback, this);
}

void SelectionControllerEfl::SetSelectionStatus(bool enable) {
  LOG(INFO) << "SelectionControllerEfl::SetSelectionStatus " << enable;
  selection_data_->SetStatus(enable);
}

bool SelectionControllerEfl::GetSelectionStatus() const {
  LOG(INFO) << "SelectionControllerEfl::GetSelectionStatus " << selection_data_->GetStatus();
  return selection_data_->GetStatus();
}

void SelectionControllerEfl::SetSelectionEditable(bool enable) {
  LOG(INFO) << "SelectionControllerEfl::SetSelectionEditable" << enable;
  selection_data_->SetEditable(enable);
}

bool SelectionControllerEfl::GetSelectionEditable() const {
  LOG(INFO) << "SelectionControllerEfl::GetSelectionEditable " << selection_data_->GetEditable();
  return selection_data_->GetEditable();
}

void SelectionControllerEfl::SetCaretSelectionStatus(const bool enable) {
  LOG(INFO) << "SelectionControllerEfl::SetCaretSelectionStatus : " << enable;
  selection_data_->SetCaretSelectionStatus(enable);
}

bool SelectionControllerEfl::GetCaretSelectionStatus() const {
  LOG(INFO) << "SelectionControllerEfl::GetCaretSelectionStatus : " << selection_data_->GetCaretSelectionStatus();
  return selection_data_->GetCaretSelectionStatus();
}

void SelectionControllerEfl::SetScrollStatus(const bool enable) {
  LOG(INFO) << __PRETTY_FUNCTION__ << " enable : " << enable;
  scrolling_ = enable;
  if (enable)
    Clear();
  else
    ShowHandleAndContextMenuIfRequired();
}

bool SelectionControllerEfl::GetScrollStatus() {
  LOG(INFO) << __PRETTY_FUNCTION__ << " " << scrolling_;
  return scrolling_;
}

void SelectionControllerEfl::UpdateSelectionData(const base::string16& text) {
  selection_data_->UpdateSelectStringData(text);
}

void SelectionControllerEfl::UpdateMagnifierScreen(Evas_Object* img) {
  magnifier_->UpdateScreen(img);
}

void SelectionControllerEfl::UpdateSelectionDataAndShow(const gfx::Rect& left_rect, const gfx::Rect& right_rect, bool is_anchor_first) {
  LOG(INFO) << __PRETTY_FUNCTION__;
  selection_data_->UpdateRectData(left_rect, right_rect, is_anchor_first);

  if (!IsSelectionValid(left_rect, right_rect)) {
    Clear();
    return;
  }

  // Do not show the context menu and handlers untill long mouse press is released
  if (long_mouse_press_)
    return;

  // Do not show the context menu and handlers while page is scrolling
  if (scrolling_)
    return;

  ShowHandleAndContextMenuIfRequired();
}

void SelectionControllerEfl::ShowHandleAndContextMenuIfRequired() {
  LOG(INFO) << __PRETTY_FUNCTION__;
  if (!selection_data_->GetStatus())
    return;

  Clear();

  // Is in edit field and no text is selected. show only single handle
  if (selection_data_->IsInEditField() && GetCaretSelectionStatus()) {
    gfx::Rect left = selection_data_->GetLeftRect();
    input_handle_->SetBasePosition(gfx::Point(left.x(), left.y()));
    input_handle_->SetCursorHandlerStatus(true);
    input_handle_->Move(gfx::Point(left.x(), left.y() + left.height()));
    input_handle_->Show();

    return;
  }

  // FIXME : Check the text Direction later
  gfx::Rect left = selection_data_->GetLeftRect();
  start_handle_->SetBasePosition(gfx::Point(left.x(), left.y()));
  start_handle_->Move(gfx::Point(left.x(), left.y() + left.height()));
  start_handle_->Show();

  gfx::Rect right = selection_data_->GetRightRect();

  end_handle_->SetBasePosition(gfx::Point(right.x(), right.y()));
  end_handle_->Move(gfx::Point(right.x() + right.width(), right.y() + right.height()));
  end_handle_->Show();

  // Do not show the context menu during selection extend
  if (!mouse_press_)
    parent_view_->ShowContextMenu(*(selection_data_->GetContextMenuParams()), MENU_TYPE_SELECTION);
  parent_view_->QuerySelectionStyle();
}

void SelectionControllerEfl::HideHandle() {
  SetCaretSelectionStatus(false);
  Clear();
}

void SelectionControllerEfl::HideHandleAndContextMenu() {
  parent_view_->CancelContextMenu(0);
  HideHandle();
}

void SelectionControllerEfl::Clear() {
  start_handle_->Hide();
  end_handle_->Hide();
  input_handle_->Hide();
}

void SelectionControllerEfl::OnMouseDown(const gfx::Point& touch_point) {
  // Hide context menu on mouse down
  parent_view_->CancelContextMenu(0);
  mouse_press_ = true;
  magnifier_->UpdateLocation(touch_point);
  magnifier_->Move(touch_point);
  magnifier_->Show();
}

void SelectionControllerEfl::OnMouseMove(const gfx::Point& touch_point, bool on_curson_handle) {
  // FIXME : Check the text Direction later
  magnifier_->UpdateLocation(touch_point);
  magnifier_->Move(touch_point);
  if (!on_curson_handle)
    parent_view_->SelectRange(start_handle_->GetBasePosition(), end_handle_->GetBasePosition());
  else
    parent_view_->MoveCaret(input_handle_->GetBasePosition());
}

void SelectionControllerEfl::OnMouseUp(const gfx::Point& touch_point) {
  selection_data_->UpdateHandleData();
  mouse_press_ = false;
  magnifier_->Hide();
  parent_view_->ShowContextMenu(*(selection_data_->GetContextMenuParams()), MENU_TYPE_SELECTION);
}

void SelectionControllerEfl::GetSelectionBounds(gfx::Rect* left, gfx::Rect* right) {
  if (left)
    *left = selection_data_->GetLeftRect();
  if (right)
    *right = selection_data_->GetRightRect();
}

void SelectionControllerEfl::HandleLongPressEvent(const gfx::Point& touch_point) {
  long_mouse_press_ = true;
  magnifier_->HandleLongPress(touch_point);
}

void SelectionControllerEfl::HandleLongPressMoveEvent(const gfx::Point& touch_point) {
  parent_view_->SelectClosestWord(touch_point);

  if (selection_data_->GetCaretSelectionStatus()) {
    parent_view_->MoveCaret(touch_point);
    SetSelectionStatus(true);
    ShowHandleAndContextMenuIfRequired();
  } else{
    parent_view_->SelectClosestWord(touch_point);
  }
}

void SelectionControllerEfl::HandleLongPressEndEvent() {
  long_mouse_press_ = false;
  if (selection_data_->GetCaretSelectionStatus()) {
    SetSelectionStatus(true);
    SetSelectionEditable(true);
  }
  ShowHandleAndContextMenuIfRequired();
}

bool SelectionControllerEfl::IsSelectionValid(const gfx::Rect& left_rect, const gfx::Rect& right_rect) {
  LOG(INFO) << __PRETTY_FUNCTION__ << " l_x = " << left_rect.x() << " l_y = " << left_rect.y() << " r_x = " << right_rect.x() << " r_y = " << right_rect.y();
  // For all normal cases the widht will be 0 and we want to check empty which Implies
  // x, y, h w all to be 0
  if ((IsRectEmpty(left_rect) || IsRectEmpty(right_rect))) {
    SetSelectionStatus(false);
    return false;
  }

  // The most of sites return width of each rects as 0 when text is selected.
  // However, some websites that have viewport attributes on meta tag v
  // return width 0 right after they are loaded, even though text is not selected.
  // Thus the width is not sufficient for checking selection condition.
  // Further invesitigation showed left_rect and right_rect always have the same x,y values
  // for such cases. So, the equality for x and y rather than width should be tested.
  if (left_rect.x()==right_rect.x() && left_rect.y()==right_rect.y() &&
      !selection_data_->IsInEditField() && !mouse_press_) {
    SetSelectionStatus(false);
    return false;
  }

  LOG(INFO) << "SelectionControllerEfl::IsSelectionValid true";
  if (!GetSelectionStatus())
    SetSelectionStatus(true);

  if (left_rect.x() != right_rect.x() || left_rect.y() != right_rect.y() &&
      selection_data_->IsInEditField() && GetCaretSelectionStatus()) {
    if (!long_mouse_press_)
      SetCaretSelectionStatus(false);
  }

  LOG(INFO) << "SelectionControllerEfl::IsSelectionValid true";
  return true;
}

void SelectionControllerEfl::ClearSelection() {
  LOG(INFO) << __PRETTY_FUNCTION__;
  Clear();
  selection_data_->SetStatus(false);
  SetSelectionEditable(false);
  SetCaretSelectionStatus(false);
}

void SelectionControllerEfl::OnParentParentViewMove() {
  LOG(INFO) << __PRETTY_FUNCTION__;
  parent_view_->CancelContextMenu(0);
  start_handle_->Move(start_handle_->GetBasePosition());
  end_handle_->Move(end_handle_->GetBasePosition());
}

gfx::Rect SelectionControllerEfl::GetLeftRect() {
  return selection_data_->GetLeftRect();
}

gfx::Rect SelectionControllerEfl::GetRightRect() {
  return selection_data_->GetRightRect();
}

}
<commit_msg>Fix text-selection malfunctions in some web page issue<commit_after>/*
   Copyright (C) 2013 Samsung Electronics

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

   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
   Library General Public License for more details.

   You should have received a copy of the GNU Library General Public License
   along with this library; see the file COPYING.LIB.  If not, write to
   the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
   Boston, MA 02110-1301, USA.
*/

#include "eweb_view.h"
#include "selection_controller_efl.h"
#include "selection_handle_efl.h"
#include "selection_box_efl.h"
#include "selection_magnifier_efl.h"

namespace content {

static bool IsRectEmpty(const gfx::Rect& rect) {
  if (rect.x() == 0 && rect.y() == 0 && rect.height() == 0 && rect.width() == 0) {
    LOG(INFO) << "SelectionControllerEfl:IsRectEmpty : true";
    return true;
  }
  return false;
}

SelectionControllerEfl::SelectionControllerEfl(EWebView* parent_view)
    :  parent_view_(parent_view),
       mouse_press_(false),
       long_mouse_press_(false),
       scrolling_(false),
       selection_data_(new SelectionBoxEfl(parent_view)),
       start_handle_(new SelectionHandleEfl(this, SelectionHandleEfl::HANDLE_TYPE_LEFT, parent_view->evas_object())),
       end_handle_(new SelectionHandleEfl(this, SelectionHandleEfl::HANDLE_TYPE_RIGHT, parent_view->evas_object())),
       input_handle_(new SelectionHandleEfl(this, SelectionHandleEfl::HANDLE_TYPE_INPUT, parent_view->evas_object())),
       magnifier_(new SelectionMagnifierEfl(this)) {
  evas_object_event_callback_add(parent_view_->evas_object(), EVAS_CALLBACK_MOVE, &EvasParentViewMoveCallback, this);
}

void SelectionControllerEfl::SetSelectionStatus(bool enable) {
  LOG(INFO) << "SelectionControllerEfl::SetSelectionStatus " << enable;
  selection_data_->SetStatus(enable);
}

bool SelectionControllerEfl::GetSelectionStatus() const {
  LOG(INFO) << "SelectionControllerEfl::GetSelectionStatus " << selection_data_->GetStatus();
  return selection_data_->GetStatus();
}

void SelectionControllerEfl::SetSelectionEditable(bool enable) {
  LOG(INFO) << "SelectionControllerEfl::SetSelectionEditable" << enable;
  selection_data_->SetEditable(enable);
}

bool SelectionControllerEfl::GetSelectionEditable() const {
  LOG(INFO) << "SelectionControllerEfl::GetSelectionEditable " << selection_data_->GetEditable();
  return selection_data_->GetEditable();
}

void SelectionControllerEfl::SetCaretSelectionStatus(const bool enable) {
  LOG(INFO) << "SelectionControllerEfl::SetCaretSelectionStatus : " << enable;
  selection_data_->SetCaretSelectionStatus(enable);
}

bool SelectionControllerEfl::GetCaretSelectionStatus() const {
  LOG(INFO) << "SelectionControllerEfl::GetCaretSelectionStatus : " << selection_data_->GetCaretSelectionStatus();
  return selection_data_->GetCaretSelectionStatus();
}

void SelectionControllerEfl::SetScrollStatus(const bool enable) {
  LOG(INFO) << __PRETTY_FUNCTION__ << " enable : " << enable;
  scrolling_ = enable;
  if (enable)
    Clear();
  else
    ShowHandleAndContextMenuIfRequired();
}

bool SelectionControllerEfl::GetScrollStatus() {
  LOG(INFO) << __PRETTY_FUNCTION__ << " " << scrolling_;
  return scrolling_;
}

void SelectionControllerEfl::UpdateSelectionData(const base::string16& text) {
  selection_data_->UpdateSelectStringData(text);
}

void SelectionControllerEfl::UpdateMagnifierScreen(Evas_Object* img) {
  magnifier_->UpdateScreen(img);
}

void SelectionControllerEfl::UpdateSelectionDataAndShow(const gfx::Rect& left_rect, const gfx::Rect& right_rect, bool is_anchor_first) {
  LOG(INFO) << __PRETTY_FUNCTION__;
  selection_data_->UpdateRectData(left_rect, right_rect, is_anchor_first);

  if (!IsSelectionValid(left_rect, right_rect)) {
    Clear();
    return;
  }

  // Do not show the context menu and handlers untill long mouse press is released
  if (long_mouse_press_)
    return;

  // Do not show the context menu and handlers while page is scrolling
  if (scrolling_)
    return;

  ShowHandleAndContextMenuIfRequired();
}

void SelectionControllerEfl::ShowHandleAndContextMenuIfRequired() {
  LOG(INFO) << __PRETTY_FUNCTION__;
  if (!selection_data_->GetStatus())
    return;

  Clear();

  // Is in edit field and no text is selected. show only single handle
  if (selection_data_->IsInEditField() && GetCaretSelectionStatus()) {
    gfx::Rect left = selection_data_->GetLeftRect();
    input_handle_->SetBasePosition(gfx::Point(left.x(), left.y()));
    input_handle_->SetCursorHandlerStatus(true);
    input_handle_->Move(gfx::Point(left.x(), left.y() + left.height()));
    input_handle_->Show();

    return;
  }

  // FIXME : Check the text Direction later
  gfx::Rect left = selection_data_->GetLeftRect();
  // The base position of start_handle should be set to the middle of the left rectangle.
  // Otherwise the start_handle may be shifted up when the right_handle is moving
  start_handle_->SetBasePosition(gfx::Point(left.x(), left.y() + (left.height() / 2)));
  start_handle_->Move(gfx::Point(left.x(), left.y() + left.height()));
  start_handle_->Show();

  gfx::Rect right = selection_data_->GetRightRect();

  // The base position of end_handle should be set to the middle of the right rectangle.
  // Otherwise the end_handle may be shifted up when the left_handle is moving
  end_handle_->SetBasePosition(gfx::Point(right.x(), right.y() + (right.height() / 2)));
  end_handle_->Move(gfx::Point(right.x() + right.width(), right.y() + right.height()));
  end_handle_->Show();

  // Do not show the context menu during selection extend
  if (!mouse_press_)
    parent_view_->ShowContextMenu(*(selection_data_->GetContextMenuParams()), MENU_TYPE_SELECTION);
  parent_view_->QuerySelectionStyle();
}

void SelectionControllerEfl::HideHandle() {
  SetCaretSelectionStatus(false);
  Clear();
}

void SelectionControllerEfl::HideHandleAndContextMenu() {
  parent_view_->CancelContextMenu(0);
  HideHandle();
}

void SelectionControllerEfl::Clear() {
  start_handle_->Hide();
  end_handle_->Hide();
  input_handle_->Hide();
}

void SelectionControllerEfl::OnMouseDown(const gfx::Point& touch_point) {
  // Hide context menu on mouse down
  parent_view_->CancelContextMenu(0);
  mouse_press_ = true;
  magnifier_->UpdateLocation(touch_point);
  magnifier_->Move(touch_point);
  magnifier_->Show();
}

void SelectionControllerEfl::OnMouseMove(const gfx::Point& touch_point, bool on_curson_handle) {
  // FIXME : Check the text Direction later
  magnifier_->UpdateLocation(touch_point);
  magnifier_->Move(touch_point);
  if (!on_curson_handle)
    parent_view_->SelectRange(start_handle_->GetBasePosition(), end_handle_->GetBasePosition());
  else
    parent_view_->MoveCaret(input_handle_->GetBasePosition());
}

void SelectionControllerEfl::OnMouseUp(const gfx::Point& touch_point) {
  selection_data_->UpdateHandleData();
  mouse_press_ = false;
  magnifier_->Hide();
  parent_view_->ShowContextMenu(*(selection_data_->GetContextMenuParams()), MENU_TYPE_SELECTION);
}

void SelectionControllerEfl::GetSelectionBounds(gfx::Rect* left, gfx::Rect* right) {
  if (left)
    *left = selection_data_->GetLeftRect();
  if (right)
    *right = selection_data_->GetRightRect();
}

void SelectionControllerEfl::HandleLongPressEvent(const gfx::Point& touch_point) {
  long_mouse_press_ = true;
  magnifier_->HandleLongPress(touch_point);
}

void SelectionControllerEfl::HandleLongPressMoveEvent(const gfx::Point& touch_point) {
  parent_view_->SelectClosestWord(touch_point);

  if (selection_data_->GetCaretSelectionStatus()) {
    parent_view_->MoveCaret(touch_point);
    SetSelectionStatus(true);
    ShowHandleAndContextMenuIfRequired();
  } else{
    parent_view_->SelectClosestWord(touch_point);
  }
}

void SelectionControllerEfl::HandleLongPressEndEvent() {
  long_mouse_press_ = false;
  if (selection_data_->GetCaretSelectionStatus()) {
    SetSelectionStatus(true);
    SetSelectionEditable(true);
  }
  ShowHandleAndContextMenuIfRequired();
}

bool SelectionControllerEfl::IsSelectionValid(const gfx::Rect& left_rect, const gfx::Rect& right_rect) {
  LOG(INFO) << __PRETTY_FUNCTION__ << " l_x = " << left_rect.x() << " l_y = " << left_rect.y() << " r_x = " << right_rect.x() << " r_y = " << right_rect.y();
  // For all normal cases the widht will be 0 and we want to check empty which Implies
  // x, y, h w all to be 0
  if ((IsRectEmpty(left_rect) || IsRectEmpty(right_rect))) {
    SetSelectionStatus(false);
    return false;
  }

  // The most of sites return width of each rects as 0 when text is selected.
  // However, some websites that have viewport attributes on meta tag v
  // return width 0 right after they are loaded, even though text is not selected.
  // Thus the width is not sufficient for checking selection condition.
  // Further invesitigation showed left_rect and right_rect always have the same x,y values
  // for such cases. So, the equality for x and y rather than width should be tested.
  if (left_rect.x()==right_rect.x() && left_rect.y()==right_rect.y() &&
      !selection_data_->IsInEditField() && !mouse_press_) {
    SetSelectionStatus(false);
    return false;
  }

  LOG(INFO) << "SelectionControllerEfl::IsSelectionValid true";
  if (!GetSelectionStatus())
    SetSelectionStatus(true);

  if (left_rect.x() != right_rect.x() || left_rect.y() != right_rect.y() &&
      selection_data_->IsInEditField() && GetCaretSelectionStatus()) {
    if (!long_mouse_press_)
      SetCaretSelectionStatus(false);
  }

  LOG(INFO) << "SelectionControllerEfl::IsSelectionValid true";
  return true;
}

void SelectionControllerEfl::ClearSelection() {
  LOG(INFO) << __PRETTY_FUNCTION__;
  Clear();
  selection_data_->SetStatus(false);
  SetSelectionEditable(false);
  SetCaretSelectionStatus(false);
}

void SelectionControllerEfl::OnParentParentViewMove() {
  LOG(INFO) << __PRETTY_FUNCTION__;
  parent_view_->CancelContextMenu(0);
  start_handle_->Move(start_handle_->GetBasePosition());
  end_handle_->Move(end_handle_->GetBasePosition());
}

gfx::Rect SelectionControllerEfl::GetLeftRect() {
  return selection_data_->GetLeftRect();
}

gfx::Rect SelectionControllerEfl::GetRightRect() {
  return selection_data_->GetRightRect();
}

}
<|endoftext|>


<commit_before><commit_msg>Fixing the google browser name in about:memory page.<commit_after><|endoftext|>


<commit_before>
public class Vector {

    private float[] vect;
    int index;

    public Vector() {
        vect = new float[3];
        index = 0;
    }

    public void setVector(float x, float y, float z) {
            vect[0] = (index*(vect[0])+x)/(index+1);
            vect[1] = (index*(vect[1])+y)/(index+1);
            vect[2] = (index*(vect[2])+z)/(index+1);
            index++;

    }

    public float[] getVector(){
        return this.vect;
    }

    public Vector unitVector(){
        float d = (float) Math.sqrt(vect[0]*vect[0]+vect[1]*vect[1]+vect[2]*vect[2]);
        Vector v = new Vector();
        v.setVector(vect[0]/d, vect[1]/d, vect[2]/d);
        return v;
    }
}
<commit_msg>the method 'dotProduct' is added to the class<commit_after>
public class Vector {

    private float[] vect;
    int index;

    public Vector() {
        vect = new float[3];
        index = 0;
    }

    public void setVector(float x, float y, float z) {
            vect[0] = (index*(vect[0])+x)/(index+1);
            vect[1] = (index*(vect[1])+y)/(index+1);
            vect[2] = (index*(vect[2])+z)/(index+1);
            index++;

    }

    public float[] getVector(){
        return this.vect;
    }

    public static float dotProduct(Vector x, Vector y){
        float[] a = x.getVector();
        float[] b = y.getVector();
        return (a[0]*b[0]+a[1]*b[1]+a[2]*b[2]);
    }

    public Vector unitVector(){
        float d = (float) Math.sqrt(vect[0]*vect[0]+vect[1]*vect[1]+vect[2]*vect[2]);
        Vector v = new Vector();
        v.setVector(vect[0]/d, vect[1]/d, vect[2]/d);
        return v;
    }
}
<|endoftext|>


<commit_before>#pragma once
//=====================================================================//
/*! @file
    @brief  サンプリング・クラス
	@copyright Copyright 2017 Kunihito Hiramatsu All Right Reserved.
    @author 平松邦仁 (hira@rvf-rc45.net)
*/
//=====================================================================//
#include "common/format.hpp"
#include "common/time.h"
#include "common/fixed_fifo.hpp"
#include "fixed_map.hpp"

namespace seeda {

	//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
	/*!
		@brief  サンプリング・ホルダー
	*/
	//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
	struct sample_t {

		enum class mode : uint8_t {
			none,	///< 無変換
			real,	///< 係数変換
			abs,	///< 絶対値変換
		};

		float		gain_;				///< 係数変換ゲイン
///		float		offset_;			///< 係数オフセット

		uint32_t	limit_lo_count_;	///< lo を超えた数
		uint32_t	limit_hi_count_;	///< hi を超えた数
		uint16_t	limit_lo_level_;	///< lo レベル
		uint16_t	limit_hi_level_;	///< hi レベル
		uint16_t	center_;

		uint16_t	ch_;
		mode		mode_;
		bool		signal_;
		uint16_t	min_;
		uint16_t	max_;
		uint16_t	average_;
		uint16_t	median_;

		sample_t() :
			gain_(1024.0f),
			limit_lo_count_(0), limit_hi_count_(0), limit_lo_level_(30000), limit_hi_level_(40000),
			center_(0),
			ch_(0), mode_(mode::none), signal_(false),
			min_(0), max_(0), average_(0), median_(0) { }

		void value_convert(uint16_t value, char* dst, uint32_t size) const
		{
			switch(mode_) {
			case mode::real:
				{
					int32_t v = static_cast<int32_t>(value) - static_cast<int32_t>(center_);
					float a = static_cast<float>(v) / 65535.0f * gain_;
					utils::sformat("%3.2f", dst, size, true) % a;
				}
				break;
			case mode::abs:
				{
					float a = static_cast<float>(value) / 65535.0f * gain_;
					utils::sformat("%3.2f", dst, size, true) % a;
				}
				break;
			default:
				utils::sformat("%d", dst, size, true) % value;
				break;
			}
		}

		void make_csv(char* dst, uint32_t size, bool append) const
		{
			static const char* modes[] = { "value", "real", "abs" };

			utils::sformat("%d,%s", dst, size, append) % ch_ % modes[static_cast<uint32_t>(mode_)];
			utils::sformat(",",     dst, size, true);
			value_convert(min_,     dst, size);
			utils::sformat(",",     dst, size, true);
			value_convert(max_,     dst, size);
			utils::sformat(",",     dst, size, true);
			value_convert(average_, dst, size);
			utils::sformat("%d,",   dst, size, true) % static_cast<uint32_t>(limit_lo_level_);
			utils::sformat("%d,",   dst, size, true) % static_cast<uint32_t>(limit_lo_count_);
			utils::sformat("%d,",   dst, size, true) % static_cast<uint32_t>(limit_hi_level_);
			utils::sformat("%d,",   dst, size, true) % static_cast<uint32_t>(limit_hi_count_);
			value_convert(median_,  dst, size);
		}

		void make_csv2(char* dst, uint32_t size, bool append) const
		{
			uint32_t count = limit_lo_count_ + limit_hi_count_;

			utils::sformat("%d,",   dst, size, append) % ch_;
			value_convert(max_,     dst, size);
			utils::sformat(",",     dst, size, true);
			value_convert(min_,     dst, size);
			utils::sformat(",",     dst, size, true);
			value_convert(average_, dst, size);
			utils::sformat(",",     dst, size, true);
			value_convert(median_,  dst, size);
			utils::sformat(",%u",   dst, size, true) % count;
		}
	};

	//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
	/*!
		@brief  サンプル・データ
	*/
	//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
	struct sample_data {
		time_t		time_;
		sample_t	smp_[8];
	};
	// sample_data FIFO (sizeof 32[sec])
	typedef utils::fixed_fifo<sample_data, 32> EADC_FIFO;

	//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
	/*!
		@brief  サンプリング・クラス
	*/
	//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
	class sample {

		sample_t	t_;

		uint32_t	sum_;
		uint32_t	count_;

		typedef utils::fixed_map<uint16_t, uint16_t, 1000> MAP;
		MAP			map_;

#if 0
		uint32_t	trav_sum_;
		uint32_t	trav_med_;
		bool		exit_trav_;

		void in_trav_(uint16_t idx)
		{
			if(exit_trav_) return;

			if(map_.get_left(idx) != -1) {
				in_trav_(map_.get_left(idx));
			}

			uint32_t cnt = map_.get_pad(idx);
			trav_sum_ += cnt;
			if(trav_sum_ >= (count_ / 2)) {
				trav_med_ = map_.get_key(idx);
				if((count_ & 1) == 0) {
					++idx;
					if(idx == 1000) {  // 要素数が１個の場合は、平均しない
						exit_trav_ = true;
						return;
					}
					trav_med_ += static_cast<uint32_t>(map_.get_key(idx));
					trav_med_ /= 2;
				}
				exit_trav_ = true;
				return;
			}

			if(map_.get_right(idx) != -1) {
				in_trav_(map_.get_right(idx));
			}
		}
#endif

	public:
		//-----------------------------------------------------------------//
		/*!
			@brief  コンストラクター
		*/
		//-----------------------------------------------------------------//
		sample() : t_(), sum_(0), count_(0), map_() { }
///			trav_sum_(0), trav_med_(0), exit_trav_(true) { }

		//-----------------------------------------------------------------//
		/*!
			@brief  クリア
		*/
		//-----------------------------------------------------------------//
		void clear()
		{
			sum_ = 0;
			count_ = 0;

			t_.min_ = 65535;
			t_.max_ = 0;
			t_.average_ = 0;
			t_.median_ = 0;
			t_.limit_lo_count_ = 0;
			t_.limit_hi_count_ = 0;

			map_.clear();
		}

		//-----------------------------------------------------------------//
		/*!
			@brief  追加
			@param[in]	data	データ
		*/
		//-----------------------------------------------------------------//
		void add(uint16_t data)
		{
			if(t_.mode_ == sample_t::mode::abs) {
				if(data >= t_.center_) data -= t_.center_;
				else data = t_.center_ - data;
			}

			sum_ += data;
			if(t_.min_ > data) t_.min_ = data;
			if(t_.max_ < data) t_.max_ = data;

			if(t_.limit_hi_level_ < data) ++t_.limit_hi_count_;
			if(t_.limit_lo_level_ > data) ++t_.limit_lo_count_;

			map_.insert(data, 1);
			++count_;
		}

		//-----------------------------------------------------------------//
		/*!
			@brief  主に median の計算
		*/
		//-----------------------------------------------------------------//
		void collect()
		{
#if 0
			trav_med_ = 0;
			trav_sum_ = 0;
			exit_trav_ = false;

///			in_trav_(0);

			t_.median_  = trav_med_;
			t_.average_ = trav_sum_ / count_;
#endif
			uint32_t med = 0;
			uint32_t sum = 0;
			uint32_t i = 0;
			while(i < 1000) {
				uint32_t cnt = map_.get_pad(i);
				sum += cnt;
				if(sum >= (count_ / 2)) {
					med = map_.get_key(i);
					if((count_ & 1) == 0) {
						++i;
						if(i >= map_.size()) {  // 要素数が１個の場合は、平均しない
							break;
						}
						med += static_cast<uint32_t>(map_.get_key(i));
						med /= 2;
					}
					break;
				}
				++i;
			}
			t_.median_ = med;
			t_.average_ = sum_ / count_;
		}

		//-----------------------------------------------------------------//
		/*!
			@brief  結果取得
			@return 結果
		*/
		//-----------------------------------------------------------------//
		const sample_t& get() const { return t_; }

		//-----------------------------------------------------------------//
		/*!
			@brief  結果参照
			@return 結果
		*/
		//-----------------------------------------------------------------//
		sample_t& at() { return t_; }
	};
}
<commit_msg>update: disable MEDIAN filter<commit_after>#pragma once
//=====================================================================//
/*! @file
    @brief  サンプリング・クラス
	@copyright Copyright 2017, 2018 Kunihito Hiramatsu All Right Reserved.
    @author 平松邦仁 (hira@rvf-rc45.net)
*/
//=====================================================================//
#include "common/format.hpp"
#include "common/time.h"
#include "common/fixed_fifo.hpp"
#include "fixed_map.hpp"

// #define MEDIAN

namespace seeda {

	//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
	/*!
		@brief  サンプリング・ホルダー
	*/
	//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
	struct sample_t {

		enum class mode : uint8_t {
			none,	///< 無変換
			real,	///< 係数変換
			abs,	///< 絶対値変換
		};

		float		gain_;				///< 係数変換ゲイン
///		float		offset_;			///< 係数オフセット

		uint32_t	limit_lo_count_;	///< lo を超えた数
		uint32_t	limit_hi_count_;	///< hi を超えた数
		uint16_t	limit_lo_level_;	///< lo レベル
		uint16_t	limit_hi_level_;	///< hi レベル
		uint16_t	center_;

		uint16_t	ch_;
		mode		mode_;
		bool		signal_;
		uint16_t	min_;
		uint16_t	max_;
		uint16_t	average_;
		uint16_t	median_;

		sample_t() :
			gain_(1024.0f),
			limit_lo_count_(0), limit_hi_count_(0), limit_lo_level_(30000), limit_hi_level_(40000),
			center_(0),
			ch_(0), mode_(mode::none), signal_(false),
			min_(0), max_(0), average_(0), median_(0) { }

		void value_convert(uint16_t value, char* dst, uint32_t size) const
		{
			switch(mode_) {
			case mode::real:
				{
					int32_t v = static_cast<int32_t>(value) - static_cast<int32_t>(center_);
					float a = static_cast<float>(v) / 65535.0f * gain_;
					utils::sformat("%3.2f", dst, size, true) % a;
				}
				break;
			case mode::abs:
				{
					float a = static_cast<float>(value) / 65535.0f * gain_;
					utils::sformat("%3.2f", dst, size, true) % a;
				}
				break;
			default:
				utils::sformat("%d", dst, size, true) % value;
				break;
			}
		}

		void make_csv(char* dst, uint32_t size, bool append) const
		{
			static const char* modes[] = { "value", "real", "abs" };

			utils::sformat("%d,%s", dst, size, append) % ch_ % modes[static_cast<uint32_t>(mode_)];
			utils::sformat(",",     dst, size, true);
			value_convert(min_,     dst, size);
			utils::sformat(",",     dst, size, true);
			value_convert(max_,     dst, size);
			utils::sformat(",",     dst, size, true);
			value_convert(average_, dst, size);
			utils::sformat("%d,",   dst, size, true) % static_cast<uint32_t>(limit_lo_level_);
			utils::sformat("%d,",   dst, size, true) % static_cast<uint32_t>(limit_lo_count_);
			utils::sformat("%d,",   dst, size, true) % static_cast<uint32_t>(limit_hi_level_);
			utils::sformat("%d,",   dst, size, true) % static_cast<uint32_t>(limit_hi_count_);
			value_convert(median_,  dst, size);
		}

		void make_csv2(char* dst, uint32_t size, bool append) const
		{
			uint32_t count = limit_lo_count_ + limit_hi_count_;

			utils::sformat("%d,",   dst, size, append) % ch_;
			value_convert(max_,     dst, size);
			utils::sformat(",",     dst, size, true);
			value_convert(min_,     dst, size);
			utils::sformat(",",     dst, size, true);
			value_convert(average_, dst, size);
			utils::sformat(",",     dst, size, true);
			value_convert(median_,  dst, size);
			utils::sformat(",%u",   dst, size, true) % count;
		}
	};

	//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
	/*!
		@brief  サンプル・データ
	*/
	//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
	struct sample_data {
		time_t		time_;
		sample_t	smp_[8];
	};
	// sample_data FIFO (sizeof 32[sec])
	typedef utils::fixed_fifo<sample_data, 32> EADC_FIFO;

	//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
	/*!
		@brief  サンプリング・クラス
	*/
	//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
	class sample {

		sample_t	t_;

		uint32_t	sum_;
		uint32_t	count_;

		typedef utils::fixed_map<uint16_t, uint16_t, 1000> MAP;
		MAP			map_;

#if 0
		uint32_t	trav_sum_;
		uint32_t	trav_med_;
		bool		exit_trav_;

		void in_trav_(uint16_t idx)
		{
			if(exit_trav_) return;

			if(map_.get_left(idx) != -1) {
				in_trav_(map_.get_left(idx));
			}

			uint32_t cnt = map_.get_pad(idx);
			trav_sum_ += cnt;
			if(trav_sum_ >= (count_ / 2)) {
				trav_med_ = map_.get_key(idx);
				if((count_ & 1) == 0) {
					++idx;
					if(idx == 1000) {  // 要素数が１個の場合は、平均しない
						exit_trav_ = true;
						return;
					}
					trav_med_ += static_cast<uint32_t>(map_.get_key(idx));
					trav_med_ /= 2;
				}
				exit_trav_ = true;
				return;
			}

			if(map_.get_right(idx) != -1) {
				in_trav_(map_.get_right(idx));
			}
		}
#endif

	public:
		//-----------------------------------------------------------------//
		/*!
			@brief  コンストラクター
		*/
		//-----------------------------------------------------------------//
		sample() : t_(), sum_(0), count_(0), map_() { }
///			trav_sum_(0), trav_med_(0), exit_trav_(true) { }

		//-----------------------------------------------------------------//
		/*!
			@brief  クリア
		*/
		//-----------------------------------------------------------------//
		void clear()
		{
			sum_ = 0;
			count_ = 0;

			t_.min_ = 65535;
			t_.max_ = 0;
			t_.average_ = 0;
			t_.median_ = 0;
			t_.limit_lo_count_ = 0;
			t_.limit_hi_count_ = 0;

			map_.clear();
		}

		//-----------------------------------------------------------------//
		/*!
			@brief  追加
			@param[in]	data	データ
		*/
		//-----------------------------------------------------------------//
		void add(uint16_t data)
		{
			if(t_.mode_ == sample_t::mode::abs) {
				if(data >= t_.center_) data -= t_.center_;
				else data = t_.center_ - data;
			}

			sum_ += data;
			if(t_.min_ > data) t_.min_ = data;
			if(t_.max_ < data) t_.max_ = data;

			if(t_.limit_hi_level_ < data) ++t_.limit_hi_count_;
			if(t_.limit_lo_level_ > data) ++t_.limit_lo_count_;
#ifdef MEDIAN
			map_.insert(data, 1);
#endif
			++count_;
		}

		//-----------------------------------------------------------------//
		/*!
			@brief  主に median の計算
		*/
		//-----------------------------------------------------------------//
		void collect()
		{
#if 0
			trav_med_ = 0;
			trav_sum_ = 0;
			exit_trav_ = false;

			t_.median_  = trav_med_;
			t_.average_ = trav_sum_ / count_;
#endif

#ifdef MEDIAN
			uint32_t med = 0;
			uint32_t sum = 0;
			uint32_t i = 0;
			while(i < 1000) {
				uint32_t cnt = map_.get_pad(i);
				sum += cnt;
				if(sum >= (count_ / 2)) {
					med = map_.get_key(i);
					if((count_ & 1) == 0) {
						++i;
						if(i >= map_.size()) {  // 要素数が１個の場合は、平均しない
							break;
						}
						med += static_cast<uint32_t>(map_.get_key(i));
						med /= 2;
					}
					break;
				}
				++i;
			}
			t_.median_ = med;
#else
			t_.median_ = (static_cast<uint32_t>(t_.min_) + static_cast<uint32_t>(t_.max_)) / 2;
#endif
			t_.average_ = sum_ / count_;
		}

		//-----------------------------------------------------------------//
		/*!
			@brief  結果取得
			@return 結果
		*/
		//-----------------------------------------------------------------//
		const sample_t& get() const { return t_; }

		//-----------------------------------------------------------------//
		/*!
			@brief  結果参照
			@return 結果
		*/
		//-----------------------------------------------------------------//
		sample_t& at() { return t_; }
	};
}
<|endoftext|>


<commit_before>#include <iostream>

#include <SDL2/SDL.h>

#include <GL/glew.h>
#include <GL/glu.h>
#include <SDL2/SDL_opengl.h>

#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>

#include "Cube.h"
#include "Origin.h"
#include "Shader.h"
#include "ShaderManager.h"

using namespace std;

const float STEP = 0.01f;

float window_width = 640.0f;
float window_height = 480.0f;

int main(int argc, char** argv) {
    int result = SDL_Init(SDL_INIT_VIDEO);
    if (result != 0) {
        cerr << "Could not initialize SDL: " << SDL_GetError() << endl;
        return 1;
    }

    SDL_Window* window = SDL_CreateWindow(argv[0], 0, 0, (int)window_width,
                                          (int)window_height,
                                          SDL_WINDOW_SHOWN | SDL_WINDOW_OPENGL);
    if (window == nullptr) {
        cerr << "Could not create window: " << SDL_GetError() << endl;
        return 2;
    }

    SDL_GL_SetAttribute( SDL_GL_CONTEXT_MAJOR_VERSION, 3 );
    SDL_GL_SetAttribute( SDL_GL_CONTEXT_MINOR_VERSION, 1 );
    SDL_GL_SetAttribute( SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE );

    SDL_GLContext gl_context = SDL_GL_CreateContext(window);
    if (gl_context == nullptr) {
        cerr << "Could not create OpenGL context: " << SDL_GetError() << endl;
        return 3;
    }

    glewExperimental = GL_TRUE;
    GLenum glewError = glewInit();
    if (glewError != GLEW_OK) {
        cerr << "Could not initialize GLEW: " << glewGetErrorString(glewError) << endl;
        return 4;
    }

    glEnable(GL_DEPTH);
    glEnable(GL_VERTEX_ARRAY);
    glEnable(GL_DEPTH_TEST);
    glDisable(GL_CULL_FACE);

    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();
    glClearColor(0.0f, 0.0f, 0.0f, 0.0f);

    auto shaders = ShaderManager();

    auto shader_transform = shaders.get("transform");
    shader_transform->apply();
    auto cube = Cube();

    auto shader_colour = shaders.get("colour");
    shader_colour->apply();
    auto origin = Origin();

    auto eye = glm::vec3(0, 0, 5.0f);
    auto at = glm::vec3(0, 0, 0);
    auto up = glm::vec3(0, 1, 0);
    auto view = glm::lookAt(eye, at, up);
    shaders.updateViewMatrices(view);

    auto proj = glm::perspective(45.f, window_width / window_height, 0.1f,
                                 -100.f);
    shaders.updateProjectionMatrices(proj);

    float angle = 0.0f;
    bool done = false;
    SDL_Event event;
    while (done == false) {
        while (SDL_PollEvent(&event) != 0) {
            if (event.type == SDL_QUIT) {
                done = true;
            } else if (event.type == SDL_KEYDOWN) {
                switch (event.key.keysym.sym) {
                    case SDLK_ESCAPE:
                        cout << "[INFO] Exiting normally at user request." << endl;
                        done = true;
                        break;
                    default:
                        break;
                }
            }
        }

        glm::vec3 direction = STEP * glm::normalize(at - eye);
        glm::vec3 right = STEP * glm::normalize(glm::cross(direction, up));

        auto keys = SDL_GetKeyboardState(nullptr);
        if (keys[SDL_SCANCODE_W]) {
            eye += direction;
            at += direction;
        }
        if (keys[SDL_SCANCODE_S]) {
            eye -= direction;
            at -= direction;
        }
        if (keys[SDL_SCANCODE_D]) {
            eye += right;
            at += right;
        }
        if (keys[SDL_SCANCODE_A]) {
            eye -= right;
            at -= right;
        }
        if (keys[SDL_SCANCODE_SPACE]) {
            eye += STEP * up;
            at += STEP * up;
        }
        if (keys[SDL_SCANCODE_LCTRL]) {
            eye -= STEP * up;
            at -= STEP * up;
        }
        auto view = glm::lookAt(eye, at, up);
        shaders.updateViewMatrices(view);

        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

        shader_colour->apply();
        auto scale = glm::mat4();
        scale = glm::scale(scale, glm::vec3(5.f, 5.f, 5.f));
        shader_colour->updateWorldMatrix(scale);
        origin.draw();

        shader_transform->apply();
        auto modelQuat = glm::quat();
        modelQuat = glm::rotate(modelQuat, angle, glm::vec3(0, 1, 0));
        auto modelMat = (glm::mat4)modelQuat;
        shader_transform->updateWorldMatrix((glm::mat4)modelMat);
        cube.draw();

        glFlush();
        SDL_GL_SwapWindow(window);

        angle += 0.01f;
    }

    SDL_DestroyWindow(window);
    SDL_Quit();

    return 0;
}<commit_msg>Mouse look.<commit_after>#include <iostream>

#include <SDL2/SDL.h>

#include <GL/glew.h>
#include <GL/glu.h>
#include <SDL2/SDL_opengl.h>

#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>

#include "Cube.h"
#include "Origin.h"
#include "Shader.h"
#include "ShaderManager.h"

using namespace std;
using glm::vec3;
using glm::vec4;

const float STEP = 0.1f;
const float ANGLE_DELTA = 3.14f;

float window_width = 640.0f;
float window_height = 480.0f;

int main(int argc, char** argv) {
    int result = SDL_Init(SDL_INIT_VIDEO);
    if (result != 0) {
        cerr << "Could not initialize SDL: " << SDL_GetError() << endl;
        return 1;
    }

    SDL_Window* window = SDL_CreateWindow(argv[0], 0, 0, (int)window_width,
                                          (int)window_height,
                                          SDL_WINDOW_SHOWN | SDL_WINDOW_OPENGL);
    if (window == nullptr) {
        cerr << "Could not create window: " << SDL_GetError() << endl;
        return 2;
    }

    SDL_ShowCursor(SDL_DISABLE);
    SDL_SetRelativeMouseMode(SDL_TRUE);

    SDL_GL_SetAttribute( SDL_GL_CONTEXT_MAJOR_VERSION, 3 );
    SDL_GL_SetAttribute( SDL_GL_CONTEXT_MINOR_VERSION, 1 );
    SDL_GL_SetAttribute( SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE );

    SDL_GLContext gl_context = SDL_GL_CreateContext(window);
    if (gl_context == nullptr) {
        cerr << "Could not create OpenGL context: " << SDL_GetError() << endl;
        return 3;
    }

    glewExperimental = GL_TRUE;
    GLenum glewError = glewInit();
    if (glewError != GLEW_OK) {
        cerr << "Could not initialize GLEW: " << glewGetErrorString(glewError) << endl;
        return 4;
    }

    glEnable(GL_DEPTH);
    glEnable(GL_VERTEX_ARRAY);
    glEnable(GL_DEPTH_TEST);
    glDisable(GL_CULL_FACE);

    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();
    glClearColor(0.0f, 0.0f, 0.0f, 0.0f);

    auto shaders = ShaderManager();

    auto shader_transform = shaders.get("transform");
    shader_transform->apply();
    auto cube = Cube();

    auto shader_colour = shaders.get("colour");
    shader_colour->apply();
    auto origin = Origin();

    auto eye = glm::vec3(0, 0, 5.0f);
    auto at = glm::vec3(0, 0, 0);
    auto up = glm::vec3(0, 1, 0);
    auto view = glm::lookAt(eye, at, up);
    shaders.updateViewMatrices(view);

    auto proj = glm::perspective(45.f, window_width / window_height, 0.1f,
                                 -100.f);
    shaders.updateProjectionMatrices(proj);

    float angle = 0.0f;
    bool done = false;
    SDL_Event event;
    while (done == false) {
        while (SDL_PollEvent(&event) != 0) {
            if (event.type == SDL_QUIT) {
                done = true;
            } else if (event.type == SDL_KEYDOWN) {
                switch (event.key.keysym.sym) {
                    case SDLK_ESCAPE:
                        cout << "[INFO] Exiting normally at user request." << endl;
                        done = true;
                        break;
                    default:
                        break;
                }
            } else if (event.type == SDL_MOUSEMOTION) {
                cout << event.motion.xrel << " " << event.motion.yrel << endl;

                const GLfloat X_SCALED = -(GLfloat)event.motion.xrel / window_width;
                const GLfloat Y_SCALED = -(GLfloat)event.motion.yrel / window_height;

                const GLfloat LEFT_RIGHT_ROT = X_SCALED * ANGLE_DELTA;
                const GLfloat UP_DOWN_ROT = Y_SCALED * ANGLE_DELTA;

                vec3 tempD(at - eye);
                vec4 d(tempD.x, tempD.y, tempD.z, 0.0f);

                vec3 right = cross(tempD, up);

                mat4 rot;
                rot = rotate(rot, UP_DOWN_ROT, right);
                rot = rotate(rot, LEFT_RIGHT_ROT, up);

                d = rot * d;

                at.x = eye.x + d.x;
                at.y = eye.y + d.y;
                at.z = eye.z + d.z;

            }
        }

        glm::vec3 direction = STEP * glm::normalize(at - eye);
        glm::vec3 right = STEP * glm::normalize(glm::cross(direction, up));

        auto keys = SDL_GetKeyboardState(nullptr);
        if (keys[SDL_SCANCODE_W]) {
            eye += direction;
            at += direction;
        }
        if (keys[SDL_SCANCODE_S]) {
            eye -= direction;
            at -= direction;
        }
        if (keys[SDL_SCANCODE_D]) {
            eye += right;
            at += right;
        }
        if (keys[SDL_SCANCODE_A]) {
            eye -= right;
            at -= right;
        }
        if (keys[SDL_SCANCODE_SPACE]) {
            eye += STEP * up;
            at += STEP * up;
        }
        if (keys[SDL_SCANCODE_LCTRL]) {
            eye -= STEP * up;
            at -= STEP * up;
        }
        auto view = glm::lookAt(eye, at, up);
        shaders.updateViewMatrices(view);

        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

        shader_colour->apply();
        auto scale = glm::mat4();
        scale = glm::scale(scale, glm::vec3(5.f, 5.f, 5.f));
        shader_colour->updateWorldMatrix(scale);
        origin.draw();

        shader_transform->apply();
        auto modelQuat = glm::quat();
        modelQuat = glm::rotate(modelQuat, angle, glm::vec3(0, 1, 0));
        auto modelMat = (glm::mat4)modelQuat;
        shader_transform->updateWorldMatrix((glm::mat4)modelMat);
        cube.draw();

        glFlush();
        SDL_GL_SwapWindow(window);

        angle += 0.01f;
    }

    SDL_DestroyWindow(window);
    SDL_Quit();

    return 0;
}<|endoftext|>


<commit_before>/*

  Copyright (C) 2003-2008  Grame
  Grame Research Laboratory, 9 rue du Garet, 69001 Lyon - France
  research@grame.fr

  This file is provided as an example of the MusicXML Library use.
*/

#ifdef VC6
# pragma warning (disable : 4786)
#endif

#include <stdlib.h>
#include <string.h>
#ifndef WIN32
#include <signal.h>
#include <string.h>
#endif

#include "musicxml2guido.h"

using namespace std;
using namespace MusicXML2;

static void usage() {
	cerr << "usage: musicxml2guido [options]  <musicxml file>" << endl;
	cerr << "       reads stdin when <musicxml file> is '-'" << endl;
	cerr << "       option: --autobars don't generates barlines" << endl;
	exit(1);
}

#ifndef WIN32

static void _sigaction(int signal, siginfo_t *si, void *arg)
{
    cerr << "Signal #" << signal << " catched!" << endl;
    exit(-2);
}

static void catchsigs()
{
	struct sigaction sa;

    memset(&sa, 0, sizeof(struct sigaction));
    sigemptyset(&sa.sa_mask);
    sa.sa_sigaction = _sigaction;
    sa.sa_flags   = SA_SIGINFO;
    sigaction(SIGSEGV, &sa, NULL);
    sigaction(SIGILL, &sa, NULL);
    sigaction(SIGFPE, &sa, NULL);
}

#else
static void catchsigs()	{}
#endif

//_______________________________________________________________________________
int main(int argc, char *argv[])
{
	catchsigs();

	bool generateBars = true;
	char * file = argv[1];
	if (argc == 3) {
		if (!strcmp(argv[1], "--autobars")) {
			generateBars = false;
			file = argv[2];
		}
		else usage();
	}
	else if (argc != 2) usage();

	xmlErr err = kNoErr;
	if (!strcmp(file, "-"))
		err = musicxmlfd2guido(stdin, generateBars, cout);
	else
		err = musicxmlfile2guido(file, generateBars, cout);
	if (err) {
		cout << "conversion failed" << endl;
		return -1;
	}
	return 0;
}
<commit_msg>exit without error for unsupported formats (time-wise)<commit_after>/*

  Copyright (C) 2003-2008  Grame
  Grame Research Laboratory, 9 rue du Garet, 69001 Lyon - France
  research@grame.fr

  This file is provided as an example of the MusicXML Library use.
*/

#ifdef VC6
# pragma warning (disable : 4786)
#endif

#include <stdlib.h>
#include <string.h>
#ifndef WIN32
#include <signal.h>
#include <string.h>
#endif

#include "libmusicxml.h"

using namespace std;
using namespace MusicXML2;

static void usage() {
	cerr << "usage: musicxml2guido [options]  <musicxml file>" << endl;
	cerr << "       reads stdin when <musicxml file> is '-'" << endl;
	cerr << "       option: --autobars don't generates barlines" << endl;
	exit(1);
}

#ifndef WIN32

static void _sigaction(int signal, siginfo_t *si, void *arg)
{
    cerr << "Signal #" << signal << " catched!" << endl;
    exit(-2);
}

static void catchsigs()
{
	struct sigaction sa;

    memset(&sa, 0, sizeof(struct sigaction));
    sigemptyset(&sa.sa_mask);
    sa.sa_sigaction = _sigaction;
    sa.sa_flags   = SA_SIGINFO;
    sigaction(SIGSEGV, &sa, NULL);
    sigaction(SIGILL, &sa, NULL);
    sigaction(SIGFPE, &sa, NULL);
}

#else
static void catchsigs()	{}
#endif

//_______________________________________________________________________________
int main(int argc, char *argv[])
{
	catchsigs();

	bool generateBars = true;
	char * file = argv[1];
	if (argc == 3) {
		if (!strcmp(argv[1], "--autobars")) {
			generateBars = false;
			file = argv[2];
		}
		else usage();
	}
	else if (argc != 2) usage();

	xmlErr err = kNoErr;
	if (!strcmp(file, "-"))
		err = musicxmlfd2guido(stdin, generateBars, cout);
	else
		err = musicxmlfile2guido(file, generateBars, cout);
	if (err == kUnsupported)
		cerr << "unsupported xml format" << endl;
	else if (err == kUnsupported) {
		cerr << "conversion failed" << endl;
		return -1;
	}
	return 0;
}
<|endoftext|>