<commit_before>// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include <string>

#include "base/file_util.h"
#include "chrome/browser/view_ids.h"
#include "chrome/common/chrome_constants.h"
#include "chrome/test/automation/constrained_window_proxy.h"
#include "chrome/test/automation/browser_proxy.h"
#include "chrome/test/automation/tab_proxy.h"
#include "chrome/test/automation/window_proxy.h"
#include "chrome/test/ui/ui_test.h"
#include "chrome/views/event.h"
#include "net/base/net_util.h"

const int kRightCloseButtonOffset = 55;
const int kBottomCloseButtonOffset = 20;

class InteractiveConstrainedWindowTest : public UITest {
 protected:
  InteractiveConstrainedWindowTest() {
    show_window_ = true;
  }
};

TEST_F(InteractiveConstrainedWindowTest, TestOpenAndResizeTo) {
  scoped_ptr<BrowserProxy> browser(automation()->GetBrowserWindow(0));
  ASSERT_TRUE(browser.get());

  scoped_ptr<WindowProxy> window(
      automation()->GetWindowForBrowser(browser.get()));
  ASSERT_TRUE(window.get());

  scoped_ptr<TabProxy> tab(browser->GetTab(0));
  ASSERT_TRUE(tab.get());

  std::wstring filename(test_data_directory_);
  file_util::AppendToPath(&filename, L"constrained_files");
  file_util::AppendToPath(&filename,
                          L"constrained_window_onload_resizeto.html");
  ASSERT_TRUE(tab->NavigateToURL(net::FilePathToFileURL(filename)));

  gfx::Rect tab_view_bounds;
  ASSERT_TRUE(window->GetViewBounds(VIEW_ID_TAB_CONTAINER,
                                    &tab_view_bounds, true));

  // Simulate a click of the actual link to force user_gesture to be
  // true; if we don't, the resulting popup will be constrained, which
  // isn't what we want to test.
  POINT link_point(tab_view_bounds.CenterPoint().ToPOINT());
  ASSERT_TRUE(window->SimulateOSClick(link_point,
                                      views::Event::EF_LEFT_BUTTON_DOWN));

  ASSERT_TRUE(automation()->WaitForWindowCountToBecome(2, 1000));

  scoped_ptr<BrowserProxy> popup_browser(automation()->GetBrowserWindow(1));
  ASSERT_TRUE(popup_browser != NULL);
  scoped_ptr<WindowProxy> popup_window(
      automation()->GetWindowForBrowser(popup_browser.get()));
  ASSERT_TRUE(popup_window != NULL);

  // Make sure we were created with the correct width and height.
  gfx::Rect rect;
  bool is_timeout = false;
  ASSERT_TRUE(popup_window->GetViewBoundsWithTimeout(
                  VIEW_ID_TAB_CONTAINER, &rect, false, 1000, &is_timeout));
  ASSERT_FALSE(is_timeout);
  ASSERT_EQ(300, rect.width());
  ASSERT_EQ(320, rect.height());

  // Send a click to the popup window to test resizeTo.
  ASSERT_TRUE(popup_window->GetViewBounds(VIEW_ID_TAB_CONTAINER,
                                          &tab_view_bounds, true));
  POINT popup_link_point(tab_view_bounds.CenterPoint().ToPOINT());
  ASSERT_TRUE(popup_window->SimulateOSClick(
                  popup_link_point, views::Event::EF_LEFT_BUTTON_DOWN));

  // No idea how to wait here other then sleeping. This timeout used to be
  // lower, then we started hitting it before it was done. :(
  Sleep(5000);

  // The actual content will be LESS than (200, 200) because resizeTo
  // deals with a window's outer{Width,Height} instead of its
  // inner{Width,Height}.
  is_timeout = false;
  ASSERT_TRUE(popup_window->GetViewBoundsWithTimeout(
                  VIEW_ID_TAB_CONTAINER, &rect, false, 1000, &is_timeout));
  ASSERT_FALSE(is_timeout);
  ASSERT_LT(rect.width(), 200);
  ASSERT_LT(rect.height(), 200);
}

// Tests that in the window.open() equivalent of a fork bomb, we stop building
// windows.
TEST_F(InteractiveConstrainedWindowTest, DISABLED_DontSpawnEndlessPopups) {
  scoped_ptr<BrowserProxy> browser(automation()->GetBrowserWindow(0));
  ASSERT_TRUE(browser.get());

  scoped_ptr<WindowProxy> window(
      automation()->GetWindowForBrowser(browser.get()));
  ASSERT_TRUE(window.get());

  scoped_ptr<TabProxy> tab(browser->GetTab(0));
  ASSERT_TRUE(tab.get());

  std::wstring filename(test_data_directory_);
  file_util::AppendToPath(&filename, L"constrained_files");
  file_util::AppendToPath(&filename,
                          L"infinite_popups.html");
  ASSERT_TRUE(tab->NavigateToURL(net::FilePathToFileURL(filename)));

  gfx::Rect tab_view_bounds;
  ASSERT_TRUE(window->GetViewBounds(VIEW_ID_TAB_CONTAINER,
                                    &tab_view_bounds, true));

  // Simulate a click of the actual link to force user_gesture to be
  // true; if we don't, the resulting popup will be constrained, which
  // isn't what we want to test.
  POINT link_point(tab_view_bounds.CenterPoint().ToPOINT());
  ASSERT_TRUE(window->SimulateOSClick(link_point,
                                      views::Event::EF_LEFT_BUTTON_DOWN));

  ASSERT_TRUE(automation()->WaitForWindowCountToBecome(2, 1000));

  scoped_ptr<BrowserProxy> popup_browser(automation()->GetBrowserWindow(1));
  ASSERT_TRUE(popup_browser.get());
  scoped_ptr<TabProxy> popup_tab(popup_browser->GetTab(0));
  ASSERT_TRUE(popup_tab.get());

  // And now we spin on this, waiting to make sure that we don't spawn popup
  // windows endlessly. The current limit is 25, so allowing for possible race
  // conditions and one off errors, don't break out until we go over 35 popup
  // windows (in which case we are bork bork bork).
  const int kMaxPopupWindows = 35;
  int constrained_window_count = 0;
  int new_constrained_window_count;
  bool continuing = true;
  while (continuing && constrained_window_count < kMaxPopupWindows) {
    continuing = popup_tab->WaitForChildWindowCountToChange(
        constrained_window_count, &new_constrained_window_count,
        100000);
    EXPECT_GE(new_constrained_window_count, constrained_window_count);
    EXPECT_LE(new_constrained_window_count, kMaxPopupWindows);
    constrained_window_count = new_constrained_window_count;
  }
}
<commit_msg>Updates one of the unit tests I disabled when I rewrote the popup blocker UI. Review URL: http://codereview.chromium.org/10206<commit_after>// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include <string>

#include "base/file_util.h"
#include "chrome/browser/view_ids.h"
#include "chrome/common/chrome_constants.h"
#include "chrome/common/l10n_util.h"
#include "chrome/test/automation/automation_constants.h"
#include "chrome/test/automation/browser_proxy.h"
#include "chrome/test/automation/constrained_window_proxy.h"
#include "chrome/test/automation/tab_proxy.h"
#include "chrome/test/automation/window_proxy.h"
#include "chrome/test/ui/ui_test.h"
#include "chrome/views/event.h"
#include "net/base/net_util.h"

#include "generated_resources.h"

const int kRightCloseButtonOffset = 55;
const int kBottomCloseButtonOffset = 20;

class InteractiveConstrainedWindowTest : public UITest {
 protected:
  InteractiveConstrainedWindowTest() {
    show_window_ = true;
  }
};

TEST_F(InteractiveConstrainedWindowTest, TestOpenAndResizeTo) {
  scoped_ptr<BrowserProxy> browser(automation()->GetBrowserWindow(0));
  ASSERT_TRUE(browser.get());

  scoped_ptr<WindowProxy> window(
      automation()->GetWindowForBrowser(browser.get()));
  ASSERT_TRUE(window.get());

  scoped_ptr<TabProxy> tab(browser->GetTab(0));
  ASSERT_TRUE(tab.get());

  std::wstring filename(test_data_directory_);
  file_util::AppendToPath(&filename, L"constrained_files");
  file_util::AppendToPath(&filename,
                          L"constrained_window_onload_resizeto.html");
  ASSERT_TRUE(tab->NavigateToURL(net::FilePathToFileURL(filename)));

  gfx::Rect tab_view_bounds;
  ASSERT_TRUE(window->GetViewBounds(VIEW_ID_TAB_CONTAINER,
                                    &tab_view_bounds, true));

  // Simulate a click of the actual link to force user_gesture to be
  // true; if we don't, the resulting popup will be constrained, which
  // isn't what we want to test.
  POINT link_point(tab_view_bounds.CenterPoint().ToPOINT());
  ASSERT_TRUE(window->SimulateOSClick(link_point,
                                      views::Event::EF_LEFT_BUTTON_DOWN));

  ASSERT_TRUE(automation()->WaitForWindowCountToBecome(2, 1000));

  scoped_ptr<BrowserProxy> popup_browser(automation()->GetBrowserWindow(1));
  ASSERT_TRUE(popup_browser != NULL);
  scoped_ptr<WindowProxy> popup_window(
      automation()->GetWindowForBrowser(popup_browser.get()));
  ASSERT_TRUE(popup_window != NULL);

  // Make sure we were created with the correct width and height.
  gfx::Rect rect;
  bool is_timeout = false;
  ASSERT_TRUE(popup_window->GetViewBoundsWithTimeout(
                  VIEW_ID_TAB_CONTAINER, &rect, false, 1000, &is_timeout));
  ASSERT_FALSE(is_timeout);
  ASSERT_EQ(300, rect.width());
  ASSERT_EQ(320, rect.height());

  // Send a click to the popup window to test resizeTo.
  ASSERT_TRUE(popup_window->GetViewBounds(VIEW_ID_TAB_CONTAINER,
                                          &tab_view_bounds, true));
  POINT popup_link_point(tab_view_bounds.CenterPoint().ToPOINT());
  ASSERT_TRUE(popup_window->SimulateOSClick(
                  popup_link_point, views::Event::EF_LEFT_BUTTON_DOWN));

  // No idea how to wait here other then sleeping. This timeout used to be
  // lower, then we started hitting it before it was done. :(
  Sleep(5000);

  // The actual content will be LESS than (200, 200) because resizeTo
  // deals with a window's outer{Width,Height} instead of its
  // inner{Width,Height}.
  is_timeout = false;
  ASSERT_TRUE(popup_window->GetViewBoundsWithTimeout(
                  VIEW_ID_TAB_CONTAINER, &rect, false, 1000, &is_timeout));
  ASSERT_FALSE(is_timeout);
  ASSERT_LT(rect.width(), 200);
  ASSERT_LT(rect.height(), 200);
}

// Helper function used to get the number of blocked popups out of the window
// title.
bool ParseCountOutOfTitle(const std::wstring& title, int* output)
{
  // Since we will be reading the number of popup windows open by grabbing the
  // number out of the window title, and that format string is localized, we
  // need to find out the offset into that string.
  const wchar_t* placeholder = L"XXXX";
  size_t offset =
      l10n_util::GetStringF(IDS_POPUPS_BLOCKED_COUNT, placeholder).
      find(placeholder);

  std::wstring number;
  while (offset < title.size() && iswdigit(title[offset])) {
    number += title[offset];
    offset++;
  }

  return StringToInt(number, output);
}

// Tests that in the window.open() equivalent of a fork bomb, we stop building
// windows.
TEST_F(InteractiveConstrainedWindowTest, DontSpawnEndlessPopups) {
  scoped_ptr<BrowserProxy> browser(automation()->GetBrowserWindow(0));
  ASSERT_TRUE(browser.get());

  scoped_ptr<WindowProxy> window(
      automation()->GetWindowForBrowser(browser.get()));
  ASSERT_TRUE(window.get());

  scoped_ptr<TabProxy> tab(browser->GetTab(0));
  ASSERT_TRUE(tab.get());

  std::wstring filename(test_data_directory_);
  file_util::AppendToPath(&filename, L"constrained_files");
  file_util::AppendToPath(&filename,
                          L"infinite_popups.html");
  ASSERT_TRUE(tab->NavigateToURL(net::FilePathToFileURL(filename)));

  gfx::Rect tab_view_bounds;
  ASSERT_TRUE(window->GetViewBounds(VIEW_ID_TAB_CONTAINER,
                                    &tab_view_bounds, true));

  // Simulate a click of the actual link to force user_gesture to be
  // true; if we don't, the resulting popup will be constrained, which
  // isn't what we want to test.
  POINT link_point(tab_view_bounds.CenterPoint().ToPOINT());
  ASSERT_TRUE(window->SimulateOSClick(link_point,
                                      views::Event::EF_LEFT_BUTTON_DOWN));

  ASSERT_TRUE(automation()->WaitForWindowCountToBecome(2, 1000));

  scoped_ptr<BrowserProxy> popup_browser(automation()->GetBrowserWindow(1));
  ASSERT_TRUE(popup_browser.get());
  scoped_ptr<TabProxy> popup_tab(popup_browser->GetTab(0));
  ASSERT_TRUE(popup_tab.get());

  int constrained_window_count = 0;
  ASSERT_TRUE(popup_tab->WaitForChildWindowCountToChange(
                  0, &constrained_window_count, 10000));
  ASSERT_EQ(1, constrained_window_count);
  scoped_ptr<ConstrainedWindowProxy> constrained_window(
      popup_tab->GetConstrainedWindow(0));
  ASSERT_TRUE(constrained_window.get());

  // And now we spin, waiting to make sure that we don't spawn popup
  // windows endlessly. The current limit is 25, so allowing for possible race
  // conditions and one off errors, don't break out until we go over 30 popup
  // windows (in which case we are bork bork bork).
  const int kMaxPopupWindows = 30;

  int popup_window_count = 0;
  int new_popup_window_count = 0;
  int times_slept = 0;
  bool continuing = true;
  while (continuing && popup_window_count < kMaxPopupWindows) {
    std::wstring title;
    ASSERT_TRUE(constrained_window->GetTitle(&title));
    ASSERT_TRUE(ParseCountOutOfTitle(title, &new_popup_window_count));
    if (new_popup_window_count == popup_window_count) {
      if (times_slept == 10) {
        continuing = false;
      } else {
        // Nothing intereseting is going on wait it out.
        Sleep(automation::kSleepTime);
        times_slept++;
      }
    } else {
      times_slept = 0;
    }

    EXPECT_GE(new_popup_window_count, popup_window_count);
    EXPECT_LE(new_popup_window_count, kMaxPopupWindows);
    popup_window_count = new_popup_window_count;
  }
}
<|endoftext|>


