<commit_before>// Copyright (c) 2013, German Neuroinformatics Node (G-Node)
//
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted under the terms of the BSD License. See
// LICENSE file in the root of the Project.

#include <nix/Source.hpp>

#include <queue>
#include <nix/File.hpp>
#include <nix/util/util.hpp>

using namespace nix;

Source::Source()
    : EntityWithMetadata()
{
}

Source::Source(const Source &other)
    : EntityWithMetadata(other.impl())
{
}

Source::Source(const std::shared_ptr<base::ISource> &p_impl)
    : EntityWithMetadata(p_impl)
{
}

Source::Source(std::shared_ptr<base::ISource> &&ptr)
    : EntityWithMetadata(std::move(ptr))
{
}

//--------------------------------------------------
// Methods concerning child sources
//--------------------------------------------------

Source Source::createSource(const std::string &name, const std::string &type) {
    util::checkEntityNameAndType(name, type);
    if(backend()->hasSource(name)) {
        throw DuplicateName("Source with the given name already exists!");
    }
    return backend()->createSource(name, type);
}

bool Source::hasSource(const Source &source) const {
    if (!util::checkEntityInput(source, false)) {
        return  false;
    }
    return backend()->hasSource(source.id());
}

std::vector<Source> Source::sources(const util::Filter<Source>::type &filter) const {
    auto f = [this] (ndsize_t i) { return getSource(i); };
    return getEntities<Source>(f, sourceCount(), filter);
}

bool Source::deleteSource(const Source &source) {
    if (!util::checkEntityInput(source, false)) {
        return  false;
    }
    return backend()->deleteSource(source.id());
}

struct SourceCont {
    Source entity;
    size_t depth;
};

std::vector<Source> Source::findSources(const util::Filter<Source>::type &filter,
                                        size_t max_depth) const
{
    std::vector<Source>  results;
    std::queue<SourceCont> todo;

    todo.push({*this, 0});

    while (todo.size() > 0)
    {
        SourceCont current = todo.front();
        todo.pop();

        bool filter_ok = filter(current.entity);
        if (filter_ok) {
            results.push_back(current.entity);
        }

        if (current.depth < max_depth) {
            std::vector<Source> children = current.entity.sources();
            size_t next_depth = current.depth + 1;

            for (auto it = children.begin(); it != children.end(); ++it) {
                todo.push({*it, next_depth});
            }
        }
    }

    return results;
}

//------------------------------------------------------
// Operators and other functions
//------------------------------------------------------

std::vector<nix::DataArray> Source::referringDataArrays() const {
    std::vector<nix::DataArray> arrays;
    nix::File f = backend()->parentFile();
    for (auto b : f.blocks()) {
        std::vector<nix::DataArray> temp = b.dataArrays(nix::util::SourceFilter<nix::DataArray>(id()));
        arrays.insert(arrays.end(), temp.begin(), temp.end());
    }
    return arrays;
}

std::vector<nix::Tag> Source::referringTags() const {
    std::vector<nix::Tag> tags;
    nix::File f = backend()->parentFile();
    for (auto b : f.blocks()) {
        std::vector<nix::Tag> temp = b.tags(nix::util::SourceFilter<nix::Tag>(id()));
        tags.insert(tags.end(), temp.begin(), temp.end());
    }
    return tags;
}

std::vector<nix::MultiTag> Source::referringMultiTags() const {
    std::vector<nix::MultiTag> tags;
    nix::File f = backend()->parentFile();
    for (auto b : f.blocks()) {
        std::vector<nix::MultiTag> temp =  b.multiTags(nix::util::SourceFilter<nix::MultiTag>(id()));
        tags.insert(tags.end(), temp.begin(), temp.end());
    }
    return tags;
}

std::ostream& nix::operator<<(std::ostream &out, const Source &ent) {
    out << "Source: {name = " << ent.name();
    out << ", type = " << ent.type();
    out << ", id = " << ent.id() << "}";
    return out;
}

<commit_msg>[Source] simplify referringXYZ methods<commit_after>// Copyright (c) 2013, German Neuroinformatics Node (G-Node)
//
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted under the terms of the BSD License. See
// LICENSE file in the root of the Project.

#include <nix/Source.hpp>

#include <queue>
#include <nix/File.hpp>
#include <nix/util/util.hpp>

using namespace nix;

Source::Source()
    : EntityWithMetadata()
{
}

Source::Source(const Source &other)
    : EntityWithMetadata(other.impl())
{
}

Source::Source(const std::shared_ptr<base::ISource> &p_impl)
    : EntityWithMetadata(p_impl)
{
}

Source::Source(std::shared_ptr<base::ISource> &&ptr)
    : EntityWithMetadata(std::move(ptr))
{
}

//--------------------------------------------------
// Methods concerning child sources
//--------------------------------------------------

Source Source::createSource(const std::string &name, const std::string &type) {
    util::checkEntityNameAndType(name, type);
    if(backend()->hasSource(name)) {
        throw DuplicateName("Source with the given name already exists!");
    }
    return backend()->createSource(name, type);
}

bool Source::hasSource(const Source &source) const {
    if (!util::checkEntityInput(source, false)) {
        return  false;
    }
    return backend()->hasSource(source.id());
}

std::vector<Source> Source::sources(const util::Filter<Source>::type &filter) const {
    auto f = [this] (ndsize_t i) { return getSource(i); };
    return getEntities<Source>(f, sourceCount(), filter);
}

bool Source::deleteSource(const Source &source) {
    if (!util::checkEntityInput(source, false)) {
        return  false;
    }
    return backend()->deleteSource(source.id());
}

struct SourceCont {
    Source entity;
    size_t depth;
};

std::vector<Source> Source::findSources(const util::Filter<Source>::type &filter,
                                        size_t max_depth) const
{
    std::vector<Source>  results;
    std::queue<SourceCont> todo;

    todo.push({*this, 0});

    while (todo.size() > 0)
    {
        SourceCont current = todo.front();
        todo.pop();

        bool filter_ok = filter(current.entity);
        if (filter_ok) {
            results.push_back(current.entity);
        }

        if (current.depth < max_depth) {
            std::vector<Source> children = current.entity.sources();
            size_t next_depth = current.depth + 1;

            for (auto it = children.begin(); it != children.end(); ++it) {
                todo.push({*it, next_depth});
            }
        }
    }

    return results;
}

//------------------------------------------------------
// Operators and other functions
//------------------------------------------------------

std::vector<nix::DataArray> Source::referringDataArrays() const {
    nix::File f = backend()->parentFile();
    nix::Block b = backend()->parentBlock();
    return b.dataArrays(nix::util::SourceFilter<nix::DataArray>(id()));
}

std::vector<nix::Tag> Source::referringTags() const {
    nix::File f = backend()->parentFile();
    nix::Block b = backend()->parentBlock();
    return b.tags(nix::util::SourceFilter<nix::Tag>(id()));
}

std::vector<nix::MultiTag> Source::referringMultiTags() const {
    nix::File f = backend()->parentFile();
    nix::Block b = backend()->parentBlock();
    return b.multiTags(nix::util::SourceFilter<nix::MultiTag>(id()));
}

std::ostream& nix::operator<<(std::ostream &out, const Source &ent) {
    out << "Source: {name = " << ent.name();
    out << ", type = " << ent.type();
    out << ", id = " << ent.id() << "}";
    return out;
}

<|endoftext|>


<commit_before>// Copyright 2011 Google Inc. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include "metrics.h"

#include <errno.h>
#include <stdio.h>
#include <string.h>

#ifndef WIN32
#include <sys/time.h>
#else
#include <windows.h>
#endif

#include "util.h"

Metrics* g_metrics = NULL;

namespace {

#ifndef WIN32
/// Compute a platform-specific high-res timer value that fits into an int64.
int64_t HighResTimer() {
  timeval tv;
  if (gettimeofday(&tv, NULL) < 0)
    Fatal("gettimeofday: %s", strerror(errno));
  return (int64_t)tv.tv_sec * 1000*1000 + tv.tv_usec;
}

/// Convert a delta of HighResTimer() values to microseconds.
int64_t TimerToMicros(int64_t dt) {
  // No conversion necessary.
  return dt;
}
#else
int64_t LargeIntegerToInt64(const LARGE_INTEGER& i) {
  return ((int64_t)i.HighPart) << 32 | i.LowPart;
}

int64_t HighResTimer() {
  LARGE_INTEGER counter;
  if (!QueryPerformanceCounter(&counter))
    Fatal("QueryPerformanceCounter: %s", GetLastErrorString().c_str());
  return LargeIntegerToInt64(counter);
}

int64_t TimerToMicros(int64_t dt) {
  static int64_t ticks_per_sec = 0;
  if (!ticks_per_sec) {
    LARGE_INTEGER freq;
    if (!QueryPerformanceFrequency(&freq))
      Fatal("QueryPerformanceFrequency: %s", GetLastErrorString().c_str());
    ticks_per_sec = LargeIntegerToInt64(freq);
  }

  // dt is in ticks.  We want microseconds.
  return (dt * 1000000) / ticks_per_sec;
}
#endif

}  // anonymous namespace

ScopedMetric::ScopedMetric(Metric* metric) {
  metric_ = metric;
  if (!metric_)
    return;
  start_ = HighResTimer();
}
ScopedMetric::~ScopedMetric() {
  if (!metric_)
    return;
  metric_->count++;
  int64_t dt = TimerToMicros(HighResTimer() - start_);
  metric_->sum += dt;
}

Metric* Metrics::NewMetric(const string& name) {
  Metric* metric = new Metric;
  metric->name = name;
  metric->count = 0;
  metric->sum = 0;
  metrics_.push_back(metric);
  return metric;
}

void Metrics::Report() {
  printf("%-10s\t%-6s\t%9s\t%s\n",
         "metric", "count", "total (ms)" , "avg (us)");
  for (vector<Metric*>::iterator i = metrics_.begin(); i != metrics_.end(); ++i) {
    Metric* metric = *i;
    double total = metric->sum / (double)1000;
    double avg = metric->sum / (double)metric->count;
    printf("%-10s\t%-6d\t%-8.1f\t%.1f\n", metric->name.c_str(),
           metric->count, total, avg);
  }
}
<commit_msg>dynamic metrics report width<commit_after>// Copyright 2011 Google Inc. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include "metrics.h"

#include <errno.h>
#include <stdio.h>
#include <string.h>

#ifndef WIN32
#include <sys/time.h>
#else
#include <windows.h>
#endif

#include "util.h"

Metrics* g_metrics = NULL;

namespace {

#ifndef WIN32
/// Compute a platform-specific high-res timer value that fits into an int64.
int64_t HighResTimer() {
  timeval tv;
  if (gettimeofday(&tv, NULL) < 0)
    Fatal("gettimeofday: %s", strerror(errno));
  return (int64_t)tv.tv_sec * 1000*1000 + tv.tv_usec;
}

/// Convert a delta of HighResTimer() values to microseconds.
int64_t TimerToMicros(int64_t dt) {
  // No conversion necessary.
  return dt;
}
#else
int64_t LargeIntegerToInt64(const LARGE_INTEGER& i) {
  return ((int64_t)i.HighPart) << 32 | i.LowPart;
}

int64_t HighResTimer() {
  LARGE_INTEGER counter;
  if (!QueryPerformanceCounter(&counter))
    Fatal("QueryPerformanceCounter: %s", GetLastErrorString().c_str());
  return LargeIntegerToInt64(counter);
}

int64_t TimerToMicros(int64_t dt) {
  static int64_t ticks_per_sec = 0;
  if (!ticks_per_sec) {
    LARGE_INTEGER freq;
    if (!QueryPerformanceFrequency(&freq))
      Fatal("QueryPerformanceFrequency: %s", GetLastErrorString().c_str());
    ticks_per_sec = LargeIntegerToInt64(freq);
  }

  // dt is in ticks.  We want microseconds.
  return (dt * 1000000) / ticks_per_sec;
}
#endif

}  // anonymous namespace

ScopedMetric::ScopedMetric(Metric* metric) {
  metric_ = metric;
  if (!metric_)
    return;
  start_ = HighResTimer();
}
ScopedMetric::~ScopedMetric() {
  if (!metric_)
    return;
  metric_->count++;
  int64_t dt = TimerToMicros(HighResTimer() - start_);
  metric_->sum += dt;
}

Metric* Metrics::NewMetric(const string& name) {
  Metric* metric = new Metric;
  metric->name = name;
  metric->count = 0;
  metric->sum = 0;
  metrics_.push_back(metric);
  return metric;
}

