<commit_before>
/*
 * Copyright (c) 2004 The Regents of The University of Michigan
 * 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 the copyright holders 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.
 */

/**
 * @file
 * Definition of a memory trace CPU object for optimal caches. Uses a memory
 * trace to access a fully associative cache with optimal replacement.
 */

#include <algorithm> // For heap functions.

#include "cpu/trace/opt_cpu.hh"
#include "cpu/trace/reader/mem_trace_reader.hh"

#include "sim/builder.hh"
#include "sim/sim_events.hh"

using namespace std;

OptCPU::OptCPU(const string &name,
               MemTraceReader *_trace,
               int block_size,
               int cache_size,
               int _assoc)
    : BaseCPU(name,1), tickEvent(this), trace(_trace),
      numBlks(cache_size/block_size), assoc(_assoc), numSets(numBlks/assoc),
      setMask(numSets - 1)
{
    int log_block_size = (int)(log((double) block_size)/log(2.0));
    MemReqPtr req;
    trace->getNextReq(req);
    refInfo.resize(numSets);
    while (req) {
        RefInfo temp;
        temp.addr = req->paddr >> log_block_size;
        int set = temp.addr & setMask;
        refInfo[set].push_back(temp);
        trace->getNextReq(req);
    }

    // Initialize top level of lookup table.
    lookupTable.resize(16);

    // Annotate references with next ref time.
    for (int k = 0; k < numSets; ++k) {
        for (RefIndex i = refInfo[k].size() - 1; i >= 0; --i) {
            Addr addr = refInfo[k][i].addr;
            initTable(addr, InfiniteRef);
            refInfo[k][i].nextRefTime = lookupValue(addr);
            setValue(addr, i);
        }
    }

    // Reset the lookup table
    for (int j = 0; j < 16; ++j) {
        if (lookupTable[j].size() == (1<<16)) {
            for (int k = 0; k < (1<<16); ++k) {
                if (lookupTable[j][k].size() == (1<<16)) {
                    for (int l = 0; l < (1<<16); ++l) {
                        lookupTable[j][k][l] = -1;
                    }
                }
            }
        }
    }

    tickEvent.schedule(0);

    hits = 0;
    misses = 0;
}

void
OptCPU::processSet(int set)
{
    // Initialize cache
    int blks_in_cache = 0;
    RefIndex i = 0;
    cacheHeap.clear();
    cacheHeap.resize(assoc);

    while (blks_in_cache < assoc) {
        RefIndex cache_index = lookupValue(refInfo[set][i].addr);
        if (cache_index == -1) {
            // First reference to this block
            misses++;
            cache_index = blks_in_cache++;
            setValue(refInfo[set][i].addr, cache_index);
        } else {
            hits++;
        }
        // update cache heap to most recent reference
        cacheHeap[cache_index] = i;
        if (++i >= refInfo[set].size()) {
            return;
        }
    }
    for (int start = assoc/2; start >= 0; --start) {
        heapify(set,start);
    }
    verifyHeap(set,0);

    for (; i < refInfo[set].size(); ++i) {
        RefIndex cache_index = lookupValue(refInfo[set][i].addr);
        if (cache_index == -1) {
            // miss
            misses++;
            // replace from cacheHeap[0]
            // mark replaced block as absent
            setValue(refInfo[set][cacheHeap[0]].addr, -1);
            cacheHeap[0] = i;
            heapify(set, 0);
        } else {
            // hit
            hits++;
            assert(refInfo[set][cacheHeap[cache_index]].addr ==
                   refInfo[set][i].addr);
            assert(refInfo[set][cacheHeap[cache_index]].nextRefTime == i);
            assert(heapLeft(cache_index) >= assoc);
        }
        cacheHeap[cache_index] = i;
        processRankIncrease(set, cache_index);
    }
}
void
OptCPU::tick()
{
    // Do opt simulation

    int references = 0;
    for (int set = 0; set < numSets; ++set) {
        if (!refInfo[set].empty()) {
            processSet(set);
        }
        references += refInfo[set].size();
    }
    // exit;
    fprintf(stderr, "OPT Misses: %d\nOPT Hits: %d\nOPT Accesses: %d\n",
            misses, hits, references);
    new SimExitEvent("Finshed Memory Trace");
}

void
OptCPU::initTable(Addr addr, RefIndex index)
{
    int l1_index = (addr >> 32) & 0x0f;
    int l2_index = (addr >> 16) & 0xffff;
    assert(l1_index == addr >> 32);
    if (lookupTable[l1_index].size() != (1<<16)) {
        lookupTable[l1_index].resize(1<<16);
    }
    if (lookupTable[l1_index][l2_index].size() != (1<<16)) {
        lookupTable[l1_index][l2_index].resize(1<<16, index);
    }
}

OptCPU::TickEvent::TickEvent(OptCPU *c)
    : Event(&mainEventQueue, CPU_Tick_Pri), cpu(c)
{
}

void
OptCPU::TickEvent::process()
{
    cpu->tick();
}

const char *
OptCPU::TickEvent::description()
{
    return "OptCPU tick event";
}

BEGIN_DECLARE_SIM_OBJECT_PARAMS(OptCPU)

    SimObjectParam<MemTraceReader *> data_trace;
    Param<int> size;
    Param<int> block_size;
Param<int> assoc;

END_DECLARE_SIM_OBJECT_PARAMS(OptCPU)

BEGIN_INIT_SIM_OBJECT_PARAMS(OptCPU)

    INIT_PARAM_DFLT(data_trace, "memory trace", NULL),
    INIT_PARAM(size, "cache size"),
    INIT_PARAM(block_size, "block size"),
    INIT_PARAM(assoc,"associativity")

END_INIT_SIM_OBJECT_PARAMS(OptCPU)

CREATE_SIM_OBJECT(OptCPU)
{
    return new OptCPU(getInstanceName(),
                      data_trace,
                      block_size,
                      size,
                      assoc);
}

REGISTER_SIM_OBJECT("OptCPU", OptCPU)
<commit_msg>Make printouts look more like stats.<commit_after>
/*
 * Copyright (c) 2004 The Regents of The University of Michigan
 * 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 the copyright holders 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.
 */

/**
 * @file
 * Definition of a memory trace CPU object for optimal caches. Uses a memory
 * trace to access a fully associative cache with optimal replacement.
 */

#include <algorithm> // For heap functions.

#include "cpu/trace/opt_cpu.hh"
#include "cpu/trace/reader/mem_trace_reader.hh"

#include "sim/builder.hh"
#include "sim/sim_events.hh"

using namespace std;

OptCPU::OptCPU(const string &name,
               MemTraceReader *_trace,
               int block_size,
               int cache_size,
               int _assoc)
    : BaseCPU(name,1), tickEvent(this), trace(_trace),
      numBlks(cache_size/block_size), assoc(_assoc), numSets(numBlks/assoc),
      setMask(numSets - 1)
{
    int log_block_size = (int)(log((double) block_size)/log(2.0));
    MemReqPtr req;
    trace->getNextReq(req);
    refInfo.resize(numSets);
    while (req) {
        RefInfo temp;
        temp.addr = req->paddr >> log_block_size;
        int set = temp.addr & setMask;
        refInfo[set].push_back(temp);
        trace->getNextReq(req);
    }

    // Initialize top level of lookup table.
    lookupTable.resize(16);

    // Annotate references with next ref time.
    for (int k = 0; k < numSets; ++k) {
        for (RefIndex i = refInfo[k].size() - 1; i >= 0; --i) {
            Addr addr = refInfo[k][i].addr;
            initTable(addr, InfiniteRef);
            refInfo[k][i].nextRefTime = lookupValue(addr);
            setValue(addr, i);
        }
    }

    // Reset the lookup table
    for (int j = 0; j < 16; ++j) {
        if (lookupTable[j].size() == (1<<16)) {
            for (int k = 0; k < (1<<16); ++k) {
                if (lookupTable[j][k].size() == (1<<16)) {
                    for (int l = 0; l < (1<<16); ++l) {
                        lookupTable[j][k][l] = -1;
                    }
                }
            }
        }
    }

    tickEvent.schedule(0);

    hits = 0;
    misses = 0;
}

void
OptCPU::processSet(int set)
{
    // Initialize cache
    int blks_in_cache = 0;
    RefIndex i = 0;
    cacheHeap.clear();
    cacheHeap.resize(assoc);

    while (blks_in_cache < assoc) {
        RefIndex cache_index = lookupValue(refInfo[set][i].addr);
        if (cache_index == -1) {
            // First reference to this block
            misses++;
            cache_index = blks_in_cache++;
            setValue(refInfo[set][i].addr, cache_index);
        } else {
            hits++;
        }
        // update cache heap to most recent reference
        cacheHeap[cache_index] = i;
        if (++i >= refInfo[set].size()) {
            return;
        }
    }
    for (int start = assoc/2; start >= 0; --start) {
        heapify(set,start);
    }
    verifyHeap(set,0);

    for (; i < refInfo[set].size(); ++i) {
        RefIndex cache_index = lookupValue(refInfo[set][i].addr);
        if (cache_index == -1) {
            // miss
            misses++;
            // replace from cacheHeap[0]
            // mark replaced block as absent
            setValue(refInfo[set][cacheHeap[0]].addr, -1);
            cacheHeap[0] = i;
            heapify(set, 0);
        } else {
            // hit
            hits++;
            assert(refInfo[set][cacheHeap[cache_index]].addr ==
                   refInfo[set][i].addr);
            assert(refInfo[set][cacheHeap[cache_index]].nextRefTime == i);
            assert(heapLeft(cache_index) >= assoc);
        }
        cacheHeap[cache_index] = i;
        processRankIncrease(set, cache_index);
    }
}
void
OptCPU::tick()
{
    // Do opt simulation

    int references = 0;
    for (int set = 0; set < numSets; ++set) {
        if (!refInfo[set].empty()) {
            processSet(set);
        }
        references += refInfo[set].size();
    }
    // exit;
    fprintf(stderr,"sys.cpu.misses %d #opt cache misses\n",misses);
    fprintf(stderr,"sys.cpu.hits %d #opt cache hits\n", hits);
    fprintf(stderr,"sys.cpu.accesses %d #opt cache acceses\n", references);
    new SimExitEvent("Finshed Memory Trace");
}

void
OptCPU::initTable(Addr addr, RefIndex index)
{
    int l1_index = (addr >> 32) & 0x0f;
    int l2_index = (addr >> 16) & 0xffff;
    assert(l1_index == addr >> 32);
    if (lookupTable[l1_index].size() != (1<<16)) {
        lookupTable[l1_index].resize(1<<16);
    }
    if (lookupTable[l1_index][l2_index].size() != (1<<16)) {
        lookupTable[l1_index][l2_index].resize(1<<16, index);
    }
}

OptCPU::TickEvent::TickEvent(OptCPU *c)
    : Event(&mainEventQueue, CPU_Tick_Pri), cpu(c)
{
}

void
OptCPU::TickEvent::process()
{
    cpu->tick();
}

const char *
OptCPU::TickEvent::description()
{
    return "OptCPU tick event";
}

BEGIN_DECLARE_SIM_OBJECT_PARAMS(OptCPU)

    SimObjectParam<MemTraceReader *> data_trace;
    Param<int> size;
    Param<int> block_size;
Param<int> assoc;

END_DECLARE_SIM_OBJECT_PARAMS(OptCPU)

BEGIN_INIT_SIM_OBJECT_PARAMS(OptCPU)

    INIT_PARAM_DFLT(data_trace, "memory trace", NULL),
    INIT_PARAM(size, "cache size"),
    INIT_PARAM(block_size, "block size"),
    INIT_PARAM(assoc,"associativity")

END_INIT_SIM_OBJECT_PARAMS(OptCPU)

CREATE_SIM_OBJECT(OptCPU)
{
    return new OptCPU(getInstanceName(),
                      data_trace,
                      block_size,
                      size,
                      assoc);
}

REGISTER_SIM_OBJECT("OptCPU", OptCPU)
<|endoftext|>


<commit_before>// This file is part of Eigen, a lightweight C++ template library
// for linear algebra.
//
// Copyright (C) 2014 Benoit Steiner <benoit.steiner.goog@gmail.com>
//
// This Source Code Form is subject to the terms of the Mozilla
// Public License v. 2.0. If a copy of the MPL was not distributed
// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.

#define EIGEN_USE_THREADS

#include "main.h"
#include <iostream>
#include <Eigen/CXX11/Tensor>

using Eigen::Tensor;
using std::isnan;

static void test_multithread_elementwise()
{
  Tensor<float, 3> in1(2,3,7);
  Tensor<float, 3> in2(2,3,7);
  Tensor<float, 3> out(2,3,7);

  in1.setRandom();
  in2.setRandom();

  Eigen::ThreadPoolDevice thread_pool_device(internal::random<int>(3, 11));
  out.device(thread_pool_device) = in1 + in2 * 3.14f;

  for (int i = 0; i < 2; ++i) {
    for (int j = 0; j < 3; ++j) {
      for (int k = 0; k < 7; ++k) {
        VERIFY_IS_APPROX(out(i,j,k), in1(i,j,k) + in2(i,j,k) * 3.14f);
      }
    }
  }
}