<commit_before>#include <algorithm>
#include <functional>
#include <utility>
#include <vector>

#include "caffe/layer.hpp"
#include "caffe/util/io.hpp"
#include "caffe/util/math_functions.hpp"
#include "caffe/vision_layers.hpp"

namespace caffe {

template <typename Dtype>
void AccuracyLayer<Dtype>::LayerSetUp(
  const vector<Blob<Dtype>*>& bottom, const vector<Blob<Dtype>*>& top) {
  top_k_ = this->layer_param_.accuracy_param().top_k();
}

template <typename Dtype>
void AccuracyLayer<Dtype>::Reshape(
  const vector<Blob<Dtype>*>& bottom, const vector<Blob<Dtype>*>& top) {
  CHECK_EQ(bottom[0]->num(), bottom[1]->num())
      << "The data and label should have the same number.";
  CHECK_LE(top_k_, bottom[0]->count() / bottom[0]->num())
      << "top_k must be less than or equal to the number of classes.";
  CHECK_EQ(bottom[1]->channels(), 1);
  CHECK_EQ(bottom[1]->height(), 1);
  CHECK_EQ(bottom[1]->width(), 1);
  top[0]->Reshape(1, 1, 1, 1);
}

template <typename Dtype>
void AccuracyLayer<Dtype>::Forward_cpu(const vector<Blob<Dtype>*>& bottom,
    const vector<Blob<Dtype>*>& top) {
  Dtype accuracy = 0;
  const Dtype* bottom_data = bottom[0]->cpu_data();
  const Dtype* bottom_label = bottom[1]->cpu_data();
  int num = bottom[0]->num();
  int dim = bottom[0]->count() / bottom[0]->num();
  vector<Dtype> maxval(top_k_+1);
  vector<int> max_id(top_k_+1);
  for (int i = 0; i < num; ++i) {
    // Top-k accuracy
    std::vector<std::pair<Dtype, int> > bottom_data_vector;
    for (int j = 0; j < dim; ++j) {
      bottom_data_vector.push_back(
          std::make_pair(bottom_data[i * dim + j], j));
    }
    std::partial_sort(
        bottom_data_vector.begin(), bottom_data_vector.begin() + top_k_,
        bottom_data_vector.end(), std::greater<std::pair<Dtype, int> >());
    // check if true label is in top k predictions
    for (int k = 0; k < top_k_; k++) {
      if (bottom_data_vector[k].second == static_cast<int>(bottom_label[i])) {
        ++accuracy;
        break;
      }
    }
  }

  // LOG(INFO) << "Accuracy: " << accuracy;
  top[0]->mutable_cpu_data()[0] = accuracy / num;
  // Accuracy layer should not be used as a loss function.
}

INSTANTIATE_CLASS(AccuracyLayer);
REGISTER_LAYER_CLASS(Accuracy);

}  // namespace caffe
<commit_msg>AccuracyLayer output is 0D (scalar)<commit_after>#include <algorithm>
#include <functional>
#include <utility>
#include <vector>

#include "caffe/layer.hpp"
#include "caffe/util/io.hpp"
#include "caffe/util/math_functions.hpp"
#include "caffe/vision_layers.hpp"

namespace caffe {

template <typename Dtype>
void AccuracyLayer<Dtype>::LayerSetUp(
  const vector<Blob<Dtype>*>& bottom, const vector<Blob<Dtype>*>& top) {
  top_k_ = this->layer_param_.accuracy_param().top_k();
}

template <typename Dtype>
void AccuracyLayer<Dtype>::Reshape(
  const vector<Blob<Dtype>*>& bottom, const vector<Blob<Dtype>*>& top) {
  CHECK_LE(top_k_, bottom[0]->count() / bottom[1]->count())
      << "top_k must be less than or equal to the number of classes.";
  CHECK_GE(bottom[0]->num_axes(), bottom[1]->num_axes());
  for (int i = 0; i < bottom[1]->num_axes(); ++i) {
    CHECK_LE(bottom[0]->shape(i), bottom[1]->shape(i))
        << "Dimension mismatch between predictions and label.";
  }
  vector<int> top_shape(0);  // Accuracy is a scalar; 0 axes.
  top[0]->Reshape(top_shape);
}

template <typename Dtype>
void AccuracyLayer<Dtype>::Forward_cpu(const vector<Blob<Dtype>*>& bottom,
    const vector<Blob<Dtype>*>& top) {
  Dtype accuracy = 0;
  const Dtype* bottom_data = bottom[0]->cpu_data();
  const Dtype* bottom_label = bottom[1]->cpu_data();
  int num = bottom[0]->num();
  int dim = bottom[0]->count() / bottom[0]->num();
  vector<Dtype> maxval(top_k_+1);
  vector<int> max_id(top_k_+1);
  for (int i = 0; i < num; ++i) {
    // Top-k accuracy
    std::vector<std::pair<Dtype, int> > bottom_data_vector;
    for (int j = 0; j < dim; ++j) {
      bottom_data_vector.push_back(
          std::make_pair(bottom_data[i * dim + j], j));
    }
    std::partial_sort(
        bottom_data_vector.begin(), bottom_data_vector.begin() + top_k_,
        bottom_data_vector.end(), std::greater<std::pair<Dtype, int> >());
    // check if true label is in top k predictions
    for (int k = 0; k < top_k_; k++) {
      if (bottom_data_vector[k].second == static_cast<int>(bottom_label[i])) {
        ++accuracy;
        break;
      }
    }
  }

  // LOG(INFO) << "Accuracy: " << accuracy;
  top[0]->mutable_cpu_data()[0] = accuracy / num;
  // Accuracy layer should not be used as a loss function.
}

INSTANTIATE_CLASS(AccuracyLayer);
REGISTER_LAYER_CLASS(Accuracy);

}  // namespace caffe
<|endoftext|>


<commit_before><commit_msg>planning: update scenario manager<commit_after><|endoftext|>


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

/*! \file reduce.inl
 *  \brief Inline file for reduce.h
 */

#pragma once

// do not attempt to compile this file with any other compiler
#ifdef __CUDACC__

#include <komrade/device_vector.h>
#include <komrade/host_vector.h>
#include <komrade/device_malloc.h>
#include <komrade/device_free.h>
#include <komrade/reduce.h>  // for second level reduction

#include <komrade/detail/device/cuda/block/reduce.h>

namespace komrade
{

namespace detail
{

namespace device
{

namespace cuda
{

/*
 * Reduction using a single thread.  Only used for small vectors.
 *
 */
template<typename InputFunctor,
         typename OutputType,
         typename BinaryFunction>
  __global__ void
  __komrade__serial_reduce_kernel(InputFunctor input,
                                  const size_t n,
                                  OutputType * block_results,
                                  BinaryFunction binary_op)
{
    if( threadIdx.x == 0 )
    {
        OutputType accum = input[0];
        for(unsigned int i = 1; i < n; i++){
            accum = binary_op(accum, input[i]);
        }
        block_results[0] = accum;
    }

} // end __komrade__serial_reduce_kernel()

/*
 * Reduce a vector of n elements using binary_op(op())
 *
 * The order of reduction is not defined, so binary_op() should
 * be a commutative (and associative) operator such as
 * (integer) addition.  Since floating point operations
 * do not completely satisfy these criteria, the result is
 * generally not the same as a consecutive reduction of
 * the elements.
 *
 * Uses the same pattern as reduce6() in the CUDA SDK
 *
 */
template<typename InputFunctor,
         typename OutputType,
         typename BinaryFunction,
         unsigned int BLOCK_SIZE>
  __global__ void
  __komrade__unordered_reduce_kernel(InputFunctor input,
                                     const unsigned int n,
                                     OutputType * block_results,
                                     BinaryFunction binary_op)
{
    __shared__ OutputType sdata[BLOCK_SIZE];

    // perform first level of reduction,
    // write per-block results to global memory for second level reduction

    const unsigned int grid_size = BLOCK_SIZE * gridDim.x;
    unsigned int i = blockIdx.x * BLOCK_SIZE + threadIdx.x;

    // accumulate local result
    OutputType accum = input[i];
    i += grid_size;

    while (i < n)
    {
        accum = binary_op(accum, input[i]);
        i += grid_size;
    }

    // copy local result to shared mem and perform reduction
    sdata[threadIdx.x] = accum;

    __syncthreads(); // wait for all writes to finish

    if (BLOCK_SIZE >= 512) { if (threadIdx.x < 256) { sdata[threadIdx.x] = binary_op(sdata[threadIdx.x], sdata[threadIdx.x + 256]); } __syncthreads(); }
    if (BLOCK_SIZE >= 256) { if (threadIdx.x < 128) { sdata[threadIdx.x] = binary_op(sdata[threadIdx.x], sdata[threadIdx.x + 128]); } __syncthreads(); }
    if (BLOCK_SIZE >= 128) { if (threadIdx.x <  64) { sdata[threadIdx.x] = binary_op(sdata[threadIdx.x], sdata[threadIdx.x +  64]); } __syncthreads(); }
    if (BLOCK_SIZE >=  64) { if (threadIdx.x <  32) { sdata[threadIdx.x] = binary_op(sdata[threadIdx.x], sdata[threadIdx.x +  32]); } __syncthreads(); }
    if (BLOCK_SIZE >=  32) { if (threadIdx.x <  16) { sdata[threadIdx.x] = binary_op(sdata[threadIdx.x], sdata[threadIdx.x +  16]); } __syncthreads(); }

    if (BLOCK_SIZE >=  16) { if (threadIdx.x <   8) { sdata[threadIdx.x] = binary_op(sdata[threadIdx.x], sdata[threadIdx.x +   8]); } __syncthreads(); }
    if (BLOCK_SIZE >=   8) { if (threadIdx.x <   4) { sdata[threadIdx.x] = binary_op(sdata[threadIdx.x], sdata[threadIdx.x +   4]); } __syncthreads(); }
    if (BLOCK_SIZE >=   4) { if (threadIdx.x <   2) { sdata[threadIdx.x] = binary_op(sdata[threadIdx.x], sdata[threadIdx.x +   2]); } __syncthreads(); }
    if (BLOCK_SIZE >=   2) { if (threadIdx.x <   1) { sdata[threadIdx.x] = binary_op(sdata[threadIdx.x], sdata[threadIdx.x +   1]); } __syncthreads(); }

    // XXX causes the following problem on CUDA 2.2 (Komrade issue #6)
    //     Advisory: Cannot tell what pointer points to, assuming global memory space
    //accum = komrade::detail::block::reduce<OutputType,BinaryFunction,BLOCK_SIZE>
    //    (sdata, threadIdx.x, binary_op);

    // write result for this block to global mem
    if (threadIdx.x == 0)
        block_results[blockIdx.x] = sdata[0];

} // end __komrade__unordered_reduce_kernel()

template<typename InputFunctor,
         typename OutputType,
         typename BinaryFunction>
  OutputType reduce(InputFunctor input,
                    const size_t n,
                    const OutputType init,
                    BinaryFunction binary_op)
{
    const size_t BLOCK_SIZE = 256;  // BLOCK_SIZE must be a power of 2
    const size_t MAX_BLOCKS = 3 * experimental::arch::max_active_threads() / BLOCK_SIZE;

    unsigned int GRID_SIZE;

    // handle zero length array case first
    if( n == 0 )
        return init;

    // TODO if n < UINT_MAX use unsigned int instead of size_t indices in kernel

    // kernels below assume n > 0
    if( n < BLOCK_SIZE )
    {
        GRID_SIZE = 1;
    }
    else
    {
        GRID_SIZE = std::min( (n / BLOCK_SIZE), MAX_BLOCKS);
    }

    // allocate storage for per-block results
    komrade::device_ptr<OutputType> block_results = komrade::device_malloc<OutputType>(GRID_SIZE);

    // do the gpu part
    if( n < BLOCK_SIZE )
    {
        __komrade__serial_reduce_kernel<InputFunctor, OutputType, BinaryFunction>
            <<<GRID_SIZE, 1>>>(input, n, block_results.get(), binary_op);
    }
    else
    {
        __komrade__unordered_reduce_kernel<InputFunctor, OutputType, BinaryFunction, BLOCK_SIZE>
            <<<GRID_SIZE, BLOCK_SIZE>>>(input, n, block_results.get(), binary_op);
    }

    // copy work array to host
    komrade::host_vector<OutputType> host_work(block_results, block_results + GRID_SIZE);

    // free device work array
    komrade::device_free(block_results);

    // reduce on the host
    return komrade::reduce(host_work.begin(), host_work.end(), init, binary_op);
} // end reduce()

} // end namespace cuda

} // end namespace device

} // end namespace detail

} // end namespace komrade