void Metrics::Report() {
  int width = 0;
  for (vector<Metric*>::iterator i = metrics_.begin();
       i != metrics_.end(); ++i) {
    width = max((int)(*i)->name.size(), width);
  }

  printf("%-*s\t%-6s\t%9s\t%s\n", width,
         "metric", "count", "total (ms)" , "avg (us)");
  for (vector<Metric*>::iterator i = metrics_.begin();
       i != metrics_.end(); ++i) {
    Metric* metric = *i;
    double total = metric->sum / (double)1000;
    double avg = metric->sum / (double)metric->count;
    printf("%-*s\t%-6d\t%-8.1f\t%.1f\n", width, metric->name.c_str(),
           metric->count, total, avg);
  }
}
<|endoftext|>


<commit_before>#include "MDPattern.hh"
#include "Elektron.hh"
#include "MDMessages.hh"
#include "helpers.h"
#include "MDParams.hh"

#include "GUI.h"

bool MDPattern::fromSysex(uint8_t *data, uint16_t len) {
  if (len != 0xACA - 6)  {
    // wrong length
    return false;
  }

  uint16_t cksum = 0;
  for (int i = 9 - 6; i < 0xAC6 - 6; i++) {
    cksum += data[i];
  }
  cksum &= 0x3FFF;
  if (cksum != to16Bit(data[0xAC6 - 6], data[0xAC7 - 6])) {
    // wrong checksum
    return false;
  }

  origPosition = data[9 - 6];
  uint8_t data2[204];
  sysex_to_data_elektron(data + 0xA - 6, data2, 74);
  uint8_t *ptr = data2;
  for (int i = 0; i < 16; i++) {
    trigPatterns[i] = to32Bit(ptr);
    ptr += 4;
  }

  sysex_to_data_elektron(data + 0x54 - 6, data2, 74);
  ptr = data2;
  for (int i = 0; i < 16; i++) {
    lockPatterns[i] = to32Bit(ptr);
    ptr += 4;
  }

  sysex_to_data_elektron(data + 0x9e - 6, data2, 19);
  accentPattern = to32Bit(data2);
  slidePattern = to32Bit(data2 + 4);
  swingPattern = to32Bit(data2 + 8);
  swingAmount = to32Bit(data2 + 12);

  accentAmount = data[0xB1 - 6];
  patternLength = data[0xB2 - 6];
  doubleTempo = (data[0xb3 - 6] == 1);
  scale = data[0xb4 - 6];
  kit = data[0xb5 - 6];
  numLockedRows = data[0xb6 - 6];
  sysex_to_data_elektron(data + 0xB7 - 6, (uint8_t *)locks, 2341);
  sysex_to_data_elektron(data + 0x9DC - 6, data2, 234);

  accentEditAll = (to32Bit(data2) == 1);
  slideEditAll = (to32Bit(data2 + 4) == 1);
  swingEditAll = (to32Bit(data2 + 8) == 1);

  ptr = data2 + 12;
  for (int i = 0; i < 16; i++) {
    accentPatterns[i] = to32Bit(ptr);
    ptr += 4;
  }
  for (int i = 0; i < 16; i++) {
    slidePatterns[i] = to32Bit(ptr);
    ptr += 4;
  }
  for (int i = 0; i < 16; i++) {
    swingPatterns[i] = to32Bit(ptr);
    ptr += 4;
  }

  for (int i = 0; i < 16; i++) {
    for (int j = 0; j < 24; j++) {
      paramLocks[i][j] = -1;
    }
  }

  numRows = 0;
  for (int i = 0; i < 64; i++) {
    lockTracks[i] = -1;
    lockParams[i] = -1;
  }

  for (int i = 0; i < 16; i++) {
    for (int j = 0; j < 24; j++) {
      paramLocks[i][j] = -1;
      if (IS_BIT_SET(lockPatterns[i], j)) {
	paramLocks[i][j] = numRows;
	lockTracks[numRows] = i;
	lockParams[numRows] = j;
	numRows++;
      }
    }
  }

  return true;

}

uint16_t MDPattern::toSysex(uint8_t *data, uint16_t len) {
  if (len < 0xacb)
    return 0;

  m_memclr(data, 0xACB);

  data[0] = 0xF0;
  m_memcpy(data + 1, machinedrum_sysex_hdr, sizeof(machinedrum_sysex_hdr));

  data[6] = MD_PATTERN_MESSAGE_ID;
  data[7] = 0x03; // version
  data[8] = 0x01;
  data[9] = origPosition;

  uint8_t data2[204];
  uint8_t *ptr = data2;

  for (int i = 0; i < 16; i++) {
    from32Bit(trigPatterns[i], ptr);
    ptr += 4;
  }
  data_to_sysex_elektron(data2, data + 0xA, 64);

  recalculateLockPatterns();
  ptr = data2;
  for (int i = 0; i < 16; i++) {
    from32Bit(lockPatterns[i], ptr);
    ptr += 4;
  }
  data_to_sysex_elektron(data2, data + 0x54, 64);

  from32Bit(accentPattern, data2);
  from32Bit(slidePattern, data2 + 4);
  from32Bit(swingPattern, data2 + 8);
  from32Bit(swingAmount, data2 + 12);
  data_to_sysex_elektron(data2, data + 0x9e, 16);

  data[0xB1] = accentAmount;
  data[0xB2] = patternLength;
  data[0xb3] = doubleTempo ? 1 : 0;
  data[0xb4] = scale;
  data[0xb5] = kit;
  data[0xb6] = numLockedRows;

  uint16_t retlen = 0;
  uint16_t cnt = 0;

  ptr = data + 0xB7;
  {
    uint16_t cnt7 = 0;

    ptr[0] = 0;

    for (int track = 0; track < 16; track++) {
      for (int param = 0; param < 24; param++) {
	if (paramLocks[track][param] != -1) {
	  uint8_t *data3 = locks[paramLocks[track][param]];

	  for (int i = 0; i < 32; i++) {
	    uint8_t c = data3[i] & 0x7F;
	    uint8_t msb = data3[i] >> 7;
	    ptr[0] |= msb << (6 - cnt7);
	    ptr[1 + cnt7] = c;

	    if (cnt7++ == 6) {
	      ptr += 8;
	      retlen += 8;
	      ptr[0] = 0;
	      cnt7 = 0;
	    }

	    cnt++;
	  }
	}
      }
    }

    for (uint16_t i = cnt; i < 64 * 32; i++) {
      uint8_t c = 0 & 0x7F;
      uint8_t msb = 0 >> 7;
      ptr[0] |= msb << (6 - cnt7);
      ptr[1 + cnt7] = c;

      if (cnt7++ == 6) {
	ptr += 8;
	retlen += 8;
	ptr[0] = 0;
	cnt7 = 0;
      }

      cnt++;
    }

    retlen += cnt7 + (cnt7 != 0 ? 1 : 0);
  }

  from32Bit(accentEditAll ? 1 : 0, data2);
  from32Bit(slideEditAll ? 1 : 0, data2 + 4);
  from32Bit(swingEditAll ? 1 : 0, data2 + 8);

  ptr = data2 + 12;
  for (int i = 0; i < 16; i++) {
    from32Bit(accentPatterns[i], ptr);
    ptr += 4;
  }
  for (int i = 0; i < 16; i++) {
    from32Bit(slidePatterns[i], ptr);
    ptr += 4;
  }
  for (int i = 0; i < 16; i++) {
    from32Bit(swingPatterns[i], ptr);
    ptr += 4;
  }
  data_to_sysex_elektron(data2, data + 0x9DC, 204);

  uint16_t checksum = 0;
  for (int i = 9; i < 0xac6; i++)
    checksum += data[i];
  data[0xac6] = (uint8_t)((checksum >> 7) & 0x7F);
  data[0xac7] = (uint8_t)(checksum & 0x7F);
  uint16_t length = 0xacb - 7 - 3;
  data[0xac8] = (uint8_t)((length >> 7) &0x7F);
  data[0xac9] = (uint8_t)(length & 0x7F);
  data[0xaca] = 0xF7;

  return 0xacb;
}

bool MDPattern::isLockPatternEmpty(uint8_t idx) {
  for (int i = 0; i < 32; i++) {
    if (locks[idx][i] != 255)
      return false;
  }
  return true;
}

bool MDPattern::isLockPatternEmpty(uint8_t idx, uint32_t trigs) {
  for (int i = 0; i < 32; i++) {
    if (locks[idx][i] != 255 || !IS_BIT_SET(trigs, i))
      return false;
  }

  return true;
}

void MDPattern::cleanupLocks() {
  for (int i = 0; i < 64; i++) {
    if (lockTracks[i] != -1) {
      if (isLockPatternEmpty(i, trigPatterns[lockTracks[i]])) {
	if (lockParams[i] != -1) {
	  paramLocks[lockTracks[i]][lockParams[i]] = -1;
	}
	lockTracks[i] = -1;
	lockParams[i] = -1;
      }
    } else {
      lockParams[i] = -1;
    }
  }
}

void MDPattern::clearPattern() {
  for (int i = 0; i < 16; i++) {
    clearTrack(i);
  }
}

void MDPattern::clearTrack(uint8_t track) {
  if (track >= 16)
    return;
  for (int i = 0; i < 32; i++) {
    clearTrig(track, i);
  }
}

void MDPattern::clearLockPattern(uint8_t lock) {
  if (lock >= 64)
    return;

  for (int i = 0; i < 32; i++) {
    locks[lock][i] = 255;
    if (lockTracks[lock] != -1 && lockParams[lock] != -1) {
      paramLocks[lockTracks[lock]][lockParams[lock]] = -1;
    }
    lockTracks[lock] = -1;
    lockParams[lock] = -1;
  }
}

void MDPattern::clearParamLocks(uint8_t track, uint8_t param) {
  int8_t idx = paramLocks[track][param];
  if (idx != -1) {
    clearLockPattern(idx);
  }
}

void MDPattern::clearTrackLocks(uint8_t track) {
  for (int i = 0; i < 24; i++) {
    clearParamLocks(track, i);
  }
}

void MDPattern::clearTrig(uint8_t track, uint8_t trig) {
  CLEAR_BIT(trigPatterns[track], trig);
  for (int i = 0; i < 24; i++) {
    clearLock(track, trig, i);
  }
}

void MDPattern::setTrig(uint8_t track, uint8_t trig) {
  SET_BIT(trigPatterns[track], trig);
}

int8_t MDPattern::getNextEmptyLock() {
  for (int i = 0; i < 64; i++) {
    if (lockTracks[i] == -1 && lockParams[i] == -1) {
      return i;
    }
  }
  return -1;
}

bool MDPattern::addLock(uint8_t track, uint8_t trig, uint8_t param, uint8_t value) {
  int8_t idx = paramLocks[track][param];
  if (idx == -1) {
    idx = getNextEmptyLock();
    if (idx == -1)
      return false;
    paramLocks[track][param] = idx;
    lockTracks[idx] = track;
    lockParams[idx] = param;
  }
  locks[idx][trig] = value;
  return true;
}

void MDPattern::clearLock(uint8_t track, uint8_t trig, uint8_t param) {
  int8_t idx = paramLocks[track][param];
  if (idx == -1)
    return;
  locks[idx][trig] = 255;

  if (isLockPatternEmpty(idx, trigPatterns[track])) {
    paramLocks[track][param] = -1;
    lockTracks[idx] = -1;
    lockParams[idx] = -1;
  }
}

void MDPattern::recalculateLockPatterns() {
  for (int track = 0; track < 16; track++) {
    lockPatterns[track] = 0;
    for (int param = 0; param < 24; param++) {
      if (paramLocks[track][param] != -1) {
	SET_BIT(lockPatterns[track], param);
      }
    }
  }
}

uint8_t MDPattern::getLock(uint8_t track, uint8_t trig, uint8_t param) {
  int8_t idx = paramLocks[track][param];
  if (idx == -1)
    return 255;
  return locks[idx][trig];
}

<commit_msg>init locks when adding a new row<commit_after>#include "MDPattern.hh"
#include "Elektron.hh"
#include "MDMessages.hh"
#include "helpers.h"
#include "MDParams.hh"

#include "GUI.h"