static void test_multithread_compound_assignment()
{
  Tensor<float, 3> in1(2,3,7);
  Tensor<float, 3> in2(2,3,7);
  Tensor<float, 3> out(2,3,7);

  in1.setRandom();
  in2.setRandom();

  Eigen::ThreadPoolDevice thread_pool_device(internal::random<int>(3, 11));
  out.device(thread_pool_device) = in1;
  out.device(thread_pool_device) += in2 * 3.14f;

  for (int i = 0; i < 2; ++i) {
    for (int j = 0; j < 3; ++j) {
      for (int k = 0; k < 7; ++k) {
        VERIFY_IS_APPROX(out(i,j,k), in1(i,j,k) + in2(i,j,k) * 3.14f);
      }
    }
  }
}

template<int DataLayout>
static void test_multithread_contraction()
{
  Tensor<float, 4, DataLayout> t_left(30, 50, 37, 31);
  Tensor<float, 5, DataLayout> t_right(37, 31, 70, 2, 10);
  Tensor<float, 5, DataLayout> t_result(30, 50, 70, 2, 10);

  t_left.setRandom();
  t_right.setRandom();

  // this contraction should be equivalent to a single matrix multiplication
  typedef Tensor<float, 1>::DimensionPair DimPair;
  Eigen::array<DimPair, 2> dims({{DimPair(2, 0), DimPair(3, 1)}});

  typedef Map<Matrix<float, Dynamic, Dynamic, DataLayout>> MapXf;
  MapXf m_left(t_left.data(), 1500, 1147);
  MapXf m_right(t_right.data(), 1147, 1400);
  Matrix<float, Dynamic, Dynamic, DataLayout> m_result(1500, 1400);

  Eigen::ThreadPoolDevice thread_pool_device(4);

  // compute results by separate methods
  t_result.device(thread_pool_device) = t_left.contract(t_right, dims);
  m_result = m_left * m_right;

 for (ptrdiff_t i = 0; i < t_result.size(); i++) {
    VERIFY(&t_result.data()[i] != &m_result.data()[i]);
    if (fabs(t_result.data()[i] - m_result.data()[i]) >= 1e-4) {
      std::cout << "mismatch detected: " << t_result.data()[i] << " vs " <<  m_result.data()[i] << std::endl;
      assert(false);
    }
  }
}

template<int DataLayout>
static void test_contraction_corner_cases()
{
  Tensor<float, 2, DataLayout> t_left(32, 500);
  Tensor<float, 2, DataLayout> t_right(32, 28*28);
  Tensor<float, 2, DataLayout> t_result(500, 28*28);

  t_left = (t_left.constant(-0.5f) + t_left.random()) * 2.0f;
  t_right = (t_right.constant(-0.6f) + t_right.random()) * 2.0f;
  t_result = t_result.constant(NAN);

  // this contraction should be equivalent to a single matrix multiplication
  typedef Tensor<float, 1>::DimensionPair DimPair;
  Eigen::array<DimPair, 1> dims{{DimPair(0, 0)}};

  typedef Map<Matrix<float, Dynamic, Dynamic, DataLayout>> MapXf;
  MapXf m_left(t_left.data(), 32, 500);
  MapXf m_right(t_right.data(), 32, 28*28);
  Matrix<float, Dynamic, Dynamic, DataLayout> m_result(500, 28*28);

  Eigen::ThreadPoolDevice thread_pool_device(12);

  // compute results by separate methods
  t_result.device(thread_pool_device) = t_left.contract(t_right, dims);
  m_result = m_left.transpose() * m_right;

  for (ptrdiff_t i = 0; i < t_result.size(); i++) {
    assert(!isnan(t_result.data()[i]));
    if (fabs(t_result.data()[i] - m_result.data()[i]) >= 1e-4) {
      std::cout << "mismatch detected at index " << i << " : " << t_result.data()[i] << " vs " <<  m_result.data()[i] << std::endl;
      assert(false);
    }
  }

  t_left.resize(32, 1);
  t_left = (t_left.constant(-0.5f) + t_left.random()) * 2.0f;
  t_result.resize (1, 28*28);
  t_result = t_result.constant(NAN);
  t_result.device(thread_pool_device) = t_left.contract(t_right, dims);
  new(&m_left) MapXf(t_left.data(), 32, 1);
  m_result = m_left.transpose() * m_right;
  for (ptrdiff_t i = 0; i < t_result.size(); i++) {
    assert(!isnan(t_result.data()[i]));
    if (fabs(t_result.data()[i] - m_result.data()[i]) >= 1e-4) {
      std::cout << "mismatch detected: " << t_result.data()[i] << " vs " <<  m_result.data()[i] << std::endl;
      assert(false);
    }
  }

  t_left.resize(32, 500);
  t_right.resize(32, 4);
  t_left = (t_left.constant(-0.5f) + t_left.random()) * 2.0f;
  t_right = (t_right.constant(-0.6f) + t_right.random()) * 2.0f;
  t_result.resize (500, 4);
  t_result = t_result.constant(NAN);
  t_result.device(thread_pool_device) = t_left.contract(t_right, dims);
  new(&m_left) MapXf(t_left.data(), 32, 500);
  new(&m_right) MapXf(t_right.data(), 32, 4);
  m_result = m_left.transpose() * m_right;
  for (ptrdiff_t i = 0; i < t_result.size(); i++) {
    assert(!isnan(t_result.data()[i]));
    if (fabs(t_result.data()[i] - m_result.data()[i]) >= 1e-4) {
      std::cout << "mismatch detected: " << t_result.data()[i] << " vs " <<  m_result.data()[i] << std::endl;
      assert(false);
    }
  }

  t_left.resize(32, 1);
  t_right.resize(32, 4);
  t_left = (t_left.constant(-0.5f) + t_left.random()) * 2.0f;
  t_right = (t_right.constant(-0.6f) + t_right.random()) * 2.0f;
  t_result.resize (1, 4);
  t_result = t_result.constant(NAN);
  t_result.device(thread_pool_device) = t_left.contract(t_right, dims);
  new(&m_left) MapXf(t_left.data(), 32, 1);
  new(&m_right) MapXf(t_right.data(), 32, 4);
  m_result = m_left.transpose() * m_right;
  for (ptrdiff_t i = 0; i < t_result.size(); i++) {
    assert(!isnan(t_result.data()[i]));
    if (fabs(t_result.data()[i] - m_result.data()[i]) >= 1e-4) {
      std::cout << "mismatch detected: " << t_result.data()[i] << " vs " <<  m_result.data()[i] << std::endl;
      assert(false);
    }
  }
}

template<int DataLayout>
static void test_multithread_contraction_agrees_with_singlethread() {
  int contract_size = internal::random<int>(1, 5000);

  Tensor<float, 3, DataLayout> left(internal::random<int>(1, 80),
                                    contract_size,
                                    internal::random<int>(1, 100));

  Tensor<float, 4, DataLayout> right(internal::random<int>(1, 25),
                                     internal::random<int>(1, 37),
                                     contract_size,
                                     internal::random<int>(1, 51));

  left.setRandom();
  right.setRandom();

  // add constants to shift values away from 0 for more precision
  left += left.constant(1.5f);
  right += right.constant(1.5f);

  typedef Tensor<float, 1>::DimensionPair DimPair;
  Eigen::array<DimPair, 1> dims({{DimPair(1, 2)}});

  Eigen::ThreadPoolDevice thread_pool_device(internal::random<int>(2, 11));

  Tensor<float, 5, DataLayout> st_result;
  st_result = left.contract(right, dims);

  Tensor<float, 5, DataLayout> tp_result(st_result.dimensions());
  tp_result.device(thread_pool_device) = left.contract(right, dims);

  VERIFY(dimensions_match(st_result.dimensions(), tp_result.dimensions()));
  for (ptrdiff_t i = 0; i < st_result.size(); i++) {
    // if both of the values are very small, then do nothing (because the test will fail
    // due to numerical precision issues when values are small)
    if (fabs(st_result.data()[i] - tp_result.data()[i]) >= 1e-4) {
      VERIFY_IS_APPROX(st_result.data()[i], tp_result.data()[i]);
    }
  }
}

static void test_memcpy() {

  for (int i = 0; i < 5; ++i) {
    const int num_threads = internal::random<int>(3, 11);
    Eigen::ThreadPoolDevice thread_pool_device(num_threads);

    const int size = internal::random<int>(13, 7632);
    Tensor<float, 1> t1(size);
    t1.setRandom();
    std::vector<float> result(size);
    thread_pool_device.memcpy(&result[0], t1.data(), size*sizeof(float));
    for (int i = 0; i < size; i++) {
      VERIFY_IS_EQUAL(t1(i), result[i]);
    }
  }
}

static void test_multithread_random()
{
  Eigen::ThreadPoolDevice device(2);
  Tensor<float, 1> t(1 << 20);
  t.device(device) = t.random<Eigen::internal::NormalRandomGenerator<float>>();
}

void test_cxx11_tensor_thread_pool()
{
  CALL_SUBTEST(test_multithread_elementwise());
  CALL_SUBTEST(test_multithread_compound_assignment());

  CALL_SUBTEST(test_multithread_contraction<ColMajor>());
  CALL_SUBTEST(test_multithread_contraction<RowMajor>());

  CALL_SUBTEST(test_multithread_contraction_agrees_with_singlethread<ColMajor>());
  CALL_SUBTEST(test_multithread_contraction_agrees_with_singlethread<RowMajor>());

  // Exercise various cases that have been problematic in the past.
  CALL_SUBTEST(test_contraction_corner_cases<ColMajor>());
  CALL_SUBTEST(test_contraction_corner_cases<RowMajor>());

  CALL_SUBTEST(test_memcpy());

  CALL_SUBTEST(test_multithread_random());
}
<commit_msg>Fixed compilation error<commit_after>// This file is part of Eigen, a lightweight C++ template library
// for linear algebra.
//
// Copyright (C) 2014 Benoit Steiner <benoit.steiner.goog@gmail.com>
//
// This Source Code Form is subject to the terms of the Mozilla
// Public License v. 2.0. If a copy of the MPL was not distributed
// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.

#define EIGEN_USE_THREADS

#include "main.h"
#include <iostream>
#include <Eigen/CXX11/Tensor>

using Eigen::Tensor;

static void test_multithread_elementwise()
{
  Tensor<float, 3> in1(2,3,7);
  Tensor<float, 3> in2(2,3,7);
  Tensor<float, 3> out(2,3,7);

  in1.setRandom();
  in2.setRandom();

  Eigen::ThreadPoolDevice thread_pool_device(internal::random<int>(3, 11));
  out.device(thread_pool_device) = in1 + in2 * 3.14f;

  for (int i = 0; i < 2; ++i) {
    for (int j = 0; j < 3; ++j) {
      for (int k = 0; k < 7; ++k) {
        VERIFY_IS_APPROX(out(i,j,k), in1(i,j,k) + in2(i,j,k) * 3.14f);
      }
    }
  }
}

static void test_multithread_compound_assignment()
{
  Tensor<float, 3> in1(2,3,7);
  Tensor<float, 3> in2(2,3,7);
  Tensor<float, 3> out(2,3,7);

  in1.setRandom();
  in2.setRandom();

  Eigen::ThreadPoolDevice thread_pool_device(internal::random<int>(3, 11));
  out.device(thread_pool_device) = in1;
  out.device(thread_pool_device) += in2 * 3.14f;

  for (int i = 0; i < 2; ++i) {
    for (int j = 0; j < 3; ++j) {
      for (int k = 0; k < 7; ++k) {
        VERIFY_IS_APPROX(out(i,j,k), in1(i,j,k) + in2(i,j,k) * 3.14f);
      }
    }
  }
}

template<int DataLayout>
static void test_multithread_contraction()
{
  Tensor<float, 4, DataLayout> t_left(30, 50, 37, 31);
  Tensor<float, 5, DataLayout> t_right(37, 31, 70, 2, 10);
  Tensor<float, 5, DataLayout> t_result(30, 50, 70, 2, 10);

  t_left.setRandom();
  t_right.setRandom();

  // this contraction should be equivalent to a single matrix multiplication
  typedef Tensor<float, 1>::DimensionPair DimPair;
  Eigen::array<DimPair, 2> dims({{DimPair(2, 0), DimPair(3, 1)}});

  typedef Map<Matrix<float, Dynamic, Dynamic, DataLayout>> MapXf;
  MapXf m_left(t_left.data(), 1500, 1147);
  MapXf m_right(t_right.data(), 1147, 1400);
  Matrix<float, Dynamic, Dynamic, DataLayout> m_result(1500, 1400);

  Eigen::ThreadPoolDevice thread_pool_device(4);

  // compute results by separate methods
  t_result.device(thread_pool_device) = t_left.contract(t_right, dims);
  m_result = m_left * m_right;

 for (ptrdiff_t i = 0; i < t_result.size(); i++) {
    VERIFY(&t_result.data()[i] != &m_result.data()[i]);
    if (fabs(t_result.data()[i] - m_result.data()[i]) >= 1e-4) {
      std::cout << "mismatch detected: " << t_result.data()[i] << " vs " <<  m_result.data()[i] << std::endl;
      assert(false);
    }
  }
}