#endif // __CUDACC__

<commit_msg>Workaround disallowed constructors on types declared in __shared__ memory in cuda::reduce.<commit_after>/*
 *  Copyright 2008-2009 NVIDIA Corporation
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 */

/*! \file reduce.inl
 *  \brief Inline file for reduce.h
 */

#pragma once

// do not attempt to compile this file with any other compiler
#ifdef __CUDACC__

#include <komrade/device_vector.h>
#include <komrade/host_vector.h>
#include <komrade/device_malloc.h>
#include <komrade/device_free.h>
#include <komrade/reduce.h>  // for second level reduction

#include <komrade/detail/device/cuda/block/reduce.h>

namespace komrade
{

namespace detail
{

namespace device
{

namespace cuda
{

/*
 * Reduction using a single thread.  Only used for small vectors.
 *
 */
template<typename InputFunctor,
         typename OutputType,
         typename BinaryFunction>
  __global__ void
  __komrade__serial_reduce_kernel(InputFunctor input,
                                  const size_t n,
                                  OutputType * block_results,
                                  BinaryFunction binary_op)
{
    if( threadIdx.x == 0 )
    {
        OutputType accum = input[0];
        for(unsigned int i = 1; i < n; i++){
            accum = binary_op(accum, input[i]);
        }
        block_results[0] = accum;
    }

} // end __komrade__serial_reduce_kernel()

/*
 * Reduce a vector of n elements using binary_op(op())
 *
 * The order of reduction is not defined, so binary_op() should
 * be a commutative (and associative) operator such as
 * (integer) addition.  Since floating point operations
 * do not completely satisfy these criteria, the result is
 * generally not the same as a consecutive reduction of
 * the elements.
 *
 * Uses the same pattern as reduce6() in the CUDA SDK
 *
 */
template<typename InputFunctor,
         typename OutputType,
         typename BinaryFunction,
         unsigned int BLOCK_SIZE>
  __global__ void
  __komrade__unordered_reduce_kernel(InputFunctor input,
                                     const unsigned int n,
                                     OutputType * block_results,
                                     BinaryFunction binary_op)
{
    __shared__ unsigned char sdata_workaround[BLOCK_SIZE * sizeof(OutputType)];
    OutputType *sdata = reinterpret_cast<OutputType*>(sdata_workaround);

    // perform first level of reduction,
    // write per-block results to global memory for second level reduction

    const unsigned int grid_size = BLOCK_SIZE * gridDim.x;
    unsigned int i = blockIdx.x * BLOCK_SIZE + threadIdx.x;

    // accumulate local result
    OutputType accum = input[i];
    i += grid_size;

    while (i < n)
    {
        accum = binary_op(accum, input[i]);
        i += grid_size;
    }

    // copy local result to shared mem and perform reduction
    sdata[threadIdx.x] = accum;

    __syncthreads(); // wait for all writes to finish

    if (BLOCK_SIZE >= 512) { if (threadIdx.x < 256) { sdata[threadIdx.x] = binary_op(sdata[threadIdx.x], sdata[threadIdx.x + 256]); } __syncthreads(); }
    if (BLOCK_SIZE >= 256) { if (threadIdx.x < 128) { sdata[threadIdx.x] = binary_op(sdata[threadIdx.x], sdata[threadIdx.x + 128]); } __syncthreads(); }
    if (BLOCK_SIZE >= 128) { if (threadIdx.x <  64) { sdata[threadIdx.x] = binary_op(sdata[threadIdx.x], sdata[threadIdx.x +  64]); } __syncthreads(); }
    if (BLOCK_SIZE >=  64) { if (threadIdx.x <  32) { sdata[threadIdx.x] = binary_op(sdata[threadIdx.x], sdata[threadIdx.x +  32]); } __syncthreads(); }
    if (BLOCK_SIZE >=  32) { if (threadIdx.x <  16) { sdata[threadIdx.x] = binary_op(sdata[threadIdx.x], sdata[threadIdx.x +  16]); } __syncthreads(); }

    if (BLOCK_SIZE >=  16) { if (threadIdx.x <   8) { sdata[threadIdx.x] = binary_op(sdata[threadIdx.x], sdata[threadIdx.x +   8]); } __syncthreads(); }
    if (BLOCK_SIZE >=   8) { if (threadIdx.x <   4) { sdata[threadIdx.x] = binary_op(sdata[threadIdx.x], sdata[threadIdx.x +   4]); } __syncthreads(); }
    if (BLOCK_SIZE >=   4) { if (threadIdx.x <   2) { sdata[threadIdx.x] = binary_op(sdata[threadIdx.x], sdata[threadIdx.x +   2]); } __syncthreads(); }
    if (BLOCK_SIZE >=   2) { if (threadIdx.x <   1) { sdata[threadIdx.x] = binary_op(sdata[threadIdx.x], sdata[threadIdx.x +   1]); } __syncthreads(); }

    // XXX causes the following problem on CUDA 2.2 (Komrade issue #6)
    //     Advisory: Cannot tell what pointer points to, assuming global memory space
    //accum = komrade::detail::block::reduce<OutputType,BinaryFunction,BLOCK_SIZE>
    //    (sdata, threadIdx.x, binary_op);

    // write result for this block to global mem
    if (threadIdx.x == 0)
        block_results[blockIdx.x] = sdata[threadIdx.x];

} // end __komrade__unordered_reduce_kernel()

template<typename InputFunctor,
         typename OutputType,
         typename BinaryFunction>
  OutputType reduce(InputFunctor input,
                    const size_t n,
                    const OutputType init,
                    BinaryFunction binary_op)
{
    const size_t BLOCK_SIZE = 256;  // BLOCK_SIZE must be a power of 2
    const size_t MAX_BLOCKS = 3 * experimental::arch::max_active_threads() / BLOCK_SIZE;

    unsigned int GRID_SIZE;

    // handle zero length array case first
    if( n == 0 )
        return init;

    // TODO if n < UINT_MAX use unsigned int instead of size_t indices in kernel

    // kernels below assume n > 0
    if( n < BLOCK_SIZE )
    {
        GRID_SIZE = 1;
    }
    else
    {
        GRID_SIZE = std::min( (n / BLOCK_SIZE), MAX_BLOCKS);
    }

    // allocate storage for per-block results
    komrade::device_ptr<OutputType> block_results = komrade::device_malloc<OutputType>(GRID_SIZE);

    // do the gpu part
    if( n < BLOCK_SIZE )
    {
        __komrade__serial_reduce_kernel<InputFunctor, OutputType, BinaryFunction>
            <<<GRID_SIZE, 1>>>(input, n, block_results.get(), binary_op);
    }
    else
    {
        __komrade__unordered_reduce_kernel<InputFunctor, OutputType, BinaryFunction, BLOCK_SIZE>
            <<<GRID_SIZE, BLOCK_SIZE>>>(input, n, block_results.get(), binary_op);
    }

    // copy work array to host
    komrade::host_vector<OutputType> host_work(block_results, block_results + GRID_SIZE);

    // free device work array
    komrade::device_free(block_results);

    // reduce on the host
    return komrade::reduce(host_work.begin(), host_work.end(), init, binary_op);
} // end reduce()

} // end namespace cuda

} // end namespace device

} // end namespace detail

} // end namespace komrade

#endif // __CUDACC__

<|endoftext|>


<commit_before>#include <system_log>
#include <kernel.hpp>
#include <os.hpp>
#include <kernel/memory.hpp>
#include <ringbuffer>
#include <kprint>

struct Log_buffer {
  uint64_t magic;
  int32_t  capacity;
  uint32_t flags;
  char     vla[0];

  static const uint64_t MAGIC = 0xDEADC0DEDEADC0DE;

  MemoryRingBuffer* get_mrb()
  { return reinterpret_cast<MemoryRingBuffer*>(&vla[0]); }
};

static FixedRingBuffer<16384> temp_mrb;
#define MRB_AREA_SIZE (65536) // 64kb
#define MRB_LOG_SIZE  (MRB_AREA_SIZE - sizeof(MemoryRingBuffer) - sizeof(Log_buffer))
//#define VIRTUAL_MOVE
static MemoryRingBuffer* mrb = nullptr;
static inline RingBuffer* get_mrb()
{
  if (mrb != nullptr) return mrb;
  return &temp_mrb;
}

inline static char* get_system_log_loc()
{
#if defined(ARCH_x86_64) && defined(VIRTUAL_MOVE)
  return (char*) ((1ull << 45) - MRB_AREA_SIZE);
#else
  return (char*) kernel::state().liveupdate_phys - MRB_AREA_SIZE;
#endif
}
inline static auto* get_ringbuffer_data()
{
  return get_system_log_loc() + sizeof(Log_buffer) + sizeof(MemoryRingBuffer);
}
inline static auto& get_log_buffer()
{
  return *(Log_buffer*) get_system_log_loc();
}

uint32_t SystemLog::get_flags()
{
  return get_log_buffer().flags;
}

void SystemLog::set_flags(uint32_t new_flags)
{
  get_log_buffer().flags |= new_flags;
}

void SystemLog::clear_flags()
{
  get_log_buffer().flags = 0;
}

void SystemLog::write(const char* buffer, size_t length)
{
  size_t free = get_mrb()->free_space();
  if (free < length) {
    get_mrb()->discard(length - free);
  }
  get_mrb()->write(buffer, length);
}

std::vector<char> SystemLog::copy()
{
  const auto* buffer = get_mrb()->sequentialize();
  return {buffer, buffer + get_mrb()->size()};
}

void SystemLog::initialize()
{
  INFO("SystemLog", "Initializing System Log");

#if defined(ARCH_x86_64) && defined(VIRTUAL_MOVE)
  using namespace util::bitops;
  const uintptr_t syslog_area = (uintptr_t) get_system_log_loc();
  const uintptr_t lu_phys = (uintptr_t) kernel::state().liveupdate_phys;
  // systemlogs physical range
  os::mem::vmmap().assign_range({
        lu_phys - MRB_AREA_SIZE,
        lu_phys - 1,
        "SystemLog physical"
      });
  // move systemlog to high memory and unpresent physical
  os::mem::virtual_move(lu_phys - MRB_AREA_SIZE, MRB_AREA_SIZE,
                        syslog_area, "SystemLog");
#endif

  auto& buffer = get_log_buffer();
  mrb = buffer.get_mrb();

  // There isn't one, so we have to create
  if(buffer.magic != Log_buffer::MAGIC)
  {
    new (mrb) MemoryRingBuffer(get_ringbuffer_data(), MRB_LOG_SIZE);
    buffer.magic = Log_buffer::MAGIC;
    buffer.capacity = mrb->capacity();
    buffer.flags    = 0;

    INFO2("Created @ %p (%i kB)", get_system_log_loc(), mrb->capacity() / 1024);
    INFO2("Data @ %p (%i bytes)", mrb->data(), mrb->capacity());
  }
  // Correct magic means (hopefully) existing system log
  else
  {
    auto* state = (int*)(&buffer.vla);
    assert(state[0] >= 16);

    new (mrb) MemoryRingBuffer(get_ringbuffer_data(),
                    state[0], state[1], state[2], state[3]);

    INFO2("Restored @ %p (%i kB) Flags: 0x%x",
      mrb->data(), mrb->capacity() / 1024, buffer.flags);
  }
  Ensures(mrb != nullptr);
  Expects(buffer.capacity == mrb->capacity());
  Expects(mrb->is_valid());

  // copy from temp RB
  SystemLog::write(temp_mrb.sequentialize(), temp_mrb.size());
}

__attribute__((constructor))
static void system_log_gconstr()
{
  os::add_stdout(SystemLog::write);
}
<commit_msg>system_log: Spin on writes and sequentialize<commit_after>#include <system_log>
#include <kernel.hpp>
#include <os.hpp>
#include <kernel/memory.hpp>
#include <ringbuffer>
#include <smp>

struct Log_buffer {
  uint64_t magic;
  int32_t  capacity;
  uint32_t flags;
  char     vla[0];

  static const uint64_t MAGIC = 0xDEADC0DEDEADC0DE;

  MemoryRingBuffer* get_mrb()
  { return reinterpret_cast<MemoryRingBuffer*>(&vla[0]); }
};

static FixedRingBuffer<16384> temp_mrb;
static spinlock_t syslog_spinner = 0;
#define MRB_AREA_SIZE (65536) // 64kb
#define MRB_LOG_SIZE  (MRB_AREA_SIZE - sizeof(MemoryRingBuffer) - sizeof(Log_buffer))
//#define VIRTUAL_MOVE
static MemoryRingBuffer* mrb = nullptr;
static inline RingBuffer* get_mrb()
{
  if (mrb != nullptr) return mrb;
  return &temp_mrb;
}