bool MDPattern::fromSysex(uint8_t *data, uint16_t len) {
  if (len != 0xACA - 6)  {
    // wrong length
    return false;
  }

  uint16_t cksum = 0;
  for (int i = 9 - 6; i < 0xAC6 - 6; i++) {
    cksum += data[i];
  }
  cksum &= 0x3FFF;
  if (cksum != to16Bit(data[0xAC6 - 6], data[0xAC7 - 6])) {
    // wrong checksum
    return false;
  }

  origPosition = data[9 - 6];
  uint8_t data2[204];
  sysex_to_data_elektron(data + 0xA - 6, data2, 74);
  uint8_t *ptr = data2;
  for (int i = 0; i < 16; i++) {
    trigPatterns[i] = to32Bit(ptr);
    ptr += 4;
  }

  sysex_to_data_elektron(data + 0x54 - 6, data2, 74);
  ptr = data2;
  for (int i = 0; i < 16; i++) {
    lockPatterns[i] = to32Bit(ptr);
    ptr += 4;
  }

  sysex_to_data_elektron(data + 0x9e - 6, data2, 19);
  accentPattern = to32Bit(data2);
  slidePattern = to32Bit(data2 + 4);
  swingPattern = to32Bit(data2 + 8);
  swingAmount = to32Bit(data2 + 12);

  accentAmount = data[0xB1 - 6];
  patternLength = data[0xB2 - 6];
  doubleTempo = (data[0xb3 - 6] == 1);
  scale = data[0xb4 - 6];
  kit = data[0xb5 - 6];
  numLockedRows = data[0xb6 - 6];
  sysex_to_data_elektron(data + 0xB7 - 6, (uint8_t *)locks, 2341);
  sysex_to_data_elektron(data + 0x9DC - 6, data2, 234);

  accentEditAll = (to32Bit(data2) == 1);
  slideEditAll = (to32Bit(data2 + 4) == 1);
  swingEditAll = (to32Bit(data2 + 8) == 1);

  ptr = data2 + 12;
  for (int i = 0; i < 16; i++) {
    accentPatterns[i] = to32Bit(ptr);
    ptr += 4;
  }
  for (int i = 0; i < 16; i++) {
    slidePatterns[i] = to32Bit(ptr);
    ptr += 4;
  }
  for (int i = 0; i < 16; i++) {
    swingPatterns[i] = to32Bit(ptr);
    ptr += 4;
  }

  for (int i = 0; i < 16; i++) {
    for (int j = 0; j < 24; j++) {
      paramLocks[i][j] = -1;
    }
  }

  numRows = 0;
  for (int i = 0; i < 64; i++) {
    lockTracks[i] = -1;
    lockParams[i] = -1;
  }

  for (int i = 0; i < 16; i++) {
    for (int j = 0; j < 24; j++) {
      paramLocks[i][j] = -1;
      if (IS_BIT_SET(lockPatterns[i], j)) {
	paramLocks[i][j] = numRows;
	lockTracks[numRows] = i;
	lockParams[numRows] = j;
	numRows++;
      }
    }
  }

  return true;

}

uint16_t MDPattern::toSysex(uint8_t *data, uint16_t len) {
  if (len < 0xacb)
    return 0;

  m_memclr(data, 0xACB);

  data[0] = 0xF0;
  m_memcpy(data + 1, machinedrum_sysex_hdr, sizeof(machinedrum_sysex_hdr));

  data[6] = MD_PATTERN_MESSAGE_ID;
  data[7] = 0x03; // version
  data[8] = 0x01;
  data[9] = origPosition;

  uint8_t data2[204];
  uint8_t *ptr = data2;

  for (int i = 0; i < 16; i++) {
    from32Bit(trigPatterns[i], ptr);
    ptr += 4;
  }
  data_to_sysex_elektron(data2, data + 0xA, 64);

  recalculateLockPatterns();
  ptr = data2;
  for (int i = 0; i < 16; i++) {
    from32Bit(lockPatterns[i], ptr);
    ptr += 4;
  }
  data_to_sysex_elektron(data2, data + 0x54, 64);

  from32Bit(accentPattern, data2);
  from32Bit(slidePattern, data2 + 4);
  from32Bit(swingPattern, data2 + 8);
  from32Bit(swingAmount, data2 + 12);
  data_to_sysex_elektron(data2, data + 0x9e, 16);

  data[0xB1] = accentAmount;
  data[0xB2] = patternLength;
  data[0xb3] = doubleTempo ? 1 : 0;
  data[0xb4] = scale;
  data[0xb5] = kit;
  data[0xb6] = numLockedRows;

  uint16_t retlen = 0;
  uint16_t cnt = 0;

  ptr = data + 0xB7;
  {
    uint16_t cnt7 = 0;

    ptr[0] = 0;

    for (int track = 0; track < 16; track++) {
      for (int param = 0; param < 24; param++) {
	if (paramLocks[track][param] != -1) {
	  uint8_t *data3 = locks[paramLocks[track][param]];

	  for (int i = 0; i < 32; i++) {
	    uint8_t c = data3[i] & 0x7F;
	    uint8_t msb = data3[i] >> 7;
	    ptr[0] |= msb << (6 - cnt7);
	    ptr[1 + cnt7] = c;

	    if (cnt7++ == 6) {
	      ptr += 8;
	      retlen += 8;
	      ptr[0] = 0;
	      cnt7 = 0;
	    }

	    cnt++;
	  }
	}
      }
    }

    for (uint16_t i = cnt; i < 64 * 32; i++) {
      uint8_t c = 0 & 0x7F;
      uint8_t msb = 0 >> 7;
      ptr[0] |= msb << (6 - cnt7);
      ptr[1 + cnt7] = c;

      if (cnt7++ == 6) {
	ptr += 8;
	retlen += 8;
	ptr[0] = 0;
	cnt7 = 0;
      }

      cnt++;
    }

    retlen += cnt7 + (cnt7 != 0 ? 1 : 0);
  }

  from32Bit(accentEditAll ? 1 : 0, data2);
  from32Bit(slideEditAll ? 1 : 0, data2 + 4);
  from32Bit(swingEditAll ? 1 : 0, data2 + 8);

  ptr = data2 + 12;
  for (int i = 0; i < 16; i++) {
    from32Bit(accentPatterns[i], ptr);
    ptr += 4;
  }
  for (int i = 0; i < 16; i++) {
    from32Bit(slidePatterns[i], ptr);
    ptr += 4;
  }
  for (int i = 0; i < 16; i++) {
    from32Bit(swingPatterns[i], ptr);
    ptr += 4;
  }
  data_to_sysex_elektron(data2, data + 0x9DC, 204);

  uint16_t checksum = 0;
  for (int i = 9; i < 0xac6; i++)
    checksum += data[i];
  data[0xac6] = (uint8_t)((checksum >> 7) & 0x7F);
  data[0xac7] = (uint8_t)(checksum & 0x7F);
  uint16_t length = 0xacb - 7 - 3;
  data[0xac8] = (uint8_t)((length >> 7) &0x7F);
  data[0xac9] = (uint8_t)(length & 0x7F);
  data[0xaca] = 0xF7;

  return 0xacb;
}

bool MDPattern::isLockPatternEmpty(uint8_t idx) {
  for (int i = 0; i < 32; i++) {
    if (locks[idx][i] != 255)
      return false;
  }
  return true;
}

bool MDPattern::isLockPatternEmpty(uint8_t idx, uint32_t trigs) {
  for (int i = 0; i < 32; i++) {
    if (locks[idx][i] != 255 || !IS_BIT_SET(trigs, i))
      return false;
  }

  return true;
}

void MDPattern::cleanupLocks() {
  for (int i = 0; i < 64; i++) {
    if (lockTracks[i] != -1) {
      if (isLockPatternEmpty(i, trigPatterns[lockTracks[i]])) {
	if (lockParams[i] != -1) {
	  paramLocks[lockTracks[i]][lockParams[i]] = -1;
	}
	lockTracks[i] = -1;
	lockParams[i] = -1;
      }
    } else {
      lockParams[i] = -1;
    }
  }
}

void MDPattern::clearPattern() {
  for (int i = 0; i < 16; i++) {
    clearTrack(i);
  }
}

void MDPattern::clearTrack(uint8_t track) {
  if (track >= 16)
    return;
  for (int i = 0; i < 32; i++) {
    clearTrig(track, i);
  }
}

void MDPattern::clearLockPattern(uint8_t lock) {
  if (lock >= 64)
    return;

  for (int i = 0; i < 32; i++) {
    locks[lock][i] = 255;
    if (lockTracks[lock] != -1 && lockParams[lock] != -1) {
      paramLocks[lockTracks[lock]][lockParams[lock]] = -1;
    }
    lockTracks[lock] = -1;
    lockParams[lock] = -1;
  }
}

void MDPattern::clearParamLocks(uint8_t track, uint8_t param) {
  int8_t idx = paramLocks[track][param];
  if (idx != -1) {
    clearLockPattern(idx);
  }
}

void MDPattern::clearTrackLocks(uint8_t track) {
  for (int i = 0; i < 24; i++) {
    clearParamLocks(track, i);
  }
}

void MDPattern::clearTrig(uint8_t track, uint8_t trig) {
  CLEAR_BIT(trigPatterns[track], trig);
  for (int i = 0; i < 24; i++) {
    clearLock(track, trig, i);
  }
}

void MDPattern::setTrig(uint8_t track, uint8_t trig) {
  SET_BIT(trigPatterns[track], trig);
}

int8_t MDPattern::getNextEmptyLock() {
  for (int i = 0; i < 64; i++) {
    if (lockTracks[i] == -1 && lockParams[i] == -1) {
      return i;
    }
  }
  return -1;
}

bool MDPattern::addLock(uint8_t track, uint8_t trig, uint8_t param, uint8_t value) {
  int8_t idx = paramLocks[track][param];
  if (idx == -1) {
    idx = getNextEmptyLock();
    if (idx == -1)
      return false;
    paramLocks[track][param] = idx;
    lockTracks[idx] = track;
    lockParams[idx] = param;
    for (int i = 0; i < 32; i++) {
      locks[idx][i] = 255;
    }
  }
  locks[idx][trig] = value;
  return true;
}

void MDPattern::clearLock(uint8_t track, uint8_t trig, uint8_t param) {
  int8_t idx = paramLocks[track][param];
  if (idx == -1)
    return;
  locks[idx][trig] = 255;

  if (isLockPatternEmpty(idx, trigPatterns[track])) {
    paramLocks[track][param] = -1;
    lockTracks[idx] = -1;
    lockParams[idx] = -1;
  }
}

void MDPattern::recalculateLockPatterns() {
  for (int track = 0; track < 16; track++) {
    lockPatterns[track] = 0;
    for (int param = 0; param < 24; param++) {
      if (paramLocks[track][param] != -1) {
	SET_BIT(lockPatterns[track], param);
      }
    }
  }
}

uint8_t MDPattern::getLock(uint8_t track, uint8_t trig, uint8_t param) {
  int8_t idx = paramLocks[track][param];
  if (idx == -1)
    return 255;
  return locks[idx][trig];
}

<|endoftext|>


<commit_before>/*
 * Copyright 2011-2017 Branimir Karadzic. All rights reserved.
 * License: https://github.com/bkaradzic/bgfx#license-bsd-2-clause
 */

#include "common.h"
#include "bgfx_utils.h"

#include <bx/uint32_t.h>
#include "imgui/imgui.h"

#include <bgfx/embedded_shader.h>

// embedded shaders
#include "vs_drawstress.bin.h"
#include "fs_drawstress.bin.h"

namespace
{

static const bgfx::EmbeddedShader s_embeddedShaders[] =
{
	BGFX_EMBEDDED_SHADER(vs_drawstress),
	BGFX_EMBEDDED_SHADER(fs_drawstress),

	BGFX_EMBEDDED_SHADER_END()
};

struct PosColorVertex
{
	float m_x;
	float m_y;
	float m_z;
	uint32_t m_abgr;

	static void init()
	{
		ms_decl
			.begin()
			.add(bgfx::Attrib::Position, 3, bgfx::AttribType::Float)
			.add(bgfx::Attrib::Color0,   4, bgfx::AttribType::Uint8, true)
			.end();
	}