template<int DataLayout>
static void test_contraction_corner_cases()
{
  Tensor<float, 2, DataLayout> t_left(32, 500);
  Tensor<float, 2, DataLayout> t_right(32, 28*28);
  Tensor<float, 2, DataLayout> t_result(500, 28*28);

  t_left = (t_left.constant(-0.5f) + t_left.random()) * 2.0f;
  t_right = (t_right.constant(-0.6f) + t_right.random()) * 2.0f;
  t_result = t_result.constant(NAN);

  // this contraction should be equivalent to a single matrix multiplication
  typedef Tensor<float, 1>::DimensionPair DimPair;
  Eigen::array<DimPair, 1> dims{{DimPair(0, 0)}};

  typedef Map<Matrix<float, Dynamic, Dynamic, DataLayout>> MapXf;
  MapXf m_left(t_left.data(), 32, 500);
  MapXf m_right(t_right.data(), 32, 28*28);
  Matrix<float, Dynamic, Dynamic, DataLayout> m_result(500, 28*28);

  Eigen::ThreadPoolDevice thread_pool_device(12);

  // compute results by separate methods
  t_result.device(thread_pool_device) = t_left.contract(t_right, dims);
  m_result = m_left.transpose() * m_right;

  for (ptrdiff_t i = 0; i < t_result.size(); i++) {
    assert(!std::isnan(t_result.data()[i]));
    if (fabs(t_result.data()[i] - m_result.data()[i]) >= 1e-4) {
      std::cout << "mismatch detected at index " << i << " : " << t_result.data()[i] << " vs " <<  m_result.data()[i] << std::endl;
      assert(false);
    }
  }

  t_left.resize(32, 1);
  t_left = (t_left.constant(-0.5f) + t_left.random()) * 2.0f;
  t_result.resize (1, 28*28);
  t_result = t_result.constant(NAN);
  t_result.device(thread_pool_device) = t_left.contract(t_right, dims);
  new(&m_left) MapXf(t_left.data(), 32, 1);
  m_result = m_left.transpose() * m_right;
  for (ptrdiff_t i = 0; i < t_result.size(); i++) {
    assert(!std::isnan(t_result.data()[i]));
    if (fabs(t_result.data()[i] - m_result.data()[i]) >= 1e-4) {
      std::cout << "mismatch detected: " << t_result.data()[i] << " vs " <<  m_result.data()[i] << std::endl;
      assert(false);
    }
  }

  t_left.resize(32, 500);
  t_right.resize(32, 4);
  t_left = (t_left.constant(-0.5f) + t_left.random()) * 2.0f;
  t_right = (t_right.constant(-0.6f) + t_right.random()) * 2.0f;
  t_result.resize (500, 4);
  t_result = t_result.constant(NAN);
  t_result.device(thread_pool_device) = t_left.contract(t_right, dims);
  new(&m_left) MapXf(t_left.data(), 32, 500);
  new(&m_right) MapXf(t_right.data(), 32, 4);
  m_result = m_left.transpose() * m_right;
  for (ptrdiff_t i = 0; i < t_result.size(); i++) {
    assert(!std::isnan(t_result.data()[i]));
    if (fabs(t_result.data()[i] - m_result.data()[i]) >= 1e-4) {
      std::cout << "mismatch detected: " << t_result.data()[i] << " vs " <<  m_result.data()[i] << std::endl;
      assert(false);
    }
  }

  t_left.resize(32, 1);
  t_right.resize(32, 4);
  t_left = (t_left.constant(-0.5f) + t_left.random()) * 2.0f;
  t_right = (t_right.constant(-0.6f) + t_right.random()) * 2.0f;
  t_result.resize (1, 4);
  t_result = t_result.constant(NAN);
  t_result.device(thread_pool_device) = t_left.contract(t_right, dims);
  new(&m_left) MapXf(t_left.data(), 32, 1);
  new(&m_right) MapXf(t_right.data(), 32, 4);
  m_result = m_left.transpose() * m_right;
  for (ptrdiff_t i = 0; i < t_result.size(); i++) {
    assert(!std::isnan(t_result.data()[i]));
    if (fabs(t_result.data()[i] - m_result.data()[i]) >= 1e-4) {
      std::cout << "mismatch detected: " << t_result.data()[i] << " vs " <<  m_result.data()[i] << std::endl;
      assert(false);
    }
  }
}

template<int DataLayout>
static void test_multithread_contraction_agrees_with_singlethread() {
  int contract_size = internal::random<int>(1, 5000);

  Tensor<float, 3, DataLayout> left(internal::random<int>(1, 80),
                                    contract_size,
                                    internal::random<int>(1, 100));

  Tensor<float, 4, DataLayout> right(internal::random<int>(1, 25),
                                     internal::random<int>(1, 37),
                                     contract_size,
                                     internal::random<int>(1, 51));

  left.setRandom();
  right.setRandom();

  // add constants to shift values away from 0 for more precision
  left += left.constant(1.5f);
  right += right.constant(1.5f);

  typedef Tensor<float, 1>::DimensionPair DimPair;
  Eigen::array<DimPair, 1> dims({{DimPair(1, 2)}});

  Eigen::ThreadPoolDevice thread_pool_device(internal::random<int>(2, 11));

  Tensor<float, 5, DataLayout> st_result;
  st_result = left.contract(right, dims);

  Tensor<float, 5, DataLayout> tp_result(st_result.dimensions());
  tp_result.device(thread_pool_device) = left.contract(right, dims);

  VERIFY(dimensions_match(st_result.dimensions(), tp_result.dimensions()));
  for (ptrdiff_t i = 0; i < st_result.size(); i++) {
    // if both of the values are very small, then do nothing (because the test will fail
    // due to numerical precision issues when values are small)
    if (fabs(st_result.data()[i] - tp_result.data()[i]) >= 1e-4) {
      VERIFY_IS_APPROX(st_result.data()[i], tp_result.data()[i]);
    }
  }
}

static void test_memcpy() {

  for (int i = 0; i < 5; ++i) {
    const int num_threads = internal::random<int>(3, 11);
    Eigen::ThreadPoolDevice thread_pool_device(num_threads);

    const int size = internal::random<int>(13, 7632);
    Tensor<float, 1> t1(size);
    t1.setRandom();
    std::vector<float> result(size);
    thread_pool_device.memcpy(&result[0], t1.data(), size*sizeof(float));
    for (int i = 0; i < size; i++) {
      VERIFY_IS_EQUAL(t1(i), result[i]);
    }
  }
}

static void test_multithread_random()
{
  Eigen::ThreadPoolDevice device(2);
  Tensor<float, 1> t(1 << 20);
  t.device(device) = t.random<Eigen::internal::NormalRandomGenerator<float>>();
}

void test_cxx11_tensor_thread_pool()
{
  CALL_SUBTEST(test_multithread_elementwise());
  CALL_SUBTEST(test_multithread_compound_assignment());

  CALL_SUBTEST(test_multithread_contraction<ColMajor>());
  CALL_SUBTEST(test_multithread_contraction<RowMajor>());

  CALL_SUBTEST(test_multithread_contraction_agrees_with_singlethread<ColMajor>());
  CALL_SUBTEST(test_multithread_contraction_agrees_with_singlethread<RowMajor>());

  // Exercise various cases that have been problematic in the past.
  CALL_SUBTEST(test_contraction_corner_cases<ColMajor>());
  CALL_SUBTEST(test_contraction_corner_cases<RowMajor>());

  CALL_SUBTEST(test_memcpy());

  CALL_SUBTEST(test_multithread_random());
}
<|endoftext|>


<commit_before>#include "core/reactor.hh"
#include "core/app-template.hh"
#include "message/messaging_service.hh"
#include "gms/failure_detector.hh"
#include "gms/gossiper.hh"

namespace bpo = boost::program_options;

int main(int ac, char ** av) {
    app_template app;
    app.add_options()
        ("seed", bpo::value<std::vector<std::string>>(), "IP address of seed node");
    return app.run(ac, av, [&] {
        net::get_messaging_service().start().then([&] {
            gms::get_failure_detector().start_single().then([&] {
                gms::get_gossiper().start_single().then([&] {
                    auto&& config = app.configuration();
                    std::set<gms::inet_address> seeds;
                    for (auto s : config["seed"].as<std::vector<std::string>>()) {
                        seeds.emplace(std::move(s));
                    }

                    std::cout << "Start gossiper service ...\n";
                    auto& gossiper = gms::get_local_gossiper();
                    gossiper.set_seeds(std::move(seeds));
                    int generation_number = 1;
                    gossiper.start(generation_number);
                });
            });
        });
    });
}
<commit_msg>tests: Allow gossip to listen on a specific IP address<commit_after>#include "core/reactor.hh"
#include "core/app-template.hh"
#include "message/messaging_service.hh"
#include "gms/failure_detector.hh"
#include "gms/gossiper.hh"

namespace bpo = boost::program_options;

int main(int ac, char ** av) {
    app_template app;
    app.add_options()
        ("seed", bpo::value<std::vector<std::string>>(), "IP address of seed node")
        ("listen-address", bpo::value<std::string>()->default_value("0.0.0.0"), "IP address to listen");
    return app.run(ac, av, [&] {
        auto&& config = app.configuration();
        auto listen = gms::inet_address(config["listen-address"].as<std::string>());
        net::get_messaging_service().start(std::ref(listen)).then([&] {
            auto& server = net::get_local_messaging_service();
            auto min = server.port_min();
            auto max = server.port_max();
            auto listen = server.listen_address();
            print("Messaging server listening on ip %s ports %d to %d ...\n", listen, min, max);
            gms::get_failure_detector().start_single().then([&] {
                gms::get_gossiper().start_single().then([&] {
                    auto&& config = app.configuration();
                    std::set<gms::inet_address> seeds;
                    for (auto s : config["seed"].as<std::vector<std::string>>()) {
                        seeds.emplace(std::move(s));
                    }

                    std::cout << "Start gossiper service ...\n";
                    auto& gossiper = gms::get_local_gossiper();
                    gossiper.set_seeds(std::move(seeds));
                    int generation_number = 1;
                    gossiper.start(generation_number);
                });
            });
        });
    });
}
<|endoftext|>


<commit_before>#include "noise.hpp"

/* template<typename result_type> result_type perlin::noise(
	result_type x,
	decltype(x) y,
	decltype(x) z
) */

/*template<typename result_type>
result_type perlin::fade(result_type t)

template<typename result_type> result_type perlin::lerp(
	result_type t,
	decltype(t) a,
	decltype(t) b
)

template<typename result_type> result_type perlin::grad(
	int hash,
	result_type x,
	decltype(x) y,
	decltype(x) z
)*/
<commit_msg>Delete noise.cpp<commit_after><|endoftext|>


<commit_before>#pragma once

#include <vector>
#include <tudocomp/def.hpp>
#include <tudocomp/ds/IntVector.hpp>
#include <tudocomp/Algorithm.hpp>

namespace tdc {
namespace lcpcomp {

/**
 * Decodes lcpcomp compressed data as described in the paper.
 * It creates an array of dynamic arrays. Each dynamic array stores in
 * the first element its size. On appending a new element, the dynamic array
 * gets resized by one (instead of doubling). This helps to keep the memory footprint low.
 * It can be faster than \ref ScanDec if its "scans"-value too small.
 */
class CompactDec : public Algorithm {
public:
    inline static Meta meta() {
        Meta m("lcpcomp_dec", "compact");
        return m;

    }
    inline void decode_lazy() const {
    }
    inline void decode_eagerly() const {
    }

private:
    len_compact_t** m_fwd;

    len_t m_cursor;
    IF_STATS(len_t m_longest_chain);
    IF_STATS(len_t m_current_chain);

    IntVector<uliteral_t> m_buffer;

    inline void decode_literal_at(len_t pos, uliteral_t c) {
		IF_STATS(++m_current_chain);
        IF_STATS(m_longest_chain = std::max(m_longest_chain, m_current_chain));

        m_buffer[pos] = c;
		DCHECK(c != 0 || pos == m_buffer.size()-1); // we assume that the text to restore does not contain a NULL-byte but at its very end

        if(m_fwd[pos] != nullptr) {
            const len_compact_t*const& bucket = m_fwd[pos];
            for(size_t i = 1; i < bucket[0]; ++i) {
                decode_literal_at(bucket[i], c); // recursion
            }
            delete [] m_fwd[pos];
            m_fwd[pos] = nullptr;
        }

        IF_STATS(--m_current_chain);
    }

public:
    CompactDec(CompactDec&& other):
        Algorithm(std::move(*this)),
        m_fwd(std::move(other.m_fwd)),
        m_cursor(std::move(other.m_cursor)),
        m_buffer(std::move(other.m_buffer))
    {
        IF_STATS(m_longest_chain = std::move(other.m_longest_chain));
        IF_STATS(m_current_chain = std::move(other.m_current_chain));

        other.m_fwd = nullptr;
    }