inline static char* get_system_log_loc()
{
#if defined(ARCH_x86_64) && defined(VIRTUAL_MOVE)
  return (char*) ((1ull << 45) - MRB_AREA_SIZE);
#else
  return (char*) kernel::state().liveupdate_phys - MRB_AREA_SIZE;
#endif
}
inline static auto* get_ringbuffer_data()
{
  return get_system_log_loc() + sizeof(Log_buffer) + sizeof(MemoryRingBuffer);
}
inline static auto& get_log_buffer()
{
  return *(Log_buffer*) get_system_log_loc();
}

uint32_t SystemLog::get_flags()
{
  return get_log_buffer().flags;
}

void SystemLog::set_flags(uint32_t new_flags)
{
  get_log_buffer().flags |= new_flags;
}

void SystemLog::clear_flags()
{
  get_log_buffer().flags = 0;
}

void SystemLog::write(const char* buffer, size_t length)
{
  scoped_spinlock { syslog_spinner };
  size_t free = get_mrb()->free_space();
  if (free < length) {
    get_mrb()->discard(length - free);
  }
  get_mrb()->write(buffer, length);
}

std::vector<char> SystemLog::copy()
{
  scoped_spinlock { syslog_spinner };
  const auto* buffer = get_mrb()->sequentialize();
  return {buffer, buffer + get_mrb()->size()};
}

void SystemLog::initialize()
{
  INFO("SystemLog", "Initializing System Log");

#if defined(ARCH_x86_64) && defined(VIRTUAL_MOVE)
  using namespace util::bitops;
  const uintptr_t syslog_area = (uintptr_t) get_system_log_loc();
  const uintptr_t lu_phys = (uintptr_t) kernel::state().liveupdate_phys;
  // systemlogs physical range
  os::mem::vmmap().assign_range({
        lu_phys - MRB_AREA_SIZE,
        lu_phys - 1,
        "SystemLog physical"
      });
  // move systemlog to high memory and unpresent physical
  os::mem::virtual_move(lu_phys - MRB_AREA_SIZE, MRB_AREA_SIZE,
                        syslog_area, "SystemLog");
#endif

  auto& buffer = get_log_buffer();
  mrb = buffer.get_mrb();

  // There isn't one, so we have to create
  if(buffer.magic != Log_buffer::MAGIC)
  {
    new (mrb) MemoryRingBuffer(get_ringbuffer_data(), MRB_LOG_SIZE);
    buffer.magic = Log_buffer::MAGIC;
    buffer.capacity = mrb->capacity();
    buffer.flags    = 0;

    INFO2("Created @ %p (%i kB)", get_system_log_loc(), mrb->capacity() / 1024);
    INFO2("Data @ %p (%i bytes)", mrb->data(), mrb->capacity());
  }
  // Correct magic means (hopefully) existing system log
  else
  {
    auto* state = (int*)(&buffer.vla);
    assert(state[0] >= 16);

    new (mrb) MemoryRingBuffer(get_ringbuffer_data(),
                    state[0], state[1], state[2], state[3]);

    INFO2("Restored @ %p (%i kB) Flags: 0x%x",
      mrb->data(), mrb->capacity() / 1024, buffer.flags);
  }
  Ensures(mrb != nullptr);
  Expects(buffer.capacity == mrb->capacity());
  Expects(mrb->is_valid());

  // copy from temp RB
  SystemLog::write(temp_mrb.sequentialize(), temp_mrb.size());
}

__attribute__((constructor))
static void system_log_gconstr()
{
  os::add_stdout(SystemLog::write);
}
<|endoftext|>


<commit_before>/*
Copyright (c) 2013 Microsoft Corporation. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.

Author: Leonardo de Moura
*/
#include <sstream>
#include "type_check.h"
#include "normalize.h"
#include "instantiate.h"
#include "builtin.h"
#include "free_vars.h"
#include "exception.h"
#include "trace.h"

namespace lean {
bool is_convertible_core(expr const & expected, expr const & given, environment const & env) {
    if (expected == given)
        return true;
    if (is_type(expected) && is_type(given)) {
        if (env.is_ge(ty_level(expected), ty_level(given)))
            return true;
    }
    return false;
}

bool is_convertible(expr const & expected, expr const & given, environment const & env, context const & ctx) {
    lean_trace("is_convertible", tout << expected << "\n" << given << "\n" << ctx << "\n";);
    if (is_convertible_core(expected, given, env))
        return true;
    expr e_n = normalize(expected, env, ctx);
    expr g_n = normalize(given, env, ctx);
    return is_convertible_core(e_n, g_n, env);
}

struct infer_type_fn {
    environment const & m_env;

    expr lookup(context const & c, unsigned i) {
        context const & def_c = ::lean::lookup(c, i);
        lean_assert(length(c) >= length(def_c));
        lean_assert(length(def_c) > 0);
        return lift_free_vars(head(def_c).get_type(), length(c) - (length(def_c) - 1));
    }

    level infer_universe(expr const & t, context const & ctx) {
        lean_trace("type_check", tout << "infer universe\n" << t << "\n";);
        expr u = normalize(infer_type(t, ctx), m_env, ctx);
        if (is_type(u))
            return ty_level(u);
        if (is_bool_type(u))
            return level();
        std::ostringstream buffer;
        buffer << "type expected, ";
        if (!empty(ctx))
            buffer << "in context:\n" << ctx << "\n";
        buffer << "got:\n" << t;
        throw exception(buffer.str());
    }

    expr check_pi(expr const & e, context const & ctx) {
        if (is_pi(e))
            return e;
        expr r = normalize(e, m_env, ctx);
        if (is_pi(r))
            return r;
        std::ostringstream buffer;
        buffer << "function expected, ";
        if (!empty(ctx))
            buffer << "in context:\n" << ctx << "\n";
        buffer << "got:\n" << e;
        throw exception(buffer.str());
    }

    expr infer_pi(expr const & e, context const & ctx) {
        return check_pi(infer_type(e, ctx), ctx);
    }

    expr infer_type(expr const & e, context const & ctx) {
        lean_trace("type_check", tout << "infer type\n" << e << "\n" << ctx << "\n";);
        switch (e.kind()) {
        case expr_kind::Constant:
            return m_env.get_object(const_name(e)).get_type();
        case expr_kind::Var:      return lookup(ctx, var_idx(e));
        case expr_kind::Type:     return mk_type(ty_level(e) + 1);
        case expr_kind::App: {
            expr f_t     = infer_pi(arg(e, 0), ctx);
            unsigned i   = 1;
            unsigned num = num_args(e);
            lean_assert(num >= 2);
            while (true) {
                expr const & c = arg(e, i);
                expr c_t       = infer_type(c, ctx);
                if (!is_convertible(abst_domain(f_t), c_t, m_env, ctx)) {
                    std::ostringstream buffer;
                    buffer << "type mismatch at argument " << i << " of\n" << e
                           << "\nexpected type:\n" << abst_domain(f_t)
                           << "\ngiven type:\n" << c_t;
                    if (!empty(ctx))
                        buffer << "\nin context:\n" << ctx;
                    throw exception(buffer.str());
                }
                f_t = instantiate(abst_body(f_t), c);
                i++;
                if (i == num)
                    return f_t;
                check_pi(f_t, ctx);
            }
        }
        case expr_kind::Eq:
            infer_type(eq_lhs(e), ctx);
            infer_type(eq_rhs(e), ctx);
            return mk_bool_type();
        case expr_kind::Lambda: {
            infer_universe(abst_domain(e), ctx);
            expr t = infer_type(abst_body(e), extend(ctx, abst_name(e), abst_domain(e)));
            return mk_pi(abst_name(e), abst_domain(e), t);
        }
        case expr_kind::Pi: {
            level l1 = infer_universe(abst_domain(e), ctx);
            level l2 = infer_universe(abst_body(e), extend(ctx, abst_name(e), abst_domain(e)));
            return mk_type(max(l1, l2));
        }
        case expr_kind::Let:
            return infer_type(let_body(e), extend(ctx, let_name(e), infer_type(let_value(e), ctx), let_value(e)));
        case expr_kind::Value:
            return to_value(e).get_type();
        }
        lean_unreachable();
        return e;
    }

    infer_type_fn(environment const & env):
        m_env(env) {
    }

    expr operator()(expr const & e, context const & ctx) {
        return infer_type(e, ctx);
    }
};

expr  infer_type(expr const & e, environment const & env, context const & ctx) {
    return infer_type_fn(env)(e, ctx);
}

level infer_universe(expr const & t, environment const & env, context const & ctx) {
    return infer_type_fn(env).infer_universe(t, ctx);
}
}
<commit_msg>Fix bug in is_convertible<commit_after>/*
Copyright (c) 2013 Microsoft Corporation. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.

Author: Leonardo de Moura
*/
#include <sstream>
#include "type_check.h"
#include "normalize.h"
#include "instantiate.h"
#include "builtin.h"
#include "free_vars.h"
#include "exception.h"
#include "trace.h"

namespace lean {
bool is_convertible_core(expr const & expected, expr const & given, environment const & env) {
    if (expected == given)
        return true;
    expr const * e = &expected;
    expr const * g = &given;
    while (true) {
        if (is_type(*e) && is_type(*g)) {
            if (env.is_ge(ty_level(*e), ty_level(*g)))
                return true;
        }
        if (is_pi(*e) && is_pi(*g) && abst_domain(*e) == abst_domain(*g)) {
            e = &abst_body(*e);
            g = &abst_body(*g);
        }
        else {
            return false;
        }
    }
}

bool is_convertible(expr const & expected, expr const & given, environment const & env, context const & ctx) {
    lean_trace("is_convertible", tout << expected << "\n" << given << "\n" << ctx << "\n";);
    if (is_convertible_core(expected, given, env))
        return true;
    expr e_n = normalize(expected, env, ctx);
    expr g_n = normalize(given, env, ctx);
    return is_convertible_core(e_n, g_n, env);
}

struct infer_type_fn {
    environment const & m_env;

    expr lookup(context const & c, unsigned i) {
        context const & def_c = ::lean::lookup(c, i);
        lean_assert(length(c) >= length(def_c));
        lean_assert(length(def_c) > 0);
        return lift_free_vars(head(def_c).get_type(), length(c) - (length(def_c) - 1));
    }

    level infer_universe(expr const & t, context const & ctx) {
        lean_trace("type_check", tout << "infer universe\n" << t << "\n";);
        expr u = normalize(infer_type(t, ctx), m_env, ctx);
        if (is_type(u))
            return ty_level(u);
        if (is_bool_type(u))
            return level();
        std::ostringstream buffer;
        buffer << "type expected, ";
        if (!empty(ctx))
            buffer << "in context:\n" << ctx << "\n";
        buffer << "got:\n" << t;
        throw exception(buffer.str());
    }

    expr check_pi(expr const & e, context const & ctx) {
        if (is_pi(e))
            return e;
        expr r = normalize(e, m_env, ctx);
        if (is_pi(r))
            return r;
        std::ostringstream buffer;
        buffer << "function expected, ";
        if (!empty(ctx))
            buffer << "in context:\n" << ctx << "\n";
        buffer << "got:\n" << e;
        throw exception(buffer.str());
    }

    expr infer_pi(expr const & e, context const & ctx) {
        return check_pi(infer_type(e, ctx), ctx);
    }

    expr infer_type(expr const & e, context const & ctx) {
        lean_trace("type_check", tout << "infer type\n" << e << "\n" << ctx << "\n";);
        switch (e.kind()) {
        case expr_kind::Constant:
            return m_env.get_object(const_name(e)).get_type();
        case expr_kind::Var:      return lookup(ctx, var_idx(e));
        case expr_kind::Type:     return mk_type(ty_level(e) + 1);
        case expr_kind::App: {
            expr f_t     = infer_pi(arg(e, 0), ctx);
            unsigned i   = 1;
            unsigned num = num_args(e);
            lean_assert(num >= 2);
            while (true) {
                expr const & c = arg(e, i);
                expr c_t       = infer_type(c, ctx);
                if (!is_convertible(abst_domain(f_t), c_t, m_env, ctx)) {
                    std::ostringstream buffer;
                    buffer << "type mismatch at argument " << i << " of\n" << e
                           << "\nexpected type:\n" << abst_domain(f_t)
                           << "\ngiven type:\n" << c_t;
                    if (!empty(ctx))
                        buffer << "\nin context:\n" << ctx;
                    throw exception(buffer.str());
                }
                f_t = instantiate(abst_body(f_t), c);
                i++;
                if (i == num)
                    return f_t;
                check_pi(f_t, ctx);
            }
        }
        case expr_kind::Eq:
            infer_type(eq_lhs(e), ctx);
            infer_type(eq_rhs(e), ctx);
            return mk_bool_type();
        case expr_kind::Lambda: {
            infer_universe(abst_domain(e), ctx);
            expr t = infer_type(abst_body(e), extend(ctx, abst_name(e), abst_domain(e)));
            return mk_pi(abst_name(e), abst_domain(e), t);
        }
        case expr_kind::Pi: {
            level l1 = infer_universe(abst_domain(e), ctx);
            level l2 = infer_universe(abst_body(e), extend(ctx, abst_name(e), abst_domain(e)));
            return mk_type(max(l1, l2));
        }
        case expr_kind::Let:
            return infer_type(let_body(e), extend(ctx, let_name(e), infer_type(let_value(e), ctx), let_value(e)));
        case expr_kind::Value:
            return to_value(e).get_type();
        }
        lean_unreachable();
        return e;
    }