	static bgfx::VertexDecl ms_decl;
};

bgfx::VertexDecl PosColorVertex::ms_decl;

static PosColorVertex s_cubeVertices[8] =
{
	{-1.0f,  1.0f,  1.0f, 0xff000000 },
	{ 1.0f,  1.0f,  1.0f, 0xff0000ff },
	{-1.0f, -1.0f,  1.0f, 0xff00ff00 },
	{ 1.0f, -1.0f,  1.0f, 0xff00ffff },
	{-1.0f,  1.0f, -1.0f, 0xffff0000 },
	{ 1.0f,  1.0f, -1.0f, 0xffff00ff },
	{-1.0f, -1.0f, -1.0f, 0xffffff00 },
	{ 1.0f, -1.0f, -1.0f, 0xffffffff },
};

static const uint16_t s_cubeIndices[36] =
{
	0, 1, 2, // 0
	1, 3, 2,
	4, 6, 5, // 2
	5, 6, 7,
	0, 2, 4, // 4
	4, 2, 6,
	1, 5, 3, // 6
	5, 7, 3,
	0, 4, 1, // 8
	4, 5, 1,
	2, 3, 6, // 10
	6, 3, 7,
};

#if BX_PLATFORM_EMSCRIPTEN
static const int64_t highwm = 1000000/35;
static const int64_t lowwm  = 1000000/27;
#else
static const int64_t highwm = 1000000/65;
static const int64_t lowwm  = 1000000/57;
#endif // BX_PLATFORM_EMSCRIPTEN

class ExampleDrawStress : public entry::AppI
{
public:
	ExampleDrawStress(const char* _name, const char* _description)
		: entry::AppI(_name, _description)
	{
	}

	void init(int32_t _argc, const char* const* _argv, uint32_t _width, uint32_t _height) override
	{
		Args args(_argc, _argv);

		m_width  = _width;
		m_height = _height;
		m_debug  = BGFX_DEBUG_NONE;
		m_reset  = BGFX_RESET_NONE;

		m_autoAdjust = true;
		m_scrollArea = 0;
		m_dim        = 16;
		m_maxDim     = 40;
		m_transform  = 0;

		m_timeOffset = bx::getHPCounter();

		m_deltaTimeNs    = 0;
		m_deltaTimeAvgNs = 0;
		m_numFrames      = 0;

		bgfx::init(args.m_type, args.m_pciId);
		bgfx::reset(m_width, m_height, m_reset);

		const bgfx::Caps* caps = bgfx::getCaps();
		m_maxDim = (int32_t)bx::fpow(float(caps->limits.maxDrawCalls), 1.0f/3.0f);

		// Enable debug text.
		bgfx::setDebug(m_debug);

		// Set view 0 clear state.
		bgfx::setViewClear(0
			, BGFX_CLEAR_COLOR|BGFX_CLEAR_DEPTH
			, 0x303030ff
			, 1.0f
			, 0
			);

		// Create vertex stream declaration.
		PosColorVertex::init();

		bgfx::RendererType::Enum type = bgfx::getRendererType();

		// Create program from shaders.
		m_program = bgfx::createProgram(
			  bgfx::createEmbeddedShader(s_embeddedShaders, type, "vs_drawstress")
			, bgfx::createEmbeddedShader(s_embeddedShaders, type, "fs_drawstress")
			, true /* destroy shaders when program is destroyed */
			);

		// Create static vertex buffer.
		m_vbh = bgfx::createVertexBuffer(
			  bgfx::makeRef(s_cubeVertices, sizeof(s_cubeVertices) )
			, PosColorVertex::ms_decl
			);

		// Create static index buffer.
		m_ibh = bgfx::createIndexBuffer(bgfx::makeRef(s_cubeIndices, sizeof(s_cubeIndices) ) );

		// Imgui.
		imguiCreate();
	}

	int shutdown() override
	{
		// Cleanup.
		imguiDestroy();
		bgfx::destroy(m_ibh);
		bgfx::destroy(m_vbh);
		bgfx::destroy(m_program);

		// Shutdown bgfx.
		bgfx::shutdown();

		return 0;
	}

	bool update() override
	{
		if (!entry::processEvents(m_width, m_height, m_debug, m_reset, &m_mouseState) )
		{
			int64_t now = bx::getHPCounter();
			static int64_t last = now;
			const int64_t hpFreq = bx::getHPFrequency();
			const int64_t frameTime = now - last;
			last = now;
			const double freq = double(hpFreq);
			const double toMs = 1000.0/freq;

			m_deltaTimeNs += frameTime*1000000/hpFreq;

			if (m_deltaTimeNs > 1000000)
			{
				m_deltaTimeAvgNs = m_deltaTimeNs / bx::int64_max(1, m_numFrames);

				if (m_autoAdjust)
				{
					if (m_deltaTimeAvgNs < highwm)
					{
						m_dim = bx::uint32_min(m_dim + 2, m_maxDim);
					}
					else if (m_deltaTimeAvgNs > lowwm)
					{
						m_dim = bx::uint32_max(m_dim - 1, 2);
					}
				}

				m_deltaTimeNs = 0;
				m_numFrames   = 0;
			}
			else
			{
				++m_numFrames;
			}

			float time = (float)( (now-m_timeOffset)/freq);

			imguiBeginFrame(m_mouseState.m_mx
				,  m_mouseState.m_my
				, (m_mouseState.m_buttons[entry::MouseButton::Left  ] ? IMGUI_MBUT_LEFT   : 0)
				| (m_mouseState.m_buttons[entry::MouseButton::Right ] ? IMGUI_MBUT_RIGHT  : 0)
				| (m_mouseState.m_buttons[entry::MouseButton::Middle] ? IMGUI_MBUT_MIDDLE : 0)
				,  m_mouseState.m_mz
				, uint16_t(m_width)
				, uint16_t(m_height)
				);

			showExampleDialog(this);

			ImGui::SetNextWindowPos(ImVec2((float)m_width - (float)m_width / 4.0f - 10.0f, 10.0f) );
			ImGui::SetNextWindowSize(ImVec2((float)m_width / 4.0f, (float)m_height / 2.0f) );
			ImGui::Begin("Settings"
				, NULL
				, ImVec2((float)m_width / 4.0f, (float)m_height / 2.0f)
				, ImGuiWindowFlags_AlwaysAutoResize
				);

			ImGui::RadioButton("Rotate",&m_transform,0);
			ImGui::RadioButton("No fragments",&m_transform,1);
			ImGui::Separator();

			ImGui::Checkbox("Auto adjust", &m_autoAdjust);

			ImGui::SliderInt("Dim", &m_dim, 5, m_maxDim);
			ImGui::Text("Draw calls: %d", m_dim*m_dim*m_dim);
			ImGui::Text("Avg Delta Time (1 second) [ms]: %0.4f", m_deltaTimeAvgNs/1000.0f);

			ImGui::Separator();
			const bgfx::Stats* stats = bgfx::getStats();
			ImGui::Text("GPU %0.6f [ms]", double(stats->gpuTimeEnd - stats->gpuTimeBegin)*1000.0/stats->gpuTimerFreq);
			ImGui::Text("CPU %0.6f [ms]", double(stats->cpuTimeEnd - stats->cpuTimeBegin)*1000.0/stats->cpuTimerFreq);
			ImGui::Text("Waiting for render thread %0.6f [ms]", double(stats->waitRender) * toMs);
			ImGui::Text("Waiting for submit thread %0.6f [ms]", double(stats->waitSubmit) * toMs);

			ImGui::End();

			imguiEndFrame();

			float at[3] = { 0.0f, 0.0f, 0.0f };
			float eye[3] = { 0.0f, 0.0f, -35.0f };

			float view[16];
			bx::mtxLookAt(view, eye, at);

			const bgfx::Caps* caps = bgfx::getCaps();
			float proj[16];
			bx::mtxProj(proj, 60.0f, float(m_width)/float(m_height), 0.1f, 100.0f, caps->homogeneousDepth);

			// Set view and projection matrix for view 0.
			bgfx::setViewTransform(0, view, proj);

			// Set view 0 default viewport.
			bgfx::setViewRect(0, 0, 0, uint16_t(m_width), uint16_t(m_height) );

			// This dummy draw call is here to make sure that view 0 is cleared
			// if no other draw calls are submitted to view 0.
			bgfx::touch(0);

			float mtxS[16];
			const float scale = 0 == m_transform ? 0.25f : 0.0f;
			bx::mtxScale(mtxS, scale, scale, scale);

			const float step = 0.6f;
			float pos[3];
			pos[0] = -step*m_dim / 2.0f;
			pos[1] = -step*m_dim / 2.0f;
			pos[2] = -15.0;

			for (uint32_t zz = 0; zz < uint32_t(m_dim); ++zz)
			{
				for (uint32_t yy = 0; yy < uint32_t(m_dim); ++yy)
				{
					for (uint32_t xx = 0; xx < uint32_t(m_dim); ++xx)
					{
						float mtxR[16];
						bx::mtxRotateXYZ(mtxR, time + xx*0.21f, time + yy*0.37f, time + yy*0.13f);

						float mtx[16];
						bx::mtxMul(mtx, mtxS, mtxR);

						mtx[12] = pos[0] + float(xx)*step;
						mtx[13] = pos[1] + float(yy)*step;
						mtx[14] = pos[2] + float(zz)*step;

						// Set model matrix for rendering.
						bgfx::setTransform(mtx);

						// Set vertex and index buffer.
						bgfx::setVertexBuffer(0, m_vbh);
						bgfx::setIndexBuffer(m_ibh);

						// Set render states.
						bgfx::setState(BGFX_STATE_DEFAULT);

						// Submit primitive for rendering to view 0.
						bgfx::submit(0, m_program);
					}
				}
			}

			// Advance to next frame. Rendering thread will be kicked to
			// process submitted rendering primitives.
			bgfx::frame();

			return true;
		}

		return false;
	}

	entry::MouseState m_mouseState;

	uint32_t m_width;
	uint32_t m_height;
	uint32_t m_debug;
	uint32_t m_reset;

	bool     m_autoAdjust;
	int32_t  m_scrollArea;
	int32_t  m_dim;
	int32_t  m_maxDim;
	int32_t  m_transform;

	int64_t  m_timeOffset;

	int64_t  m_deltaTimeNs;
	int64_t  m_deltaTimeAvgNs;
	int64_t  m_numFrames;

	bgfx::ProgramHandle m_program;
	bgfx::VertexBufferHandle m_vbh;
	bgfx::IndexBufferHandle  m_ibh;
};

} // namespace

ENTRY_IMPLEMENT_MAIN(ExampleDrawStress, "17-drawstress", "Draw stress, maximizing number of draw calls.");
<commit_msg>Switching 17-drawstress to use encoder API.<commit_after>/*
 * Copyright 2011-2017 Branimir Karadzic. All rights reserved.
 * License: https://github.com/bkaradzic/bgfx#license-bsd-2-clause
 */

#include "common.h"
#include "bgfx_utils.h"

#include <bx/uint32_t.h>
#include "imgui/imgui.h"

#include <bgfx/embedded_shader.h>

// embedded shaders
#include "vs_drawstress.bin.h"
#include "fs_drawstress.bin.h"

namespace
{

static const bgfx::EmbeddedShader s_embeddedShaders[] =
{
	BGFX_EMBEDDED_SHADER(vs_drawstress),
	BGFX_EMBEDDED_SHADER(fs_drawstress),

	BGFX_EMBEDDED_SHADER_END()
};

struct PosColorVertex
{
	float m_x;
	float m_y;
	float m_z;
	uint32_t m_abgr;

	static void init()
	{
		ms_decl
			.begin()
			.add(bgfx::Attrib::Position, 3, bgfx::AttribType::Float)
			.add(bgfx::Attrib::Color0,   4, bgfx::AttribType::Uint8, true)
			.end();
	}

	static bgfx::VertexDecl ms_decl;
};

bgfx::VertexDecl PosColorVertex::ms_decl;

static PosColorVertex s_cubeVertices[8] =
{
	{-1.0f,  1.0f,  1.0f, 0xff000000 },
	{ 1.0f,  1.0f,  1.0f, 0xff0000ff },
	{-1.0f, -1.0f,  1.0f, 0xff00ff00 },
	{ 1.0f, -1.0f,  1.0f, 0xff00ffff },
	{-1.0f,  1.0f, -1.0f, 0xffff0000 },
	{ 1.0f,  1.0f, -1.0f, 0xffff00ff },
	{-1.0f, -1.0f, -1.0f, 0xffffff00 },
	{ 1.0f, -1.0f, -1.0f, 0xffffffff },
};

static const uint16_t s_cubeIndices[36] =
{
	0, 1, 2, // 0
	1, 3, 2,
	4, 6, 5, // 2
	5, 6, 7,
	0, 2, 4, // 4
	4, 2, 6,
	1, 5, 3, // 6
	5, 7, 3,
	0, 4, 1, // 8
	4, 5, 1,
	2, 3, 6, // 10
	6, 3, 7,
};

#if BX_PLATFORM_EMSCRIPTEN
static const int64_t highwm = 1000000/35;
static const int64_t lowwm  = 1000000/27;
#else
static const int64_t highwm = 1000000/65;
static const int64_t lowwm  = 1000000/57;
#endif // BX_PLATFORM_EMSCRIPTEN

class ExampleDrawStress : public entry::AppI
{
public:
	ExampleDrawStress(const char* _name, const char* _description)
		: entry::AppI(_name, _description)
	{
	}