    ~CompactDec() {
        if(m_fwd != nullptr) {
            for(size_t i = 0; i < m_buffer.size(); ++i) {
                if(m_fwd[i] == nullptr) continue;
                delete [] m_fwd[i];
            }
            delete [] m_fwd;
        }
    }
    inline CompactDec(Env&& env, len_t size)
        : Algorithm(std::move(env)), m_cursor(0), m_buffer(size,0) {

        IF_STATS(m_longest_chain = 0);
        IF_STATS(m_current_chain = 0);

        m_fwd = new len_compact_t*[size];
        std::fill(m_fwd,m_fwd+size,nullptr);
    }

    inline void decode_literal(uliteral_t c) {
        decode_literal_at(m_cursor++, c);
    }

    inline void decode_factor(len_t pos, len_t num) {
        for(len_t i = 0; i < num; i++) {
            len_t src = pos+i;
            if(m_buffer[src]) {
                decode_literal_at(m_cursor, m_buffer[src]);
            } else {
                len_compact_t*& bucket = m_fwd[src];
                if(bucket == nullptr) {
                    bucket = new len_compact_t[2];
                    DCHECK(m_fwd[src] == bucket);
                    bucket[0] = 2;
					bucket[1] = m_cursor;
                }
				else
                { // this block implements the call of m_fwd[src]->push_back(m_cursor);
					++bucket[0]; // increase the size of a bucket only by one!
					bucket = (len_compact_t*) realloc(bucket, sizeof(len_compact_t)*bucket[0]);
                    bucket[bucket[0]-1] = m_cursor;
                }
            }

            ++m_cursor;
        }
    }

    IF_STATS(
    inline len_t longest_chain() const {
        return m_longest_chain;
    })

    inline void write_to(std::ostream& out) const {
        for(auto c : m_buffer) out << c;
    }
};

}} //ns

<commit_msg>fix undefined behavior in CompactDec.hpp<commit_after>#pragma once

#include <vector>
#include <tudocomp/def.hpp>
#include <tudocomp/ds/IntVector.hpp>
#include <tudocomp/Algorithm.hpp>

namespace tdc {
namespace lcpcomp {

/**
 * Decodes lcpcomp compressed data as described in the paper.
 * It creates an array of dynamic arrays. Each dynamic array stores in
 * the first element its size. On appending a new element, the dynamic array
 * gets resized by one (instead of doubling). This helps to keep the memory footprint low.
 * It can be faster than \ref ScanDec if its "scans"-value too small.
 */
class CompactDec : public Algorithm {
public:
    inline static Meta meta() {
        Meta m("lcpcomp_dec", "compact");
        return m;

    }
    inline void decode_lazy() const {
    }
    inline void decode_eagerly() const {
    }

private:
    len_compact_t** m_fwd;

    len_t m_cursor;
    IF_STATS(len_t m_longest_chain);
    IF_STATS(len_t m_current_chain);

    IntVector<uliteral_t> m_buffer;

    inline void decode_literal_at(len_t pos, uliteral_t c) {
		IF_STATS(++m_current_chain);
        IF_STATS(m_longest_chain = std::max(m_longest_chain, m_current_chain));

        m_buffer[pos] = c;
		DCHECK(c != 0 || pos == m_buffer.size()-1); // we assume that the text to restore does not contain a NULL-byte but at its very end

        if(m_fwd[pos] != nullptr) {
            const len_compact_t*const& bucket = m_fwd[pos];
            for(size_t i = 1; i < bucket[0]; ++i) {
                decode_literal_at(bucket[i], c); // recursion
            }
            free(m_fwd[pos]);
            m_fwd[pos] = nullptr;
        }

        IF_STATS(--m_current_chain);
    }

public:
    CompactDec(CompactDec&& other):
        Algorithm(std::move(*this)),
        m_fwd(std::move(other.m_fwd)),
        m_cursor(std::move(other.m_cursor)),
        m_buffer(std::move(other.m_buffer))
    {
        IF_STATS(m_longest_chain = std::move(other.m_longest_chain));
        IF_STATS(m_current_chain = std::move(other.m_current_chain));

        other.m_fwd = nullptr;
    }

    ~CompactDec() {
        if(m_fwd != nullptr) {
            for(size_t i = 0; i < m_buffer.size(); ++i) {
                if(m_fwd[i] == nullptr) continue;
                free(m_fwd[i]);
            }
            delete [] m_fwd;
        }
    }
    inline CompactDec(Env&& env, len_t size)
        : Algorithm(std::move(env)), m_cursor(0), m_buffer(size,0) {

        IF_STATS(m_longest_chain = 0);
        IF_STATS(m_current_chain = 0);

        m_fwd = new len_compact_t*[size];
        std::fill(m_fwd,m_fwd+size,nullptr);
    }

    inline void decode_literal(uliteral_t c) {
        decode_literal_at(m_cursor++, c);
    }

    inline void decode_factor(len_t pos, len_t num) {
        for(len_t i = 0; i < num; i++) {
            len_t src = pos+i;
            if(m_buffer[src]) {
                decode_literal_at(m_cursor, m_buffer[src]);
            } else {
                len_compact_t*& bucket = m_fwd[src];
                if(bucket == nullptr) {
                    bucket = (len_compact_t*) malloc(sizeof(len_compact_t) * 2);
                    DCHECK(m_fwd[src] == bucket);
                    bucket[0] = 2;
					bucket[1] = m_cursor;
                }
				else
                { // this block implements the call of m_fwd[src]->push_back(m_cursor);
					++bucket[0]; // increase the size of a bucket only by one!
					bucket = (len_compact_t*) realloc(bucket, sizeof(len_compact_t)*bucket[0]);
                    bucket[bucket[0]-1] = m_cursor;
                }
            }

            ++m_cursor;
        }
    }

    IF_STATS(
    inline len_t longest_chain() const {
        return m_longest_chain;
    })

    inline void write_to(std::ostream& out) const {
        for(auto c : m_buffer) out << c;
    }
};

}} //ns

<|endoftext|>


<commit_before>#include <iostream>

#include "google/protobuf/descriptor.h"

#include "vtrc-server/vtrc-application.h"
#include "vtrc-server/vtrc-channels.h"

#include "vtrc-common/vtrc-pool-pair.h"
#include "vtrc-common/vtrc-closure-holder.h"
#include "vtrc-common/vtrc-rpc-service-wrapper.h"

#include "protocol/calculator.pb.h"

#include "vtrc-listener-tcp.h"
#include "vtrc-listener-unix-local.h"
#include "vtrc-listener-win-pipe.h"

#include "vtrc-memory.h"

#include <math.h>
#include <boost/lexical_cast.hpp>

using namespace vtrc::server;
using namespace vtrc::common;

class calculator_impl: public vtrc_example::calculator {

    application      &app_;
    connection_iface *client_;
    vtrc::unique_ptr<rpc_channel> client_channel_;

    static rpc_channel *client_channel( connection_iface *client )
    {
        return channels
                ::unicast
                ::create_callback_channel(client->shared_from_this( ));
    }

public:

    calculator_impl( application &app, connection_iface *client )
        :app_(app)
        ,client_(client)
        ,client_channel_(client_channel(client_))
    { }

private:

    typedef std::pair<double, double> number_pair;

    double request_client_variable( const std::string &name ) const
    {
        vtrc_example::variable_pool_Stub stub(client_channel_.get( ));
        vtrc_example::number num;
        num.set_name( name );
        stub.get_variable( NULL, &num, &num, NULL );
        return num.value( );
    }

    number_pair extract_number( const vtrc_example::number_pair* req ) const
    {
        std::pair<double, double> result;

        if( req->first( ).has_value( ) ) result.first = req->first( ).value( );
        else result.first = request_client_variable( req->first( ).name( ) );

        if( req->second( ).has_value( )) result.second = req->second( ).value();
        else result.second = request_client_variable( req->second( ).name( ) );

        return result;
    }

    void sum(::google::protobuf::RpcController* /*controller*/,
             const ::vtrc_example::number_pair* request,
             ::vtrc_example::number* response,
             ::google::protobuf::Closure* done)
    {
        closure_holder done_holder( done );

        number_pair req = extract_number( request );
        response->set_value( req.first + req.second );

    }
    void mul(::google::protobuf::RpcController* /*controller*/,
             const ::vtrc_example::number_pair* request,
             ::vtrc_example::number* response,
             ::google::protobuf::Closure* done)
    {
        closure_holder done_holder( done );
        number_pair req = extract_number( request );
        response->set_value( req.first * req.second );

    }
    void div(::google::protobuf::RpcController* /*controller*/,
             const ::vtrc_example::number_pair* request,
             ::vtrc_example::number* response,
             ::google::protobuf::Closure* done)
    {
        closure_holder done_holder( done );
        number_pair req = extract_number( request );

        if( req.second == 0 )
            throw std::logic_error( "Division by zero. =(" );

        response->set_value( req.first / req.second );

    }

    void pow(::google::protobuf::RpcController* /*controller*/,
             const ::vtrc_example::number_pair* request,
             ::vtrc_example::number* response,
             ::google::protobuf::Closure* done)
    {
        closure_holder done_holder( done );
        number_pair req = extract_number( request );
        response->set_value( ::pow(req.first, req.second) );
    }
};

class my_rpc_wrapper: public rpc_service_wrapper
{
public:
    my_rpc_wrapper( google::protobuf::Service *my_serv )
        :rpc_service_wrapper(my_serv)
    { }
};

class server_application: public application {
public:
    server_application( pool_pair &pair )
        :application( pair )
    {}
    vtrc::shared_ptr<rpc_service_wrapper>
             get_service_by_name( connection_iface* connection,
                                  const std::string &service_name )
    {
        static const std::string calculator_name =
                calculator_impl::descriptor( )->full_name( );

        if( calculator_name == service_name )
            return vtrc::make_shared<my_rpc_wrapper>(
                                    new calculator_impl( *this, connection ) );

        return vtrc::shared_ptr<my_rpc_wrapper>();
    }
};

void usage(  )
{
    std::cout
          << "Usage: \n\tcalculator_server <server ip> <server port>\n"
          << "or:\n\tcalculator_server <localname>\n"
          << "examples:\n"
          << "\tfor tcp: calculator_server 0.0.0.0 55555\n"
          << "\tfor unix: calculator_server /tmp/calculator.sock\n"
          << "\tfor win pipe: calculator_server \\\\.\\pipe\\calculator_pipe\n";
}

int main( int argc, char **argv ) try
{
    if( argc < 2 ) {
        usage( );
        return 1;
    }
    pool_pair pp(1, 1);
    server_application app( pp );

    vtrc::shared_ptr<listener> main_listener;

    if( argc < 3 ) {
#ifndef _WIN32
        main_listener = listeners::unix_local::create(app, argv[1]);
#else
        main_listener = listeners::win_pipe::create(app, argv[1]);
#endif
    } else {
        main_listener = listeners::tcp::create(app, argv[1],
                boost::lexical_cast<unsigned short>(argv[2]));
    }

    std::cout << "starting '" << main_listener->name( ) << "'...";

    main_listener->start( );

    std::cout << "success\n";

    pp.join_all( );

    return 0;

} catch( const std::exception &ex ) {
    std::cout << "General server error: " << ex.what( ) << "\n";
    return 2;
}

<commit_msg>examples/<commit_after>#include <iostream>

#include "google/protobuf/descriptor.h"

#include "vtrc-server/vtrc-application.h"
#include "vtrc-server/vtrc-channels.h"

#include "vtrc-common/vtrc-pool-pair.h"
#include "vtrc-common/vtrc-closure-holder.h"
#include "vtrc-common/vtrc-rpc-service-wrapper.h"

#include "protocol/calculator.pb.h"

#include "vtrc-listener-tcp.h"
#include "vtrc-listener-unix-local.h"
#include "vtrc-listener-win-pipe.h"

#include "vtrc-memory.h"

#include <math.h>
#include <boost/lexical_cast.hpp>

using namespace vtrc::server;
using namespace vtrc::common;

/// calculator implementation
class calculator_impl: public vtrc_example::calculator {

    application      &app_;
    connection_iface *client_;
    vtrc::unique_ptr<rpc_channel> client_channel_;

    static rpc_channel *client_channel( connection_iface *client )
    {
        return channels
                ::unicast
                ::create_callback_channel(client->shared_from_this( ));
    }

public:

    calculator_impl( application &app, connection_iface *client )
        :app_(app)
        ,client_(client)
        ,client_channel_(client_channel(client_))
    { }

private:

    typedef std::pair<double, double> number_pair;

    double request_client_variable( const std::string &name ) const
    {
        vtrc_example::variable_pool_Stub stub(client_channel_.get( ));
        vtrc_example::number num;
        num.set_name( name );
        stub.get_variable( NULL, &num, &num, NULL );
        return num.value( );
    }

    number_pair extract_number( const vtrc_example::number_pair* req ) const
    {
        std::pair<double, double> result;

        if( req->first( ).has_value( ) ) result.first = req->first( ).value( );
        else result.first = request_client_variable( req->first( ).name( ) );

        if( req->second( ).has_value( )) result.second = req->second( ).value();
        else result.second = request_client_variable( req->second( ).name( ) );

        return result;
    }

    void sum(::google::protobuf::RpcController* /*controller*/,
             const ::vtrc_example::number_pair* request,
             ::vtrc_example::number* response,
             ::google::protobuf::Closure* done)
    {
        closure_holder done_holder( done );

        number_pair req = extract_number( request );
        response->set_value( req.first + req.second );

    }
    void mul(::google::protobuf::RpcController* /*controller*/,
             const ::vtrc_example::number_pair* request,
             ::vtrc_example::number* response,
             ::google::protobuf::Closure* done)
    {
        closure_holder done_holder( done );
        number_pair req = extract_number( request );
        response->set_value( req.first * req.second );

    }
    void div(::google::protobuf::RpcController* /*controller*/,
             const ::vtrc_example::number_pair* request,
             ::vtrc_example::number* response,
             ::google::protobuf::Closure* done)
    {
        closure_holder done_holder( done );
        number_pair req = extract_number( request );

        if( req.second == 0 )
            throw std::logic_error( "Division by zero. =(" );

        response->set_value( req.first / req.second );

    }

    void pow(::google::protobuf::RpcController* /*controller*/,
             const ::vtrc_example::number_pair* request,
             ::vtrc_example::number* response,
             ::google::protobuf::Closure* done)
    {
        closure_holder done_holder( done );
        number_pair req = extract_number( request );
        response->set_value( ::pow(req.first, req.second) );
    }
};

/// just in case; rpc_service_wrapper can be used instead
class my_rpc_wrapper: public rpc_service_wrapper
{
public:
    my_rpc_wrapper( google::protobuf::Service *my_serv )
        :rpc_service_wrapper(my_serv)
    { }
};

class server_application: public application {
public:
    server_application( pool_pair &pair )
        :application( pair )
    {}
    vtrc::shared_ptr<rpc_service_wrapper>
             get_service_by_name( connection_iface* connection,
                                  const std::string &service_name )
    {
        static const std::string calculator_name =
                calculator_impl::descriptor( )->full_name( );

        if( calculator_name == service_name )
            return vtrc::make_shared<my_rpc_wrapper>(
                                    new calculator_impl( *this, connection ) );

        return vtrc::shared_ptr<my_rpc_wrapper>();
    }
};

void usage(  )
{
    std::cout
          << "Usage: \n\tcalculator_server <server ip> <server port>\n"
          << "or:\n\tcalculator_server <localname>\n"
          << "examples:\n"
          << "\tfor tcp: calculator_server 0.0.0.0 55555\n"
          << "\tfor unix: calculator_server /tmp/calculator.sock\n"
          << "\tfor win pipe: calculator_server \\\\.\\pipe\\calculator_pipe\n";
}

int main( int argc, char **argv ) try
{
    if( argc < 2 ) {
        usage( );
        return 1;
    }
    pool_pair pp(1, 1);
    server_application app( pp );

    vtrc::shared_ptr<listener> main_listener;

    if( argc < 3 ) {
#ifndef _WIN32
        main_listener = listeners::unix_local::create(app, argv[1]);
#else
        main_listener = listeners::win_pipe::create(app, argv[1]);
#endif
    } else {
        main_listener = listeners::tcp::create(app, argv[1],
                boost::lexical_cast<unsigned short>(argv[2]));
    }

    std::cout << "starting '" << main_listener->name( ) << "'...";

    main_listener->start( );

    std::cout << "success\n";

    pp.join_all( );

    return 0;

} catch( const std::exception &ex ) {
    std::cout << "General server error: " << ex.what( ) << "\n";
    return 2;
}

<|endoftext|>


<commit_before>/**
 * @file llhints.cpp
 * @brief Hint popups for displaying context sensitive help in a UI overlay
 *
 * $LicenseInfo:firstyear=2000&license=viewerlgpl$
 * Second Life Viewer Source Code
 * Copyright (C) 2010, Linden Research, Inc.
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation;
 * version 2.1 of the License only.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 *
 * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
 * $/LicenseInfo$
 */

#include "llviewerprecompiledheaders.h" // must be first include

#include "llhints.h"

#include "llbutton.h"
#include "lltextbox.h"
#include "llviewerwindow.h"
#include "llviewercontrol.h"
#include "lliconctrl.h"
#include "llsdparam.h"

class LLHintPopup : public LLPanel
{
public:

	typedef enum e_popup_direction
	{
		LEFT,
		TOP,
		RIGHT,
		BOTTOM,
		TOP_RIGHT
	} EPopupDirection;

	struct PopupDirections : public LLInitParam::TypeValuesHelper<LLHintPopup::EPopupDirection, PopupDirections>
	{
		static void declareValues()
		{
			declare("left", LLHintPopup::LEFT);
			declare("right", LLHintPopup::RIGHT);
			declare("top", LLHintPopup::TOP);
			declare("bottom", LLHintPopup::BOTTOM);
			declare("top_right", LLHintPopup::TOP_RIGHT);
		}
	};

	struct TargetParams : public LLInitParam::Block<TargetParams>
	{
		Mandatory<std::string>	target;
		Mandatory<EPopupDirection, PopupDirections> direction;

		TargetParams()
		:	target("target"),
			direction("direction")
		{}
	};

	struct Params : public LLInitParam::Block<Params, LLPanel::Params>
	{
		Mandatory<LLNotificationPtr>	notification;
		Optional<TargetParams>			target_params;
		Optional<S32>					distance;
		Optional<LLUIImage*>			left_arrow,
										up_arrow,
										right_arrow,
										down_arrow,
										lower_left_arrow,
										hint_image;

		Optional<S32>					left_arrow_offset,
										up_arrow_offset,
										right_arrow_offset,
										down_arrow_offset;
		Optional<F32>					fade_in_time,
										fade_out_time;

		Params()
		:	distance("distance"),
			left_arrow("left_arrow"),
			up_arrow("up_arrow"),
			right_arrow("right_arrow"),
			down_arrow("down_arrow"),
			lower_left_arrow("lower_left_arrow"),
			hint_image("hint_image"),
			left_arrow_offset("left_arrow_offset"),
			up_arrow_offset("up_arrow_offset"),
			right_arrow_offset("right_arrow_offset"),
			down_arrow_offset("down_arrow_offset"),
			fade_in_time("fade_in_time"),
			fade_out_time("fade_out_time")
		{}
	};

	LLHintPopup(const Params&);

	/*virtual*/ BOOL postBuild();

	void onClickClose() { hide(); LLNotifications::instance().cancel(mNotification); }
	void draw();
	void hide() { if(!mHidden) {mHidden = true; mFadeTimer.reset();} }

private:
	LLNotificationPtr	mNotification;
	std::string			mTarget;
	EPopupDirection		mDirection;
	S32					mDistance;
	LLUIImagePtr		mArrowLeft,
						mArrowUp,
						mArrowRight,
						mArrowDown,
						mArrowDownAndLeft;
	S32					mArrowLeftOffset,
						mArrowUpOffset,
						mArrowRightOffset,
						mArrowDownOffset;
	LLFrameTimer		mFadeTimer;
	F32					mFadeInTime,
						mFadeOutTime;
	bool				mHidden;
};

static LLDefaultChildRegistry::Register<LLHintPopup> r("hint_popup");

LLHintPopup::LLHintPopup(const LLHintPopup::Params& p)
:	mNotification(p.notification),
	mDirection(TOP),
	mDistance(p.distance),
	mArrowLeft(p.left_arrow),
	mArrowUp(p.up_arrow),
	mArrowRight(p.right_arrow),
	mArrowDown(p.down_arrow),
	mArrowDownAndLeft(p.lower_left_arrow),
	mArrowLeftOffset(p.left_arrow_offset),
	mArrowUpOffset(p.up_arrow_offset),
	mArrowRightOffset(p.right_arrow_offset),
	mArrowDownOffset(p.down_arrow_offset),
	mHidden(false),
	mFadeInTime(p.fade_in_time),
	mFadeOutTime(p.fade_out_time),
	LLPanel(p)
{
	if (p.target_params.isProvided())
	{
		mDirection = p.target_params.direction;
		mTarget = p.target_params.target;
	}
	if (p.hint_image.isProvided())
	{
		buildFromFile("panel_hint_image.xml", NULL, p);
		getChild<LLIconCtrl>("hint_image")->setImage(p.hint_image());
	}
	else
	{
		buildFromFile( "panel_hint.xml", NULL, p);
	}
}

BOOL LLHintPopup::postBuild()
{
	LLTextBox& hint_text = getChildRef<LLTextBox>("hint_text");
	hint_text.setText(mNotification->getMessage());

	getChild<LLButton>("close")->setClickedCallback(boost::bind(&LLHintPopup::onClickClose, this));
	getChild<LLTextBox>("hint_title")->setText(mNotification->getLabel());

	LLRect text_bounds = hint_text.getTextBoundingRect();
	S32 delta_height = text_bounds.getHeight() - hint_text.getRect().getHeight();
	reshape(getRect().getWidth(), getRect().getHeight() + delta_height);
	return TRUE;
}

void LLHintPopup::draw()
{
	F32 alpha = 1.f;
	if (mHidden)
	{
		alpha = clamp_rescale(mFadeTimer.getElapsedTimeF32(), 0.f, mFadeOutTime, 1.f, 0.f);
		if (alpha == 0.f)
		{
			die();
			return;
		}
	}
	else
	{
		alpha = clamp_rescale(mFadeTimer.getElapsedTimeF32(), 0.f, mFadeInTime, 0.f, 1.f);
	}

	{	LLViewDrawContext context(alpha);

		if (mTarget.empty())
		{
			// just draw contents, no arrow, in default position
			LLPanel::draw();
		}
		else
		{
			LLView* targetp = LLHints::getHintTarget(mTarget).get();
			if (!targetp)
			{
				// target widget is no longer valid, go away
				die();
			}
			else if (!targetp->isInVisibleChain())
			{
				// if target is invisible, don't draw, but keep alive in case widget comes back
			}
			else
			{
				LLRect target_rect;
				targetp->localRectToOtherView(targetp->getLocalRect(), &target_rect, getParent());

				LLRect my_local_rect = getLocalRect();
				LLRect my_rect;
				LLRect arrow_rect;
				LLUIImagePtr arrow_imagep;

				switch(mDirection)
				{
				case LEFT:
					my_rect.setCenterAndSize(	target_rect.mLeft - (my_local_rect.getWidth() / 2 + mDistance),
												target_rect.getCenterY(),
												my_local_rect.getWidth(),
												my_local_rect.getHeight());
					if (mArrowRight)
					{
						arrow_rect.setCenterAndSize(my_local_rect.mRight + mArrowRight->getWidth() / 2 + mArrowRightOffset,
													my_local_rect.getCenterY(),
													mArrowRight->getWidth(),
													mArrowRight->getHeight());
						arrow_imagep = mArrowRight;
					}
					break;
				case TOP:
					my_rect.setCenterAndSize(	target_rect.getCenterX(),
												target_rect.mTop + (my_local_rect.getHeight() / 2 + mDistance),
												my_local_rect.getWidth(),
												my_local_rect.getHeight());
					if (mArrowDown)
					{
						arrow_rect.setCenterAndSize(my_local_rect.getCenterX(),
													my_local_rect.mBottom - mArrowDown->getHeight() / 2 + mArrowDownOffset,
													mArrowDown->getWidth(),
													mArrowDown->getHeight());
						arrow_imagep = mArrowDown;
					}
					break;
				case RIGHT:
					my_rect.setCenterAndSize(	target_rect.mRight + (my_local_rect.getWidth() / 2 + mDistance),
												target_rect.getCenterY(),
												my_local_rect.getWidth(),
												my_local_rect.getHeight());
					if (mArrowLeft)
					{
						arrow_rect.setCenterAndSize(my_local_rect.mLeft - mArrowLeft->getWidth() / 2 + mArrowLeftOffset,
													my_local_rect.getCenterY(),
													mArrowLeft->getWidth(),
													mArrowLeft->getHeight());
						arrow_imagep = mArrowLeft;
					}
					break;
				case BOTTOM:
					my_rect.setCenterAndSize(	target_rect.getCenterX(),
												target_rect.mBottom - (my_local_rect.getHeight() / 2 + mDistance),
												my_local_rect.getWidth(),
												my_local_rect.getHeight());
					if (mArrowUp)
					{
						arrow_rect.setCenterAndSize(my_local_rect.getCenterX(),
													my_local_rect.mTop + mArrowUp->getHeight() / 2 + mArrowUpOffset,
													mArrowUp->getWidth(),
													mArrowUp->getHeight());
						arrow_imagep = mArrowUp;
					}
					break;
				case TOP_RIGHT:
					my_rect.setCenterAndSize(	target_rect.mRight + (my_local_rect.getWidth() / 2),
												target_rect.mTop + (my_local_rect.getHeight() / 2 + mDistance),
												my_local_rect.getWidth(),
												my_local_rect.getHeight());
					if (mArrowDownAndLeft)
					{
						arrow_rect.setCenterAndSize(my_local_rect.mLeft + mArrowDownAndLeft->getWidth() / 2 + mArrowLeftOffset,
													my_local_rect.mBottom - mArrowDownAndLeft->getHeight() / 2 + mArrowDownOffset,
													mArrowDownAndLeft->getWidth(),
													mArrowDownAndLeft->getHeight());
						arrow_imagep = mArrowDownAndLeft;
					}
				}
				setShape(my_rect);
				LLPanel::draw();

				if (arrow_imagep) arrow_imagep->draw(arrow_rect, LLColor4(1.f, 1.f, 1.f, alpha));
			}
		}
	}
}