    infer_type_fn(environment const & env):
        m_env(env) {
    }

    expr operator()(expr const & e, context const & ctx) {
        return infer_type(e, ctx);
    }
};

expr  infer_type(expr const & e, environment const & env, context const & ctx) {
    return infer_type_fn(env)(e, ctx);
}

level infer_universe(expr const & t, environment const & env, context const & ctx) {
    return infer_type_fn(env).infer_universe(t, ctx);
}
}
<|endoftext|>


<commit_before>//   Copyright 2016-2020 Jean-Francois Poilpret
//
//   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.

/*
 * Check DS1307 I2C device (real-time clock) and display output to the UART console.
 * This program uses FastArduino DS1307 support API.
 *
 * Wiring:
 * NB: you should add pullup resistors (10K-22K typically) on both SDA and SCL lines.
 * WARNING: wiring is very sensitive for I2C connections! When using breadboard, ensure
 * wires connections are tight and stable.
 * - on ATmega328P based boards (including Arduino UNO):
 *   - A4 (PC4, SDA): connected to DS1307 SDA pin
 *   - A5 (PC5, SCL): connected to DS1307 SCL pin
 *   - direct USB access
 * - on Arduino LEONARDO:
 *   - D2 (PD1, SDA): connected to DS1307 SDA pin
 *   - D3 (PD0, SCL): connected to DS1307 SDA pin
 *   - direct USB access
 * - on Arduino MEGA:
 *   - D20 (PD1, SDA): connected to DS1307 SDA pin
 *   - D21 (PD0, SCL): connected to DS1307 SDA pin
 *   - direct USB access
 * - on ATtinyX4 based boards:
 *   - D6 (PA6, SDA): connected to DS1307 SDA pin
 *   - D4 (PA4, SCL): connected to DS1307 SDA pin
 *   - D8 (PB0, TX): connected to SerialUSB converter
 * - on ATtinyX5 based boards:
 *   - D0 (PB0, SDA): connected to DS1307 SDA pin
 *   - D2 (PB2, SCL): connected to DS1307 SDA pin
 *   - D3 (PB3, TX): connected to SerialUSB converter
 */

#include <fastarduino/time.h>
#include <fastarduino/new_i2c_handler.h>
#include <fastarduino/devices/new_ds1307.h>
#include <fastarduino/iomanip.h>
#include <fastarduino/new_i2c_debug.h>

#if defined(ARDUINO_UNO) || defined(ARDUINO_NANO) || defined(BREADBOARD_ATMEGA328P)
#define HARDWARE_UART 1
#include <fastarduino/uart.h>
static constexpr const board::USART UART = board::USART::USART0;
static constexpr const uint8_t OUTPUT_BUFFER_SIZE = 64;
static constexpr uint8_t I2C_BUFFER_SIZE = 32;
static i2c::I2CCommand i2c_buffer[I2C_BUFFER_SIZE];
// Define vectors we need in the example
REGISTER_UATX_ISR(0)
#elif defined(ARDUINO_MEGA)
#define HARDWARE_UART 1
#include <fastarduino/uart.h>
static constexpr const board::USART UART = board::USART::USART0;
static constexpr const uint8_t OUTPUT_BUFFER_SIZE = 64;
static constexpr uint8_t I2C_BUFFER_SIZE = 32;
static i2c::I2CCommand i2c_buffer[I2C_BUFFER_SIZE];
// Define vectors we need in the example
REGISTER_UATX_ISR(0)
#elif defined(ARDUINO_LEONARDO)
#define HARDWARE_UART 1
#include <fastarduino/uart.h>
static constexpr const board::USART UART = board::USART::USART1;
static constexpr const uint8_t OUTPUT_BUFFER_SIZE = 64;
static constexpr uint8_t I2C_BUFFER_SIZE = 32;
static i2c::I2CCommand i2c_buffer[I2C_BUFFER_SIZE];
// Define vectors we need in the example
REGISTER_UATX_ISR(1)
#elif defined(BREADBOARD_ATTINYX4)
#define HARDWARE_UART 0
#include <fastarduino/soft_uart.h>
static constexpr const board::DigitalPin TX = board::DigitalPin::D8_PB0;
static constexpr const uint8_t OUTPUT_BUFFER_SIZE = 64;
#elif defined(BREADBOARD_ATTINYX5)
#define HARDWARE_UART 0
#include <fastarduino/soft_uart.h>
static constexpr const board::DigitalPin TX = board::DigitalPin::D3_PB3;
static constexpr const uint8_t OUTPUT_BUFFER_SIZE = 64;
#else
#error "Current target is not yet supported!"
#endif

// UART buffer for traces
static char output_buffer[OUTPUT_BUFFER_SIZE];

using devices::rtc::DS1307;
using devices::rtc::WeekDay;
using devices::rtc::tm;
using devices::rtc::SquareWaveFrequency;
using namespace streams;

#if I2C_TRUE_ASYNC
static constexpr const uint8_t DEBUG_SIZE = 32;
using DEBUGGER = i2c::debug::I2CAsyncDebugger<DEBUG_SIZE>;
// using MANAGER = i2c::I2CManager<i2c::I2CMode::STANDARD, false, false>;
using MANAGER = i2c::I2CManager<i2c::I2CMode::STANDARD, false, true, DEBUGGER&>;
REGISTER_I2C_ISR(MANAGER)
#else
using DEBUGGER = i2c::debug::I2CSyncDebugger;
// using MANAGER = i2c::I2CManager<i2c::I2CMode::STANDARD, false, false>;
using MANAGER = i2c::I2CManager<i2c::I2CMode::STANDARD, false, true, DEBUGGER&>;
#endif

void display_status(ostream& out, char index, uint8_t status)
{
	out << hex << F("status #") << index << ' ' << status << endl;
}

void display_ram(ostream& out, const uint8_t* data, uint8_t size)
{
	out << hex << F("RAM content\n");
	for (uint8_t i = 0; i < size; ++i)
	{
		if (!(i % 8)) out << endl;
		out << setw(2) << data[i] << ' ';
	}
	out << endl;
}

void display_time(ostream& out, const tm& time)
{
	out	<< dec << F("RTC: [")
		<< uint8_t(time.tm_wday) << ']'
		<< time.tm_mday << '.'
		<< time.tm_mon << '.'
		<< time.tm_year << ' '
		<< time.tm_hour << ':'
		<< time.tm_min << ':'
		<< time.tm_sec
		<< endl;
}

int main() __attribute__((OS_main));
int main()
{
	board::init();
	sei();
#if HARDWARE_UART
	serial::hard::UATX<UART> uart{output_buffer};
#else
	serial::soft::UATX<TX> uart{output_buffer};
#endif
	uart.begin(115200);
	ostream out = uart.out();
	out << F("Start") << endl;

	// Start TWI interface
	//====================
#if I2C_TRUE_ASYNC
	DEBUGGER debugger;
	MANAGER manager{i2c_buffer, debugger, i2c::I2CErrorPolicy::CLEAR_ALL_COMMANDS};
#else
	DEBUGGER debugger{out};
	MANAGER manager{debugger, i2c::I2CErrorPolicy::CLEAR_ALL_COMMANDS};
#endif
	manager.begin();
	out << F("I2C interface started") << endl;
	display_status(out, '1', manager.status());
	time::delay_ms(1000);

	DS1307<MANAGER> rtc{manager};

	// read RAM content and print out
	uint8_t data[DS1307<MANAGER>::ram_size()];
	memset(data, 0, sizeof data);
	rtc.get_ram(0, data);
	display_status(out, '2', manager.status());
	display_ram(out, data, sizeof data);
	debugger.trace(out);

	tm time1;
	time1.tm_hour = 8;
	time1.tm_min = 45;
	time1.tm_sec = 30;
	time1.tm_wday = WeekDay::TUESDAY;
	time1.tm_mday = 13;
	time1.tm_mon = 6;
	time1.tm_year = 17;

	// Initialize clock date
	//=======================
	rtc.set_datetime(time1);
	display_status(out, '3', manager.status());
	debugger.trace(out);

	time::delay_ms(2000);

	// Read clock
	//============
	tm time2;
	rtc.get_datetime(time2);
	display_status(out, '4', manager.status());
	display_time(out, time2);
	debugger.trace(out);

	// Enable output clock
	//====================
	rtc.enable_output(SquareWaveFrequency::FREQ_1HZ);
	display_status(out, '5', manager.status());
	debugger.trace(out);

	// Provide 10 seconds delay to allow checking square wave output with an oscilloscope
	time::delay_ms(10000);

	rtc.disable_output(false);
	display_status(out, '6', manager.status());
	debugger.trace(out);

	// write RAM content
	for (uint8_t i = 0; i < sizeof(data); ++i)
		data[i] = i;
	rtc.set_ram(0, data);
	display_status(out, '7', manager.status());
	debugger.trace(out);

	// Stop TWI interface
	//===================
	manager.end();
	out << F("End") << endl;
}
<commit_msg>Add compile options for debug/no debug<commit_after>//   Copyright 2016-2020 Jean-Francois Poilpret
//
//   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.

/*
 * Check DS1307 I2C device (real-time clock) and display output to the UART console.
 * This program uses FastArduino DS1307 support API.
 *
 * Wiring:
 * NB: you should add pullup resistors (10K-22K typically) on both SDA and SCL lines.
 * WARNING: wiring is very sensitive for I2C connections! When using breadboard, ensure
 * wires connections are tight and stable.
 * - on ATmega328P based boards (including Arduino UNO):
 *   - A4 (PC4, SDA): connected to DS1307 SDA pin
 *   - A5 (PC5, SCL): connected to DS1307 SCL pin
 *   - direct USB access
 * - on Arduino LEONARDO:
 *   - D2 (PD1, SDA): connected to DS1307 SDA pin
 *   - D3 (PD0, SCL): connected to DS1307 SDA pin
 *   - direct USB access
 * - on Arduino MEGA:
 *   - D20 (PD1, SDA): connected to DS1307 SDA pin
 *   - D21 (PD0, SCL): connected to DS1307 SDA pin
 *   - direct USB access
 * - on ATtinyX4 based boards:
 *   - D6 (PA6, SDA): connected to DS1307 SDA pin
 *   - D4 (PA4, SCL): connected to DS1307 SDA pin
 *   - D8 (PB0, TX): connected to SerialUSB converter
 * - on ATtinyX5 based boards:
 *   - D0 (PB0, SDA): connected to DS1307 SDA pin
 *   - D2 (PB2, SCL): connected to DS1307 SDA pin
 *   - D3 (PB3, TX): connected to SerialUSB converter
 */

#include <fastarduino/time.h>
#include <fastarduino/new_i2c_handler.h>
#include <fastarduino/devices/new_ds1307.h>
#include <fastarduino/iomanip.h>
#include <fastarduino/new_i2c_debug.h>

#if defined(ARDUINO_UNO) || defined(ARDUINO_NANO) || defined(BREADBOARD_ATMEGA328P)
#define HARDWARE_UART 1
#include <fastarduino/uart.h>
static constexpr const board::USART UART = board::USART::USART0;
static constexpr const uint8_t OUTPUT_BUFFER_SIZE = 64;
static constexpr uint8_t I2C_BUFFER_SIZE = 32;
static i2c::I2CCommand i2c_buffer[I2C_BUFFER_SIZE];
// Define vectors we need in the example
REGISTER_UATX_ISR(0)
#elif defined(ARDUINO_MEGA)
#define HARDWARE_UART 1
#include <fastarduino/uart.h>
static constexpr const board::USART UART = board::USART::USART0;
static constexpr const uint8_t OUTPUT_BUFFER_SIZE = 64;
static constexpr uint8_t I2C_BUFFER_SIZE = 32;
static i2c::I2CCommand i2c_buffer[I2C_BUFFER_SIZE];
// Define vectors we need in the example
REGISTER_UATX_ISR(0)
#elif defined(ARDUINO_LEONARDO)
#define HARDWARE_UART 1
#include <fastarduino/uart.h>
static constexpr const board::USART UART = board::USART::USART1;
static constexpr const uint8_t OUTPUT_BUFFER_SIZE = 64;
static constexpr uint8_t I2C_BUFFER_SIZE = 32;
static i2c::I2CCommand i2c_buffer[I2C_BUFFER_SIZE];
// Define vectors we need in the example
REGISTER_UATX_ISR(1)
#elif defined(BREADBOARD_ATTINYX4)
#define HARDWARE_UART 0
#include <fastarduino/soft_uart.h>
static constexpr const board::DigitalPin TX = board::DigitalPin::D8_PB0;
static constexpr const uint8_t OUTPUT_BUFFER_SIZE = 64;
#elif defined(BREADBOARD_ATTINYX5)
#define HARDWARE_UART 0
#include <fastarduino/soft_uart.h>
static constexpr const board::DigitalPin TX = board::DigitalPin::D3_PB3;
static constexpr const uint8_t OUTPUT_BUFFER_SIZE = 64;
#else
#error "Current target is not yet supported!"
#endif