	void init(int32_t _argc, const char* const* _argv, uint32_t _width, uint32_t _height) override
	{
		Args args(_argc, _argv);

		m_width  = _width;
		m_height = _height;
		m_debug  = BGFX_DEBUG_NONE;
		m_reset  = BGFX_RESET_NONE;

		m_autoAdjust = true;
		m_scrollArea = 0;
		m_dim        = 16;
		m_maxDim     = 40;
		m_transform  = 0;

		m_timeOffset = bx::getHPCounter();

		m_deltaTimeNs    = 0;
		m_deltaTimeAvgNs = 0;
		m_numFrames      = 0;

		bgfx::init(args.m_type, args.m_pciId);
		bgfx::reset(m_width, m_height, m_reset);

		const bgfx::Caps* caps = bgfx::getCaps();
		m_maxDim = (int32_t)bx::fpow(float(caps->limits.maxDrawCalls), 1.0f/3.0f);

		// Enable debug text.
		bgfx::setDebug(m_debug);

		// Set view 0 clear state.
		bgfx::setViewClear(0
			, BGFX_CLEAR_COLOR|BGFX_CLEAR_DEPTH
			, 0x303030ff
			, 1.0f
			, 0
			);

		// Create vertex stream declaration.
		PosColorVertex::init();

		bgfx::RendererType::Enum type = bgfx::getRendererType();

		// Create program from shaders.
		m_program = bgfx::createProgram(
			  bgfx::createEmbeddedShader(s_embeddedShaders, type, "vs_drawstress")
			, bgfx::createEmbeddedShader(s_embeddedShaders, type, "fs_drawstress")
			, true /* destroy shaders when program is destroyed */
			);

		// Create static vertex buffer.
		m_vbh = bgfx::createVertexBuffer(
			  bgfx::makeRef(s_cubeVertices, sizeof(s_cubeVertices) )
			, PosColorVertex::ms_decl
			);

		// Create static index buffer.
		m_ibh = bgfx::createIndexBuffer(bgfx::makeRef(s_cubeIndices, sizeof(s_cubeIndices) ) );

		// Imgui.
		imguiCreate();
	}

	int shutdown() override
	{
		// Cleanup.
		imguiDestroy();
		bgfx::destroy(m_ibh);
		bgfx::destroy(m_vbh);
		bgfx::destroy(m_program);

		// Shutdown bgfx.
		bgfx::shutdown();

		return 0;
	}

	bool update() override
	{
		if (!entry::processEvents(m_width, m_height, m_debug, m_reset, &m_mouseState) )
		{
			int64_t now = bx::getHPCounter();
			static int64_t last = now;
			const int64_t hpFreq = bx::getHPFrequency();
			const int64_t frameTime = now - last;
			last = now;
			const double freq = double(hpFreq);
			const double toMs = 1000.0/freq;

			m_deltaTimeNs += frameTime*1000000/hpFreq;

			if (m_deltaTimeNs > 1000000)
			{
				m_deltaTimeAvgNs = m_deltaTimeNs / bx::int64_max(1, m_numFrames);

				if (m_autoAdjust)
				{
					if (m_deltaTimeAvgNs < highwm)
					{
						m_dim = bx::uint32_min(m_dim + 2, m_maxDim);
					}
					else if (m_deltaTimeAvgNs > lowwm)
					{
						m_dim = bx::uint32_max(m_dim - 1, 2);
					}
				}

				m_deltaTimeNs = 0;
				m_numFrames   = 0;
			}
			else
			{
				++m_numFrames;
			}

			float time = (float)( (now-m_timeOffset)/freq);

			imguiBeginFrame(m_mouseState.m_mx
				,  m_mouseState.m_my
				, (m_mouseState.m_buttons[entry::MouseButton::Left  ] ? IMGUI_MBUT_LEFT   : 0)
				| (m_mouseState.m_buttons[entry::MouseButton::Right ] ? IMGUI_MBUT_RIGHT  : 0)
				| (m_mouseState.m_buttons[entry::MouseButton::Middle] ? IMGUI_MBUT_MIDDLE : 0)
				,  m_mouseState.m_mz
				, uint16_t(m_width)
				, uint16_t(m_height)
				);

			showExampleDialog(this);

			ImGui::SetNextWindowPos(ImVec2((float)m_width - (float)m_width / 4.0f - 10.0f, 10.0f) );
			ImGui::SetNextWindowSize(ImVec2((float)m_width / 4.0f, (float)m_height / 2.0f) );
			ImGui::Begin("Settings"
				, NULL
				, ImVec2((float)m_width / 4.0f, (float)m_height / 2.0f)
				, ImGuiWindowFlags_AlwaysAutoResize
				);

			ImGui::RadioButton("Rotate",&m_transform,0);
			ImGui::RadioButton("No fragments",&m_transform,1);
			ImGui::Separator();

			ImGui::Checkbox("Auto adjust", &m_autoAdjust);

			ImGui::SliderInt("Dim", &m_dim, 5, m_maxDim);
			ImGui::Text("Draw calls: %d", m_dim*m_dim*m_dim);
			ImGui::Text("Avg Delta Time (1 second) [ms]: %0.4f", m_deltaTimeAvgNs/1000.0f);

			ImGui::Separator();
			const bgfx::Stats* stats = bgfx::getStats();
			ImGui::Text("GPU %0.6f [ms]", double(stats->gpuTimeEnd - stats->gpuTimeBegin)*1000.0/stats->gpuTimerFreq);
			ImGui::Text("CPU %0.6f [ms]", double(stats->cpuTimeEnd - stats->cpuTimeBegin)*1000.0/stats->cpuTimerFreq);
			ImGui::Text("Waiting for render thread %0.6f [ms]", double(stats->waitRender) * toMs);
			ImGui::Text("Waiting for submit thread %0.6f [ms]", double(stats->waitSubmit) * toMs);

			ImGui::End();

			imguiEndFrame();

			float at[3] = { 0.0f, 0.0f, 0.0f };
			float eye[3] = { 0.0f, 0.0f, -35.0f };

			float view[16];
			bx::mtxLookAt(view, eye, at);

			const bgfx::Caps* caps = bgfx::getCaps();
			float proj[16];
			bx::mtxProj(proj, 60.0f, float(m_width)/float(m_height), 0.1f, 100.0f, caps->homogeneousDepth);

			// Set view and projection matrix for view 0.
			bgfx::setViewTransform(0, view, proj);

			// Set view 0 default viewport.
			bgfx::setViewRect(0, 0, 0, uint16_t(m_width), uint16_t(m_height) );

			// This dummy draw call is here to make sure that view 0 is cleared
			// if no other draw calls are submitted to view 0.
			bgfx::touch(0);

			float mtxS[16];
			const float scale = 0 == m_transform ? 0.25f : 0.0f;
			bx::mtxScale(mtxS, scale, scale, scale);

			const float step = 0.6f;
			float pos[3];
			pos[0] = -step*m_dim / 2.0f;
			pos[1] = -step*m_dim / 2.0f;
			pos[2] = -15.0;

			bgfx::Encoder* encoder = bgfx::begin();

			for (uint32_t zz = 0; zz < uint32_t(m_dim); ++zz)
			{
				for (uint32_t yy = 0; yy < uint32_t(m_dim); ++yy)
				{
					for (uint32_t xx = 0; xx < uint32_t(m_dim); ++xx)
					{
						float mtxR[16];
						bx::mtxRotateXYZ(mtxR, time + xx*0.21f, time + yy*0.37f, time + yy*0.13f);

						float mtx[16];
						bx::mtxMul(mtx, mtxS, mtxR);

						mtx[12] = pos[0] + float(xx)*step;
						mtx[13] = pos[1] + float(yy)*step;
						mtx[14] = pos[2] + float(zz)*step;

						// Set model matrix for rendering.
						encoder->setTransform(mtx);

						// Set vertex and index buffer.
						encoder->setVertexBuffer(0, m_vbh);
						encoder->setIndexBuffer(m_ibh);

						// Set render states.
						encoder->setState(BGFX_STATE_DEFAULT);

						// Submit primitive for rendering to view 0.
						encoder->submit(0, m_program);
					}
				}
			}

			bgfx::end(encoder);

			// Advance to next frame. Rendering thread will be kicked to
			// process submitted rendering primitives.
			bgfx::frame();

			return true;
		}

		return false;
	}

	entry::MouseState m_mouseState;

	uint32_t m_width;
	uint32_t m_height;
	uint32_t m_debug;
	uint32_t m_reset;

	bool     m_autoAdjust;
	int32_t  m_scrollArea;
	int32_t  m_dim;
	int32_t  m_maxDim;
	int32_t  m_transform;

	int64_t  m_timeOffset;

	int64_t  m_deltaTimeNs;
	int64_t  m_deltaTimeAvgNs;
	int64_t  m_numFrames;

	bgfx::ProgramHandle m_program;
	bgfx::VertexBufferHandle m_vbh;
	bgfx::IndexBufferHandle  m_ibh;
};

} // namespace

ENTRY_IMPLEMENT_MAIN(ExampleDrawStress, "17-drawstress", "Draw stress, maximizing number of draw calls.");
<|endoftext|>


<commit_before>// [[Rcpp::depends(RcppArmadillo)]]
#include <RcppArmadillo.h>
#include <Rmath.h>

#include <vector>
#include <cassert>

#include "vmat.h"
#include "gmat.h"
#include "DataPairs.h"
#include "quadrule.h"
#include "pn.h"
#include "functions.h"

using namespace Rcpp;
using namespace arma;
using namespace std;

const double twopi = 2*datum::pi;

/////////////////////////////////////////////////////////////////////////////////////////////////
/* Full loglikelihood */
double loglikfull(unsigned row, DataPairs &data, const gmat &sigmaMarg, const gmat &sigmaJoint, const gmat &sigmaCond, vmat sigmaU, vec u, bool full=1){

  data.pi_gen(row, u); // Estimation of pi based on u

  irowvec causes = data.causes_get(row); // Failure causes for pair in question

  double res = 0; // Initialising output (loglik contribution)

  if ((causes(0) > 0) & (causes(1) > 0)){
    /* Both individuals experience failure */
    res = logdF2(row, causes, data, sigmaJoint, u);
  }
  else if((causes(0) <= 0) & (causes(1) <= 0)){
    /* Neither individual experience failure */

    if ((causes(0) < 0) & (causes(1) < 0)){
      // Full follow-up for both individuals
      for (unsigned i=1; i<=2; i++){ // Over individuals
	double lik = 1;
	for (unsigned j=1; j<=data.ncauses; j++){ // Over failure causes
	  double prob = F1(row, j, i, data);
	  lik -= prob;
	}
	res += log(lik);
      }
    }
    else if (((causes(0) < 0) & (causes(1) == 0)) | ((causes(0) == 0) & (causes(1) < 0))){
      // Full follow-up for only one individual
      for (unsigned i=1; i<=2; i++){ // Over individuals
	double lik = 1;
	for (unsigned j=1; j<=data.ncauses; j++){ // Over failure causes
	  if (causes(i-1) < 0){
	    double prob = F1(row, j, i, data);
	    lik -= prob;
	  }
	  else {
	    double prob = F1(row, j, i, data, sigmaMarg, u);
	    lik -= prob;
	  }
	}
	res += log(lik);
      }
    }
    else {
      // Full follow-up for neither individual
      double lik = 1;
      // Marginal probabilities
      for (unsigned i=1; i<=2; i++){ // Over individuals
	for (unsigned j=1; j<=data.ncauses; j++){ // Over failure causes
	  double prob = F1(row, j, i, data, sigmaMarg, u);
	  lik -= prob; // Subtracting
	}
      }
      // Bivariate probabilities
      for (unsigned k=1; k<=data.ncauses; k++){ // Over failure causes
	for (unsigned l=1; l<=data.ncauses; l++){
	  irowvec vcauses(2);
	  vcauses(0) = k; vcauses(1) = l;
	  double prob = F2(row, vcauses, data, sigmaJoint, u);
	  lik += prob; // Adding
	}
      }
      res = log(lik);
    }
  }
  else {
    /* One individual experiences failure the other does not */
    for (unsigned i=1; i<=2; i++){ // Over individuals
      unsigned cause = causes(i-1);
      if (cause > 0){
	// Marginal probability of failure
	res += logdF1(row, cause, i, data, sigmaMarg, u);
      }
      else {
	// Marginal probability of no failure
	unsigned cond_cause;
	if (i==1){
	  cond_cause = causes(1);
	}
	else {
	  cond_cause = causes(0);
	}
	for (unsigned j=1; j<=data.ncauses; j++){ // Over failure causes
	  double lik = 1;
	  if (cause < 0){
	    // Unconditional
	    double prob = F1(row, j, i, data);
	    lik -= prob;
	  }
	  else {
	    // Conditional
	    double prob = F1(row, j, i, cond_cause, data, sigmaCond, u);
	    lik -= prob;
	  }
	  res += log(lik);
	}
      }
    }
  }
  /* Contribution from u */
  if (full){
    vmat sig = sigmaU; // Variance-covariance matrix of u
    double inner = as_scalar(u*sig.inv*u.t());

    // PDF of u
    double logpdfu = log(pow(twopi,-(data.ncauses/2))) + sig.loginvsqdet - 0.5*inner;

    // Adding to the loglik
    res += logpdfu;
  }

  /* Return */
  return(res);
}