LLRegistry<std::string, LLHandle<LLView> > LLHints::sTargetRegistry;
std::map<LLNotificationPtr, class LLHintPopup*> LLHints::sHints;

//static
void LLHints::show(LLNotificationPtr hint)
{
	LLHintPopup::Params p(LLUICtrlFactory::getDefaultParams<LLHintPopup>());

	LLParamSDParser parser;
	parser.readSD(hint->getPayload(), p, true);
	p.notification = hint;

	if (p.validateBlock())
	{
		LLHintPopup* popup = new LLHintPopup(p);

		sHints[hint] = popup;

		LLView* hint_holder = gViewerWindow->getHintHolder();
		if (hint_holder)
		{
			hint_holder->addChild(popup);
			popup->centerWithin(hint_holder->getLocalRect());
		}
	}
}

//static
void LLHints::hide(LLNotificationPtr hint)
{
	hint_map_t::iterator found_it = sHints.find(hint);
	if (found_it != sHints.end())
	{
		found_it->second->hide();
		sHints.erase(found_it);
	}
}

//static
void LLHints::registerHintTarget(const std::string& name, LLHandle<LLView> target)
{
	sTargetRegistry.defaultRegistrar().replace(name, target);
}

//static
LLHandle<LLView> LLHints::getHintTarget(const std::string& name)
{
	LLHandle<LLView>* handlep = sTargetRegistry.getValue(name);
	if (handlep)
	{
		return *handlep;
	}
	else
	{
		return LLHandle<LLView>();
	}
}

//static
void LLHints::initClass()
{
	sRegister.reference();

	LLControlVariablePtr control = gSavedSettings.getControl("EnableUIHints");
	control->getSignal()->connect(boost::bind(&showHints, _2));
	gViewerWindow->getHintHolder()->setVisible(control->getValue().asBoolean());

}

//staic
void LLHints::showHints(const LLSD& show)
{
	bool visible = show.asBoolean();
	gViewerWindow->getHintHolder()->setVisible(visible);
}
<commit_msg>EXP-229 FIXED Double clicking x on UI hint crashes Skylight Viewer<commit_after>/**
 * @file llhints.cpp
 * @brief Hint popups for displaying context sensitive help in a UI overlay
 *
 * $LicenseInfo:firstyear=2000&license=viewerlgpl$
 * Second Life Viewer Source Code
 * Copyright (C) 2010, Linden Research, Inc.
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation;
 * version 2.1 of the License only.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 *
 * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
 * $/LicenseInfo$
 */

#include "llviewerprecompiledheaders.h" // must be first include

#include "llhints.h"

#include "llbutton.h"
#include "lltextbox.h"
#include "llviewerwindow.h"
#include "llviewercontrol.h"
#include "lliconctrl.h"
#include "llsdparam.h"

class LLHintPopup : public LLPanel
{
public:

	typedef enum e_popup_direction
	{
		LEFT,
		TOP,
		RIGHT,
		BOTTOM,
		TOP_RIGHT
	} EPopupDirection;

	struct PopupDirections : public LLInitParam::TypeValuesHelper<LLHintPopup::EPopupDirection, PopupDirections>
	{
		static void declareValues()
		{
			declare("left", LLHintPopup::LEFT);
			declare("right", LLHintPopup::RIGHT);
			declare("top", LLHintPopup::TOP);
			declare("bottom", LLHintPopup::BOTTOM);
			declare("top_right", LLHintPopup::TOP_RIGHT);
		}
	};

	struct TargetParams : public LLInitParam::Block<TargetParams>
	{
		Mandatory<std::string>	target;
		Mandatory<EPopupDirection, PopupDirections> direction;

		TargetParams()
		:	target("target"),
			direction("direction")
		{}
	};

	struct Params : public LLInitParam::Block<Params, LLPanel::Params>
	{
		Mandatory<LLNotificationPtr>	notification;
		Optional<TargetParams>			target_params;
		Optional<S32>					distance;
		Optional<LLUIImage*>			left_arrow,
										up_arrow,
										right_arrow,
										down_arrow,
										lower_left_arrow,
										hint_image;

		Optional<S32>					left_arrow_offset,
										up_arrow_offset,
										right_arrow_offset,
										down_arrow_offset;
		Optional<F32>					fade_in_time,
										fade_out_time;

		Params()
		:	distance("distance"),
			left_arrow("left_arrow"),
			up_arrow("up_arrow"),
			right_arrow("right_arrow"),
			down_arrow("down_arrow"),
			lower_left_arrow("lower_left_arrow"),
			hint_image("hint_image"),
			left_arrow_offset("left_arrow_offset"),
			up_arrow_offset("up_arrow_offset"),
			right_arrow_offset("right_arrow_offset"),
			down_arrow_offset("down_arrow_offset"),
			fade_in_time("fade_in_time"),
			fade_out_time("fade_out_time")
		{}
	};

	LLHintPopup(const Params&);

	/*virtual*/ BOOL postBuild();

	void onClickClose()
	{
		if (!mHidden)
		{
			hide();
			LLNotifications::instance().cancel(mNotification);
		}
	}
	void draw();
	void hide() { if(!mHidden) {mHidden = true; mFadeTimer.reset();} }

private:
	LLNotificationPtr	mNotification;
	std::string			mTarget;
	EPopupDirection		mDirection;
	S32					mDistance;
	LLUIImagePtr		mArrowLeft,
						mArrowUp,
						mArrowRight,
						mArrowDown,
						mArrowDownAndLeft;
	S32					mArrowLeftOffset,
						mArrowUpOffset,
						mArrowRightOffset,
						mArrowDownOffset;
	LLFrameTimer		mFadeTimer;
	F32					mFadeInTime,
						mFadeOutTime;
	bool				mHidden;
};

static LLDefaultChildRegistry::Register<LLHintPopup> r("hint_popup");

LLHintPopup::LLHintPopup(const LLHintPopup::Params& p)
:	mNotification(p.notification),
	mDirection(TOP),
	mDistance(p.distance),
	mArrowLeft(p.left_arrow),
	mArrowUp(p.up_arrow),
	mArrowRight(p.right_arrow),
	mArrowDown(p.down_arrow),
	mArrowDownAndLeft(p.lower_left_arrow),
	mArrowLeftOffset(p.left_arrow_offset),
	mArrowUpOffset(p.up_arrow_offset),
	mArrowRightOffset(p.right_arrow_offset),
	mArrowDownOffset(p.down_arrow_offset),
	mHidden(false),
	mFadeInTime(p.fade_in_time),
	mFadeOutTime(p.fade_out_time),
	LLPanel(p)
{
	if (p.target_params.isProvided())
	{
		mDirection = p.target_params.direction;
		mTarget = p.target_params.target;
	}
	if (p.hint_image.isProvided())
	{
		buildFromFile("panel_hint_image.xml", NULL, p);
		getChild<LLIconCtrl>("hint_image")->setImage(p.hint_image());
	}
	else
	{
		buildFromFile( "panel_hint.xml", NULL, p);
	}
}

BOOL LLHintPopup::postBuild()
{
	LLTextBox& hint_text = getChildRef<LLTextBox>("hint_text");
	hint_text.setText(mNotification->getMessage());

	getChild<LLButton>("close")->setClickedCallback(boost::bind(&LLHintPopup::onClickClose, this));
	getChild<LLTextBox>("hint_title")->setText(mNotification->getLabel());

	LLRect text_bounds = hint_text.getTextBoundingRect();
	S32 delta_height = text_bounds.getHeight() - hint_text.getRect().getHeight();
	reshape(getRect().getWidth(), getRect().getHeight() + delta_height);
	return TRUE;
}

void LLHintPopup::draw()
{
	F32 alpha = 1.f;
	if (mHidden)
	{
		alpha = clamp_rescale(mFadeTimer.getElapsedTimeF32(), 0.f, mFadeOutTime, 1.f, 0.f);
		if (alpha == 0.f)
		{
			die();
			return;
		}
	}
	else
	{
		alpha = clamp_rescale(mFadeTimer.getElapsedTimeF32(), 0.f, mFadeInTime, 0.f, 1.f);
	}

	{	LLViewDrawContext context(alpha);

		if (mTarget.empty())
		{
			// just draw contents, no arrow, in default position
			LLPanel::draw();
		}
		else
		{
			LLView* targetp = LLHints::getHintTarget(mTarget).get();
			if (!targetp)
			{
				// target widget is no longer valid, go away
				die();
			}
			else if (!targetp->isInVisibleChain())
			{
				// if target is invisible, don't draw, but keep alive in case widget comes back
			}
			else
			{
				LLRect target_rect;
				targetp->localRectToOtherView(targetp->getLocalRect(), &target_rect, getParent());

				LLRect my_local_rect = getLocalRect();
				LLRect my_rect;
				LLRect arrow_rect;
				LLUIImagePtr arrow_imagep;

				switch(mDirection)
				{
				case LEFT:
					my_rect.setCenterAndSize(	target_rect.mLeft - (my_local_rect.getWidth() / 2 + mDistance),
												target_rect.getCenterY(),
												my_local_rect.getWidth(),
												my_local_rect.getHeight());
					if (mArrowRight)
					{
						arrow_rect.setCenterAndSize(my_local_rect.mRight + mArrowRight->getWidth() / 2 + mArrowRightOffset,
													my_local_rect.getCenterY(),
													mArrowRight->getWidth(),
													mArrowRight->getHeight());
						arrow_imagep = mArrowRight;
					}
					break;
				case TOP:
					my_rect.setCenterAndSize(	target_rect.getCenterX(),
												target_rect.mTop + (my_local_rect.getHeight() / 2 + mDistance),
												my_local_rect.getWidth(),
												my_local_rect.getHeight());
					if (mArrowDown)
					{
						arrow_rect.setCenterAndSize(my_local_rect.getCenterX(),
													my_local_rect.mBottom - mArrowDown->getHeight() / 2 + mArrowDownOffset,
													mArrowDown->getWidth(),
													mArrowDown->getHeight());
						arrow_imagep = mArrowDown;
					}
					break;
				case RIGHT:
					my_rect.setCenterAndSize(	target_rect.mRight + (my_local_rect.getWidth() / 2 + mDistance),
												target_rect.getCenterY(),
												my_local_rect.getWidth(),
												my_local_rect.getHeight());
					if (mArrowLeft)
					{
						arrow_rect.setCenterAndSize(my_local_rect.mLeft - mArrowLeft->getWidth() / 2 + mArrowLeftOffset,
													my_local_rect.getCenterY(),
													mArrowLeft->getWidth(),
													mArrowLeft->getHeight());
						arrow_imagep = mArrowLeft;
					}
					break;
				case BOTTOM:
					my_rect.setCenterAndSize(	target_rect.getCenterX(),
												target_rect.mBottom - (my_local_rect.getHeight() / 2 + mDistance),
												my_local_rect.getWidth(),
												my_local_rect.getHeight());
					if (mArrowUp)
					{
						arrow_rect.setCenterAndSize(my_local_rect.getCenterX(),
													my_local_rect.mTop + mArrowUp->getHeight() / 2 + mArrowUpOffset,
													mArrowUp->getWidth(),
													mArrowUp->getHeight());
						arrow_imagep = mArrowUp;
					}
					break;
				case TOP_RIGHT:
					my_rect.setCenterAndSize(	target_rect.mRight + (my_local_rect.getWidth() / 2),
												target_rect.mTop + (my_local_rect.getHeight() / 2 + mDistance),
												my_local_rect.getWidth(),
												my_local_rect.getHeight());
					if (mArrowDownAndLeft)
					{
						arrow_rect.setCenterAndSize(my_local_rect.mLeft + mArrowDownAndLeft->getWidth() / 2 + mArrowLeftOffset,
													my_local_rect.mBottom - mArrowDownAndLeft->getHeight() / 2 + mArrowDownOffset,
													mArrowDownAndLeft->getWidth(),
													mArrowDownAndLeft->getHeight());
						arrow_imagep = mArrowDownAndLeft;
					}
				}
				setShape(my_rect);
				LLPanel::draw();

				if (arrow_imagep) arrow_imagep->draw(arrow_rect, LLColor4(1.f, 1.f, 1.f, alpha));
			}
		}
	}
}