// #define DEBUG_I2C

// UART buffer for traces
static char output_buffer[OUTPUT_BUFFER_SIZE];

using devices::rtc::DS1307;
using devices::rtc::WeekDay;
using devices::rtc::tm;
using devices::rtc::SquareWaveFrequency;
using namespace streams;

#if I2C_TRUE_ASYNC

#ifdef DEBUG_I2C
static constexpr const uint8_t DEBUG_SIZE = 32;
using DEBUGGER = i2c::debug::I2CAsyncDebugger<DEBUG_SIZE>;
using MANAGER = i2c::I2CManager<i2c::I2CMode::STANDARD, false, true, DEBUGGER&>;
#define TRACE() debugger.trace(out)
#else
using MANAGER = i2c::I2CManager<i2c::I2CMode::STANDARD, false, false>;
#define TRACE()
#endif
REGISTER_I2C_ISR(MANAGER)

#else

#define TRACE()
#ifdef DEBUG_I2C
using DEBUGGER = i2c::debug::I2CSyncDebugger;
using MANAGER = i2c::I2CManager<i2c::I2CMode::STANDARD, false, true, DEBUGGER&>;
#else
using MANAGER = i2c::I2CManager<i2c::I2CMode::STANDARD, false, false>;
#endif

#endif

void display_status(ostream& out, char index, uint8_t status)
{
	out << hex << F("status #") << index << ' ' << status << endl;
}

void display_ram(ostream& out, const uint8_t* data, uint8_t size)
{
	out << hex << F("RAM content\n");
	for (uint8_t i = 0; i < size; ++i)
	{
		if (!(i % 8)) out << endl;
		out << setw(2) << data[i] << ' ';
	}
	out << endl;
}

void display_time(ostream& out, const tm& time)
{
	out	<< dec << F("RTC: [")
		<< uint8_t(time.tm_wday) << ']'
		<< time.tm_mday << '.'
		<< time.tm_mon << '.'
		<< time.tm_year << ' '
		<< time.tm_hour << ':'
		<< time.tm_min << ':'
		<< time.tm_sec
		<< endl;
}

int main() __attribute__((OS_main));
int main()
{
	board::init();
	sei();
#if HARDWARE_UART
	serial::hard::UATX<UART> uart{output_buffer};
#else
	serial::soft::UATX<TX> uart{output_buffer};
#endif
	uart.begin(115200);
	ostream out = uart.out();
	out << F("Start") << endl;

	// Start TWI interface
	//====================
#if I2C_TRUE_ASYNC

#ifdef DEBUG_I2C
	DEBUGGER debugger;
	MANAGER manager{i2c_buffer, debugger, i2c::I2CErrorPolicy::CLEAR_ALL_COMMANDS};
#else
	MANAGER manager{i2c_buffer, i2c::I2CErrorPolicy::CLEAR_ALL_COMMANDS};
#endif

#else

#ifdef DEBUG_I2C
	DEBUGGER debugger{out};
	MANAGER manager{debugger, i2c::I2CErrorPolicy::CLEAR_ALL_COMMANDS};
#else
	MANAGER manager{i2c::I2CErrorPolicy::CLEAR_ALL_COMMANDS};
#endif

#endif

	manager.begin();
	out << F("I2C interface started") << endl;
	display_status(out, '1', manager.status());
	time::delay_ms(1000);

	DS1307<MANAGER> rtc{manager};

	// read RAM content and print out
	uint8_t data[DS1307<MANAGER>::ram_size()];
	memset(data, 0, sizeof data);
	rtc.get_ram(0, data);
	display_status(out, '2', manager.status());
	display_ram(out, data, sizeof data);
	TRACE();

	tm time1;
	time1.tm_hour = 8;
	time1.tm_min = 45;
	time1.tm_sec = 30;
	time1.tm_wday = WeekDay::TUESDAY;
	time1.tm_mday = 13;
	time1.tm_mon = 6;
	time1.tm_year = 17;

	// Initialize clock date
	//=======================
	rtc.set_datetime(time1);
	display_status(out, '3', manager.status());
	TRACE();

	time::delay_ms(2000);

	// Read clock
	//============
	tm time2;
	rtc.get_datetime(time2);
	display_status(out, '4', manager.status());
	display_time(out, time2);
	TRACE();

	// Enable output clock
	//====================
	rtc.enable_output(SquareWaveFrequency::FREQ_1HZ);
	display_status(out, '5', manager.status());
	TRACE();

	// Provide 10 seconds delay to allow checking square wave output with an oscilloscope
	time::delay_ms(10000);

	rtc.disable_output(false);
	display_status(out, '6', manager.status());
	TRACE();

	// write RAM content
	for (uint8_t i = 0; i < sizeof(data); ++i)
		data[i] = i;
	rtc.set_ram(0, data);
	display_status(out, '7', manager.status());
	TRACE();

	// Stop TWI interface
	//===================
	manager.end();
	out << F("End") << endl;
}
<|endoftext|>


<commit_before>#include "AbstractTemplatePage.h"
#include "private/AbstractTemplatePage_p.h"

#include <QtCore/QCoreApplication>
#include <QtCore/QDebug>
#include <QtCore/QDir>
#include <QtCore/QFile>
#include <QtXml/QDomDocument>

namespace web
{
namespace page
{
namespace templates
{

AbstractTemplatePage::~AbstractTemplatePage()
{
    Q_D(AbstractTemplatePage);

    delete d->pageModel;
    qDeleteAll(d->templateModels);

    delete d_ptr;
}

QByteArray AbstractTemplatePage::getContent()
{
    Q_D(AbstractTemplatePage);

    if ( d->pageData.isEmpty() ) {
            initPage();
        }

    if ( d->templates.isEmpty() ) {
            initTemplates();
        }

    initModels();

    render();

    destroyModels();

    return d->content;
}

void AbstractTemplatePage::setSession(website::WebSession *s)
{
    Q_D(AbstractTemplatePage);
    d->session = s;
}

void AbstractTemplatePage::setRequest(Tufao::HttpServerRequest *r)
{
    Q_D(AbstractTemplatePage);
    d->request = r;
}

void AbstractTemplatePage::setResponse(Tufao::HttpServerResponse *r)
{
    Q_D(AbstractTemplatePage);
    d->response = r;
}

void AbstractTemplatePage::setPostRequestData(QMap<QByteArray, QByteArray> data)
{
    Q_D(AbstractTemplatePage);
    d->post = data;
}

void AbstractTemplatePage::clearPostRequestData()
{
    Q_D(AbstractTemplatePage);
    d->post.clear();
}

void AbstractTemplatePage::setGetRequestData(QMap<QByteArray, QByteArray> data)
{
    Q_D(AbstractTemplatePage);
    d->get = data;
}

void AbstractTemplatePage::clearGetRequestData()
{
    Q_D(AbstractTemplatePage);
    d->get.clear();
}

void AbstractTemplatePage::setRequestPath(const QString & path)
{
    Q_D(AbstractTemplatePage);
    d->requestPath = path;
}

AbstractTemplatePage::AbstractTemplatePage(AbstractTemplatePagePrivate *d) :
    d_ptr(d)
{
}

void AbstractTemplatePage::initPage()
{
    Q_D(AbstractTemplatePage);
    QString filepath = QCoreApplication::applicationDirPath() + QDir::separator() + d->pageFilename;
    QFile f(filepath);
    if ( f.open(QIODevice::ReadOnly) ) {
            QByteArray data = f.readAll();
            d->pageData = data;
            f.close();
        }
    else {
            qDebug() << Q_FUNC_INFO << f.errorString();
        }
}

void AbstractTemplatePage::initTemplate(QString name, QString filename)
{
    QFile f(filename);
    if ( f.open(QIODevice::ReadOnly) ) {
            Q_D(AbstractTemplatePage);
            QByteArray data = f.readAll();
            d->templates.insert(name, data);
            f.close();
        }
    else {
            qDebug() << Q_FUNC_INFO << f.errorString();
    }
}

void AbstractTemplatePage::loadModel(const QString & name)
{
    Q_D(AbstractTemplatePage);
    model::AbstractListModel * model = d->templateModels.value(name);
    model->load();
}

void AbstractTemplatePage::unloadModel(const QString & name)
{
    Q_D(AbstractTemplatePage);
    model::AbstractListModel * model = d->templateModels.value(name);
    model->unload();
}

void AbstractTemplatePage::render()
{
    Q_D(AbstractTemplatePage);

    QDomDocument doc;
    QString errMsg;
    int errLine, errColumn;
    doc.setContent(d->pageData, false, &errMsg, &errLine, &errColumn);

    QDomNodeList templates = doc.elementsByTagName("tpl");
    const int templateSize = templates.size();
    // We need to go backwards because otherwise the deleting of nodes doesnt work
    for (int i = templateSize-1; i >= 0 ; --i) {
            QDomElement element = templates.item(i).toElement();
            QDomNode parentNode = element.parentNode();

            if (element.hasAttribute("src")) {
                    QString tplName = element.attribute("src");
                    bool isAllowedToShow = true;

                    if (element.hasAttribute("if")) {
                            QString ifAttribute = element.attribute("if");
                            isAllowedToShow = d->isTemplateAllowed(ifAttribute, d->pageModel);
                        }
                    else if (element.hasAttribute("if-not")) {
                            QString ifAttribute = element.attribute("if-not");
                            isAllowedToShow = !d->isTemplateAllowed(ifAttribute, d->pageModel);
                        }

                    if (isAllowedToShow) {

                            QString templateStartTag = QStringLiteral("<tpl>");
                            QString templateEndTag = QStringLiteral("</tpl>");
                            QString templateContent = d->templates[tplName].replace(templateStartTag, "").replace(templateEndTag, "");
                            QString templateFilled;

                            if (element.hasAttribute("model")) {
                                    QString modelName = element.attribute("model");
                                    web::page::model::AbstractListModel *model = d->templateModels[modelName];
                                    model->load();
                                    QList<web::page::model::AbstractModel *> modelList = model->models();
                                    QString modelIfAttribute;
                                    int modelCountAttribute = -1;
                                    int modelStartCountAttribute = -1;

                                    bool hasIfAttribute = false;

                                    if (element.hasAttribute("if-model")) {
                                            modelIfAttribute = element.attribute("if-model");
                                            hasIfAttribute = true;
                                        }

                                    if (element.hasAttribute("model-start-count")) {
                                        modelStartCountAttribute = d->getTemplateAttribute<int>(element,
                                                                                "model-start-count",
                                                                                d->pageModel);
                                    }

                                    if (element.hasAttribute("model-count")) {
                                        modelCountAttribute = d->getTemplateAttribute<int>(element,
                                                                                "model-count",
                                                                                d->pageModel);
                                    }

                                    if ( modelStartCountAttribute < 0 ) {
                                        modelStartCountAttribute = 0;
                                    }

                                    if ( modelCountAttribute <= 0 ) {
                                        modelCountAttribute  = modelList.size();
                                    }
                                    else {
                                        modelCountAttribute = modelStartCountAttribute + modelCountAttribute;
                                    }

                                    for (int i = modelStartCountAttribute; i < modelCountAttribute; ++i) {
                                            QString modelTemplate = templateContent;
                                            web::page::model::AbstractModel *templateModel = modelList.at(i);

                                            if (d->isTemplateAllowed(modelIfAttribute, templateModel) || !hasIfAttribute) {
                                                    d->replaceModelPlaceholders(modelTemplate, templateModel);
                                                    templateFilled += modelTemplate;
                                                }

                                            model->unload();
                                        }
                                } else {
                                    templateFilled = templateContent;
                                }

                            templateFilled = templateStartTag + templateFilled + templateEndTag;
                            QDomDocument tplDoc;
                            tplDoc.setContent(templateFilled, false, &errMsg, &errLine, &errColumn);

                            parentNode.replaceChild(tplDoc.documentElement(), element);
                        } else {
                            parentNode.removeChild(element);
                        }
                }
            else {
                    parentNode.removeChild(element);
                }
        }

    QString content = doc.toString();
    d->replaceModelPlaceholders(content, d->pageModel);

    d->content = content.toUtf8();
}

AbstractTemplatePage *createTemplatePage(AbstractTemplatePage *t)
{
    t->createModels();
    return t;
}

}
}
}
<commit_msg>This will prevent the application from crashing when the start is too big<commit_after>#include "AbstractTemplatePage.h"
#include "private/AbstractTemplatePage_p.h"

#include <QtCore/QCoreApplication>
#include <QtCore/QDebug>
#include <QtCore/QDir>
#include <QtCore/QFile>
#include <QtXml/QDomDocument>