/////////////////////////////////////////////////////////////////////////////////////////////////
/* Score function of full loglikelihood */
rowvec Dloglikfull(unsigned row, DataPairs &data, const gmat &sigmaMarg, const gmat &sigmaJoint, const gmat &sigmaCond, vmat sigmaU, vec u, bool full=1){

  /* Estimation of pi, dpidu and dlogpidu */
  data.pi_gen(row, u);
  data.dpidu_gen(row, u);
  data.dlogpidu_gen(row, u);

  irowvec causes = data.causes_get(row); // Failure causes for pair in question

  rowvec res = zeros<rowvec>(data.ncauses); // Initialising output (score contribution)

  if ((causes(0) > 0) & (causes(1) > 0)){
    /* Both individuals experience failure */
    res = dlogdF2du(row, causes, data, sigmaJoint, u);
  }
  else if((causes(0) <= 0) & (causes(1) <= 0)){
    /* Neither individual experience failure */

    if ((causes(0) < 0) & (causes(1) < 0)){
      // Full follow-up for both individuals
      for (unsigned i=1; i<=2; i++){ // Over individuals
	double lik = 1;
	rowvec likdu = zeros<rowvec>(data.ncauses);
	for (unsigned j=1; j<=data.ncauses; j++){ // Over failure causes
	  double prob = F1(row, j, i, data);
	  rowvec probdu = dF1du(row, j, i, data);
	  lik -= prob;
	  likdu -= probdu;
	}
	res += (1/lik)*likdu;
      }
    }
    else if (((causes(0) < 0) & (causes(1) == 0)) | ((causes(0) == 0) & (causes(1) < 0))){
      // Full follow-up for only one individual
      for (unsigned i=1; i<=2; i++){ // Over individuals
	double lik = 1;
	rowvec likdu = zeros<rowvec>(data.ncauses);
	for (unsigned j=1; j<=data.ncauses; j++){ // Over failure causes
	  if (causes(i-1) < 0){
	    double prob = F1(row, j, i, data);
	    rowvec probdu = dF1du(row, j, i, data);
	    lik -= prob;
	    likdu -= probdu;
	  }
	  else {
	    double prob = F1(row, j, i, data, sigmaMarg, u);
	    rowvec probdu = dF1du(row, j, i, data, sigmaMarg, u);
	    lik -= prob;
	    likdu -= probdu;
	  }
	}
	res += (1/lik)*likdu;
      }
    }
    else {
      // Full follow-up for neither individual
      double lik = 1;
      rowvec likdu = zeros<rowvec>(data.ncauses);
      // Marginal probabilities
      for (unsigned i=1; i<=2; i++){ // Over individuals
	for (unsigned j=1; j<=data.ncauses; j++){ // Over failure causes
	  double prob = F1(row, j, i, data, sigmaMarg, u);
	  rowvec probdu = dF1du(row, j, i, data, sigmaMarg, u);
	  lik -= prob; // Subtracting
	  likdu -= probdu;
	}
      }
      // Bivariate probabilities
      for (unsigned k=1; k<=data.ncauses; k++){ // Over failure causes
	for (unsigned l=1; l<=data.ncauses; l++){
	  irowvec vcauses(2);
	  vcauses(0) = k; vcauses(1) = l;
	  double prob = F2(row, vcauses, data, sigmaJoint, u);
	  rowvec probdu = dF2du(row, vcauses, data, sigmaJoint, u);
	  lik += prob; // Adding
	  likdu += probdu;
	}
      }
      res = (1/lik)*likdu;
    }
  }
  else {
    /* One individual experiences failure the other does not */
    for (unsigned i=1; i<=2; i++){ // Over individuals
      unsigned cause = causes(i-1);
      if (cause > 0){
	// Marginal probability of failure
	res += dlogdF1du(row, cause, i, data, sigmaMarg, u);
      }
      else {
	// Marginal probability of no failure
	unsigned cond_cause;
	if (i==1){
	  cond_cause = causes(1);
	}
	else {
	  cond_cause = causes(0);
	}
	for (unsigned j=1; j<=data.ncauses; j++){ // Over failure causes
	  double lik = 1;
	  rowvec likdu = zeros<rowvec>(data.ncauses);
	  if (cause < 0){ // Uncondtional
	    double prob = F1(row, j, i, data);
	    rowvec probdu = dF1du(row, j, i, data);
	    lik -= prob;
	    likdu -= probdu;
	  }
	  else { // Conditional
	    double prob = F1(row, j, i, cond_cause, data, sigmaCond, u);
	    rowvec probdu = dF1du(row, j, i, cond_cause, data, sigmaCond, u);
	    lik -= prob;
	    likdu -= probdu;
	  }
	  res += (1/lik)*likdu;
	}
      }
    }
  }
  /* Contribution from u */
  if (full){

    vmat sig = sigmaU; // Variance-covariance matrix etc. of u

    // Adding to the score
    res += -u.t()*sig.inv;
  };
  return(res);
}

/////////////////////////////////////////////////////////////////////////////
// FOR TESTING

double loglikout(mat sigma, vec u, int ncauses, imat causes, mat alpha, mat dalpha, mat beta, mat gamma){

  // Initialising gmats of sigma (Joint, Cond)
  gmat sigmaJoint = gmat(ncauses, ncauses);
  gmat sigmaCond = gmat(ncauses, ncauses);
  gmat sigmaMarg = gmat(ncauses, 1);

  // Vectors for extracting rows and columns from sigma
  uvec rcJ(2); /* for joint */
  uvec rc1(1); /* for conditional */
  uvec rc2(ncauses+1); /* for conditional */
  uvec rcu(ncauses);
  for (int h=0; h<ncauses; h++){
    rcu(h) = ncauses + h;
  };

  // Calculating and setting sigmaJoint
  for (int h=0; h<ncauses; h++){
    for (int i=0; i<ncauses; i++){
      rcJ(0)=h;
      rcJ(1)=ncauses+i;
      vmat x = vmat(sigma, rcJ, rcu);
      sigmaJoint.set(h,i,x);
    };
  };

  // Calculating and setting sigmaMarg
  for (int h=0; h<ncauses; h++){
    rc1(0) = h;
    vmat x = vmat(sigma, rc1, rcu);
    sigmaMarg.set(h,1,x);
  };

  // Calculating and setting sigmaCond
  for (int h=0; h<ncauses; h++){
    for (int i=0; i<ncauses; i++){
      rc1(0) = h;
      rc2(0) = i;
      for (int j=0; j<ncauses; j++){
	rc2(j+1) = rcu(j);
      };
      vmat x = vmat(sigma, rc1, rc2);
      sigmaCond.set(h,i,x);
    };
  };

  // vmat of the us
  mat matU = sigma.submat(rcu,rcu);
  vmat sigmaU = vmat(matU);

  // Generating DataPairs
  DataPairs data = DataPairs(ncauses, causes, alpha, dalpha, beta, gamma);

  unsigned row = 1;

  // Estimating likelihood contribution
  double loglik = loglikfull(row, data, sigmaMarg, sigmaJoint, sigmaCond, sigmaU, u);

  // Return
  return loglik;
};

//rowvec Dloglikout(unsigned row, mat sigma, mat data, vec u){

  // Generating gmats of sigma (Marg, Joint, MargCond, sigU)

  // Generating DataPairs

  // Estimating score contribution
//  rowvec score = Dloglikfull(unsigned row, DataPairs data, gmat sigmaJoint, gmat sigmaMargCond, vmat sigmaU, vec u, bool full=1);

  // Return
//  return score;
//};
<commit_msg>export<commit_after>// [[Rcpp::depends(RcppArmadillo)]]
#include <RcppArmadillo.h>
#include <Rmath.h>

#include <vector>
#include <cassert>

#include "vmat.h"
#include "gmat.h"
#include "DataPairs.h"
#include "quadrule.h"
#include "pn.h"
#include "functions.h"

using namespace Rcpp;
using namespace arma;
using namespace std;

const double twopi = 2*datum::pi;

/////////////////////////////////////////////////////////////////////////////////////////////////
/* Full loglikelihood */
double loglikfull(unsigned row, DataPairs &data, const gmat &sigmaMarg, const gmat &sigmaJoint, const gmat &sigmaCond, vmat sigmaU, vec u, bool full=1){

  data.pi_gen(row, u); // Estimation of pi based on u

  irowvec causes = data.causes_get(row); // Failure causes for pair in question

  double res = 0; // Initialising output (loglik contribution)

  if ((causes(0) > 0) & (causes(1) > 0)){
    /* Both individuals experience failure */
    res = logdF2(row, causes, data, sigmaJoint, u);
  }
  else if((causes(0) <= 0) & (causes(1) <= 0)){
    /* Neither individual experience failure */

    if ((causes(0) < 0) & (causes(1) < 0)){
      // Full follow-up for both individuals
      for (unsigned i=1; i<=2; i++){ // Over individuals
	double lik = 1;
	for (unsigned j=1; j<=data.ncauses; j++){ // Over failure causes
	  double prob = F1(row, j, i, data);
	  lik -= prob;
	}
	res += log(lik);
      }
    }
    else if (((causes(0) < 0) & (causes(1) == 0)) | ((causes(0) == 0) & (causes(1) < 0))){
      // Full follow-up for only one individual
      for (unsigned i=1; i<=2; i++){ // Over individuals
	double lik = 1;
	for (unsigned j=1; j<=data.ncauses; j++){ // Over failure causes
	  if (causes(i-1) < 0){
	    double prob = F1(row, j, i, data);
	    lik -= prob;
	  }
	  else {
	    double prob = F1(row, j, i, data, sigmaMarg, u);
	    lik -= prob;
	  }
	}
	res += log(lik);
      }
    }
    else {
      // Full follow-up for neither individual
      double lik = 1;
      // Marginal probabilities
      for (unsigned i=1; i<=2; i++){ // Over individuals
	for (unsigned j=1; j<=data.ncauses; j++){ // Over failure causes
	  double prob = F1(row, j, i, data, sigmaMarg, u);
	  lik -= prob; // Subtracting
	}
      }
      // Bivariate probabilities
      for (unsigned k=1; k<=data.ncauses; k++){ // Over failure causes
	for (unsigned l=1; l<=data.ncauses; l++){
	  irowvec vcauses(2);
	  vcauses(0) = k; vcauses(1) = l;
	  double prob = F2(row, vcauses, data, sigmaJoint, u);
	  lik += prob; // Adding
	}
      }
      res = log(lik);
    }
  }
  else {
    /* One individual experiences failure the other does not */
    for (unsigned i=1; i<=2; i++){ // Over individuals
      unsigned cause = causes(i-1);
      if (cause > 0){
	// Marginal probability of failure
	res += logdF1(row, cause, i, data, sigmaMarg, u);
      }
      else {
	// Marginal probability of no failure
	unsigned cond_cause;
	if (i==1){
	  cond_cause = causes(1);
	}
	else {
	  cond_cause = causes(0);
	}
	for (unsigned j=1; j<=data.ncauses; j++){ // Over failure causes
	  double lik = 1;
	  if (cause < 0){
	    // Unconditional
	    double prob = F1(row, j, i, data);
	    lik -= prob;
	  }
	  else {
	    // Conditional
	    double prob = F1(row, j, i, cond_cause, data, sigmaCond, u);
	    lik -= prob;
	  }
	  res += log(lik);
	}
      }
    }
  }
  /* Contribution from u */
  if (full){
    vmat sig = sigmaU; // Variance-covariance matrix of u
    double inner = as_scalar(u*sig.inv*u.t());

    // PDF of u
    double logpdfu = log(pow(twopi,-(data.ncauses/2))) + sig.loginvsqdet - 0.5*inner;

    // Adding to the loglik
    res += logpdfu;
  }

  /* Return */
  return(res);
}