LLRegistry<std::string, LLHandle<LLView> > LLHints::sTargetRegistry;
std::map<LLNotificationPtr, class LLHintPopup*> LLHints::sHints;

//static
void LLHints::show(LLNotificationPtr hint)
{
	LLHintPopup::Params p(LLUICtrlFactory::getDefaultParams<LLHintPopup>());

	LLParamSDParser parser;
	parser.readSD(hint->getPayload(), p, true);
	p.notification = hint;

	if (p.validateBlock())
	{
		LLHintPopup* popup = new LLHintPopup(p);

		sHints[hint] = popup;

		LLView* hint_holder = gViewerWindow->getHintHolder();
		if (hint_holder)
		{
			hint_holder->addChild(popup);
			popup->centerWithin(hint_holder->getLocalRect());
		}
	}
}

//static
void LLHints::hide(LLNotificationPtr hint)
{
	hint_map_t::iterator found_it = sHints.find(hint);
	if (found_it != sHints.end())
	{
		found_it->second->hide();
		sHints.erase(found_it);
	}
}

//static
void LLHints::registerHintTarget(const std::string& name, LLHandle<LLView> target)
{
	sTargetRegistry.defaultRegistrar().replace(name, target);
}

//static
LLHandle<LLView> LLHints::getHintTarget(const std::string& name)
{
	LLHandle<LLView>* handlep = sTargetRegistry.getValue(name);
	if (handlep)
	{
		return *handlep;
	}
	else
	{
		return LLHandle<LLView>();
	}
}

//static
void LLHints::initClass()
{
	sRegister.reference();

	LLControlVariablePtr control = gSavedSettings.getControl("EnableUIHints");
	control->getSignal()->connect(boost::bind(&showHints, _2));
	gViewerWindow->getHintHolder()->setVisible(control->getValue().asBoolean());

}

//staic
void LLHints::showHints(const LLSD& show)
{
	bool visible = show.asBoolean();
	gViewerWindow->getHintHolder()->setVisible(visible);
}
<|endoftext|>


<commit_before>#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <string>
#include <vector>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
using namespace std;

/*TODO: refine the commandexec algorithm before proceeding further.
This current algorithm was an initial attempt.
It does not work, and will be replaced. */

int main ()
{

	//bool value use to determine when to kill rshell loop
	bool killrshell = false;

	while (!killrshell && cin.good())
	{

		//bool will store syntax error
		bool synerror = false;
		//string will store raw user input
		string rawinput;
		//vector of strings, will convert to array for execvp
		vector<string> cmds;

		//simple command prompt print
		printf("%s", "$ ");

		//obtain user input commands
		getline(cin, rawinput);

		//temporary break loop condition: user inputs 'exit'
		if (rawinput.substr(0,4) == "exit")
		{
			killrshell = true;
			break;
		}

		//parse through raw input and remove comments if entered
		//removes everything after '#'
		if (rawinput.find('#') != string::npos) rawinput = rawinput.substr(0, rawinput.find('#'));

		//execute the following code ONLY IF STRING IS NOT EMPTY
		if (!rawinput.empty())
		{

			//variables to keep track of whitespaces
			int wspos = 0;
			string parsedinput = rawinput;

			//first remove leading whitespaces at the very beginning of the string
			while (parsedinput.at(wspos) == ' ') wspos++;
			parsedinput = parsedinput.substr(wspos, parsedinput.size());
			//then reinit wsend for removing inner whitespaces
			wspos = 0;

			//next remove trailing whitespaces at the end of the string
			parsedinput += ' '; //add space at the end to make removal easier.
			wspos = parsedinput.size()-1;
			if(parsedinput.at(wspos) == ' ')
			{
				while (parsedinput.at(wspos) == ' ')
				{
					--wspos;
				}

				parsedinput = parsedinput.substr(0, wspos+1);
			}

			//add semicolon to the end of the string to make parsing easier
			parsedinput += ';';

			//initial scan for syntax errors
			if (!isalpha(parsedinput.at(0))) synerror = true;

			//bool variable to tell when the inner for loop is done
			bool seploopdone = false;

			//iterate through string and separate into commands and connectors
			while (synerror != true && seploopdone == false)
			{
				string parsecmd;
				for (unsigned i=0; i<parsedinput.size(); i++)
				{
					if (i >= parsedinput.size()-1) break; //accomodates for concatenated ; at the end of the string
					//checks for & and |
					if ( (parsedinput.at(i) == '&' || parsedinput.at(i) == '|') && parsedinput.at(i+1) == parsedinput.at(i) )
					{
						//if 3 &&& ||| -- syntax error
						if (parsedinput.at(i+2) == parsedinput.at(i))
						{
							synerror =true;
							break;
						}
						else
						{
							string con1;
							con1 += parsedinput.at(i);
							string con2;
							con2 += parsedinput.at(i+1);
							string constring = con1 + con2;
							cmds.push_back(constring);
							parsecmd.clear();
							i++;
						}
					}
					else if (parsedinput.at(i) != ' ')
					{
						parsecmd += parsedinput.at(i);
						if (!isalpha(parsedinput.at(i+1)))
						{
							cmds.push_back(parsecmd);
							parsecmd.clear();
						}
					}
				}
				if(synerror == true) break;
				seploopdone = true;
			}
		}
		cmds.push_back(string(";"));

		vector<string> newvec;
		for (unsigned i = 0; i < cmds.size(); i++)
		{
			//TODO: sort through vector, stop when &&, ||, or ; is found.
			if (cmds.at(i) == "&&" || cmds.at(i) == "||" || cmds.at(i) == ";")
			{
				char** newargv = new char*[newvec.size()+1];
				for (unsigned j = 0; j < newvec.size(); j++)
				{
					newargv[j] = new char[newvec.at(j).size()+1];
					strcpy(newargv[j], newvec.at(j).c_str());
				}
				newargv[newvec.size()] = '\0';

				int execret = 0; //keeps track of exec return value. init to 0
				int pid = fork(); if (pid == -1) perror("fork");
				//if we're in the child
				if (pid == 0)
				{
					execret = execvp(newargv[0], newargv);
					if (-1 == execret)
					{
						perror(*newargv);
						for (unsigned k=0; k < newvec.size(); k++)
						{
							delete[] newargv[i];
						}
						delete[] newargv;
						exit(1);
					}

					//conditions for && and ||
					if (cmds.at(i) == "||" && execret == 0) cmds.clear();
					if (cmds.at(i) == ";" && i == cmds.size()-1) cmds.clear();
				}

				else
				{
					if (-1 == wait(0))
					{
						perror("wait");
						exit(1);
					}
				}
				if (newvec.size() > 0)
				{
					newvec.clear();
					for (unsigned k=0; k < newvec.size(); k++)
					{
							delete[] newargv[i];
					}
					delete[] newargv;
				}
			}
			else
			{
				newvec.push_back(cmds.at(i));
			}
		}

	}

	return 0;
}
<commit_msg>fixed '&&' and '||' errors. added syntax error msg<commit_after>#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <string>
#include <vector>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
using namespace std;

/*TODO: refine the commandexec algorithm before proceeding further.
This current algorithm was an initial attempt.
It does not work, and will be replaced. */

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

	//bool value use to determine when to kill rshell loop
	bool killrshell = false;

	while (!killrshell && cin.good())
	{

		//bool will store syntax error
		bool synerror = false;
		//string will store raw user input
		string rawinput;
		//vector of strings, will convert to array for execvp
		vector<string> cmds;

		//simple command prompt print
		printf("%s", "$ ");

		//obtain user input commands
		getline(cin, rawinput);

		//temporary break loop condition: user inputs 'exit'
		if (rawinput.substr(0,4) == "exit")
		{
			killrshell = true;
			break;
		}

		//parse through raw input and remove comments if entered
		//removes everything after '#'
		if (rawinput.find('#') != string::npos) rawinput = rawinput.substr(0, rawinput.find('#'));

		//execute the following code ONLY IF STRING IS NOT EMPTY
		if (!rawinput.empty())
		{

			//variables to keep track of whitespaces
			int wspos = 0;
			string parsedinput = rawinput;

			//first remove leading whitespaces at the very beginning of the string
			while (parsedinput.at(wspos) == ' ') wspos++;
			parsedinput = parsedinput.substr(wspos, parsedinput.size());
			//then reinit wsend for removing inner whitespaces
			wspos = 0;

			//next remove trailing whitespaces at the end of the string
			parsedinput += ' '; //add space at the end to make removal easier.
			wspos = parsedinput.size()-1;
			if(parsedinput.at(wspos) == ' ')
			{
				while (parsedinput.at(wspos) == ' ')
				{
					--wspos;
				}

				parsedinput = parsedinput.substr(0, wspos+1);
			}

			//add semicolon to the end of the string to make parsing easier
			parsedinput += ';';

			//initial scan for syntax errors
			if (!isalpha(parsedinput.at(0))) synerror = true;

			//bool variable to tell when the inner for loop is done
			bool seploopdone = false;

			//iterate through string and separate into commands and connectors
			while (synerror != true && seploopdone == false)
			{
				string parsecmd;
				for (unsigned i=0; i<parsedinput.size(); i++)
				{
					if (i >= parsedinput.size()-1) break; //accomodates for concatenated ; at the end of the string
					//checks for & and |
					if ( (parsedinput.at(i) == '&' || parsedinput.at(i) == '|') && parsedinput.at(i+1) == parsedinput.at(i) )
					{
						//if 3 &&& ||| -- syntax error
						if (parsedinput.at(i+2) == parsedinput.at(i))
						{
							synerror =true;
							break;
						}
						//if 2+ ;; -- syntax error
						if (parsedinput.at(i) == ';' && (parsedinput.at(i+1) == parsedinput.at(i)))
						{
							synerror = true;
							break;
						}

						else
						{
							string con1;
							con1 += parsedinput.at(i);
							string con2;
							con2 += parsedinput.at(i+1);
							string constring = con1 + con2;
							cmds.push_back(constring);
							parsecmd.clear();
							i++;
						}
					}
					else if (parsedinput.at(i) != ' ')
					{
						parsecmd += parsedinput.at(i);
						if (!isalpha(parsedinput.at(i+1)))
						{
							cmds.push_back(parsecmd);
							parsecmd.clear();
						}
					}
				}
				if(synerror == true) break;
				seploopdone = true;
			}
		}

		if (synerror != true)
		{

			cmds.push_back(string(";"));

			vector<string> newvec;
			for (unsigned i = 0; i < cmds.size(); i++)

				if (cmds.at(i) == "&&" || cmds.at(i) == "||" || cmds.at(i) == ";")
				{
					char** newargv = new char*[newvec.size()+1];
					for (unsigned j = 0; j < newvec.size(); j++)
					{
						newargv[j] = new char[newvec.at(j).size()+1];
						strcpy(newargv[j], newvec.at(j).c_str());
					}
					newargv[newvec.size()] = '\0';

					int execret = 0; //keeps track of exec return value. init to 0
					int pid = fork();
					if (pid == -1) perror("fork");
					//if we're in the child
					if (pid == 0)
					{
						execret = execvp(newargv[0], newargv);
						if (-1 == execret)
						{
							perror(*newargv);
							for (unsigned k=0; k < newvec.size(); k++)
							{
								delete[] newargv[i];
							}
							delete[] newargv;
							exit(1);
						}
					}
					else
					{
						if (-1 == wait(0))
						{
							perror("wait");
							exit(1);
						}
					}
					if (newvec.size() > 0)
					{
						newvec.clear();
						for (unsigned k=0; k < newvec.size(); k++)
						{
								delete[] newargv[i];
						}
						delete[] newargv;
					}
					if (cmds.at(i) == "||" && execret == 0) break;
					if (cmds.at(i) == ";" && i == cmds.size()-1) break;
				}
				else if (cmds.at(i) == "exit" && (cmds.at(i-1) == ";" || cmds.at(i-1) == "&&"))
				{
					killrshell = true;
					break;
				}
				else
				{
					newvec.push_back(cmds.at(i));
				}
			}
			if (synerror == true)
			{
				printf("Syntax error.\n");
			}
		}

	return 0;
}
<|endoftext|>


<commit_before>#include <iostream>     // std::cout
#include <stdlib.h>     // rand()
#include <time.h>       // time()

#include "gtest/gtest.h"

#include "sorting.h"
#include "printarray.h"
#include "verifyarrays.h"