namespace web
{
namespace page
{
namespace templates
{

AbstractTemplatePage::~AbstractTemplatePage()
{
    Q_D(AbstractTemplatePage);

    delete d->pageModel;
    qDeleteAll(d->templateModels);

    delete d_ptr;
}

QByteArray AbstractTemplatePage::getContent()
{
    Q_D(AbstractTemplatePage);

    if ( d->pageData.isEmpty() ) {
            initPage();
        }

    if ( d->templates.isEmpty() ) {
            initTemplates();
        }

    initModels();

    render();

    destroyModels();

    return d->content;
}

void AbstractTemplatePage::setSession(website::WebSession *s)
{
    Q_D(AbstractTemplatePage);
    d->session = s;
}

void AbstractTemplatePage::setRequest(Tufao::HttpServerRequest *r)
{
    Q_D(AbstractTemplatePage);
    d->request = r;
}

void AbstractTemplatePage::setResponse(Tufao::HttpServerResponse *r)
{
    Q_D(AbstractTemplatePage);
    d->response = r;
}

void AbstractTemplatePage::setPostRequestData(QMap<QByteArray, QByteArray> data)
{
    Q_D(AbstractTemplatePage);
    d->post = data;
}

void AbstractTemplatePage::clearPostRequestData()
{
    Q_D(AbstractTemplatePage);
    d->post.clear();
}

void AbstractTemplatePage::setGetRequestData(QMap<QByteArray, QByteArray> data)
{
    Q_D(AbstractTemplatePage);
    d->get = data;
}

void AbstractTemplatePage::clearGetRequestData()
{
    Q_D(AbstractTemplatePage);
    d->get.clear();
}

void AbstractTemplatePage::setRequestPath(const QString & path)
{
    Q_D(AbstractTemplatePage);
    d->requestPath = path;
}

AbstractTemplatePage::AbstractTemplatePage(AbstractTemplatePagePrivate *d) :
    d_ptr(d)
{
}

void AbstractTemplatePage::initPage()
{
    Q_D(AbstractTemplatePage);
    QString filepath = QCoreApplication::applicationDirPath() + QDir::separator() + d->pageFilename;
    QFile f(filepath);
    if ( f.open(QIODevice::ReadOnly) ) {
            QByteArray data = f.readAll();
            d->pageData = data;
            f.close();
        }
    else {
            qDebug() << Q_FUNC_INFO << f.errorString();
        }
}

void AbstractTemplatePage::initTemplate(QString name, QString filename)
{
    QFile f(filename);
    if ( f.open(QIODevice::ReadOnly) ) {
            Q_D(AbstractTemplatePage);
            QByteArray data = f.readAll();
            d->templates.insert(name, data);
            f.close();
        }
    else {
            qDebug() << Q_FUNC_INFO << f.errorString();
    }
}

void AbstractTemplatePage::loadModel(const QString & name)
{
    Q_D(AbstractTemplatePage);
    model::AbstractListModel * model = d->templateModels.value(name);
    model->load();
}

void AbstractTemplatePage::unloadModel(const QString & name)
{
    Q_D(AbstractTemplatePage);
    model::AbstractListModel * model = d->templateModels.value(name);
    model->unload();
}

void AbstractTemplatePage::render()
{
    Q_D(AbstractTemplatePage);

    QDomDocument doc;
    QString errMsg;
    int errLine, errColumn;
    doc.setContent(d->pageData, false, &errMsg, &errLine, &errColumn);

    QDomNodeList templates = doc.elementsByTagName("tpl");
    const int templateSize = templates.size();
    // We need to go backwards because otherwise the deleting of nodes doesnt work
    for (int i = templateSize-1; i >= 0 ; --i) {
            QDomElement element = templates.item(i).toElement();
            QDomNode parentNode = element.parentNode();

            if (element.hasAttribute("src")) {
                    QString tplName = element.attribute("src");
                    bool isAllowedToShow = true;

                    if (element.hasAttribute("if")) {
                            QString ifAttribute = element.attribute("if");
                            isAllowedToShow = d->isTemplateAllowed(ifAttribute, d->pageModel);
                        }
                    else if (element.hasAttribute("if-not")) {
                            QString ifAttribute = element.attribute("if-not");
                            isAllowedToShow = !d->isTemplateAllowed(ifAttribute, d->pageModel);
                        }

                    if (isAllowedToShow) {

                            QString templateStartTag = QStringLiteral("<tpl>");
                            QString templateEndTag = QStringLiteral("</tpl>");
                            QString templateContent = d->templates[tplName].replace(templateStartTag, "").replace(templateEndTag, "");
                            QString templateFilled;

                            if (element.hasAttribute("model")) {
                                    QString modelName = element.attribute("model");
                                    web::page::model::AbstractListModel *model = d->templateModels[modelName];
                                    model->load();
                                    QList<web::page::model::AbstractModel *> modelList = model->models();
                                    QString modelIfAttribute;
                                    int modelCountAttribute = -1;
                                    int modelStartCountAttribute = -1;

                                    bool hasIfAttribute = false;

                                    if (element.hasAttribute("if-model")) {
                                            modelIfAttribute = element.attribute("if-model");
                                            hasIfAttribute = true;
                                        }

                                    if (element.hasAttribute("model-start-count")) {
                                        modelStartCountAttribute = d->getTemplateAttribute<int>(element,
                                                                                "model-start-count",
                                                                                d->pageModel);
                                    }

                                    if (element.hasAttribute("model-count")) {
                                        modelCountAttribute = d->getTemplateAttribute<int>(element,
                                                                                "model-count",
                                                                                d->pageModel);
                                    }

                                    if ( modelStartCountAttribute < 0 ) {
                                        modelStartCountAttribute = 0;
                                    }

                                    if ( modelCountAttribute <= 0 ) {
                                        modelCountAttribute  = modelList.size();
                                    }
                                    else {
                                        modelCountAttribute = modelStartCountAttribute + modelCountAttribute;
                                    }

                                    const int maxCount = modelList.size();

                                    for (int i = modelStartCountAttribute; i < modelCountAttribute && i < maxCount; ++i) {
                                            QString modelTemplate = templateContent;
                                            web::page::model::AbstractModel *templateModel = modelList.at(i);

                                            if (d->isTemplateAllowed(modelIfAttribute, templateModel) || !hasIfAttribute) {
                                                    d->replaceModelPlaceholders(modelTemplate, templateModel);
                                                    templateFilled += modelTemplate;
                                                }

                                            model->unload();
                                        }
                                } else {
                                    templateFilled = templateContent;
                                }

                            templateFilled = templateStartTag + templateFilled + templateEndTag;
                            QDomDocument tplDoc;
                            tplDoc.setContent(templateFilled, false, &errMsg, &errLine, &errColumn);

                            parentNode.replaceChild(tplDoc.documentElement(), element);
                        } else {
                            parentNode.removeChild(element);
                        }
                }
            else {
                    parentNode.removeChild(element);
                }
        }

    QString content = doc.toString();
    d->replaceModelPlaceholders(content, d->pageModel);

    d->content = content.toUtf8();
}

AbstractTemplatePage *createTemplatePage(AbstractTemplatePage *t)
{
    t->createModels();
    return t;
}

}
}
}
<|endoftext|>


<commit_before>#include "Globals.h"  // NOTE: MSVC stupidness requires this to be the same across all modules

#include "Player.h"
#include "ArrowEntity.h"
#include "../Chunk.h"
#include "FastRandom.h"

cArrowEntity::cArrowEntity(cEntity * a_Creator, double a_X, double a_Y, double a_Z, const Vector3d & a_Speed) :
	super(pkArrow, a_Creator, a_X, a_Y, a_Z, 0.5, 0.5),
	m_PickupState(psNoPickup),
	m_DamageCoeff(2),
	m_IsCritical(false),
	m_Timer(0),
	m_HitGroundTimer(0),
	m_HasTeleported(false),
	m_bIsCollected(false),
	m_HitBlockPos(Vector3i(0, 0, 0))
{
	SetSpeed(a_Speed);
	SetMass(0.1);
	SetYawFromSpeed();
	SetPitchFromSpeed();
	LOGD("Created arrow %d with speed {%.02f, %.02f, %.02f} and rot {%.02f, %.02f}",
		m_UniqueID, GetSpeedX(), GetSpeedY(), GetSpeedZ(),
		GetYaw(), GetPitch()
	);
}

cArrowEntity::cArrowEntity(cPlayer & a_Player, double a_Force) :
	super(pkArrow, &a_Player, a_Player.GetThrowStartPos(), a_Player.GetThrowSpeed(a_Force * 1.5 * 20), 0.5, 0.5),
	m_PickupState(psInSurvivalOrCreative),
	m_DamageCoeff(2),
	m_IsCritical((a_Force >= 1)),
	m_Timer(0),
	m_HitGroundTimer(0),
	m_HasTeleported(false),
	m_bIsCollected(false),
	m_HitBlockPos(0, 0, 0)
{
	if (a_Player.IsGameModeCreative())
	{
		m_PickupState = psInCreative;
	}
}

bool cArrowEntity::CanPickup(const cPlayer & a_Player) const
{
	switch (m_PickupState)
	{
		case psNoPickup:             return false;
		case psInSurvivalOrCreative: return (a_Player.IsGameModeSurvival() || a_Player.IsGameModeCreative());
		case psInCreative:           return a_Player.IsGameModeCreative();
	}
	ASSERT(!"Unhandled pickup state");
	return false;
}

void cArrowEntity::OnHitSolidBlock(const Vector3d & a_HitPos, eBlockFace a_HitFace)
{
	if (a_HitFace == BLOCK_FACE_NONE) { return; }

	super::OnHitSolidBlock(a_HitPos, a_HitFace);
	int a_X = (int)a_HitPos.x, a_Y = (int)a_HitPos.y, a_Z = (int)a_HitPos.z;

	switch (a_HitFace)
	{
		case BLOCK_FACE_XM: // Strangely, bounding boxes / block tracers return the actual block for these two directions, so AddFace not needed
		case BLOCK_FACE_YM:
		{
			break;
		}
		default: AddFaceDirection(a_X, a_Y, a_Z, a_HitFace, true);
	}

	m_HitBlockPos = Vector3i(a_X, a_Y, a_Z);

	// Broadcast arrow hit sound
	m_World->BroadcastSoundEffect("random.bowhit", (int)GetPosX() * 8, (int)GetPosY() * 8, (int)GetPosZ() * 8, 0.5f, (float)(0.75 + ((float)((GetUniqueID() * 23) % 32)) / 64));
}

void cArrowEntity::OnHitEntity(cEntity & a_EntityHit, const Vector3d & a_HitPos)
{
	if (!a_EntityHit.IsMob() && !a_EntityHit.IsMinecart() && !a_EntityHit.IsPlayer() && !a_EntityHit.IsBoat())
	{
		// Not an entity that interacts with an arrow
		return;
	}

	int Damage = (int)(GetSpeed().Length() / 20 * m_DamageCoeff + 0.5);
	if (m_IsCritical)
	{
		Damage += m_World->GetTickRandomNumber(Damage / 2 + 2);
	}
	a_EntityHit.TakeDamage(dtRangedAttack, this, Damage, 1);

	// Broadcast successful hit sound
	m_World->BroadcastSoundEffect(
		"random.successful_hit",
		(int)std::floor(GetPosX() * 8.0),
		(int)std::floor(GetPosY() * 8.0),
		(int)std::floor(GetPosZ() * 8.0),
		0.5f,
		0.75f + ((float)((GetUniqueID() * 23) % 32)) / 64.0f
	);

	Destroy();
}

void cArrowEntity::CollectedBy(cPlayer * a_Dest)
{
	if (m_IsInGround && !m_bIsCollected && CanPickup(*a_Dest))
	{
		if (m_PickupState == psInSurvivalOrCreative)
		{
			int NumAdded = a_Dest->GetInventory().AddItem(E_ITEM_ARROW);
			if (NumAdded == 0)
			{
				// No space in the inventory
				return;
			}
		}

		m_World->BroadcastCollectPickup((const cPickup &)*this, *a_Dest);
		m_bIsCollected = true;

		cFastRandom Random;
		m_World->BroadcastSoundEffect(
			"random.pop",
			(int)std::floor(GetPosX() * 8.0),
			(int)std::floor(GetPosY() * 8),
			(int)std::floor(GetPosZ() * 8),
			0.2F,
			((Random.NextFloat(1.0F) - Random.NextFloat(1.0F)) * 0.7F + 1.0F) * 2.0F
		);
	}
}

void cArrowEntity::Tick(float a_Dt, cChunk & a_Chunk)
{
	super::Tick(a_Dt, a_Chunk);
	m_Timer += a_Dt;

	if (m_bIsCollected)
	{
		if (m_Timer > 500.f)  // 0.5 seconds
		{
			Destroy();
			return;
		}
	}
	else if (m_Timer > 1000 * 60 * 5)  // 5 minutes
	{
		Destroy();
		return;
	}

	if (m_IsInGround)
	{
		// When an arrow hits, the client doesn't think its in the ground and keeps on moving, IF BroadcastMovementUpdate() and TeleportEntity was called during flight, AT ALL
		// Fix is to simply not sync with the client and send a teleport to confirm pos after arrow has stabilised (around 1 sec after landing)
		// We can afford to do this because xoft's algorithm for trajectory is near perfect, so things are pretty close anyway without sync
		// Besides, this seems to be what the vanilla server does, note how arrows teleport half a second after they hit to the server position

		if (!m_HasTeleported) // Sent a teleport already, don't do again
		{
			if (m_HitGroundTimer > 1000.f) // Send after a second, could be less, but just in case
			{
				m_World->BroadcastTeleportEntity(*this);
				m_HasTeleported = true;
			}
			else
			{
				m_HitGroundTimer += a_Dt;
			}
		}

		int RelPosX = m_HitBlockPos.x - a_Chunk.GetPosX() * cChunkDef::Width;
		int RelPosZ = m_HitBlockPos.z - a_Chunk.GetPosZ() * cChunkDef::Width;
		cChunk * Chunk = a_Chunk.GetRelNeighborChunkAdjustCoords(RelPosX, RelPosZ);

		if (Chunk == NULL)
		{
			// Inside an unloaded chunk, abort
			return;
		}

		if (Chunk->GetBlock(RelPosX, m_HitBlockPos.y, RelPosZ) == E_BLOCK_AIR) // Block attached to was destroyed?
		{
			m_IsInGround = false; // Yes, begin simulating physics again
		}
	}
}
<commit_msg>GameMode check<commit_after>#include "Globals.h"  // NOTE: MSVC stupidness requires this to be the same across all modules