/////////////////////////////////////////////////////////////////////////////////////////////////
/* Score function of full loglikelihood */
rowvec Dloglikfull(unsigned row, DataPairs &data, const gmat &sigmaMarg, const gmat &sigmaJoint, const gmat &sigmaCond, vmat sigmaU, vec u, bool full=1){

  /* Estimation of pi, dpidu and dlogpidu */
  data.pi_gen(row, u);
  data.dpidu_gen(row, u);
  data.dlogpidu_gen(row, u);

  irowvec causes = data.causes_get(row); // Failure causes for pair in question

  rowvec res = zeros<rowvec>(data.ncauses); // Initialising output (score contribution)

  if ((causes(0) > 0) & (causes(1) > 0)){
    /* Both individuals experience failure */
    res = dlogdF2du(row, causes, data, sigmaJoint, u);
  }
  else if((causes(0) <= 0) & (causes(1) <= 0)){
    /* Neither individual experience failure */

    if ((causes(0) < 0) & (causes(1) < 0)){
      // Full follow-up for both individuals
      for (unsigned i=1; i<=2; i++){ // Over individuals
	double lik = 1;
	rowvec likdu = zeros<rowvec>(data.ncauses);
	for (unsigned j=1; j<=data.ncauses; j++){ // Over failure causes
	  double prob = F1(row, j, i, data);
	  rowvec probdu = dF1du(row, j, i, data);
	  lik -= prob;
	  likdu -= probdu;
	}
	res += (1/lik)*likdu;
      }
    }
    else if (((causes(0) < 0) & (causes(1) == 0)) | ((causes(0) == 0) & (causes(1) < 0))){
      // Full follow-up for only one individual
      for (unsigned i=1; i<=2; i++){ // Over individuals
	double lik = 1;
	rowvec likdu = zeros<rowvec>(data.ncauses);
	for (unsigned j=1; j<=data.ncauses; j++){ // Over failure causes
	  if (causes(i-1) < 0){
	    double prob = F1(row, j, i, data);
	    rowvec probdu = dF1du(row, j, i, data);
	    lik -= prob;
	    likdu -= probdu;
	  }
	  else {
	    double prob = F1(row, j, i, data, sigmaMarg, u);
	    rowvec probdu = dF1du(row, j, i, data, sigmaMarg, u);
	    lik -= prob;
	    likdu -= probdu;
	  }
	}
	res += (1/lik)*likdu;
      }
    }
    else {
      // Full follow-up for neither individual
      double lik = 1;
      rowvec likdu = zeros<rowvec>(data.ncauses);
      // Marginal probabilities
      for (unsigned i=1; i<=2; i++){ // Over individuals
	for (unsigned j=1; j<=data.ncauses; j++){ // Over failure causes
	  double prob = F1(row, j, i, data, sigmaMarg, u);
	  rowvec probdu = dF1du(row, j, i, data, sigmaMarg, u);
	  lik -= prob; // Subtracting
	  likdu -= probdu;
	}
      }
      // Bivariate probabilities
      for (unsigned k=1; k<=data.ncauses; k++){ // Over failure causes
	for (unsigned l=1; l<=data.ncauses; l++){
	  irowvec vcauses(2);
	  vcauses(0) = k; vcauses(1) = l;
	  double prob = F2(row, vcauses, data, sigmaJoint, u);
	  rowvec probdu = dF2du(row, vcauses, data, sigmaJoint, u);
	  lik += prob; // Adding
	  likdu += probdu;
	}
      }
      res = (1/lik)*likdu;
    }
  }
  else {
    /* One individual experiences failure the other does not */
    for (unsigned i=1; i<=2; i++){ // Over individuals
      unsigned cause = causes(i-1);
      if (cause > 0){
	// Marginal probability of failure
	res += dlogdF1du(row, cause, i, data, sigmaMarg, u);
      }
      else {
	// Marginal probability of no failure
	unsigned cond_cause;
	if (i==1){
	  cond_cause = causes(1);
	}
	else {
	  cond_cause = causes(0);
	}
	for (unsigned j=1; j<=data.ncauses; j++){ // Over failure causes
	  double lik = 1;
	  rowvec likdu = zeros<rowvec>(data.ncauses);
	  if (cause < 0){ // Uncondtional
	    double prob = F1(row, j, i, data);
	    rowvec probdu = dF1du(row, j, i, data);
	    lik -= prob;
	    likdu -= probdu;
	  }
	  else { // Conditional
	    double prob = F1(row, j, i, cond_cause, data, sigmaCond, u);
	    rowvec probdu = dF1du(row, j, i, cond_cause, data, sigmaCond, u);
	    lik -= prob;
	    likdu -= probdu;
	  }
	  res += (1/lik)*likdu;
	}
      }
    }
  }
  /* Contribution from u */
  if (full){

    vmat sig = sigmaU; // Variance-covariance matrix etc. of u

    // Adding to the score
    res += -u.t()*sig.inv;
  };
  return(res);
}

/////////////////////////////////////////////////////////////////////////////
// FOR TESTING

// [[Rcpp::export]]
double loglikout(mat sigma, vec u, int ncauses, imat causes, mat alpha, mat dalpha, mat beta, mat gamma){

  // Initialising gmats of sigma (Joint, Cond)
  gmat sigmaJoint = gmat(ncauses, ncauses);
  gmat sigmaCond = gmat(ncauses, ncauses);
  gmat sigmaMarg = gmat(ncauses, 1);

  // Vectors for extracting rows and columns from sigma
  uvec rcJ(2); /* for joint */
  uvec rc1(1); /* for conditional */
  uvec rc2(ncauses+1); /* for conditional */
  uvec rcu(ncauses);
  for (int h=0; h<ncauses; h++){
    rcu(h) = ncauses + h;
  };

  // Calculating and setting sigmaJoint
  for (int h=0; h<ncauses; h++){
    for (int i=0; i<ncauses; i++){
      rcJ(0)=h;
      rcJ(1)=ncauses+i;
      vmat x = vmat(sigma, rcJ, rcu);
      sigmaJoint.set(h,i,x);
    };
  };

  // Calculating and setting sigmaMarg
  for (int h=0; h<ncauses; h++){
    rc1(0) = h;
    vmat x = vmat(sigma, rc1, rcu);
    sigmaMarg.set(h,1,x);
  };

  // Calculating and setting sigmaCond
  for (int h=0; h<ncauses; h++){
    for (int i=0; i<ncauses; i++){
      rc1(0) = h;
      rc2(0) = i;
      for (int j=0; j<ncauses; j++){
	rc2(j+1) = rcu(j);
      };
      vmat x = vmat(sigma, rc1, rc2);
      sigmaCond.set(h,i,x);
    };
  };

  // vmat of the us
  mat matU = sigma.submat(rcu,rcu);
  vmat sigmaU = vmat(matU);

  // Generating DataPairs
  DataPairs data = DataPairs(ncauses, causes, alpha, dalpha, beta, gamma);

  unsigned row = 1;

  // Estimating likelihood contribution
  double loglik = loglikfull(row, data, sigmaMarg, sigmaJoint, sigmaCond, sigmaU, u);

  // Return
  return loglik;
};

//rowvec Dloglikout(unsigned row, mat sigma, mat data, vec u){

  // Generating gmats of sigma (Marg, Joint, MargCond, sigU)

  // Generating DataPairs

  // Estimating score contribution
//  rowvec score = Dloglikfull(unsigned row, DataPairs data, gmat sigmaJoint, gmat sigmaMargCond, vmat sigmaU, vec u, bool full=1);

  // Return
//  return score;
//};
<|endoftext|>


<commit_before>/*
 * Copyright (c) 2014 Juniper Networks, Inc. All rights reserved.
 */

extern "C" {
#include <ovsdb_wrapper.h>
};
#include <cmn/agent.h>
#include <oper/vn.h>
#include <oper/vxlan.h>
#include <oper/physical_device_vn.h>
#include <ovs_tor_agent/tor_agent_init.h>
#include <ovsdb_client.h>
#include <ovsdb_client_idl.h>
#include <ovsdb_client_session.h>
#include <base/util.h>
#include <net/mac_address.h>
#include <oper/agent_sandesh.h>
#include <ovsdb_types.h>
#include <ovsdb_route_peer.h>
#include <logical_switch_ovsdb.h>
#include <unicast_mac_local_ovsdb.h>

using OVSDB::UnicastMacLocalOvsdb;
using OVSDB::UnicastMacLocalEntry;
using OVSDB::OvsdbClientSession;
using std::string;

UnicastMacLocalEntry::UnicastMacLocalEntry(UnicastMacLocalOvsdb *table,
        const UnicastMacLocalEntry *key) : OvsdbEntry(table), mac_(key->mac_),
    logical_switch_name_(key->logical_switch_name_), dest_ip_(key->dest_ip_) {
}

UnicastMacLocalEntry::UnicastMacLocalEntry(UnicastMacLocalOvsdb *table,
        struct ovsdb_idl_row *row) : OvsdbEntry(table),
    mac_(ovsdb_wrapper_ucast_mac_local_mac(row)),
    logical_switch_name_(ovsdb_wrapper_ucast_mac_local_logical_switch(row)),
    dest_ip_() {
    if (ovsdb_wrapper_ucast_mac_local_dst_ip(row))
        dest_ip_ = ovsdb_wrapper_ucast_mac_local_dst_ip(row);
}

UnicastMacLocalEntry::~UnicastMacLocalEntry() {
}

bool UnicastMacLocalEntry::Add() {
    UnicastMacLocalOvsdb *table = static_cast<UnicastMacLocalOvsdb *>(table_);
    OVSDB_TRACE(Trace, "Adding Route " + mac_ + " VN uuid " +
            logical_switch_name_ + " destination IP " + dest_ip_);
    LogicalSwitchTable *l_table = table_->client_idl()->logical_switch_table();
    LogicalSwitchEntry l_key(l_table, logical_switch_name_.c_str());
    LogicalSwitchEntry *ls_entry =
        static_cast<LogicalSwitchEntry *>(l_table->Find(&l_key));
    const PhysicalDeviceVn *dev_vn =
        static_cast<const PhysicalDeviceVn *>(ls_entry->GetDBEntry());
    vrf_ = dev_vn->vn()->GetVrf();
    vxlan_id_ = dev_vn->vn()->vxlan_id()->vxlan_id();
    boost::system::error_code err;
    Ip4Address dest = Ip4Address::from_string(dest_ip_, err);
    table->peer()->AddOvsRoute(dev_vn->vn(), MacAddress(mac_), dest);
    return true;
}

bool UnicastMacLocalEntry::Delete() {
    UnicastMacLocalOvsdb *table = static_cast<UnicastMacLocalOvsdb *>(table_);
    OVSDB_TRACE(Trace, "Deleting Route " + mac_ + " VN uuid " +
            logical_switch_name_ + " destination IP " + dest_ip_);
    table->peer()->DeleteOvsRoute(vrf_, vxlan_id_, MacAddress(mac_));
    return true;
}

bool UnicastMacLocalEntry::IsLess(const KSyncEntry& entry) const {
    const UnicastMacLocalEntry &ucast =
        static_cast<const UnicastMacLocalEntry&>(entry);
    if (mac_ != ucast.mac_)
        return mac_ < ucast.mac_;
    return logical_switch_name_ < ucast.logical_switch_name_;
}

KSyncEntry *UnicastMacLocalEntry::UnresolvedReference() {
    LogicalSwitchTable *l_table = table_->client_idl()->logical_switch_table();
    LogicalSwitchEntry key(l_table, logical_switch_name_.c_str());
    LogicalSwitchEntry *l_switch =
        static_cast<LogicalSwitchEntry *>(l_table->GetReference(&key));
    if (!l_switch->IsResolved()) {
        return l_switch;
    }
    return NULL;
}

const std::string &UnicastMacLocalEntry::mac() const {
    return mac_;
}

const std::string &UnicastMacLocalEntry::logical_switch_name() const {
    return logical_switch_name_;
}

const std::string &UnicastMacLocalEntry::dest_ip() const {
    return dest_ip_;
}

UnicastMacLocalOvsdb::UnicastMacLocalOvsdb(OvsdbClientIdl *idl, OvsPeer *peer) :
    OvsdbObject(idl), peer_(peer) {
    idl->Register(OvsdbClientIdl::OVSDB_UCAST_MAC_LOCAL,
            boost::bind(&UnicastMacLocalOvsdb::Notify, this, _1, _2));
}