#define quiet

// *********************************************************************
TEST(SimpleSorts, InsertionSort)
{
    const int N = 5;

    double *to_sort_data = new double[N];
    double *sorted_data  = new double[N];

    to_sort_data[0] = 21.3;
    to_sort_data[1] = 68.2;
    to_sort_data[2] = 1.3;
    to_sort_data[3] = 44.3;
    to_sort_data[4] = 10.3;

    memcpy(sorted_data, to_sort_data, N*sizeof(double));

    sorting::simple::InsertionSort(sorted_data, N);

#ifndef quiet
    std::cout << "Arrays" << std::endl;
    std::cout << "Index Original     Sorted " << std::endl;
    for (int i = 0 ; i < N ; i++)
    {
        std::cout << i+1 << "/" << N << "   "
                    << to_sort_data[i] << "        "
                    << sorted_data[i] << std::endl;
    }
#endif // quiet

    for (int i = 1 ; i < N ; i++)
    {
        EXPECT_GE(sorted_data[i], sorted_data[i-1]);
    }

    for (int i = 0 ; i < N ; i++)
    {
        EXPECT_NE(sorted_data[i], 0);
    }
    ASSERT_TRUE(VerifyIfAllNotNaN(sorted_data, N));
    ASSERT_TRUE(VerifyIfOrdered(sorted_data, N));
    ASSERT_TRUE(VerifySortedUnique(to_sort_data, sorted_data, N));

    delete[] to_sort_data;
    delete[] sorted_data;
}

// *********************************************************************
TEST(SimpleSorts, InsertionSortBestCase)
{
    // Best case is O(N) when array already sorted
    const int N = 1000;

    int *to_sort_data = new int[N];
    int *sorted_data  = new int[N];

    for (int i = 0 ; i < N ; i++)
    {
        to_sort_data[i] = i;
    }

    memcpy(sorted_data, to_sort_data, N*sizeof(int));

    sorting::simple::InsertionSort(sorted_data, N);

#ifndef quiet
    std::cout << "Arrays" << std::endl;
    std::cout << "Index Original     Sorted " << std::endl;
    for (int i = 0 ; i < N ; i++)
    {
        std::cout << i+1 << "/" << N << "   "
                    << to_sort_data[i] << "        "
                    << sorted_data[i] << std::endl;
    }
#endif // quiet

    for (int i = 1 ; i < N ; i++)
    {
        EXPECT_GE(sorted_data[i], sorted_data[i-1]);
    }

    ASSERT_TRUE(VerifyIfAllNotNaN(sorted_data, N));
    ASSERT_TRUE(VerifyIfOrdered(sorted_data, N));
    ASSERT_TRUE(VerifySortedUnique(to_sort_data, sorted_data, N));

    delete[] to_sort_data;
    delete[] sorted_data;

}

// *********************************************************************
TEST(SimpleSorts, InsertionSortWorstCase)
{
    // Worst case is O(N^2) when array already sorted, but in reverse order.
    const int N = 1000;

    int *to_sort_data = new int[N];
    int *sorted_data  = new int[N];

    for (int i = 0 ; i < N ; i++)
    {
        to_sort_data[i] = N-i;
    }

    memcpy(sorted_data, to_sort_data, N*sizeof(int));

    sorting::simple::InsertionSort(sorted_data, N);

#ifndef quiet
    std::cout << "Arrays" << std::endl;
    std::cout << "Index Original     Sorted " << std::endl;
    for (int i = 0 ; i < N ; i++)
    {
        std::cout << i+1 << "/" << N << "   "
                    << to_sort_data[i] << "        "
                    << sorted_data[i] << std::endl;
    }
#endif // quiet

    for (int i = 1 ; i < N ; i++)
    {
        EXPECT_GE(sorted_data[i], sorted_data[i-1]);
    }

    ASSERT_TRUE(VerifyIfAllNotNaN(sorted_data, N));
    ASSERT_TRUE(VerifyIfOrdered(sorted_data, N));
    ASSERT_TRUE(VerifySortedUnique(to_sort_data, sorted_data, N));

    delete[] to_sort_data;
    delete[] sorted_data;

}

TEST(SimpleSorts, SelectionSort)
{
    const int N = 1000;

    double *to_sort_data = new double[N];
    double *sorted_data  = new double[N];

    // Initialize the array with random values between 1 and 100
    // NOTE: rand() is a terrible pseudo-random number generator (PRNG).
    // It is still used here for a simple testing task, but don't use it
    // for anything serious.
    srand(time(NULL));
    for (int i = 0 ; i < N ; i++)
    {
        to_sort_data[i] = rand() % 100 + 1;
    }

    memcpy(sorted_data, to_sort_data, N*sizeof(double));

    sorting::simple::SelectionSort(sorted_data, N);

#ifndef quiet
    std::cout << "Arrays" << std::endl;
    std::cout << "Index Original     Sorted " << std::endl;
    for (int i = 0 ; i < N ; i++)
    {
        std::cout << i+1 << "/" << N << "   "
                    << to_sort_data[i] << "        "
                    << sorted_data[i] << std::endl;
    }
#endif // quiet

    for (int i = 1 ; i < N ; i++)
    {
        EXPECT_GE(sorted_data[i], sorted_data[i-1]);
    }

    for (int i = 0 ; i < N ; i++)
    {
        EXPECT_NE(sorted_data[i], 0);
    }
    ASSERT_TRUE(VerifyIfAllNotNaN(sorted_data, N));
    ASSERT_TRUE(VerifyIfOrdered(sorted_data, N));
    ASSERT_TRUE(VerifySortedUnique(to_sort_data, sorted_data, N));

    delete[] to_sort_data;
    delete[] sorted_data;
}

<commit_msg>Adapted simple sorts to new testing macros<commit_after>#include <iostream>     // std::cout
#include <stdlib.h>     // rand()
#include <time.h>       // time()

#include "gtest/gtest.h"

#include "sorting.h"
#include "verifysortedarrays.h"

#define quiet

// *********************************************************************
TEST(SimpleSorts, InsertionSortMultipleSizesDouble)
{
    const double to_sorts[] = {6.0,   5.0,  3.0,  1.0,  2.4, 4.0, 10.0, 7.0,
                               3.42, 32.2, 44.2, 56.3, 67.9, 3.2, 44.2, 2.0};

    VERIFY_SORTING_FIXED_SIZE_ARRAYS(16, double, to_sorts, sorting::simple::InsertionSort, false);
}

// *********************************************************************
TEST(SimpleSorts, InsertionSortMultipleSizesInt)
{
    const double to_sorts[] = {6,  5,  3,  1,  2, 4, 10, 7,
                               3, 32, 44, 56, 67, 3, 44, 2};

    VERIFY_SORTING_FIXED_SIZE_ARRAYS(16, int, to_sorts, sorting::simple::InsertionSort, false);
}

// *********************************************************************
TEST(SimpleSorts, InsertionortKnownResultDouble)
{
    const double to_sorts[] = {6.0,   5.0,  3.0,  1.0,  2.4, 4.0, 10.0, 7.0,
                               3.42, 32.2, 44.2, 56.3, 67.9, 3.2, 44.2, 2.0};
    const double known_sorted[] = { 1.0, 2.0,  2.4,  3.0,  3.2,  3.42,  4.0,  5.0,
                                    6.0, 7.0, 10.0, 32.2, 44.2, 44.2,  56.3, 67.9};

    VERIFY_SORTING_FIXED_SIZE_ARRAYS_AND_COMPARE(16, double, to_sorts, known_sorted, sorting::simple::InsertionSort, false);
}

// *********************************************************************
TEST(SimpleSorts, InsertionSortKnownResultInt)
{
    const double to_sorts[] = {6,   5,  3,  1,  2, 4, 10, 7,
                               3, 32, 44, 56, 67, 3, 44, 2};
    const double known_sorted[] = { 1, 2,  2,  3,  3,  3,  4,  5,
                                    6, 7, 10, 32, 44, 44,  56, 67};

    VERIFY_SORTING_FIXED_SIZE_ARRAYS_AND_COMPARE(16, int, to_sorts, known_sorted, sorting::simple::InsertionSort, false);
}

// *********************************************************************
TEST(SimpleSorts, InsertionSortMultipleSizesRandomDouble)
{
    VERIFY_SORTING_RANDOM_ARRAYS(100, double, sorting::simple::InsertionSort, false)
}

// *********************************************************************
TEST(SimpleSorts, InsertionSortMultipleSizesRandomInt)
{
    VERIFY_SORTING_RANDOM_ARRAYS(100, int, sorting::simple::InsertionSort, false)
}

// *********************************************************************
TEST(SimpleSorts, InsertionSortSortedDouble)
{
    VERIFY_SORTING_SORTED_ARRAY(100, double, sorting::simple::InsertionSort, false);
}

// *********************************************************************
TEST(SimpleSorts, InsertionSortSortedInt)
{
    VERIFY_SORTING_SORTED_ARRAY(100, int, sorting::simple::InsertionSort, false);
}

// *********************************************************************
TEST(SimpleSorts, InsertionSortInvSortedDouble)
{
    VERIFY_SORTING_INV_SORTED_ARRAY(100, double, sorting::simple::InsertionSort, false);
}

// *********************************************************************
TEST(SimpleSorts, InsertionSortInvSortedInt)
{
    VERIFY_SORTING_INV_SORTED_ARRAY(100, int, sorting::simple::InsertionSort, false);
}

// #####################################################################
// #####################################################################

// *********************************************************************
TEST(SimpleSorts, SelectionSortMultipleSizesDouble)
{
    const double to_sorts[] = {6.0,   5.0,  3.0,  1.0,  2.4, 4.0, 10.0, 7.0,
                               3.42, 32.2, 44.2, 56.3, 67.9, 3.2, 44.2, 2.0};

    VERIFY_SORTING_FIXED_SIZE_ARRAYS(16, double, to_sorts, sorting::simple::SelectionSort, false);
}

// *********************************************************************
TEST(SimpleSorts, SelectionSortMultipleSizesInt)
{
    const double to_sorts[] = {6,  5,  3,  1,  2, 4, 10, 7,
                               3, 32, 44, 56, 67, 3, 44, 2};

    VERIFY_SORTING_FIXED_SIZE_ARRAYS(16, int, to_sorts, sorting::simple::SelectionSort, false);
}

// *********************************************************************
TEST(SimpleSorts, SelectionSortKnownResultDouble)
{
    const double to_sorts[] = {6.0,   5.0,  3.0,  1.0,  2.4, 4.0, 10.0, 7.0,
                               3.42, 32.2, 44.2, 56.3, 67.9, 3.2, 44.2, 2.0};
    const double known_sorted[] = { 1.0, 2.0,  2.4,  3.0,  3.2,  3.42,  4.0,  5.0,
                                    6.0, 7.0, 10.0, 32.2, 44.2, 44.2,  56.3, 67.9};

    VERIFY_SORTING_FIXED_SIZE_ARRAYS_AND_COMPARE(16, double, to_sorts, known_sorted, sorting::simple::SelectionSort, false);
}

// *********************************************************************
TEST(SimpleSorts, SelectionSortKnownResultInt)
{
    const double to_sorts[] = {6,   5,  3,  1,  2, 4, 10, 7,
                               3, 32, 44, 56, 67, 3, 44, 2};
    const double known_sorted[] = { 1, 2,  2,  3,  3,  3,  4,  5,
                                    6, 7, 10, 32, 44, 44,  56, 67};

    VERIFY_SORTING_FIXED_SIZE_ARRAYS_AND_COMPARE(16, int, to_sorts, known_sorted, sorting::simple::SelectionSort, false);
}

// *********************************************************************
TEST(SimpleSorts, SelectionSortMultipleSizesRandomDouble)
{
    VERIFY_SORTING_RANDOM_ARRAYS(100, double, sorting::simple::SelectionSort, false)
}

// *********************************************************************
TEST(SimpleSorts, SelectionSortMultipleSizesRandomInt)
{
    VERIFY_SORTING_RANDOM_ARRAYS(100, int, sorting::simple::SelectionSort, false)
}

// *********************************************************************
TEST(SimpleSorts, SelectionSortSortedDouble)
{
    VERIFY_SORTING_SORTED_ARRAY(100, double, sorting::simple::SelectionSort, false);
}

// *********************************************************************
TEST(SimpleSorts, SelectionSortSortedInt)
{
    VERIFY_SORTING_SORTED_ARRAY(100, int, sorting::simple::SelectionSort, false);
}

// *********************************************************************
TEST(SimpleSorts, SelectionSortInvSortedDouble)
{
    VERIFY_SORTING_INV_SORTED_ARRAY(100, double, sorting::simple::SelectionSort, false);
}

// *********************************************************************
TEST(SimpleSorts, SelectionSortInvSortedInt)
{
    VERIFY_SORTING_INV_SORTED_ARRAY(100, int, sorting::simple::SelectionSort, false);
}
<|endoftext|>