#include "Player.h"
#include "ArrowEntity.h"
#include "../Chunk.h"
#include "FastRandom.h"

cArrowEntity::cArrowEntity(cEntity * a_Creator, double a_X, double a_Y, double a_Z, const Vector3d & a_Speed) :
	super(pkArrow, a_Creator, a_X, a_Y, a_Z, 0.5, 0.5),
	m_PickupState(psNoPickup),
	m_DamageCoeff(2),
	m_IsCritical(false),
	m_Timer(0),
	m_HitGroundTimer(0),
	m_HasTeleported(false),
	m_bIsCollected(false),
	m_HitBlockPos(Vector3i(0, 0, 0))
{
	SetSpeed(a_Speed);
	SetMass(0.1);
	SetYawFromSpeed();
	SetPitchFromSpeed();
	LOGD("Created arrow %d with speed {%.02f, %.02f, %.02f} and rot {%.02f, %.02f}",
		m_UniqueID, GetSpeedX(), GetSpeedY(), GetSpeedZ(),
		GetYaw(), GetPitch()
	);
}

cArrowEntity::cArrowEntity(cPlayer & a_Player, double a_Force) :
	super(pkArrow, &a_Player, a_Player.GetThrowStartPos(), a_Player.GetThrowSpeed(a_Force * 1.5 * 20), 0.5, 0.5),
	m_PickupState(psInSurvivalOrCreative),
	m_DamageCoeff(2),
	m_IsCritical((a_Force >= 1)),
	m_Timer(0),
	m_HitGroundTimer(0),
	m_HasTeleported(false),
	m_bIsCollected(false),
	m_HitBlockPos(0, 0, 0)
{
	if (a_Player.IsGameModeCreative())
	{
		m_PickupState = psInCreative;
	}
}

bool cArrowEntity::CanPickup(const cPlayer & a_Player) const
{
	switch (m_PickupState)
	{
		case psNoPickup:             return false;
		case psInSurvivalOrCreative: return (a_Player.IsGameModeSurvival() || a_Player.IsGameModeCreative());
		case psInCreative:           return a_Player.IsGameModeCreative();
	}
	ASSERT(!"Unhandled pickup state");
	return false;
}

void cArrowEntity::OnHitSolidBlock(const Vector3d & a_HitPos, eBlockFace a_HitFace)
{
	if (a_HitFace == BLOCK_FACE_NONE) { return; }

	super::OnHitSolidBlock(a_HitPos, a_HitFace);
	int a_X = (int)a_HitPos.x, a_Y = (int)a_HitPos.y, a_Z = (int)a_HitPos.z;

	switch (a_HitFace)
	{
		case BLOCK_FACE_XM: // Strangely, bounding boxes / block tracers return the actual block for these two directions, so AddFace not needed
		case BLOCK_FACE_YM:
		{
			break;
		}
		default: AddFaceDirection(a_X, a_Y, a_Z, a_HitFace, true);
	}

	m_HitBlockPos = Vector3i(a_X, a_Y, a_Z);

	// Broadcast arrow hit sound
	m_World->BroadcastSoundEffect("random.bowhit", (int)GetPosX() * 8, (int)GetPosY() * 8, (int)GetPosZ() * 8, 0.5f, (float)(0.75 + ((float)((GetUniqueID() * 23) % 32)) / 64));
}

void cArrowEntity::OnHitEntity(cEntity & a_EntityHit, const Vector3d & a_HitPos)
{
	if (!a_EntityHit.IsMob() && !a_EntityHit.IsMinecart() && !a_EntityHit.IsPlayer() && !a_EntityHit.IsBoat())
	{
		// Not an entity that interacts with an arrow
		return;
	}

	int Damage = (int)(GetSpeed().Length() / 20 * m_DamageCoeff + 0.5);
	if (m_IsCritical)
	{
		Damage += m_World->GetTickRandomNumber(Damage / 2 + 2);
	}
	a_EntityHit.TakeDamage(dtRangedAttack, this, Damage, 1);

	// Broadcast successful hit sound
	m_World->BroadcastSoundEffect(
		"random.successful_hit",
		(int)std::floor(GetPosX() * 8.0),
		(int)std::floor(GetPosY() * 8.0),
		(int)std::floor(GetPosZ() * 8.0),
		0.5f,
		0.75f + ((float)((GetUniqueID() * 23) % 32)) / 64.0f
	);

	Destroy();
}

void cArrowEntity::CollectedBy(cPlayer * a_Dest)
{
	if (m_IsInGround && !m_bIsCollected && CanPickup(*a_Dest))
	{
		if (!a_Dest->IsGameModeCreative())
		{
			int NumAdded = a_Dest->GetInventory().AddItem(E_ITEM_ARROW);
			if (NumAdded == 0)
			{
				// No space in the inventory
				return;
			}
		}

		m_World->BroadcastCollectPickup((const cPickup &)*this, *a_Dest);
		m_bIsCollected = true;

		cFastRandom Random;
		m_World->BroadcastSoundEffect(
			"random.pop",
			(int)std::floor(GetPosX() * 8.0),
			(int)std::floor(GetPosY() * 8),
			(int)std::floor(GetPosZ() * 8),
			0.2F,
			((Random.NextFloat(1.0F) - Random.NextFloat(1.0F)) * 0.7F + 1.0F) * 2.0F
		);
	}
}

void cArrowEntity::Tick(float a_Dt, cChunk & a_Chunk)
{
	super::Tick(a_Dt, a_Chunk);
	m_Timer += a_Dt;

	if (m_bIsCollected)
	{
		if (m_Timer > 500.f)  // 0.5 seconds
		{
			Destroy();
			return;
		}
	}
	else if (m_Timer > 1000 * 60 * 5)  // 5 minutes
	{
		Destroy();
		return;
	}

	if (m_IsInGround)
	{
		// When an arrow hits, the client doesn't think its in the ground and keeps on moving, IF BroadcastMovementUpdate() and TeleportEntity was called during flight, AT ALL
		// Fix is to simply not sync with the client and send a teleport to confirm pos after arrow has stabilised (around 1 sec after landing)
		// We can afford to do this because xoft's algorithm for trajectory is near perfect, so things are pretty close anyway without sync
		// Besides, this seems to be what the vanilla server does, note how arrows teleport half a second after they hit to the server position

		if (!m_HasTeleported) // Sent a teleport already, don't do again
		{
			if (m_HitGroundTimer > 1000.f) // Send after a second, could be less, but just in case
			{
				m_World->BroadcastTeleportEntity(*this);
				m_HasTeleported = true;
			}
			else
			{
				m_HitGroundTimer += a_Dt;
			}
		}

		int RelPosX = m_HitBlockPos.x - a_Chunk.GetPosX() * cChunkDef::Width;
		int RelPosZ = m_HitBlockPos.z - a_Chunk.GetPosZ() * cChunkDef::Width;
		cChunk * Chunk = a_Chunk.GetRelNeighborChunkAdjustCoords(RelPosX, RelPosZ);

		if (Chunk == NULL)
		{
			// Inside an unloaded chunk, abort
			return;
		}

		if (Chunk->GetBlock(RelPosX, m_HitBlockPos.y, RelPosZ) == E_BLOCK_AIR) // Block attached to was destroyed?
		{
			m_IsInGround = false; // Yes, begin simulating physics again
		}
	}
}
<|endoftext|>


<commit_before>#include "depthai/pipeline/datatype/StereoDepthConfig.hpp"

namespace dai {

std::shared_ptr<RawBuffer> StereoDepthConfig::serialize() const {
    return raw;
}

StereoDepthConfig::StereoDepthConfig() : Buffer(std::make_shared<RawStereoDepthConfig>()), cfg(*dynamic_cast<RawStereoDepthConfig*>(raw.get())) {}
StereoDepthConfig::StereoDepthConfig(std::shared_ptr<RawStereoDepthConfig> ptr)
    : Buffer(std::move(ptr)), cfg(*dynamic_cast<RawStereoDepthConfig*>(raw.get())) {}

void StereoDepthConfig::setConfidenceThreshold(int confThr) {
    cfg.costMatching.confidenceThreshold = confThr;
}

int StereoDepthConfig::getConfidenceThreshold() const {
    return cfg.costMatching.confidenceThreshold;
}

void StereoDepthConfig::setMedianFilter(dai::MedianFilter median) {
    cfg.postProcessing.median = median;
}

dai::MedianFilter StereoDepthConfig::getMedianFilter() const {
    return cfg.postProcessing.median;
}

void StereoDepthConfig::setBilateralFilterSigma(uint16_t sigma) {
    cfg.postProcessing.bilateralSigmaValue = sigma;
}

uint16_t StereoDepthConfig::getBilateralFilterSigma() const {
    return cfg.postProcessing.bilateralSigmaValue;
}

void StereoDepthConfig::setLeftRightCheckThreshold(int threshold) {
    cfg.algorithmControl.leftRightCheckThreshold = threshold;
}

int StereoDepthConfig::getLeftRightCheckThreshold() const {
    return cfg.algorithmControl.leftRightCheckThreshold;
}

void StereoDepthConfig::setLeftRightCheck(bool enable) {
    cfg.algorithmControl.enableLeftRightCheck = enable;
}

void StereoDepthConfig::setSubpixel(bool enable) {
    cfg.algorithmControl.enableSubpixel = enable;
}

float StereoDepthConfig::getMaxDisparity() const {
    float maxDisp = 95.0;
    if(false) maxDisp *= 2;  // TODO re-enable with extended
    if(cfg.algorithmControl.enableSubpixel) maxDisp *= (1 << cfg.algorithmControl.subpixelFractionalBits);
    return maxDisp;
}

dai::RawStereoDepthConfig StereoDepthConfig::get() const {
    return cfg;
}

void StereoDepthConfig::set(dai::RawStereoDepthConfig config) {
    cfg = config;
}

}  // namespace dai
<commit_msg>Handle disparity companding in getMaxDisparity<commit_after>#include "depthai/pipeline/datatype/StereoDepthConfig.hpp"

namespace dai {

std::shared_ptr<RawBuffer> StereoDepthConfig::serialize() const {
    return raw;
}

StereoDepthConfig::StereoDepthConfig() : Buffer(std::make_shared<RawStereoDepthConfig>()), cfg(*dynamic_cast<RawStereoDepthConfig*>(raw.get())) {}
StereoDepthConfig::StereoDepthConfig(std::shared_ptr<RawStereoDepthConfig> ptr)
    : Buffer(std::move(ptr)), cfg(*dynamic_cast<RawStereoDepthConfig*>(raw.get())) {}

void StereoDepthConfig::setConfidenceThreshold(int confThr) {
    cfg.costMatching.confidenceThreshold = confThr;
}

int StereoDepthConfig::getConfidenceThreshold() const {
    return cfg.costMatching.confidenceThreshold;
}

void StereoDepthConfig::setMedianFilter(dai::MedianFilter median) {
    cfg.postProcessing.median = median;
}

dai::MedianFilter StereoDepthConfig::getMedianFilter() const {
    return cfg.postProcessing.median;
}

void StereoDepthConfig::setBilateralFilterSigma(uint16_t sigma) {
    cfg.postProcessing.bilateralSigmaValue = sigma;
}

uint16_t StereoDepthConfig::getBilateralFilterSigma() const {
    return cfg.postProcessing.bilateralSigmaValue;
}

void StereoDepthConfig::setLeftRightCheckThreshold(int threshold) {
    cfg.algorithmControl.leftRightCheckThreshold = threshold;
}

int StereoDepthConfig::getLeftRightCheckThreshold() const {
    return cfg.algorithmControl.leftRightCheckThreshold;
}

void StereoDepthConfig::setLeftRightCheck(bool enable) {
    cfg.algorithmControl.enableLeftRightCheck = enable;
}

void StereoDepthConfig::setSubpixel(bool enable) {
    cfg.algorithmControl.enableSubpixel = enable;
}

float StereoDepthConfig::getMaxDisparity() const {
    float maxDisp = 95.0;
    if(cfg.costMatching.disparityWidth == RawStereoDepthConfig::CostMatching::DisparityWidth::DISPARITY_64) {
        maxDisp = 63;
    }
    if(cfg.costMatching.enableCompanding) maxDisp = 175;
    if(false) maxDisp *= 2;  // TODO re-enable with extended
    if(cfg.algorithmControl.enableSubpixel) maxDisp *= (1 << cfg.algorithmControl.subpixelFractionalBits);
    return maxDisp;
}

dai::RawStereoDepthConfig StereoDepthConfig::get() const {
    return cfg;
}

void StereoDepthConfig::set(dai::RawStereoDepthConfig config) {
    cfg = config;
}

}  // namespace dai
<|endoftext|>