UnicastMacLocalOvsdb::~UnicastMacLocalOvsdb() {
    client_idl_->UnRegister(OvsdbClientIdl::OVSDB_UCAST_MAC_LOCAL);
}

OvsPeer *UnicastMacLocalOvsdb::peer() {
    return peer_;
}

void UnicastMacLocalOvsdb::Notify(OvsdbClientIdl::Op op,
        struct ovsdb_idl_row *row) {
    const char *ls_name = ovsdb_wrapper_ucast_mac_local_logical_switch(row);
    const char *dest_ip = ovsdb_wrapper_ucast_mac_local_dst_ip(row);
    /* ignore if ls_name is not present */
    if (ls_name == NULL) {
        return;
    }
    UnicastMacLocalEntry key(this, row);
    UnicastMacLocalEntry *entry =
        static_cast<UnicastMacLocalEntry *>(FindActiveEntry(&key));
    /* trigger delete if dest ip is not available */
    if (op == OvsdbClientIdl::OVSDB_DEL || dest_ip == NULL) {
        if (entry != NULL) {
            Delete(entry);
        }
    } else if (op == OvsdbClientIdl::OVSDB_ADD) {
        if (entry == NULL) {
            entry = static_cast<UnicastMacLocalEntry *>(Create(&key));
        }
    } else {
        assert(0);
    }
}

KSyncEntry *UnicastMacLocalOvsdb::Alloc(const KSyncEntry *key, uint32_t index) {
    const UnicastMacLocalEntry *k_entry =
        static_cast<const UnicastMacLocalEntry *>(key);
    UnicastMacLocalEntry *entry = new UnicastMacLocalEntry(this, k_entry);
    return entry;
}

/////////////////////////////////////////////////////////////////////////////
// Sandesh routines
/////////////////////////////////////////////////////////////////////////////
class UnicastMacLocalSandeshTask : public Task {
public:
    UnicastMacLocalSandeshTask(std::string resp_ctx) :
        Task((TaskScheduler::GetInstance()->GetTaskId("Agent::KSync")), -1),
        resp_(new OvsdbUnicastMacLocalResp()), resp_data_(resp_ctx) {
    }
    virtual ~UnicastMacLocalSandeshTask() {}
    virtual bool Run() {
        std::vector<OvsdbUnicastMacLocalEntry> macs;
        TorAgentInit *init =
            static_cast<TorAgentInit *>(Agent::GetInstance()->agent_init());
        OvsdbClientSession *session = init->ovsdb_client()->next_session(NULL);
        UnicastMacLocalOvsdb *table =
            session->client_idl()->unicast_mac_local_ovsdb();
        UnicastMacLocalEntry *entry =
            static_cast<UnicastMacLocalEntry *>(table->Next(NULL));
        while (entry != NULL) {
            OvsdbUnicastMacLocalEntry oentry;
            oentry.set_state(entry->StateString());
            oentry.set_mac(entry->mac());
            oentry.set_logical_switch(entry->logical_switch_name());
            oentry.set_dest_ip(entry->dest_ip());
            macs.push_back(oentry);
            entry = static_cast<UnicastMacLocalEntry *>(table->Next(entry));
        }
        resp_->set_macs(macs);
        SendResponse();
        return true;
    }
private:
    void SendResponse() {
        resp_->set_context(resp_data_);
        resp_->set_more(false);
        resp_->Response();
    }

    OvsdbUnicastMacLocalResp *resp_;
    std::string resp_data_;
    DISALLOW_COPY_AND_ASSIGN(UnicastMacLocalSandeshTask);
};

void OvsdbUnicastMacLocalReq::HandleRequest() const {
    UnicastMacLocalSandeshTask *task = new UnicastMacLocalSandeshTask(context());
    TaskScheduler *scheduler = TaskScheduler::GetInstance();
    scheduler->Enqueue(task);
}

<commit_msg>change to use right API to get VXlan id<commit_after>/*
 * Copyright (c) 2014 Juniper Networks, Inc. All rights reserved.
 */

extern "C" {
#include <ovsdb_wrapper.h>
};
#include <cmn/agent.h>
#include <oper/vn.h>
#include <oper/vxlan.h>
#include <oper/physical_device_vn.h>
#include <ovs_tor_agent/tor_agent_init.h>
#include <ovsdb_client.h>
#include <ovsdb_client_idl.h>
#include <ovsdb_client_session.h>
#include <base/util.h>
#include <net/mac_address.h>
#include <oper/agent_sandesh.h>
#include <ovsdb_types.h>
#include <ovsdb_route_peer.h>
#include <logical_switch_ovsdb.h>
#include <unicast_mac_local_ovsdb.h>

using OVSDB::UnicastMacLocalOvsdb;
using OVSDB::UnicastMacLocalEntry;
using OVSDB::OvsdbClientSession;
using std::string;

UnicastMacLocalEntry::UnicastMacLocalEntry(UnicastMacLocalOvsdb *table,
        const UnicastMacLocalEntry *key) : OvsdbEntry(table), mac_(key->mac_),
    logical_switch_name_(key->logical_switch_name_), dest_ip_(key->dest_ip_) {
}

UnicastMacLocalEntry::UnicastMacLocalEntry(UnicastMacLocalOvsdb *table,
        struct ovsdb_idl_row *row) : OvsdbEntry(table),
    mac_(ovsdb_wrapper_ucast_mac_local_mac(row)),
    logical_switch_name_(ovsdb_wrapper_ucast_mac_local_logical_switch(row)),
    dest_ip_() {
    if (ovsdb_wrapper_ucast_mac_local_dst_ip(row))
        dest_ip_ = ovsdb_wrapper_ucast_mac_local_dst_ip(row);
}

UnicastMacLocalEntry::~UnicastMacLocalEntry() {
}

bool UnicastMacLocalEntry::Add() {
    UnicastMacLocalOvsdb *table = static_cast<UnicastMacLocalOvsdb *>(table_);
    OVSDB_TRACE(Trace, "Adding Route " + mac_ + " VN uuid " +
            logical_switch_name_ + " destination IP " + dest_ip_);
    LogicalSwitchTable *l_table = table_->client_idl()->logical_switch_table();
    LogicalSwitchEntry l_key(l_table, logical_switch_name_.c_str());
    LogicalSwitchEntry *ls_entry =
        static_cast<LogicalSwitchEntry *>(l_table->Find(&l_key));
    const PhysicalDeviceVn *dev_vn =
        static_cast<const PhysicalDeviceVn *>(ls_entry->GetDBEntry());
    vrf_ = dev_vn->vn()->GetVrf();
    vxlan_id_ = dev_vn->vn()->GetVxLanId();
    boost::system::error_code err;
    Ip4Address dest = Ip4Address::from_string(dest_ip_, err);
    table->peer()->AddOvsRoute(dev_vn->vn(), MacAddress(mac_), dest);
    return true;
}

bool UnicastMacLocalEntry::Delete() {
    UnicastMacLocalOvsdb *table = static_cast<UnicastMacLocalOvsdb *>(table_);
    OVSDB_TRACE(Trace, "Deleting Route " + mac_ + " VN uuid " +
            logical_switch_name_ + " destination IP " + dest_ip_);
    table->peer()->DeleteOvsRoute(vrf_, vxlan_id_, MacAddress(mac_));
    return true;
}

bool UnicastMacLocalEntry::IsLess(const KSyncEntry& entry) const {
    const UnicastMacLocalEntry &ucast =
        static_cast<const UnicastMacLocalEntry&>(entry);
    if (mac_ != ucast.mac_)
        return mac_ < ucast.mac_;
    return logical_switch_name_ < ucast.logical_switch_name_;
}

KSyncEntry *UnicastMacLocalEntry::UnresolvedReference() {
    LogicalSwitchTable *l_table = table_->client_idl()->logical_switch_table();
    LogicalSwitchEntry key(l_table, logical_switch_name_.c_str());
    LogicalSwitchEntry *l_switch =
        static_cast<LogicalSwitchEntry *>(l_table->GetReference(&key));
    if (!l_switch->IsResolved()) {
        return l_switch;
    }
    return NULL;
}

const std::string &UnicastMacLocalEntry::mac() const {
    return mac_;
}

const std::string &UnicastMacLocalEntry::logical_switch_name() const {
    return logical_switch_name_;
}

const std::string &UnicastMacLocalEntry::dest_ip() const {
    return dest_ip_;
}

UnicastMacLocalOvsdb::UnicastMacLocalOvsdb(OvsdbClientIdl *idl, OvsPeer *peer) :
    OvsdbObject(idl), peer_(peer) {
    idl->Register(OvsdbClientIdl::OVSDB_UCAST_MAC_LOCAL,
            boost::bind(&UnicastMacLocalOvsdb::Notify, this, _1, _2));
}

UnicastMacLocalOvsdb::~UnicastMacLocalOvsdb() {
    client_idl_->UnRegister(OvsdbClientIdl::OVSDB_UCAST_MAC_LOCAL);
}

OvsPeer *UnicastMacLocalOvsdb::peer() {
    return peer_;
}

void UnicastMacLocalOvsdb::Notify(OvsdbClientIdl::Op op,
        struct ovsdb_idl_row *row) {
    const char *ls_name = ovsdb_wrapper_ucast_mac_local_logical_switch(row);
    const char *dest_ip = ovsdb_wrapper_ucast_mac_local_dst_ip(row);
    /* ignore if ls_name is not present */
    if (ls_name == NULL) {
        return;
    }
    UnicastMacLocalEntry key(this, row);
    UnicastMacLocalEntry *entry =
        static_cast<UnicastMacLocalEntry *>(FindActiveEntry(&key));
    /* trigger delete if dest ip is not available */
    if (op == OvsdbClientIdl::OVSDB_DEL || dest_ip == NULL) {
        if (entry != NULL) {
            Delete(entry);
        }
    } else if (op == OvsdbClientIdl::OVSDB_ADD) {
        if (entry == NULL) {
            entry = static_cast<UnicastMacLocalEntry *>(Create(&key));
        }
    } else {
        assert(0);
    }
}

KSyncEntry *UnicastMacLocalOvsdb::Alloc(const KSyncEntry *key, uint32_t index) {
    const UnicastMacLocalEntry *k_entry =
        static_cast<const UnicastMacLocalEntry *>(key);
    UnicastMacLocalEntry *entry = new UnicastMacLocalEntry(this, k_entry);
    return entry;
}

/////////////////////////////////////////////////////////////////////////////
// Sandesh routines
/////////////////////////////////////////////////////////////////////////////
class UnicastMacLocalSandeshTask : public Task {
public:
    UnicastMacLocalSandeshTask(std::string resp_ctx) :
        Task((TaskScheduler::GetInstance()->GetTaskId("Agent::KSync")), -1),
        resp_(new OvsdbUnicastMacLocalResp()), resp_data_(resp_ctx) {
    }
    virtual ~UnicastMacLocalSandeshTask() {}
    virtual bool Run() {
        std::vector<OvsdbUnicastMacLocalEntry> macs;
        TorAgentInit *init =
            static_cast<TorAgentInit *>(Agent::GetInstance()->agent_init());
        OvsdbClientSession *session = init->ovsdb_client()->next_session(NULL);
        UnicastMacLocalOvsdb *table =
            session->client_idl()->unicast_mac_local_ovsdb();
        UnicastMacLocalEntry *entry =
            static_cast<UnicastMacLocalEntry *>(table->Next(NULL));
        while (entry != NULL) {
            OvsdbUnicastMacLocalEntry oentry;
            oentry.set_state(entry->StateString());
            oentry.set_mac(entry->mac());
            oentry.set_logical_switch(entry->logical_switch_name());
            oentry.set_dest_ip(entry->dest_ip());
            macs.push_back(oentry);
            entry = static_cast<UnicastMacLocalEntry *>(table->Next(entry));
        }
        resp_->set_macs(macs);
        SendResponse();
        return true;
    }
private:
    void SendResponse() {
        resp_->set_context(resp_data_);
        resp_->set_more(false);
        resp_->Response();
    }

    OvsdbUnicastMacLocalResp *resp_;
    std::string resp_data_;
    DISALLOW_COPY_AND_ASSIGN(UnicastMacLocalSandeshTask);
};

void OvsdbUnicastMacLocalReq::HandleRequest() const {
    UnicastMacLocalSandeshTask *task = new UnicastMacLocalSandeshTask(context());
    TaskScheduler *scheduler = TaskScheduler::GetInstance();
    scheduler->Enqueue(task);
}

<|endoftext|>