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

#define EIGEN_TEST_NO_LONGDOUBLE
#define EIGEN_TEST_NO_COMPLEX
#define EIGEN_TEST_FUNC cxx11_float16

#include "main.h"
#include <Eigen/src/Core/arch/CUDA/Half.h>

using Eigen::half;

void test_conversion()
{
  // Conversion from float.
  VERIFY_IS_EQUAL(half(1.0f).x, 0x3c00);
  VERIFY_IS_EQUAL(half(0.5f).x, 0x3800);
  VERIFY_IS_EQUAL(half(0.33333f).x, 0x3555);
  VERIFY_IS_EQUAL(half(0.0f).x, 0x0000);
  VERIFY_IS_EQUAL(half(-0.0f).x, 0x8000);
  VERIFY_IS_EQUAL(half(65504.0f).x, 0x7bff);
  VERIFY_IS_EQUAL(half(65536.0f).x, 0x7c00);  // Becomes infinity.

  // Denormals.
  VERIFY_IS_EQUAL(half(-5.96046e-08f).x, 0x8001);
  VERIFY_IS_EQUAL(half(5.96046e-08f).x, 0x0001);
  VERIFY_IS_EQUAL(half(1.19209e-07f).x, 0x0002);

  // Verify round-to-nearest-even behavior.
  float val1 = float(half(__half{0x3c00}));
  float val2 = float(half(__half{0x3c01}));
  float val3 = float(half(__half{0x3c02}));
  VERIFY_IS_EQUAL(half(0.5 * (val1 + val2)).x, 0x3c00);
  VERIFY_IS_EQUAL(half(0.5 * (val2 + val3)).x, 0x3c02);

  // Conversion from int.
  VERIFY_IS_EQUAL(half(-1).x, 0xbc00);
  VERIFY_IS_EQUAL(half(0).x, 0x0000);
  VERIFY_IS_EQUAL(half(1).x, 0x3c00);
  VERIFY_IS_EQUAL(half(2).x, 0x4000);
  VERIFY_IS_EQUAL(half(3).x, 0x4200);

  // Conversion from bool.
  VERIFY_IS_EQUAL(half(false).x, 0x0000);
  VERIFY_IS_EQUAL(half(true).x, 0x3c00);

  // Conversion to float.
  VERIFY_IS_EQUAL(float(half(__half{0x0000})), 0.0f);
  VERIFY_IS_EQUAL(float(half(__half{0x3c00})), 1.0f);

  // Denormals.
  VERIFY_IS_APPROX(float(half(__half{0x8001})), -5.96046e-08f);
  VERIFY_IS_APPROX(float(half(__half{0x0001})), 5.96046e-08f);
  VERIFY_IS_APPROX(float(half(__half{0x0002})), 1.19209e-07f);

  // NaNs and infinities.
  VERIFY(!(numext::isinf)(float(half(65504.0f))));  // Largest finite number.
  VERIFY(!(numext::isnan)(float(half(0.0f))));
  VERIFY((numext::isinf)(float(half(__half{0xfc00}))));
  VERIFY((numext::isnan)(float(half(__half{0xfc01}))));
  VERIFY((numext::isinf)(float(half(__half{0x7c00}))));
  VERIFY((numext::isnan)(float(half(__half{0x7c01}))));

#if !EIGEN_COMP_MSVC
  // Visual Studio errors out on divisions by 0
  VERIFY((numext::isnan)(float(half(0.0 / 0.0))));
  VERIFY((numext::isinf)(float(half(1.0 / 0.0))));
  VERIFY((numext::isinf)(float(half(-1.0 / 0.0))));
#endif

  // Exactly same checks as above, just directly on the half representation.
  VERIFY(!(numext::isinf)(half(__half{0x7bff})));
  VERIFY(!(numext::isnan)(half(__half{0x0000})));
  VERIFY((numext::isinf)(half(__half{0xfc00})));
  VERIFY((numext::isnan)(half(__half{0xfc01})));
  VERIFY((numext::isinf)(half(__half{0x7c00})));
  VERIFY((numext::isnan)(half(__half{0x7c01})));

#if !EIGEN_COMP_MSVC
  // Visual Studio errors out on divisions by 0
  VERIFY((numext::isnan)(half(0.0 / 0.0)));
  VERIFY((numext::isinf)(half(1.0 / 0.0)));
  VERIFY((numext::isinf)(half(-1.0 / 0.0)));
#endif
}

void test_arithmetic()
{
  VERIFY_IS_EQUAL(float(half(2) + half(2)), 4);
  VERIFY_IS_EQUAL(float(half(2) + half(-2)), 0);
  VERIFY_IS_APPROX(float(half(0.33333f) + half(0.66667f)), 1.0f);
  VERIFY_IS_EQUAL(float(half(2.0f) * half(-5.5f)), -11.0f);
  VERIFY_IS_APPROX(float(half(1.0f) / half(3.0f)), 0.33333f);
  VERIFY_IS_EQUAL(float(-half(4096.0f)), -4096.0f);
  VERIFY_IS_EQUAL(float(-half(-4096.0f)), 4096.0f);
}

void test_comparison()
{
  VERIFY(half(1.0f) > half(0.5f));
  VERIFY(half(0.5f) < half(1.0f));
  VERIFY(!(half(1.0f) < half(0.5f)));
  VERIFY(!(half(0.5f) > half(1.0f)));

  VERIFY(!(half(4.0f) > half(4.0f)));
  VERIFY(!(half(4.0f) < half(4.0f)));

  VERIFY(!(half(0.0f) < half(-0.0f)));
  VERIFY(!(half(-0.0f) < half(0.0f)));
  VERIFY(!(half(0.0f) > half(-0.0f)));
  VERIFY(!(half(-0.0f) > half(0.0f)));

  VERIFY(half(0.2f) > half(-1.0f));
  VERIFY(half(-1.0f) < half(0.2f));
  VERIFY(half(-16.0f) < half(-15.0f));

  VERIFY(half(1.0f) == half(1.0f));
  VERIFY(half(1.0f) != half(2.0f));

  // Comparisons with NaNs and infinities.
#if !EIGEN_COMP_MSVC
  // Visual Studio errors out on divisions by 0
  VERIFY(!(half(0.0 / 0.0) == half(0.0 / 0.0)));
  VERIFY(half(0.0 / 0.0) != half(0.0 / 0.0));

  VERIFY(!(half(1.0) == half(0.0 / 0.0)));
  VERIFY(!(half(1.0) < half(0.0 / 0.0)));
  VERIFY(!(half(1.0) > half(0.0 / 0.0)));
  VERIFY(half(1.0) != half(0.0 / 0.0));

  VERIFY(half(1.0) < half(1.0 / 0.0));
  VERIFY(half(1.0) > half(-1.0 / 0.0));
#endif
}

void test_basic_functions()
{
  VERIFY_IS_EQUAL(float(numext::abs(half(3.5f))), 3.5f);
  VERIFY_IS_EQUAL(float(numext::abs(half(-3.5f))), 3.5f);

  VERIFY_IS_APPROX(float(numext::sqrt(half(0.0f))), 0.0f);
  VERIFY_IS_APPROX(float(numext::sqrt(half(4.0f))), 2.0f);

  VERIFY_IS_APPROX(float(numext::pow(half(0.0f), half(1.0f))), 0.0f);
  VERIFY_IS_APPROX(float(numext::pow(half(2.0f), half(2.0f))), 4.0f);

  VERIFY_IS_EQUAL(float(numext::exp(half(0.0f))), 1.0f);
  VERIFY_IS_APPROX(float(numext::exp(half(EIGEN_PI))), float(20.0 + EIGEN_PI));

  VERIFY_IS_EQUAL(float(numext::log(half(1.0f))), 0.0f);
  VERIFY_IS_APPROX(float(numext::log(half(10.0f))), 2.30273f);
}

void test_trigonometric_functions()
{
  VERIFY_IS_APPROX(numext::cos(half(0.0f)), half(cosf(0.0f)));
  VERIFY_IS_APPROX(numext::cos(half(EIGEN_PI)), half(cosf(EIGEN_PI)));
  //VERIFY_IS_APPROX(numext::cos(half(EIGEN_PI/2)), half(cosf(EIGEN_PI/2)));
  //VERIFY_IS_APPROX(numext::cos(half(3*EIGEN_PI/2)), half(cosf(3*EIGEN_PI/2)));
  VERIFY_IS_APPROX(numext::cos(half(3.5f)), half(cosf(3.5f)));

  VERIFY_IS_APPROX(numext::sin(half(0.0f)), half(sinf(0.0f)));
  //  VERIFY_IS_APPROX(numext::sin(half(EIGEN_PI)), half(sinf(EIGEN_PI)));
  VERIFY_IS_APPROX(numext::sin(half(EIGEN_PI/2)), half(sinf(EIGEN_PI/2)));
  VERIFY_IS_APPROX(numext::sin(half(3*EIGEN_PI/2)), half(sinf(3*EIGEN_PI/2)));
  VERIFY_IS_APPROX(numext::sin(half(3.5f)), half(sinf(3.5f)));

  VERIFY_IS_APPROX(numext::tan(half(0.0f)), half(tanf(0.0f)));
  //  VERIFY_IS_APPROX(numext::tan(half(EIGEN_PI)), half(tanf(EIGEN_PI)));
  //  VERIFY_IS_APPROX(numext::tan(half(EIGEN_PI/2)), half(tanf(EIGEN_PI/2)));
  //VERIFY_IS_APPROX(numext::tan(half(3*EIGEN_PI/2)), half(tanf(3*EIGEN_PI/2)));
  VERIFY_IS_APPROX(numext::tan(half(3.5f)), half(tanf(3.5f)));
}

void test_cxx11_float16()
{
  CALL_SUBTEST(test_conversion());
  CALL_SUBTEST(test_arithmetic());
  CALL_SUBTEST(test_comparison());
  CALL_SUBTEST(test_basic_functions());
  CALL_SUBTEST(test_trigonometric_functions());
}
<commit_msg>Added tests to validate flooring and ceiling of fp16<commit_after>// This file is part of Eigen, a lightweight C++ template library
// for linear algebra.
//
// This Source Code Form is subject to the terms of the Mozilla
// Public License v. 2.0. If a copy of the MPL was not distributed
// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.

#define EIGEN_TEST_NO_LONGDOUBLE
#define EIGEN_TEST_NO_COMPLEX
#define EIGEN_TEST_FUNC cxx11_float16

#include "main.h"
#include <Eigen/src/Core/arch/CUDA/Half.h>

using Eigen::half;

void test_conversion()
{
  // Conversion from float.
  VERIFY_IS_EQUAL(half(1.0f).x, 0x3c00);
  VERIFY_IS_EQUAL(half(0.5f).x, 0x3800);
  VERIFY_IS_EQUAL(half(0.33333f).x, 0x3555);
  VERIFY_IS_EQUAL(half(0.0f).x, 0x0000);
  VERIFY_IS_EQUAL(half(-0.0f).x, 0x8000);
  VERIFY_IS_EQUAL(half(65504.0f).x, 0x7bff);
  VERIFY_IS_EQUAL(half(65536.0f).x, 0x7c00);  // Becomes infinity.

  // Denormals.
  VERIFY_IS_EQUAL(half(-5.96046e-08f).x, 0x8001);
  VERIFY_IS_EQUAL(half(5.96046e-08f).x, 0x0001);
  VERIFY_IS_EQUAL(half(1.19209e-07f).x, 0x0002);

  // Verify round-to-nearest-even behavior.
  float val1 = float(half(__half{0x3c00}));
  float val2 = float(half(__half{0x3c01}));
  float val3 = float(half(__half{0x3c02}));
  VERIFY_IS_EQUAL(half(0.5 * (val1 + val2)).x, 0x3c00);
  VERIFY_IS_EQUAL(half(0.5 * (val2 + val3)).x, 0x3c02);

  // Conversion from int.
  VERIFY_IS_EQUAL(half(-1).x, 0xbc00);
  VERIFY_IS_EQUAL(half(0).x, 0x0000);
  VERIFY_IS_EQUAL(half(1).x, 0x3c00);
  VERIFY_IS_EQUAL(half(2).x, 0x4000);
  VERIFY_IS_EQUAL(half(3).x, 0x4200);

  // Conversion from bool.
  VERIFY_IS_EQUAL(half(false).x, 0x0000);
  VERIFY_IS_EQUAL(half(true).x, 0x3c00);

  // Conversion to float.
  VERIFY_IS_EQUAL(float(half(__half{0x0000})), 0.0f);
  VERIFY_IS_EQUAL(float(half(__half{0x3c00})), 1.0f);

  // Denormals.
  VERIFY_IS_APPROX(float(half(__half{0x8001})), -5.96046e-08f);
  VERIFY_IS_APPROX(float(half(__half{0x0001})), 5.96046e-08f);
  VERIFY_IS_APPROX(float(half(__half{0x0002})), 1.19209e-07f);

  // NaNs and infinities.
  VERIFY(!(numext::isinf)(float(half(65504.0f))));  // Largest finite number.
  VERIFY(!(numext::isnan)(float(half(0.0f))));
  VERIFY((numext::isinf)(float(half(__half{0xfc00}))));
  VERIFY((numext::isnan)(float(half(__half{0xfc01}))));
  VERIFY((numext::isinf)(float(half(__half{0x7c00}))));
  VERIFY((numext::isnan)(float(half(__half{0x7c01}))));

#if !EIGEN_COMP_MSVC
  // Visual Studio errors out on divisions by 0
  VERIFY((numext::isnan)(float(half(0.0 / 0.0))));
  VERIFY((numext::isinf)(float(half(1.0 / 0.0))));
  VERIFY((numext::isinf)(float(half(-1.0 / 0.0))));
#endif

  // Exactly same checks as above, just directly on the half representation.
  VERIFY(!(numext::isinf)(half(__half{0x7bff})));
  VERIFY(!(numext::isnan)(half(__half{0x0000})));
  VERIFY((numext::isinf)(half(__half{0xfc00})));
  VERIFY((numext::isnan)(half(__half{0xfc01})));
  VERIFY((numext::isinf)(half(__half{0x7c00})));
  VERIFY((numext::isnan)(half(__half{0x7c01})));

#if !EIGEN_COMP_MSVC
  // Visual Studio errors out on divisions by 0
  VERIFY((numext::isnan)(half(0.0 / 0.0)));
  VERIFY((numext::isinf)(half(1.0 / 0.0)));
  VERIFY((numext::isinf)(half(-1.0 / 0.0)));
#endif
}

void test_arithmetic()
{
  VERIFY_IS_EQUAL(float(half(2) + half(2)), 4);
  VERIFY_IS_EQUAL(float(half(2) + half(-2)), 0);
  VERIFY_IS_APPROX(float(half(0.33333f) + half(0.66667f)), 1.0f);
  VERIFY_IS_EQUAL(float(half(2.0f) * half(-5.5f)), -11.0f);
  VERIFY_IS_APPROX(float(half(1.0f) / half(3.0f)), 0.33333f);
  VERIFY_IS_EQUAL(float(-half(4096.0f)), -4096.0f);
  VERIFY_IS_EQUAL(float(-half(-4096.0f)), 4096.0f);
}

void test_comparison()
{
  VERIFY(half(1.0f) > half(0.5f));
  VERIFY(half(0.5f) < half(1.0f));
  VERIFY(!(half(1.0f) < half(0.5f)));
  VERIFY(!(half(0.5f) > half(1.0f)));

  VERIFY(!(half(4.0f) > half(4.0f)));
  VERIFY(!(half(4.0f) < half(4.0f)));

  VERIFY(!(half(0.0f) < half(-0.0f)));
  VERIFY(!(half(-0.0f) < half(0.0f)));
  VERIFY(!(half(0.0f) > half(-0.0f)));
  VERIFY(!(half(-0.0f) > half(0.0f)));

  VERIFY(half(0.2f) > half(-1.0f));
  VERIFY(half(-1.0f) < half(0.2f));
  VERIFY(half(-16.0f) < half(-15.0f));

  VERIFY(half(1.0f) == half(1.0f));
  VERIFY(half(1.0f) != half(2.0f));

  // Comparisons with NaNs and infinities.
#if !EIGEN_COMP_MSVC
  // Visual Studio errors out on divisions by 0
  VERIFY(!(half(0.0 / 0.0) == half(0.0 / 0.0)));
  VERIFY(half(0.0 / 0.0) != half(0.0 / 0.0));

  VERIFY(!(half(1.0) == half(0.0 / 0.0)));
  VERIFY(!(half(1.0) < half(0.0 / 0.0)));
  VERIFY(!(half(1.0) > half(0.0 / 0.0)));
  VERIFY(half(1.0) != half(0.0 / 0.0));

  VERIFY(half(1.0) < half(1.0 / 0.0));
  VERIFY(half(1.0) > half(-1.0 / 0.0));
#endif
}

void test_basic_functions()
{
  VERIFY_IS_EQUAL(float(numext::abs(half(3.5f))), 3.5f);
  VERIFY_IS_EQUAL(float(numext::abs(half(-3.5f))), 3.5f);

  VERIFY_IS_EQUAL(float(numext::floor(half(3.5f))), 3.0f);
  VERIFY_IS_EQUAL(float(numext::floor(half(-3.5f))), -4.0f);

  VERIFY_IS_EQUAL(float(numext::ceil(half(3.5f))), 4.0f);
  VERIFY_IS_EQUAL(float(numext::ceil(half(-3.5f))), -3.0f);

  VERIFY_IS_APPROX(float(numext::sqrt(half(0.0f))), 0.0f);
  VERIFY_IS_APPROX(float(numext::sqrt(half(4.0f))), 2.0f);

  VERIFY_IS_APPROX(float(numext::pow(half(0.0f), half(1.0f))), 0.0f);
  VERIFY_IS_APPROX(float(numext::pow(half(2.0f), half(2.0f))), 4.0f);

  VERIFY_IS_EQUAL(float(numext::exp(half(0.0f))), 1.0f);
  VERIFY_IS_APPROX(float(numext::exp(half(EIGEN_PI))), float(20.0 + EIGEN_PI));

  VERIFY_IS_EQUAL(float(numext::log(half(1.0f))), 0.0f);
  VERIFY_IS_APPROX(float(numext::log(half(10.0f))), 2.30273f);
}

void test_trigonometric_functions()
{
  VERIFY_IS_APPROX(numext::cos(half(0.0f)), half(cosf(0.0f)));
  VERIFY_IS_APPROX(numext::cos(half(EIGEN_PI)), half(cosf(EIGEN_PI)));
  //VERIFY_IS_APPROX(numext::cos(half(EIGEN_PI/2)), half(cosf(EIGEN_PI/2)));
  //VERIFY_IS_APPROX(numext::cos(half(3*EIGEN_PI/2)), half(cosf(3*EIGEN_PI/2)));
  VERIFY_IS_APPROX(numext::cos(half(3.5f)), half(cosf(3.5f)));

  VERIFY_IS_APPROX(numext::sin(half(0.0f)), half(sinf(0.0f)));
  //  VERIFY_IS_APPROX(numext::sin(half(EIGEN_PI)), half(sinf(EIGEN_PI)));
  VERIFY_IS_APPROX(numext::sin(half(EIGEN_PI/2)), half(sinf(EIGEN_PI/2)));
  VERIFY_IS_APPROX(numext::sin(half(3*EIGEN_PI/2)), half(sinf(3*EIGEN_PI/2)));
  VERIFY_IS_APPROX(numext::sin(half(3.5f)), half(sinf(3.5f)));

  VERIFY_IS_APPROX(numext::tan(half(0.0f)), half(tanf(0.0f)));
  //  VERIFY_IS_APPROX(numext::tan(half(EIGEN_PI)), half(tanf(EIGEN_PI)));
  //  VERIFY_IS_APPROX(numext::tan(half(EIGEN_PI/2)), half(tanf(EIGEN_PI/2)));
  //VERIFY_IS_APPROX(numext::tan(half(3*EIGEN_PI/2)), half(tanf(3*EIGEN_PI/2)));
  VERIFY_IS_APPROX(numext::tan(half(3.5f)), half(tanf(3.5f)));
}

void test_cxx11_float16()
{
  CALL_SUBTEST(test_conversion());
  CALL_SUBTEST(test_arithmetic());
  CALL_SUBTEST(test_comparison());
  CALL_SUBTEST(test_basic_functions());
  CALL_SUBTEST(test_trigonometric_functions());
}
<|endoftext|>


<commit_before>// ======================================================================== //
// Copyright 2009-2016 Intel 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.                                           //
// ======================================================================== //

/* This is a small example tutorial how to use OSPRay in an application.
 *
 * On Linux build it in the build_directory with
 *   g++ ../apps/ospTutorial.cpp -I ../ospray/include -I .. -I ../ospray/embree/common ./libospray.so -Wl,-rpath,. -o ospTutorial
 * On Windows build it in the build_directory\$Configuration with
 *   cl ..\..\apps\ospTutorial.cpp /EHsc -I ..\..\ospray\include -I ..\.. -I ..\..\ospray\embree\common ospray.lib
 */

#include <stdint.h>
#include <stdio.h>
#include <alloca.h>
#include "ospray/ospray.h"

// helper function to write the rendered image as PPM file
void writePPM(const char *fileName,
              const osp::vec2i &size,
              const uint32_t *pixel)
{
  FILE *file = fopen(fileName, "wb");
  fprintf(file, "P6\n%i %i\n255\n", size.x, size.y);
  unsigned char *out = (unsigned char *)alloca(3*size.x);
  for (int y = 0; y < size.y; y++) {
    const unsigned char *in = (const unsigned char *)&pixel[(size.y-1-y)*size.x];
    for (int x = 0; x < size.x; x++) {
      out[3*x + 0] = in[4*x + 0];
      out[3*x + 1] = in[4*x + 1];
      out[3*x + 2] = in[4*x +2 ];
    }
    fwrite(out, 3*size.x, sizeof(char), file);
  }
  fprintf(file, "\n");
  fclose(file);
}

int main(int ac, const char **av) {
  // image size
  osp::vec2i imgSize;
  imgSize.x = 1024; // width
  imgSize.y = 768; // height

  // camera
  float cam_pos[] = {0.f, 0.f, 0.f};
  float cam_up [] = {0.f, 1.f, 0.f};
  float cam_view [] = {0.1f, 0.f, 1.f};

  // triangle mesh data
  float vertex[] = { -1.0f, -1.0f, 3.0f, 0.f,
                     -1.0f,  1.0f, 3.0f, 0.f,
                      1.0f, -1.0f, 3.0f, 0.f,
                      0.1f,  0.1f, 0.3f, 0.f };
  float color[] =  { 0.9f, 0.5f, 0.5f, 1.0f,
                     0.8f, 0.8f, 0.8f, 1.0f,
                     0.8f, 0.8f, 0.8f, 1.0f,
                     0.5f, 0.9f, 0.5f, 1.0f };
  int32_t index[] = { 0, 1, 2,
                      1, 2, 3 };

  // initialize OSPRay; OSPRay parses (and removes) its commandline parameters, e.g. "--osp:debug"
  ospInit(&ac, av);

  // create and setup camera
  OSPCamera camera = ospNewCamera("perspective");
  ospSetf(camera, "aspect", imgSize.x/(float)imgSize.y);
  ospSet3fv(camera, "pos", cam_pos);
  ospSet3fv(camera, "dir", cam_view);
  ospSet3fv(camera, "up",  cam_up);
  ospCommit(camera); // commit each object to indicate modifications are done

  // create and setup model and mesh
  OSPGeometry mesh = ospNewGeometry("triangles");
  OSPData data = ospNewData(4, OSP_FLOAT3A, vertex); // OSP_FLOAT3 format is also supported for vertex positions (currently not on MIC)
  ospCommit(data);
  ospSetData(mesh, "vertex", data);

  data = ospNewData(4, OSP_FLOAT4, color);
  ospCommit(data);
  ospSetData(mesh, "vertex.color", data);

  data = ospNewData(2, OSP_INT3, index); // OSP_INT4 format is also supported for triangle indices
  ospCommit(data);
  ospSetData(mesh, "index", data);

  ospCommit(mesh);

  OSPModel world = ospNewModel();
  ospAddGeometry(world, mesh);
  ospCommit(world);

  // create and setup renderer
  OSPRenderer renderer = ospNewRenderer("scivis"); // choose Scientific Visualization renderer
  ospSet1f(renderer, "aoWeight", 1.0f);            // with full Ambient Occlusion
  ospSetObject(renderer, "model",  world);
  ospSetObject(renderer, "camera", camera);
  ospCommit(renderer);

  // create and setup framebuffer
  OSPFrameBuffer framebuffer = ospNewFrameBuffer(imgSize, OSP_RGBA_I8, OSP_FB_COLOR | /*OSP_FB_DEPTH |*/ OSP_FB_ACCUM);
  ospFrameBufferClear(framebuffer, OSP_FB_COLOR | OSP_FB_ACCUM);

  // render one frame
  ospRenderFrame(framebuffer, renderer, OSP_FB_COLOR | OSP_FB_ACCUM);

  // access framebuffer and write its content as PPM file
  const uint32_t * fb = (uint32_t*)ospMapFrameBuffer(framebuffer, OSP_FB_COLOR);
  writePPM("firstFrame.ppm", imgSize, fb);
  ospUnmapFrameBuffer(fb, framebuffer);

  // render 10 more frames, which are accumulated to result in a better converged image
  for (int frames = 0; frames < 10; frames++)
    ospRenderFrame(framebuffer, renderer, OSP_FB_COLOR | OSP_FB_ACCUM);

  fb = (uint32_t*)ospMapFrameBuffer(framebuffer, OSP_FB_COLOR);
  writePPM("accumulatedFrame.ppm", imgSize, fb);
  ospUnmapFrameBuffer(fb, framebuffer);

  return 0;
}
<commit_msg>Fix ospTutorial for Windows<commit_after>// ======================================================================== //
// Copyright 2009-2016 Intel 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.                                           //
// ======================================================================== //

/* This is a small example tutorial how to use OSPRay in an application.
 *
 * On Linux build it in the build_directory with
 *   g++ ../apps/ospTutorial.cpp -I ../ospray/include -I .. -I ../ospray/embree/common ./libospray.so -Wl,-rpath,. -o ospTutorial
 * On Windows build it in the build_directory\$Configuration with
 *   cl ..\..\apps\ospTutorial.cpp /EHsc -I ..\..\ospray\include -I ..\.. -I ..\..\ospray\embree\common ospray.lib
 */

#include <stdint.h>
#include <stdio.h>
#ifdef _WIN32
#  include <malloc.h>
#else
#  include <alloca.h>
#endif
#include "ospray/ospray.h"

// helper function to write the rendered image as PPM file
void writePPM(const char *fileName,
              const osp::vec2i &size,
              const uint32_t *pixel)
{
  FILE *file = fopen(fileName, "wb");
  fprintf(file, "P6\n%i %i\n255\n", size.x, size.y);
  unsigned char *out = (unsigned char *)alloca(3*size.x);
  for (int y = 0; y < size.y; y++) {
    const unsigned char *in = (const unsigned char *)&pixel[(size.y-1-y)*size.x];
    for (int x = 0; x < size.x; x++) {
      out[3*x + 0] = in[4*x + 0];
      out[3*x + 1] = in[4*x + 1];
      out[3*x + 2] = in[4*x +2 ];
    }
    fwrite(out, 3*size.x, sizeof(char), file);
  }
  fprintf(file, "\n");
  fclose(file);
}

int main(int ac, const char **av) {
  // image size
  osp::vec2i imgSize;
  imgSize.x = 1024; // width
  imgSize.y = 768; // height

  // camera
  float cam_pos[] = {0.f, 0.f, 0.f};
  float cam_up [] = {0.f, 1.f, 0.f};
  float cam_view [] = {0.1f, 0.f, 1.f};

  // triangle mesh data
  float vertex[] = { -1.0f, -1.0f, 3.0f, 0.f,
                     -1.0f,  1.0f, 3.0f, 0.f,
                      1.0f, -1.0f, 3.0f, 0.f,
                      0.1f,  0.1f, 0.3f, 0.f };
  float color[] =  { 0.9f, 0.5f, 0.5f, 1.0f,
                     0.8f, 0.8f, 0.8f, 1.0f,
                     0.8f, 0.8f, 0.8f, 1.0f,
                     0.5f, 0.9f, 0.5f, 1.0f };
  int32_t index[] = { 0, 1, 2,
                      1, 2, 3 };

  // initialize OSPRay; OSPRay parses (and removes) its commandline parameters, e.g. "--osp:debug"
  ospInit(&ac, av);

  // create and setup camera
  OSPCamera camera = ospNewCamera("perspective");
  ospSetf(camera, "aspect", imgSize.x/(float)imgSize.y);
  ospSet3fv(camera, "pos", cam_pos);
  ospSet3fv(camera, "dir", cam_view);
  ospSet3fv(camera, "up",  cam_up);
  ospCommit(camera); // commit each object to indicate modifications are done

  // create and setup model and mesh
  OSPGeometry mesh = ospNewGeometry("triangles");
  OSPData data = ospNewData(4, OSP_FLOAT3A, vertex); // OSP_FLOAT3 format is also supported for vertex positions (currently not on MIC)
  ospCommit(data);
  ospSetData(mesh, "vertex", data);

  data = ospNewData(4, OSP_FLOAT4, color);
  ospCommit(data);
  ospSetData(mesh, "vertex.color", data);

  data = ospNewData(2, OSP_INT3, index); // OSP_INT4 format is also supported for triangle indices
  ospCommit(data);
  ospSetData(mesh, "index", data);

  ospCommit(mesh);

  OSPModel world = ospNewModel();
  ospAddGeometry(world, mesh);
  ospCommit(world);

  // create and setup renderer
  OSPRenderer renderer = ospNewRenderer("scivis"); // choose Scientific Visualization renderer
  ospSet1f(renderer, "aoWeight", 1.0f);            // with full Ambient Occlusion
  ospSetObject(renderer, "model",  world);
  ospSetObject(renderer, "camera", camera);
  ospCommit(renderer);

  // create and setup framebuffer
  OSPFrameBuffer framebuffer = ospNewFrameBuffer(imgSize, OSP_RGBA_I8, OSP_FB_COLOR | /*OSP_FB_DEPTH |*/ OSP_FB_ACCUM);
  ospFrameBufferClear(framebuffer, OSP_FB_COLOR | OSP_FB_ACCUM);

  // render one frame
  ospRenderFrame(framebuffer, renderer, OSP_FB_COLOR | OSP_FB_ACCUM);

  // access framebuffer and write its content as PPM file
  const uint32_t * fb = (uint32_t*)ospMapFrameBuffer(framebuffer, OSP_FB_COLOR);
  writePPM("firstFrame.ppm", imgSize, fb);
  ospUnmapFrameBuffer(fb, framebuffer);

  // render 10 more frames, which are accumulated to result in a better converged image
  for (int frames = 0; frames < 10; frames++)
    ospRenderFrame(framebuffer, renderer, OSP_FB_COLOR | OSP_FB_ACCUM);

  fb = (uint32_t*)ospMapFrameBuffer(framebuffer, OSP_FB_COLOR);
  writePPM("accumulatedFrame.ppm", imgSize, fb);
  ospUnmapFrameBuffer(fb, framebuffer);

  return 0;
}
<|endoftext|>


<commit_before>/****************************************************************************
**
** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the examples of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** No Commercial Usage
** This file contains pre-release code and may not be distributed.
** You may use this file in accordance with the terms and conditions
** contained in the Technology Preview License Agreement accompanying
** this package.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights.  These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
**
**
**
**
**
**

[sbox-maemo6-i486: ~/w/QMLContacts] > xeyes
**
**
** $QT_END_LICENSE$
**
****************************************************************************/
#include "qmlcontactsa.h"

#include <QtDebug>
#include <QFile>
#include <QIODevice>
#include <qcontactfetchrequest.h>
#include <qcontactlocalidfilter.h>
#include <qcontactdetails.h>
#include <qversitreader.h>
#include <qversitcontactimporter.h>

QT_USE_NAMESPACE
QTM_USE_NAMESPACE

QTM_BEGIN_NAMESPACE

// ![0]
QMLContactManagerAsync::QMLContactManagerAsync(QObject *parent)
: QObject(parent)
{
    qc = new QContactManager();

}

QMLContactManagerAsync::~QMLContactManagerAsync()
{
    delete qc;
}

QString QMLContactManagerAsync::availableManagers() const
{
    return QContactManager::availableManagers().join(" ");
}

QString QMLContactManagerAsync::manager()
{
    return qc->managerName();
}

void QMLContactManagerAsync::fillContactsIntoMemoryEngine(QContactManager* manager)
{
    QVersitReader reader;
    QFile file(":/contents/example.vcf");
    bool ok = file.open(QIODevice::ReadOnly);
    if (ok) {
       reader.setDevice(&file);
       if (reader.readAll()) {
           QVersitContactImporter importer;
           QList<QVersitDocument> documents = reader.result();
           foreach (const QVersitDocument& document, documents) {
                QContact c = importer.importContact(document);
                manager->saveContact(&c);
           }
       }
    }

}

void QMLContactManagerAsync::setManager(QString manager)
{
    delete qc;
    qc = new QContactManager(manager);
    if(!qc)
        qc = new QContactManager();
    connect(qc, SIGNAL(contactsAdded(QList<QContactLocalId>)), this, SIGNAL(contactsAdded(QList<QContactLocalId>)));
    connect(qc, SIGNAL(contactsChanged(QList<QContactLocalId>)), this, SIGNAL(contactsChanged(QList<QContactLocalId>)));
    connect(qc, SIGNAL(contactsRemoved(QList<QContactLocalId>)), this, SIGNAL(contactsRemoved(QList<QContactLocalId>)));
    connect(qc, SIGNAL(relationshipsAdded(QList<QContactLocalId>)), this, SIGNAL(relationshipsAdded(QList<QContactLocalId>)));
    connect(qc, SIGNAL(relationshipsRemoved(QList<QContactLocalId>)), this, SIGNAL(relationshipsRemoved(QList<QContactLocalId>)));

    if (manager == "memory" && qc->contacts().isEmpty()) {
        fillContactsIntoMemoryEngine(qc);
    }

    qWarning() << "Changed backend to: " << manager;
}

QString QMLContactManagerAsync::contactListToQString(const QList<QContactLocalId>& contactIds) const
{
    QString list;
    int i;

    for (i = 0; i < contactIds.count(); i++) {
            list += QString::number(contactIds.at(i)) +  " ";
        }

    return list;
}

QStringList QMLContactManagerAsync::contactListToQString(const QList<QContact>& contact) const
{
    QStringList list;
    int i;

    for (i = 0; i < contact.count(); i++) {
        list += qc->synthesizeDisplayLabel(contact.at(i));
     }

    return list;
}

int QMLContactManagerAsync::numContacts()
{
    QList<QContactLocalId> qlid;

    qlid = qc->contacts();

    return qlid.count();
}

void QMLContactManagerAsync::contacts()
{
    m_contactIds.clear();
    QContactFetchRequest* req = new QContactFetchRequest;
    QContactLocalIdFilter idFil;
    idFil.setIds(qc->contacts());
    req->setFilter(idFil);
    req->setManager(qc);
    connect(req, SIGNAL(progress(QContactFetchRequest*, bool)), this, SLOT(contactProgress(QContactFetchRequest*,bool)));
    req->start();
}

void QMLContactManagerAsync::contactProgress(QContactFetchRequest *request, bool appendOnly)
{
    Q_UNUSED(appendOnly);

    // first, check to make sure that the request is still valid.
    if (qc != request->manager() ||
        request->status() == QContactAbstractRequest::Cancelled) {
        delete request;
        return; // ignore these results.
    }

    if(request->contacts().count() > 0) {
        QContact c;
        foreach(c, request->contacts()) {
            //qWarning() << "Local Id: " << c.localId() << " count: " << m_contactIds.count();
            QmlContact qmlc(c);
            emit contactsLoaded(&qmlc);
        }
    }

    // check to see if the request status is "finished" - clean up.
    if (request->status() == QContactAbstractRequest::Finished) {
        delete request;
        emit contactsLoadedDone();
    }

}

QString QMLContactManagerAsync::idToName(QString name)
{
    QContact c = qc->contact(name.toInt());
    return qc->synthesizeDisplayLabel(c);
}

// ![0]

#include "moc_qmlcontactsa.cpp"

QTM_END_NAMESPACE
QML_DEFINE_TYPE(QMLContactManagerAsync, 1, 0, QMLContactManagerAsync, QMLContactManagerAsync);
<commit_msg>remove the deprecated apis<commit_after>/****************************************************************************
**
** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the examples of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** No Commercial Usage
** This file contains pre-release code and may not be distributed.
** You may use this file in accordance with the terms and conditions
** contained in the Technology Preview License Agreement accompanying
** this package.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights.  These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
**
**
**
**
**
**

[sbox-maemo6-i486: ~/w/QMLContacts] > xeyes
**
**
** $QT_END_LICENSE$
**
****************************************************************************/
#include "qmlcontactsa.h"

#include <QtDebug>
#include <QFile>
#include <QIODevice>
#include <qcontactfetchrequest.h>
#include <qcontactlocalidfilter.h>
#include <qcontactdetails.h>
#include <qversitreader.h>
#include <qversitcontactimporter.h>

QT_USE_NAMESPACE
QTM_USE_NAMESPACE

QTM_BEGIN_NAMESPACE

// ![0]
QMLContactManagerAsync::QMLContactManagerAsync(QObject *parent)
: QObject(parent)
{
    qc = new QContactManager();

}

QMLContactManagerAsync::~QMLContactManagerAsync()
{
    delete qc;
}

QString QMLContactManagerAsync::availableManagers() const
{
    return QContactManager::availableManagers().join(" ");
}

QString QMLContactManagerAsync::manager()
{
    return qc->managerName();
}

void QMLContactManagerAsync::fillContactsIntoMemoryEngine(QContactManager* manager)
{
    QVersitReader reader;
    QFile file(":/contents/example.vcf");
    bool ok = file.open(QIODevice::ReadOnly);
    if (ok) {
       reader.setDevice(&file);
       if (reader.startReading() && reader.waitForFinished()) {
           QVersitContactImporter importer;
           QList<QContact> contacts = importer.importContacts(reader.results());
           QMap<int, QContactManager::Error> errors;
           manager->saveContacts(&contacts, &errors);
       }
    }

}

void QMLContactManagerAsync::setManager(QString manager)
{
    delete qc;
    qc = new QContactManager(manager);
    if(!qc)
        qc = new QContactManager();
    connect(qc, SIGNAL(contactsAdded(QList<QContactLocalId>)), this, SIGNAL(contactsAdded(QList<QContactLocalId>)));
    connect(qc, SIGNAL(contactsChanged(QList<QContactLocalId>)), this, SIGNAL(contactsChanged(QList<QContactLocalId>)));
    connect(qc, SIGNAL(contactsRemoved(QList<QContactLocalId>)), this, SIGNAL(contactsRemoved(QList<QContactLocalId>)));
    connect(qc, SIGNAL(relationshipsAdded(QList<QContactLocalId>)), this, SIGNAL(relationshipsAdded(QList<QContactLocalId>)));
    connect(qc, SIGNAL(relationshipsRemoved(QList<QContactLocalId>)), this, SIGNAL(relationshipsRemoved(QList<QContactLocalId>)));

    if (manager == "memory" && qc->contactIds().isEmpty()) {
        fillContactsIntoMemoryEngine(qc);
    }

    qWarning() << "Changed backend to: " << manager;
}

QString QMLContactManagerAsync::contactListToQString(const QList<QContactLocalId>& contactIds) const
{
    QString list;
    int i;

    for (i = 0; i < contactIds.count(); i++) {
            list += QString::number(contactIds.at(i)) +  " ";
        }

    return list;
}

QStringList QMLContactManagerAsync::contactListToQString(const QList<QContact>& contact) const
{
    QStringList list;
    int i;

    for (i = 0; i < contact.count(); i++) {
        list += qc->synthesizedDisplayLabel(contact.at(i));
     }

    return list;
}

int QMLContactManagerAsync::numContacts()
{
    QList<QContactLocalId> qlid;

    qlid = qc->contactIds();

    return qlid.count();
}

void QMLContactManagerAsync::contacts()
{
    m_contactIds.clear();
    QContactFetchRequest* req = new QContactFetchRequest;
    QContactLocalIdFilter idFil;
    idFil.setIds(qc->contactIds());
    req->setFilter(idFil);
    req->setManager(qc);
    connect(req, SIGNAL(progress(QContactFetchRequest*, bool)), this, SLOT(contactProgress(QContactFetchRequest*,bool)));
    req->start();
}

void QMLContactManagerAsync::contactProgress(QContactFetchRequest *request, bool appendOnly)
{
    Q_UNUSED(appendOnly);

    // first, check to make sure that the request is still valid.
    if (qc != request->manager() ||
        request->state() == QContactAbstractRequest::CanceledState) {
        delete request;
        return; // ignore these results.
    }

    if(request->contacts().count() > 0) {
        QContact c;
        foreach(c, request->contacts()) {
            //qWarning() << "Local Id: " << c.localId() << " count: " << m_contactIds.count();
            QmlContact qmlc(c);
            emit contactsLoaded(&qmlc);
        }
    }

    // check to see if the request status is "finished" - clean up.
    if (request->state() == QContactAbstractRequest::FinishedState) {
        delete request;
        emit contactsLoadedDone();
    }

}

QString QMLContactManagerAsync::idToName(QString name)
{
    QContact c = qc->contact(name.toInt());
    return qc->synthesizedDisplayLabel(c);
}

// ![0]

#include "moc_qmlcontactsa.cpp"

QTM_END_NAMESPACE
QML_DEFINE_TYPE(QMLContactManagerAsync, 1, 0, QMLContactManagerAsync, QMLContactManagerAsync);
<|endoftext|>


<commit_before>/*=========================================================================

  Program:   ParaView
  Module:    vtkSelectionNode.cxx

  Copyright (c) Kitware, Inc.
  All rights reserved.
  See Copyright.txt or http://www.paraview.org/HTML/Copyright.html for details.

     This software is distributed WITHOUT ANY WARRANTY; without even
     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
     PURPOSE.  See the above copyright notice for more information.

=========================================================================*/
#include "vtkSelectionNode.h"

#include "vtkDataSetAttributes.h"
#include "vtkIdTypeArray.h"
#include "vtkInformation.h"
#include "vtkInformationIntegerKey.h"
#include "vtkInformationIterator.h"
#include "vtkInformationObjectBaseKey.h"
#include "vtkInformationStringKey.h"
#include "vtkInformationDoubleKey.h"
#include "vtkInformationVector.h"
#include "vtkObjectFactory.h"
#include "vtkSmartPointer.h"

#include <algorithm>
#include <set>
#include <iterator>

vtkStandardNewMacro(vtkSelectionNode);
vtkCxxSetObjectMacro(vtkSelectionNode, SelectionData, vtkDataSetAttributes);

vtkInformationKeyMacro(vtkSelectionNode,CONTENT_TYPE,Integer);
vtkInformationKeyMacro(vtkSelectionNode,SOURCE,ObjectBase);
vtkInformationKeyMacro(vtkSelectionNode,SOURCE_ID,Integer);
vtkInformationKeyMacro(vtkSelectionNode,PROP,ObjectBase);
vtkInformationKeyMacro(vtkSelectionNode,PROP_ID,Integer);
vtkInformationKeyMacro(vtkSelectionNode,PROCESS_ID,Integer);
vtkInformationKeyMacro(vtkSelectionNode,COMPOSITE_INDEX,Integer);
vtkInformationKeyMacro(vtkSelectionNode,HIERARCHICAL_LEVEL,Integer);
vtkInformationKeyMacro(vtkSelectionNode,HIERARCHICAL_INDEX,Integer);
vtkInformationKeyMacro(vtkSelectionNode,FIELD_TYPE,Integer);
vtkInformationKeyMacro(vtkSelectionNode,EPSILON,Double);
vtkInformationKeyMacro(vtkSelectionNode,CONTAINING_CELLS,Integer);
vtkInformationKeyMacro(vtkSelectionNode,PIXEL_COUNT,Integer);
vtkInformationKeyMacro(vtkSelectionNode,INVERSE,Integer);
vtkInformationKeyMacro(vtkSelectionNode,INDEXED_VERTICES,Integer);
vtkInformationKeyMacro(vtkSelectionNode,COMPONENT_NUMBER,Integer);

//----------------------------------------------------------------------------
vtkSelectionNode::vtkSelectionNode()
{
  this->SelectionData = vtkDataSetAttributes::New();
  this->Properties = vtkInformation::New();
  this->QueryString = 0;
}

//----------------------------------------------------------------------------
vtkSelectionNode::~vtkSelectionNode()
{
  this->Properties->Delete();
  if (this->SelectionData)
    {
    this->SelectionData->Delete();
    }
  this->SetQueryString(0);
}

//----------------------------------------------------------------------------
void vtkSelectionNode::Initialize()
{
  this->Properties->Clear();
  if (this->SelectionData)
    {
    this->SelectionData->Initialize();
    }
  this->Modified();
}

//----------------------------------------------------------------------------
vtkAbstractArray* vtkSelectionNode::GetSelectionList()
{
  if (this->SelectionData && this->SelectionData->GetNumberOfArrays() > 0)
    {
    return this->SelectionData->GetAbstractArray(0);
    }
  return 0;
}

//----------------------------------------------------------------------------
void vtkSelectionNode::SetSelectionList(vtkAbstractArray* arr)
{
  if (!this->SelectionData)
    {
    this->SelectionData = vtkDataSetAttributes::New();
    }
  this->SelectionData->Initialize();
  this->SelectionData->AddArray(arr);
}

//----------------------------------------------------------------------------
void vtkSelectionNode::PrintSelf(ostream& os, vtkIndent indent)
{
  this->Superclass::PrintSelf(os, indent);

  os << indent << "ContentType: ";
  switch (this->GetContentType())
    {
    case GLOBALIDS:
      os << "GLOBALIDS";
      break;
    case PEDIGREEIDS:
      os << "PEDIGREEIDS";
      break;
    case VALUES:
      os << "VALUES";
      break;
    case INDICES:
      os << "INDICES";
      break;
    case FRUSTUM:
      os << "FRUSTUM";
      break;
    case LOCATIONS:
      os << "LOCATIONS";
      break;
    case THRESHOLDS:
      os << "THRESHOLDS";
      break;
    case BLOCKS:
      os << "BLOCKS";
      break;
    default:
      os << "UNKNOWN";
      break;
    }
  os << endl;
  os << indent << "FieldType: ";
  switch (this->GetFieldType())
    {
    case CELL:
      os << "CELL";
      break;
    case POINT:
      os << "POINT";
      break;
    case FIELD:
      os << "FIELD";
      break;
    case VERTEX:
      os << "VERTEX";
      break;
    case EDGE:
      os << "EDGE";
      break;
    case ROW:
      os << "ROW";
      break;
    default:
      os << "UNKNOWN";
      break;
    }
  os << endl;
  os << indent << "Properties: " << (this->Properties ? "" : "(none)") << endl;
  if (this->Properties)
    {
    this->Properties->PrintSelf(os, indent.GetNextIndent());
    }
  os << indent << "SelectionData: " << (this->SelectionData ? "" : "(none)") << endl;
  if (this->SelectionData)
    {
    this->SelectionData->PrintSelf(os, indent.GetNextIndent());
    }
  os << indent << "QueryString: " << (this->QueryString ? this->QueryString : "NULL") << endl;
}

//----------------------------------------------------------------------------
void vtkSelectionNode::ShallowCopy(vtkSelectionNode* input)
{
  if (!input)
    {
    return;
    }
  this->Initialize();
  this->Properties->Copy(input->Properties, 0);
  this->SelectionData->ShallowCopy(input->SelectionData);
  this->SetQueryString(input->GetQueryString());
  this->Modified();
}

//----------------------------------------------------------------------------
void vtkSelectionNode::DeepCopy(vtkSelectionNode* input)
{
  if (!input)
    {
    return;
    }
  this->Initialize();
  this->Properties->Copy(input->Properties, 1);
  this->SelectionData->DeepCopy(input->SelectionData);
  this->SetQueryString(input->GetQueryString());
  this->Modified();
}

//----------------------------------------------------------------------------
void vtkSelectionNode::SetContentType(int type)
{
  this->GetProperties()->Set(vtkSelectionNode::CONTENT_TYPE(), type);
}

//----------------------------------------------------------------------------
int vtkSelectionNode::GetContentType()
{
  if (this->GetProperties()->Has(vtkSelectionNode::CONTENT_TYPE()))
    {
    return this->GetProperties()->Get(vtkSelectionNode::CONTENT_TYPE());
    }
  return -1;
}

//----------------------------------------------------------------------------
void vtkSelectionNode::SetFieldType(int type)
{
  this->GetProperties()->Set(vtkSelectionNode::FIELD_TYPE(), type);
}

//----------------------------------------------------------------------------
int vtkSelectionNode::GetFieldType()
{
  if (this->GetProperties()->Has(vtkSelectionNode::FIELD_TYPE()))
    {
    return this->GetProperties()->Get(vtkSelectionNode::FIELD_TYPE());
    }
  return -1;
}

//----------------------------------------------------------------------------
bool vtkSelectionNode::EqualProperties(vtkSelectionNode* other,
  bool fullcompare/*=true*/)
{
  if (!other)
    {
    return false;
    }

  vtkSmartPointer<vtkInformationIterator> iterSelf =
    vtkSmartPointer<vtkInformationIterator>::New();

  iterSelf->SetInformation(this->Properties);

  vtkInformation* otherProperties = other->GetProperties();
  for (iterSelf->InitTraversal(); !iterSelf->IsDoneWithTraversal();
    iterSelf->GoToNextItem())
    {
    vtkInformationKey* key = iterSelf->GetCurrentKey();
    vtkInformationIntegerKey* ikey =
      vtkInformationIntegerKey::SafeDownCast(key);
    vtkInformationObjectBaseKey* okey =
      vtkInformationObjectBaseKey::SafeDownCast(key);
    if (ikey)
      {
      if (!otherProperties->Has(ikey) ||
        this->Properties->Get(ikey) != otherProperties->Get(ikey))
        {
        return false;
        }
      }
    if (okey)
      {
      if (!otherProperties->Has(okey) ||
        this->Properties->Get(okey) != otherProperties->Get(okey))
        {
        return false;
        }
      }
    }

  // Also check that array names match for certain content types
  // For VALUES and THRESHOLDS, names represent array where values come from.
  // For PEDIGREEIDS, names represent the domain of the selection.
  if (this->GetContentType() == vtkSelectionNode::VALUES ||
      this->GetContentType() == vtkSelectionNode::PEDIGREEIDS ||
      this->GetContentType() == vtkSelectionNode::THRESHOLDS)
    {
    int numArrays = other->SelectionData->GetNumberOfArrays();
    if (this->SelectionData->GetNumberOfArrays() != numArrays)
      {
      return false;
      }
    for (int a = 0; a < numArrays; ++a)
      {
      vtkAbstractArray* arr = this->SelectionData->GetAbstractArray(a);
      vtkAbstractArray* otherArr = other->SelectionData->GetAbstractArray(a);
      if (!arr->GetName() && otherArr->GetName())
        {
        return false;
        }
      if (arr->GetName() && !otherArr->GetName())
        {
        return false;
        }
      if (arr->GetName() && otherArr->GetName() && strcmp(arr->GetName(), otherArr->GetName()))
        {
        return false;
        }
      }
    }

  if (fullcompare)
    {
    return other->EqualProperties(this, false);
    }

  return true;
}

//----------------------------------------------------------------------------
void vtkSelectionNode::UnionSelectionList(vtkSelectionNode* other)
{
  int type = this->Properties->Get(CONTENT_TYPE());
  switch (type)
    {
  case GLOBALIDS:
  case PEDIGREEIDS:
  case VALUES:
  case INDICES:
  case LOCATIONS:
  case THRESHOLDS:
  case BLOCKS:
      {
      vtkDataSetAttributes* fd1 = this->GetSelectionData();
      vtkDataSetAttributes* fd2 = other->GetSelectionData();
      if (fd1->GetNumberOfArrays() != fd2->GetNumberOfArrays())
        {
        vtkErrorMacro(<< "Cannot take the union where the number of arrays do not match.");
        }
      for (int i = 0; i < fd1->GetNumberOfArrays(); i++)
        {
        vtkAbstractArray* aa1 = fd1->GetAbstractArray(i);
        vtkAbstractArray* aa2 = 0;
        if (i == 0 && type != VALUES && type != THRESHOLDS)
          {
          aa2 = fd2->GetAbstractArray(i);
          }
        else
          {
          aa2 = fd2->GetAbstractArray(aa1->GetName());
          }
        if (!aa2)
          {
          vtkErrorMacro(<< "Could not find array with name "
                        << aa1->GetName() << " in other selection.");
          }
        if (aa1->GetDataType() != aa2->GetDataType())
          {
          vtkErrorMacro(<< "Cannot take the union where selection list types "
            << "do not match.");
          return;
          }
        if (aa1->GetNumberOfComponents() != aa2->GetNumberOfComponents())
          {
          vtkErrorMacro(<< "Cannot take the union where selection list number "
            << "of components do not match.");
          return;
          }
        // If it is the same array, we are done.
        if (aa1 == aa2)
          {
          return;
          }
        int numComps = aa2->GetNumberOfComponents();
        vtkIdType numTuples = aa2->GetNumberOfTuples();
        for (vtkIdType j = 0; j < numTuples; j++)
          {
          // Avoid duplicates on single-component arrays.
          if (numComps != 1 || aa1->LookupValue(aa2->GetVariantValue(j)) == -1)
            {
            aa1->InsertNextTuple(j, aa2);
            }
          }
        }
      break;
      }
  case FRUSTUM:
  default:
      {
      vtkErrorMacro(<< "Do not know how to take the union of content type "
        << type << ".");
      return;
      }
    }
}

//----------------------------------------------------------------------------
void vtkSelectionNode::SubtractSelectionList(vtkSelectionNode* other)
{
  int type = this->Properties->Get(CONTENT_TYPE());
  switch(type)
    {
    case GLOBALIDS:
    case INDICES:
    case PEDIGREEIDS:
      {
      vtkDataSetAttributes * fd1 = this->GetSelectionData();
      vtkDataSetAttributes * fd2 = other->GetSelectionData();
      if(fd1->GetNumberOfArrays() != fd2->GetNumberOfArrays())
        {
        vtkErrorMacro(<< "Cannot take subtract selections if the number of arrays do not match.");
        }
        if( fd1->GetNumberOfArrays() != 1 || fd2->GetNumberOfArrays() != 1)
          {
          vtkErrorMacro(<<"Cannot subtract selections with more than one array.");
          return;
          }

        if( fd1->GetArray(0)->GetDataType() != VTK_ID_TYPE || fd2->GetArray(0)->GetDataType() != VTK_ID_TYPE )
          {
          vtkErrorMacro(<<"Can only subtract selections with vtkIdTypeArray lists.");
          }

          vtkIdTypeArray * fd1_array = (vtkIdTypeArray*)fd1->GetArray(0);
          vtkIdTypeArray * fd2_array = (vtkIdTypeArray*)fd2->GetArray(0);

          vtkIdType fd1_N = fd1_array->GetNumberOfTuples();
          vtkIdType fd2_N = fd2_array->GetNumberOfTuples();

          vtkIdType * fd1_P = (vtkIdType*)fd1_array->GetVoidPointer(0);
          vtkIdType * fd2_P = (vtkIdType*)fd2_array->GetVoidPointer(0);

          // make sure both arrays are sorted
          std::sort( fd1_P, fd1_P + fd1_N );
          std::sort( fd2_P, fd2_P + fd2_N );

          std::set<vtkIdType> result;

          std::set_difference(fd1_P, fd1_P + fd1_N,
                                 fd2_P, fd2_P + fd2_N,
                                 std::inserter(result, result.end()));

          fd1_array->Reset();
          for(std::set<vtkIdType>::const_iterator p = result.begin(); p!=result.end(); ++p)
            {
            fd1_array->InsertNextValue( *p );
            }
      break;
      }
    case BLOCKS:
    case FRUSTUM:
    case LOCATIONS:
    case THRESHOLDS:
    case VALUES:
    default:
      {
      vtkErrorMacro(<< "Do not know how to subtract the given content type " << type << ".");
      }
    };
}

//----------------------------------------------------------------------------
unsigned long vtkSelectionNode::GetMTime()
{
  unsigned long mTime = this->MTime.GetMTime();
  unsigned long propMTime;
  unsigned long fieldMTime;
  if (this->Properties)
    {
    propMTime = this->Properties->GetMTime();
    mTime = (propMTime > mTime ? propMTime : mTime);
    }
  if (this->SelectionData)
    {
    fieldMTime = this->SelectionData->GetMTime();
    mTime = (fieldMTime > mTime ? fieldMTime : mTime);
    }
  return mTime;
}
<commit_msg>Silence clang static analyzer warning about null deref<commit_after>/*=========================================================================

  Program:   ParaView
  Module:    vtkSelectionNode.cxx

  Copyright (c) Kitware, Inc.
  All rights reserved.
  See Copyright.txt or http://www.paraview.org/HTML/Copyright.html for details.

     This software is distributed WITHOUT ANY WARRANTY; without even
     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
     PURPOSE.  See the above copyright notice for more information.

=========================================================================*/
#include "vtkSelectionNode.h"

#include "vtkDataSetAttributes.h"
#include "vtkIdTypeArray.h"
#include "vtkInformation.h"
#include "vtkInformationIntegerKey.h"
#include "vtkInformationIterator.h"
#include "vtkInformationObjectBaseKey.h"
#include "vtkInformationStringKey.h"
#include "vtkInformationDoubleKey.h"
#include "vtkInformationVector.h"
#include "vtkObjectFactory.h"
#include "vtkSmartPointer.h"

#include <algorithm>
#include <set>
#include <iterator>

vtkStandardNewMacro(vtkSelectionNode);
vtkCxxSetObjectMacro(vtkSelectionNode, SelectionData, vtkDataSetAttributes);

vtkInformationKeyMacro(vtkSelectionNode,CONTENT_TYPE,Integer);
vtkInformationKeyMacro(vtkSelectionNode,SOURCE,ObjectBase);
vtkInformationKeyMacro(vtkSelectionNode,SOURCE_ID,Integer);
vtkInformationKeyMacro(vtkSelectionNode,PROP,ObjectBase);
vtkInformationKeyMacro(vtkSelectionNode,PROP_ID,Integer);
vtkInformationKeyMacro(vtkSelectionNode,PROCESS_ID,Integer);
vtkInformationKeyMacro(vtkSelectionNode,COMPOSITE_INDEX,Integer);
vtkInformationKeyMacro(vtkSelectionNode,HIERARCHICAL_LEVEL,Integer);
vtkInformationKeyMacro(vtkSelectionNode,HIERARCHICAL_INDEX,Integer);
vtkInformationKeyMacro(vtkSelectionNode,FIELD_TYPE,Integer);
vtkInformationKeyMacro(vtkSelectionNode,EPSILON,Double);
vtkInformationKeyMacro(vtkSelectionNode,CONTAINING_CELLS,Integer);
vtkInformationKeyMacro(vtkSelectionNode,PIXEL_COUNT,Integer);
vtkInformationKeyMacro(vtkSelectionNode,INVERSE,Integer);
vtkInformationKeyMacro(vtkSelectionNode,INDEXED_VERTICES,Integer);
vtkInformationKeyMacro(vtkSelectionNode,COMPONENT_NUMBER,Integer);

//----------------------------------------------------------------------------
vtkSelectionNode::vtkSelectionNode()
{
  this->SelectionData = vtkDataSetAttributes::New();
  this->Properties = vtkInformation::New();
  this->QueryString = 0;
}

//----------------------------------------------------------------------------
vtkSelectionNode::~vtkSelectionNode()
{
  this->Properties->Delete();
  if (this->SelectionData)
    {
    this->SelectionData->Delete();
    }
  this->SetQueryString(0);
}

//----------------------------------------------------------------------------
void vtkSelectionNode::Initialize()
{
  this->Properties->Clear();
  if (this->SelectionData)
    {
    this->SelectionData->Initialize();
    }
  this->Modified();
}

//----------------------------------------------------------------------------
vtkAbstractArray* vtkSelectionNode::GetSelectionList()
{
  if (this->SelectionData && this->SelectionData->GetNumberOfArrays() > 0)
    {
    return this->SelectionData->GetAbstractArray(0);
    }
  return 0;
}

//----------------------------------------------------------------------------
void vtkSelectionNode::SetSelectionList(vtkAbstractArray* arr)
{
  if (!this->SelectionData)
    {
    this->SelectionData = vtkDataSetAttributes::New();
    }
  this->SelectionData->Initialize();
  this->SelectionData->AddArray(arr);
}

//----------------------------------------------------------------------------
void vtkSelectionNode::PrintSelf(ostream& os, vtkIndent indent)
{
  this->Superclass::PrintSelf(os, indent);

  os << indent << "ContentType: ";
  switch (this->GetContentType())
    {
    case GLOBALIDS:
      os << "GLOBALIDS";
      break;
    case PEDIGREEIDS:
      os << "PEDIGREEIDS";
      break;
    case VALUES:
      os << "VALUES";
      break;
    case INDICES:
      os << "INDICES";
      break;
    case FRUSTUM:
      os << "FRUSTUM";
      break;
    case LOCATIONS:
      os << "LOCATIONS";
      break;
    case THRESHOLDS:
      os << "THRESHOLDS";
      break;
    case BLOCKS:
      os << "BLOCKS";
      break;
    default:
      os << "UNKNOWN";
      break;
    }
  os << endl;
  os << indent << "FieldType: ";
  switch (this->GetFieldType())
    {
    case CELL:
      os << "CELL";
      break;
    case POINT:
      os << "POINT";
      break;
    case FIELD:
      os << "FIELD";
      break;
    case VERTEX:
      os << "VERTEX";
      break;
    case EDGE:
      os << "EDGE";
      break;
    case ROW:
      os << "ROW";
      break;
    default:
      os << "UNKNOWN";
      break;
    }
  os << endl;
  os << indent << "Properties: " << (this->Properties ? "" : "(none)") << endl;
  if (this->Properties)
    {
    this->Properties->PrintSelf(os, indent.GetNextIndent());
    }
  os << indent << "SelectionData: " << (this->SelectionData ? "" : "(none)") << endl;
  if (this->SelectionData)
    {
    this->SelectionData->PrintSelf(os, indent.GetNextIndent());
    }
  os << indent << "QueryString: " << (this->QueryString ? this->QueryString : "NULL") << endl;
}

//----------------------------------------------------------------------------
void vtkSelectionNode::ShallowCopy(vtkSelectionNode* input)
{
  if (!input)
    {
    return;
    }
  this->Initialize();
  this->Properties->Copy(input->Properties, 0);
  this->SelectionData->ShallowCopy(input->SelectionData);
  this->SetQueryString(input->GetQueryString());
  this->Modified();
}

//----------------------------------------------------------------------------
void vtkSelectionNode::DeepCopy(vtkSelectionNode* input)
{
  if (!input)
    {
    return;
    }
  this->Initialize();
  this->Properties->Copy(input->Properties, 1);
  this->SelectionData->DeepCopy(input->SelectionData);
  this->SetQueryString(input->GetQueryString());
  this->Modified();
}

//----------------------------------------------------------------------------
void vtkSelectionNode::SetContentType(int type)
{
  this->GetProperties()->Set(vtkSelectionNode::CONTENT_TYPE(), type);
}

//----------------------------------------------------------------------------
int vtkSelectionNode::GetContentType()
{
  if (this->GetProperties()->Has(vtkSelectionNode::CONTENT_TYPE()))
    {
    return this->GetProperties()->Get(vtkSelectionNode::CONTENT_TYPE());
    }
  return -1;
}

//----------------------------------------------------------------------------
void vtkSelectionNode::SetFieldType(int type)
{
  this->GetProperties()->Set(vtkSelectionNode::FIELD_TYPE(), type);
}

//----------------------------------------------------------------------------
int vtkSelectionNode::GetFieldType()
{
  if (this->GetProperties()->Has(vtkSelectionNode::FIELD_TYPE()))
    {
    return this->GetProperties()->Get(vtkSelectionNode::FIELD_TYPE());
    }
  return -1;
}

//----------------------------------------------------------------------------
bool vtkSelectionNode::EqualProperties(vtkSelectionNode* other,
  bool fullcompare/*=true*/)
{
  if (!other)
    {
    return false;
    }

  vtkSmartPointer<vtkInformationIterator> iterSelf =
    vtkSmartPointer<vtkInformationIterator>::New();

  iterSelf->SetInformation(this->Properties);

  vtkInformation* otherProperties = other->GetProperties();
  for (iterSelf->InitTraversal(); !iterSelf->IsDoneWithTraversal();
    iterSelf->GoToNextItem())
    {
    vtkInformationKey* key = iterSelf->GetCurrentKey();
    vtkInformationIntegerKey* ikey =
      vtkInformationIntegerKey::SafeDownCast(key);
    vtkInformationObjectBaseKey* okey =
      vtkInformationObjectBaseKey::SafeDownCast(key);
    if (ikey)
      {
      if (!otherProperties->Has(ikey) ||
        this->Properties->Get(ikey) != otherProperties->Get(ikey))
        {
        return false;
        }
      }
    if (okey)
      {
      if (!otherProperties->Has(okey) ||
        this->Properties->Get(okey) != otherProperties->Get(okey))
        {
        return false;
        }
      }
    }

  // Also check that array names match for certain content types
  // For VALUES and THRESHOLDS, names represent array where values come from.
  // For PEDIGREEIDS, names represent the domain of the selection.
  if (this->GetContentType() == vtkSelectionNode::VALUES ||
      this->GetContentType() == vtkSelectionNode::PEDIGREEIDS ||
      this->GetContentType() == vtkSelectionNode::THRESHOLDS)
    {
    int numArrays = other->SelectionData->GetNumberOfArrays();
    if (this->SelectionData->GetNumberOfArrays() != numArrays)
      {
      return false;
      }
    for (int a = 0; a < numArrays; ++a)
      {
      vtkAbstractArray* arr = this->SelectionData->GetAbstractArray(a);
      vtkAbstractArray* otherArr = other->SelectionData->GetAbstractArray(a);
      if (!arr->GetName() && otherArr->GetName())
        {
        return false;
        }
      if (arr->GetName() && !otherArr->GetName())
        {
        return false;
        }
      if (arr->GetName() && otherArr->GetName() && strcmp(arr->GetName(), otherArr->GetName()))
        {
        return false;
        }
      }
    }

  if (fullcompare)
    {
    return other->EqualProperties(this, false);
    }

  return true;
}

//----------------------------------------------------------------------------
void vtkSelectionNode::UnionSelectionList(vtkSelectionNode* other)
{
  int type = this->Properties->Get(CONTENT_TYPE());
  switch (type)
    {
  case GLOBALIDS:
  case PEDIGREEIDS:
  case VALUES:
  case INDICES:
  case LOCATIONS:
  case THRESHOLDS:
  case BLOCKS:
      {
      vtkDataSetAttributes* fd1 = this->GetSelectionData();
      vtkDataSetAttributes* fd2 = other->GetSelectionData();
      if (fd1->GetNumberOfArrays() != fd2->GetNumberOfArrays())
        {
        vtkErrorMacro(<< "Cannot take the union where the number of arrays do not match.");
        }
      for (int i = 0; i < fd1->GetNumberOfArrays(); i++)
        {
        vtkAbstractArray* aa1 = fd1->GetAbstractArray(i);
        vtkAbstractArray* aa2 = 0;
        if (i == 0 && type != VALUES && type != THRESHOLDS)
          {
          aa2 = fd2->GetAbstractArray(i);
          }
        else
          {
          aa2 = fd2->GetAbstractArray(aa1->GetName());
          }
        if (!aa2)
          {
          vtkErrorMacro(<< "Could not find array with name "
                        << aa1->GetName() << " in other selection.");
          return;
          }
        if (aa1->GetDataType() != aa2->GetDataType())
          {
          vtkErrorMacro(<< "Cannot take the union where selection list types "
            << "do not match.");
          return;
          }
        if (aa1->GetNumberOfComponents() != aa2->GetNumberOfComponents())
          {
          vtkErrorMacro(<< "Cannot take the union where selection list number "
            << "of components do not match.");
          return;
          }
        // If it is the same array, we are done.
        if (aa1 == aa2)
          {
          return;
          }
        int numComps = aa2->GetNumberOfComponents();
        vtkIdType numTuples = aa2->GetNumberOfTuples();
        for (vtkIdType j = 0; j < numTuples; j++)
          {
          // Avoid duplicates on single-component arrays.
          if (numComps != 1 || aa1->LookupValue(aa2->GetVariantValue(j)) == -1)
            {
            aa1->InsertNextTuple(j, aa2);
            }
          }
        }
      break;
      }
  case FRUSTUM:
  default:
      {
      vtkErrorMacro(<< "Do not know how to take the union of content type "
        << type << ".");
      return;
      }
    }
}

//----------------------------------------------------------------------------
void vtkSelectionNode::SubtractSelectionList(vtkSelectionNode* other)
{
  int type = this->Properties->Get(CONTENT_TYPE());
  switch(type)
    {
    case GLOBALIDS:
    case INDICES:
    case PEDIGREEIDS:
      {
      vtkDataSetAttributes * fd1 = this->GetSelectionData();
      vtkDataSetAttributes * fd2 = other->GetSelectionData();
      if(fd1->GetNumberOfArrays() != fd2->GetNumberOfArrays())
        {
        vtkErrorMacro(<< "Cannot take subtract selections if the number of arrays do not match.");
        }
        if( fd1->GetNumberOfArrays() != 1 || fd2->GetNumberOfArrays() != 1)
          {
          vtkErrorMacro(<<"Cannot subtract selections with more than one array.");
          return;
          }

        if( fd1->GetArray(0)->GetDataType() != VTK_ID_TYPE || fd2->GetArray(0)->GetDataType() != VTK_ID_TYPE )
          {
          vtkErrorMacro(<<"Can only subtract selections with vtkIdTypeArray lists.");
          }

          vtkIdTypeArray * fd1_array = (vtkIdTypeArray*)fd1->GetArray(0);
          vtkIdTypeArray * fd2_array = (vtkIdTypeArray*)fd2->GetArray(0);

          vtkIdType fd1_N = fd1_array->GetNumberOfTuples();
          vtkIdType fd2_N = fd2_array->GetNumberOfTuples();

          vtkIdType * fd1_P = (vtkIdType*)fd1_array->GetVoidPointer(0);
          vtkIdType * fd2_P = (vtkIdType*)fd2_array->GetVoidPointer(0);

          // make sure both arrays are sorted
          std::sort( fd1_P, fd1_P + fd1_N );
          std::sort( fd2_P, fd2_P + fd2_N );

          std::set<vtkIdType> result;

          std::set_difference(fd1_P, fd1_P + fd1_N,
                                 fd2_P, fd2_P + fd2_N,
                                 std::inserter(result, result.end()));

          fd1_array->Reset();
          for(std::set<vtkIdType>::const_iterator p = result.begin(); p!=result.end(); ++p)
            {
            fd1_array->InsertNextValue( *p );
            }
      break;
      }
    case BLOCKS:
    case FRUSTUM:
    case LOCATIONS:
    case THRESHOLDS:
    case VALUES:
    default:
      {
      vtkErrorMacro(<< "Do not know how to subtract the given content type " << type << ".");
      }
    };
}

//----------------------------------------------------------------------------
unsigned long vtkSelectionNode::GetMTime()
{
  unsigned long mTime = this->MTime.GetMTime();
  unsigned long propMTime;
  unsigned long fieldMTime;
  if (this->Properties)
    {
    propMTime = this->Properties->GetMTime();
    mTime = (propMTime > mTime ? propMTime : mTime);
    }
  if (this->SelectionData)
    {
    fieldMTime = this->SelectionData->GetMTime();
    mTime = (fieldMTime > mTime ? fieldMTime : mTime);
    }
  return mTime;
}
<|endoftext|>


<commit_before>#include "sleepy_discord/websocketpp_websocket.h"
#include <thread>

class GameClient : public SleepyDiscord::DiscordClient {
private:
	enum State {
		NA        = 0,
		GET_READY = 1,	//Game is starting
		SHOOT     = 2,	//waiting for answer
		ENDED     = 3
	};
	struct Game {
		SleepyDiscord::User player;
		std::thread thread;
		State* state;

		Game(const SleepyDiscord::User gamePlayer) :
			player(gamePlayer) {}
		Game(const Game& game) : player(game.player), state(game.state) {}	//needed when we want to copy a game
		~Game() { if (thread.joinable()) { thread.join(); } }	//notice how we don't copy the threads to copies

		void run(std::function<void(State**)> startGame) {
			thread = std::thread(startGame, &state);
		}
	};
	std::list<Game> games;

	enum Weapon {
		ROCK     = 0,
		PAPER    = 1,
		SCISSORS = 2
	};

	enum winState {
		WIN  = 1,
		TIE  = 0,
		LOSE = 2
	};
	/*
	ROCK     - SCISSORS = 0 - 2 = -2 -> (-2 + 3) % 3 = WIN
	PAPER    - SCISSORS = 1 - 2 = -1 -> (-1 + 3) % 3 = LOSE
	ROCK     - PAPER    = 0 - 1 = -1 -> (-1 + 3) % 3 = LOSE
	PAPER    - ROCK     = 1 - 0 =  1 -> ( 1 + 3) % 3 = WIN
	SCISSORS - PAPER    = 2 - 1 =  1 -> ( 1 + 3) % 3 = WIN
	SCISSORS - ROCK     = 2 - 0 =  2 -> ( 2 + 3) % 3 = LOSE
	*/

public:
	using SleepyDiscord::DiscordClient::DiscordClient;
	void onMessage(SleepyDiscord::Message message) {
		games.remove_if([](Game game) -> bool {	//remove all games that have state pointing to nullptr
			return game.state == nullptr;
		});

		if (message.startsWith("whcg hello")) {
			games.push_back(Game(message.author));	//create a game put it on the end of the list of games
			games.back().run([=](State** statePointer) {	//run the last game on another thread. Please see the run function above.
				State state = GET_READY;
				*statePointer = &state;	//needed so that we can end the game when the player picks a weapon
				SleepyDiscord::Message countMessage = sendMessage(message.channel_id, "**ROCK!**");
				sleep(1000);  //wait a second
				editMessage(countMessage, "**PAPER!**"); //message.edit("**PAPER!**"); I don't know if this is a better idea
				sleep(1000);
				editMessage(countMessage, "**SCISSORS!**");
				state = SHOOT;
				sleep(1000);
				editMessage(countMessage, "**SHOOT!**");
				sleep(1000);
				if (state != ENDED) {
					state = ENDED;
					sendMessage(message.channel_id, "You lose.\\nWhen I say ``shoot``, you pick ``rock``, ``paper``, or ``scissors``");
				}
				*statePointer = nullptr;  //state should be removed after this line
			});
			return;
		}

		if (games.empty()) return;

		//get the player's choice
		Weapon playerChoice;
		if      (message.content == "rock"     || message.content == ":fist:"       ) playerChoice = ROCK;
		else if (message.content == "paper"    || message.content == ":raised_hand:") playerChoice = PAPER;
		else if (message.content == "scissors" || message.content == ":v:"          ) playerChoice = SCISSORS;
		else return;	//go back if there's no choice was detected
		games.remove_if([=](Game game) -> bool {	//remove game from the list, when the player wins or loses
			if (game.player == message.author) {
				switch (*game.state) {
				case SHOOT: {
					Weapon botChoice = static_cast<Weapon>(rand() % 3);	//random number 0 to 2
					switch (botChoice) {
					case ROCK:     sendMessage(message.channel_id, ":fist:"); break;
					case PAPER:    sendMessage(message.channel_id, ":raised_hand:"); break;
					case SCISSORS: sendMessage(message.channel_id, ":v:"); break;
					}
					switch ((playerChoice - botChoice + 3) % 3) {
					case LOSE: sendMessage(message.channel_id, ":smiley: I won, and you lost!");  break;
					case TIE:  sendMessage(message.channel_id, ":neutral_face: It's a tie");      break;
					case WIN:  sendMessage(message.channel_id, ":frowning: I lost, and you won"); break;
					}
					*game.state = ENDED;
					return true;	//remove the game from the list
				} break;
				case ENDED: return true; break;
				case GET_READY: sendMessage(message.channel_id, "Not yet, I didn't get to say ``shoot``."); break;
				default: sendMessage(message.channel_id, "Error: unknown state"); break;
				}
			}
			return false;	//keep the game in the list
		});
	}

	~GameClient() {
		for (Game game : games) {
			if (game.thread.joinable()) game.thread.join();
		}
	}
};

int main() {
	srand(time(0));
	GameClient client("Your Token Goes Here", 2);
	client.run();
}<commit_msg>fixed bug in the rock paper scissors example<commit_after>#include "sleepy_discord/websocketpp_websocket.h"
#include <thread>

class GameClient : public SleepyDiscord::DiscordClient {
private:
	enum State {
		NA        = 0,
		GET_READY = 1,	//Game is starting
		SHOOT     = 2,	//waiting for answer
		ENDED     = 3
	};
	struct Game {
		SleepyDiscord::User player;
		std::thread thread;
		State* state;

		Game(const SleepyDiscord::User gamePlayer) :
			player(gamePlayer) {}
		Game(const Game& game) : player(game.player), state(game.state) {}	//needed when we want to copy a game
		~Game() { if (thread.joinable()) { thread.join(); } }	//notice how we don't copy the threads to copies

		void run(std::function<void(State**)> startGame) {
			thread = std::thread(startGame, &state);
		}
	};
	std::list<Game> games;

	enum Weapon {
		ROCK     = 0,
		PAPER    = 1,
		SCISSORS = 2
	};

	enum winState {
		WIN  = 1,
		TIE  = 0,
		LOSE = 2
	};
	/*
	ROCK     - SCISSORS = 0 - 2 = -2 -> (-2 + 3) % 3 = WIN
	PAPER    - SCISSORS = 1 - 2 = -1 -> (-1 + 3) % 3 = LOSE
	ROCK     - PAPER    = 0 - 1 = -1 -> (-1 + 3) % 3 = LOSE
	PAPER    - ROCK     = 1 - 0 =  1 -> ( 1 + 3) % 3 = WIN
	SCISSORS - PAPER    = 2 - 1 =  1 -> ( 1 + 3) % 3 = WIN
	SCISSORS - ROCK     = 2 - 0 =  2 -> ( 2 + 3) % 3 = LOSE
	*/

public:
	using SleepyDiscord::DiscordClient::DiscordClient;
	void onMessage(SleepyDiscord::Message message) {
		games.remove_if([](Game game) -> bool {	//remove all games that have state pointing to nullptr
			return game.state == nullptr;
		});

		if (message.startsWith("whcg hello")) {
			games.push_back(Game(message.author));	//create a game put it on the end of the list of games
			games.back().run([=](State** statePointer) {	//run the last game on another thread. Please see the run function above.
				State state = GET_READY;
				*statePointer = &state;	//needed so that we can end the game when the player picks a weapon
				SleepyDiscord::Message countMessage = sendMessage(message.channel_id, "**ROCK!**");
				sleep(1000);  //wait a second
				editMessage(countMessage, "**PAPER!**"); //message.edit("**PAPER!**"); I don't know if this is a better idea
				sleep(1000);
				editMessage(countMessage, "**SCISSORS!**");
				state = SHOOT;
				sleep(1000);
				editMessage(countMessage, "**SHOOT!**");
				sleep(1000);
				if (state != ENDED) {
					state = ENDED;
					sendMessage(message.channel_id, "You lose.\\nWhen I say ``shoot``, you pick ``rock``, ``paper``, or ``scissors``");
				}
				*statePointer = nullptr;  //state should be removed after this line
			});
			return;
		}

		if (games.empty()) return;

		//get the player's choice
		Weapon playerChoice;
		if      (message.content == "rock"     || message.content == ":fist:"       ) playerChoice = ROCK;
		else if (message.content == "paper"    || message.content == ":raised_hand:") playerChoice = PAPER;
		else if (message.content == "scissors" || message.content == ":v:"          ) playerChoice = SCISSORS;
		else return;	//go back if there's no choice was detected
		games.remove_if([=](Game game) -> bool {	//remove game from the list, when the player wins or loses
			if (game.player == message.author) {
				switch (*game.state) {
				case SHOOT: {
					*game.state = ENDED; //game state is set to end here, so that "you lose" isn't sent after a weapon was picked
					Weapon botChoice = static_cast<Weapon>(rand() % 3);	//random number 0 to 2
					switch (botChoice) {
					case ROCK:     sendMessage(message.channel_id, ":fist:"); break;
					case PAPER:    sendMessage(message.channel_id, ":raised_hand:"); break;
					case SCISSORS: sendMessage(message.channel_id, ":v:"); break;
					}
					switch ((playerChoice - botChoice + 3) % 3) {
					case LOSE: sendMessage(message.channel_id, ":smiley: I won, and you lost!");  break;
					case TIE:  sendMessage(message.channel_id, ":neutral_face: It's a tie");      break;
					case WIN:  sendMessage(message.channel_id, ":frowning: I lost, and you won"); break;
					}
					return true;	//remove the game from the list
				} break;
				case ENDED: return true; break;
				case GET_READY: sendMessage(message.channel_id, "Not yet, I didn't get to say ``shoot``."); break;
				default: sendMessage(message.channel_id, "Error: unknown state"); break;
				}
			}
			return false;	//keep the game in the list
		});
	}

	~GameClient() {
		for (Game game : games) {
			if (game.thread.joinable()) game.thread.join();
		}
	}
};

int main() {
	srand(time(0));
	GameClient client("Your Token Goes Here", 2);
	client.run();
}<|endoftext|>


<commit_before>#include <stdio.h>
#include <iostream>
#include <hip_runtime.h>

#include "ResultDatabase.h"

// Cmdline parms:
bool          p_verbose = false;
bool          p_pinned  = true;
int           p_iterations   = 10;
int           p_device  = 0;
int           p_detailed  = 0;

bool          p_h2d = true;
bool          p_d2h = true;

#define CHECK_HIP_ERROR()                                                    \
{                                                                             \
    hipError_t err = hipGetLastError();                                     \
    if (err != hipSuccess)                                                   \
    {                                                                         \
        printf("error=%d name=%s at "                                         \
               "ln: %d\n  ",err,hipGetErrorString(err),__LINE__);            \
        exit(EXIT_FAILURE);                                                  \
    }                                                                         \
}

// ****************************************************************************
// Function: runBenchmark
//
// Purpose:
//   Measures the bandwidth of the bus connecting the host processor to the
//   OpenCL device.  This benchmark repeatedly transfers data chunks of various
//   sizes across the bus to the OpenCL device, and calculates the bandwidth.
//
//
// Arguments:
//
// Returns:  nothing
//
// Programmer: Jeremy Meredith
// Creation: September 08, 2009
//
// Modifications:
//    Jeremy Meredith, Wed Dec  1 17:05:27 EST 2010
//    Added calculation of latency estimate.
//    Ben Sander - moved to standalone test
//
// ****************************************************************************
void RunBenchmark_H2D(ResultDatabase &resultDB)
{
    // Sizes are in kb
    int nSizes  = 20;
    int sizes[20] = {1,2,4,8,16,32,64,128,256,512,1024,2048,4096,8192,16384,
		     32768,65536,131072,262144,524288};
    long long numMaxFloats = 1024 * (sizes[nSizes-1]) / 4;

    hipSetDevice(p_device);

    // Create some host memory pattern
    float *hostMem = NULL;
    if (p_pinned)
    {
        hipMallocHost((void**)&hostMem, sizeof(float) * numMaxFloats);
        while (hipGetLastError() != hipSuccess)
        {
 	    // drop the size and try again
	    if (p_verbose) std::cout << " - dropping size allocating pinned mem\n";
	    --nSizes;
	    if (nSizes < 1)
	    {
            std::cerr << "Error: Couldn't allocated any pinned buffer\n";
		return;
	    }
	    numMaxFloats = 1024 * (sizes[nSizes-1]) / 4;
            hipMallocHost((void**)&hostMem, sizeof(float) * numMaxFloats);
        }
    }
    else
    {
        hostMem = new float[numMaxFloats];
    }

    for (int i = 0; i < numMaxFloats; i++)
    {
        hostMem[i] = i % 77;
    }

    float *device;
    hipMalloc((void**)&device, sizeof(float) * numMaxFloats);
    while (hipGetLastError() != hipSuccess)
    {
	// drop the size and try again
	if (p_verbose) std::cout << " - dropping size allocating device mem\n";
	--nSizes;
	if (nSizes < 1)
	{
        std::cerr << "Error: Couldn't allocated any device buffer\n";
	    return;
	}
	numMaxFloats = 1024 * (sizes[nSizes-1]) / 4;
        hipMalloc((void**)&device, sizeof(float) * numMaxFloats);
    }

    hipEvent_t start, stop;
    hipEventCreate(&start);
    hipEventCreate(&stop);
    CHECK_HIP_ERROR();

    // Three passes, forward and backward both
    for (int pass = 0; pass < p_iterations; pass++)
    {
        // store the times temporarily to estimate latency
        //float times[nSizes];
        // Step through sizes forward on even passes and backward on odd
        for (int i = 0; i < nSizes; i++)
        {
            int sizeIndex;
            if ((pass % 2) == 0)
                sizeIndex = i;
            else
                sizeIndex = (nSizes - 1) - i;

            int nbytes = sizes[sizeIndex] * 1024;

            hipEventRecord(start, 0);
            hipMemcpy(device, hostMem, nbytes, hipMemcpyHostToDevice);
            hipEventRecord(stop, 0);
            hipEventSynchronize(stop);
            float t = 0;
            hipEventElapsedTime(&t, start, stop);
            //times[sizeIndex] = t;

            // Convert to GB/sec
            if (p_verbose)
            {
                std::cerr << "size " << sizes[sizeIndex] << "k took " << t <<
                        " ms\n";
            }

            double speed = (double(sizes[sizeIndex]) * 1024. / (1000*1000)) / t;
            char sizeStr[256];
            sprintf(sizeStr, "% 7dkB", sizes[sizeIndex]);
            resultDB.AddResult("DownloadSpeed", sizeStr, "GB/sec", speed);
            resultDB.AddResult("DownloadTime", sizeStr, "ms", t);
        }
    }

    // Cleanup
    hipFree((void*)device);
    CHECK_HIP_ERROR();
    if (p_pinned)
    {
        hipFreeHost((void*)hostMem);
        CHECK_HIP_ERROR();
    }
    else
    {
        delete[] hostMem;
    }
    hipEventDestroy(start);
    hipEventDestroy(stop);
}

void RunBenchmark_D2H(ResultDatabase &resultDB)
{

    // Sizes are in kb
    int nSizes  = 20;
    int sizes[20] = {1,2,4,8,16,32,64,128,256,512,1024,2048,4096,8192,16384,
		     32768,65536,131072,262144,524288};
    long long numMaxFloats = 1024 * (sizes[nSizes-1]) / 4;

    // Create some host memory pattern
    float *hostMem1;
    float *hostMem2;
    if (p_pinned)
    {
        hipMallocHost((void**)&hostMem1, sizeof(float)*numMaxFloats);
        hipError_t err1 = hipGetLastError();
        hipMallocHost((void**)&hostMem2, sizeof(float)*numMaxFloats);
        hipError_t err2 = hipGetLastError();
	while (err1 != hipSuccess || err2 != hipSuccess)
	{
	    // free the first buffer if only the second failed
	    if (err1 == hipSuccess)
	        hipFreeHost((void*)hostMem1);

	    // drop the size and try again
	    if (p_verbose) std::cout << " - dropping size allocating pinned mem\n";
	    --nSizes;
	    if (nSizes < 1)
	    {
            std::cerr << "Error: Couldn't allocated any pinned buffer\n";
		return;
	    }
	    numMaxFloats = 1024 * (sizes[nSizes-1]) / 4;
            hipMallocHost((void**)&hostMem1, sizeof(float)*numMaxFloats);
            err1 = hipGetLastError();
            hipMallocHost((void**)&hostMem2, sizeof(float)*numMaxFloats);
            err2 = hipGetLastError();
	}
   }
    else
    {
        hostMem1 = new float[numMaxFloats];
        hostMem2 = new float[numMaxFloats];
    }
    for (int i=0; i<numMaxFloats; i++)
        hostMem1[i] = i % 77;

    float *device;
    hipMalloc((void**)&device, sizeof(float) * numMaxFloats);
    while (hipGetLastError() != hipSuccess)
    {
	// drop the size and try again
	if (p_verbose) std::cout << " - dropping size allocating device mem\n";
	--nSizes;
	if (nSizes < 1)
	{
        std::cerr << "Error: Couldn't allocated any device buffer\n";
	    return;
	}
	numMaxFloats = 1024 * (sizes[nSizes-1]) / 4;
        hipMalloc((void**)&device, sizeof(float) * numMaxFloats);
    }

    hipMemcpy(device, hostMem1,
               numMaxFloats*sizeof(float), hipMemcpyHostToDevice);
    hipDeviceSynchronize();

    hipEvent_t start, stop;
    hipEventCreate(&start);
    hipEventCreate(&stop);
    CHECK_HIP_ERROR();

    // Three passes, forward and backward both
    for (int pass = 0; pass < p_iterations; pass++)
    {
        // store the times temporarily to estimate latency
        //float times[nSizes];
        // Step through sizes forward on even passes and backward on odd
        for (int i = 0; i < nSizes; i++)
        {
            int sizeIndex;
            if ((pass % 2) == 0)
                sizeIndex = i;
            else
                sizeIndex = (nSizes - 1) - i;

            int nbytes = sizes[sizeIndex] * 1024;

            hipEventRecord(start, 0);
            hipMemcpy(hostMem2, device,
                       nbytes, hipMemcpyDeviceToHost);
            hipEventRecord(stop, 0);
            hipEventSynchronize(stop);
            float t = 0;
            hipEventElapsedTime(&t, start, stop);
            //times[sizeIndex] = t;

            // Convert to GB/sec
            if (p_verbose)
            {
                std::cerr << "size " <<sizes[sizeIndex] << "k took " << t <<
                        " ms\n";
            }

            double speed = (double(sizes[sizeIndex]) * 1024. / (1000*1000)) / t;
            char sizeStr[256];
            sprintf(sizeStr, "% 7dkB", sizes[sizeIndex]);
            resultDB.AddResult("ReadbackSpeed", sizeStr, "GB/sec", speed);
            resultDB.AddResult("ReadbackTime", sizeStr, "ms", t);
        }
	//resultDB.AddResult("ReadbackLatencyEstimate", "1-2kb", "ms", times[0]-(times[1]-times[0])/1.);
	//resultDB.AddResult("ReadbackLatencyEstimate", "1-4kb", "ms", times[0]-(times[2]-times[0])/3.);
	//resultDB.AddResult("ReadbackLatencyEstimate", "2-4kb", "ms", times[1]-(times[2]-times[1])/1.);
    }

    // Cleanup
    hipFree((void*)device);
    CHECK_HIP_ERROR();
    if (p_pinned)
    {
        hipFreeHost((void*)hostMem1);
        CHECK_HIP_ERROR();
        hipFreeHost((void*)hostMem2);
        CHECK_HIP_ERROR();
    }
    else
    {
        delete[] hostMem1;
        delete[] hostMem2;
        hipEventDestroy(start);
	    hipEventDestroy(stop);
    }
}

#define failed(...) \
    printf ("error: ");\
    printf (__VA_ARGS__);\
    printf ("\n");\
    exit(EXIT_FAILURE);

int parseInt(const char *str, int *output)
{
    char *next;
    *output = strtol(str, &next, 0);
    return !strlen(next);
}

void help() {
};

int parseStandardArguments(int argc, char *argv[])
{
    for (int i = 1; i < argc; i++) {
        const char *arg = argv[i];

        if (!strcmp(arg, " ")) {
            // skip NULL args.
        } else if (!strcmp(arg, "--iterations") || (!strcmp(arg, "-i"))) {
            if (++i >= argc || !parseInt(argv[i], &p_iterations)) {
               failed("Bad iterations argument");
            }
        } else if (!strcmp(arg, "--device") || (!strcmp(arg, "-d"))) {
            if (++i >= argc || !parseInt(argv[i], &p_device)) {
               failed("Bad device argument");
            }
        } else if (!strcmp(arg, "--unpinned")) {
            p_pinned = 0;
        } else if (!strcmp(arg, "--h2d")) {
            p_h2d = true;
            p_d2h = false;

        } else if (!strcmp(arg, "--d2h")) {
            p_h2d = false;
            p_d2h = true;

        } else if (!strcmp(arg, "--help")  || (!strcmp(arg, "-h"))) {
            help();

        } else if (!strcmp(arg, "--verbose")) {
            p_verbose = 1;
        } else if (!strcmp(arg, "--detailed")) {
            p_detailed = 1;
        } else {
            failed("Bad argument '%s'", arg);
        }
    }

    return 0;
};

int main(int argc, char *argv[])
{
    parseStandardArguments(argc, argv);

    if (p_h2d) {
        ResultDatabase resultDB;
        RunBenchmark_H2D(resultDB);

        resultDB.DumpSummary(std::cout);

        if (p_detailed) {
            resultDB.DumpDetailed(std::cout);
        }
    }

    if (p_d2h) {
        ResultDatabase resultDB;
        RunBenchmark_D2H(resultDB);

        resultDB.DumpSummary(std::cout);

        if (p_detailed) {
            resultDB.DumpDetailed(std::cout);
        }
    }
}
<commit_msg>Add D2H test<commit_after>#include <stdio.h>
#include <iostream>
#include <hip_runtime.h>

#include "ResultDatabase.h"

// Cmdline parms:
bool          p_verbose = false;
bool          p_pinned  = true;
int           p_iterations   = 10;
int           p_device  = 0;
int           p_detailed  = 0;

bool          p_h2d = true;
bool          p_d2h = true;

#define CHECK_HIP_ERROR()                                                    \
{                                                                             \
    hipError_t err = hipGetLastError();                                     \
    if (err != hipSuccess)                                                   \
    {                                                                         \
        printf("error=%d name=%s at "                                         \
               "ln: %d\n  ",err,hipGetErrorString(err),__LINE__);            \
        exit(EXIT_FAILURE);                                                  \
    }                                                                         \
}

// ****************************************************************************
// Function: runBenchmark
//
// Purpose:
//   Measures the bandwidth of the bus connecting the host processor to the
//   OpenCL device.  This benchmark repeatedly transfers data chunks of various
//   sizes across the bus to the OpenCL device, and calculates the bandwidth.
//
//
// Arguments:
//
// Returns:  nothing
//
// Programmer: Jeremy Meredith
// Creation: September 08, 2009
//
// Modifications:
//    Jeremy Meredith, Wed Dec  1 17:05:27 EST 2010
//    Added calculation of latency estimate.
//    Ben Sander - moved to standalone test
//
// ****************************************************************************
void RunBenchmark_H2D(ResultDatabase &resultDB)
{
    // Sizes are in kb
    int nSizes  = 20;
    int sizes[20] = {1,2,4,8,16,32,64,128,256,512,1024,2048,4096,8192,16384,
		     32768,65536,131072,262144,524288};
    long long numMaxFloats = 1024 * (sizes[nSizes-1]) / 4;

    hipSetDevice(p_device);

    // Create some host memory pattern
    float *hostMem = NULL;
    if (p_pinned)
    {
        hipMallocHost((void**)&hostMem, sizeof(float) * numMaxFloats);
        while (hipGetLastError() != hipSuccess)
        {
 	    // drop the size and try again
	    if (p_verbose) std::cout << " - dropping size allocating pinned mem\n";
	    --nSizes;
	    if (nSizes < 1)
	    {
            std::cerr << "Error: Couldn't allocated any pinned buffer\n";
		return;
	    }
	    numMaxFloats = 1024 * (sizes[nSizes-1]) / 4;
            hipMallocHost((void**)&hostMem, sizeof(float) * numMaxFloats);
        }
    }
    else
    {
        hostMem = new float[numMaxFloats];
    }

    for (int i = 0; i < numMaxFloats; i++)
    {
        hostMem[i] = i % 77;
    }

    float *device;
    hipMalloc((void**)&device, sizeof(float) * numMaxFloats);
    while (hipGetLastError() != hipSuccess)
    {
	// drop the size and try again
	if (p_verbose) std::cout << " - dropping size allocating device mem\n";
	--nSizes;
	if (nSizes < 1)
	{
        std::cerr << "Error: Couldn't allocated any device buffer\n";
	    return;
	}
	numMaxFloats = 1024 * (sizes[nSizes-1]) / 4;
        hipMalloc((void**)&device, sizeof(float) * numMaxFloats);
    }

    hipEvent_t start, stop;
    hipEventCreate(&start);
    hipEventCreate(&stop);
    CHECK_HIP_ERROR();

    // Three passes, forward and backward both
    for (int pass = 0; pass < p_iterations; pass++)
    {
        // store the times temporarily to estimate latency
        //float times[nSizes];
        // Step through sizes forward on even passes and backward on odd
        for (int i = 0; i < nSizes; i++)
        {
            int sizeIndex;
            if ((pass % 2) == 0)
                sizeIndex = i;
            else
                sizeIndex = (nSizes - 1) - i;

            int nbytes = sizes[sizeIndex] * 1024;

            hipEventRecord(start, 0);
            hipMemcpy(device, hostMem, nbytes, hipMemcpyHostToDevice);
            hipEventRecord(stop, 0);
            hipEventSynchronize(stop);
            float t = 0;
            hipEventElapsedTime(&t, start, stop);
            //times[sizeIndex] = t;

            // Convert to GB/sec
            if (p_verbose)
            {
                std::cerr << "size " << sizes[sizeIndex] << "k took " << t <<
                        " ms\n";
            }

            double speed = (double(sizes[sizeIndex]) * 1024. / (1000*1000)) / t;
            char sizeStr[256];
            sprintf(sizeStr, "% 7dkB", sizes[sizeIndex]);
            resultDB.AddResult("H2D_Bandwidth", sizeStr, "GB/sec", speed);
            resultDB.AddResult("H2D_Time", sizeStr, "ms", t);
        }
    }

    // Cleanup
    hipFree((void*)device);
    CHECK_HIP_ERROR();
    if (p_pinned)
    {
        hipFreeHost((void*)hostMem);
        CHECK_HIP_ERROR();
    }
    else
    {
        delete[] hostMem;
    }
    hipEventDestroy(start);
    hipEventDestroy(stop);
}

void RunBenchmark_D2H(ResultDatabase &resultDB)
{

    // Sizes are in kb
    int nSizes  = 20;
    int sizes[20] = {1,2,4,8,16,32,64,128,256,512,1024,2048,4096,8192,16384,
		     32768,65536,131072,262144,524288};
    long long numMaxFloats = 1024 * (sizes[nSizes-1]) / 4;

    // Create some host memory pattern
    float *hostMem1;
    float *hostMem2;
    if (p_pinned)
    {
        hipMallocHost((void**)&hostMem1, sizeof(float)*numMaxFloats);
        hipError_t err1 = hipGetLastError();
        hipMallocHost((void**)&hostMem2, sizeof(float)*numMaxFloats);
        hipError_t err2 = hipGetLastError();
	while (err1 != hipSuccess || err2 != hipSuccess)
	{
	    // free the first buffer if only the second failed
	    if (err1 == hipSuccess)
	        hipFreeHost((void*)hostMem1);

	    // drop the size and try again
	    if (p_verbose) std::cout << " - dropping size allocating pinned mem\n";
	    --nSizes;
	    if (nSizes < 1)
	    {
            std::cerr << "Error: Couldn't allocated any pinned buffer\n";
		return;
	    }
	    numMaxFloats = 1024 * (sizes[nSizes-1]) / 4;
            hipMallocHost((void**)&hostMem1, sizeof(float)*numMaxFloats);
            err1 = hipGetLastError();
            hipMallocHost((void**)&hostMem2, sizeof(float)*numMaxFloats);
            err2 = hipGetLastError();
	}
   }
    else
    {
        hostMem1 = new float[numMaxFloats];
        hostMem2 = new float[numMaxFloats];
    }
    for (int i=0; i<numMaxFloats; i++)
        hostMem1[i] = i % 77;

    float *device;
    hipMalloc((void**)&device, sizeof(float) * numMaxFloats);
    while (hipGetLastError() != hipSuccess)
    {
	// drop the size and try again
	if (p_verbose) std::cout << " - dropping size allocating device mem\n";
	--nSizes;
	if (nSizes < 1)
	{
        std::cerr << "Error: Couldn't allocated any device buffer\n";
	    return;
	}
	numMaxFloats = 1024 * (sizes[nSizes-1]) / 4;
        hipMalloc((void**)&device, sizeof(float) * numMaxFloats);
    }

    hipMemcpy(device, hostMem1,
               numMaxFloats*sizeof(float), hipMemcpyHostToDevice);
    hipDeviceSynchronize();

    hipEvent_t start, stop;
    hipEventCreate(&start);
    hipEventCreate(&stop);
    CHECK_HIP_ERROR();

    // Three passes, forward and backward both
    for (int pass = 0; pass < p_iterations; pass++)
    {
        // store the times temporarily to estimate latency
        //float times[nSizes];
        // Step through sizes forward on even passes and backward on odd
        for (int i = 0; i < nSizes; i++)
        {
            int sizeIndex;
            if ((pass % 2) == 0)
                sizeIndex = i;
            else
                sizeIndex = (nSizes - 1) - i;

            int nbytes = sizes[sizeIndex] * 1024;

            hipEventRecord(start, 0);
            hipMemcpy(hostMem2, device,
                       nbytes, hipMemcpyDeviceToHost);
            hipEventRecord(stop, 0);
            hipEventSynchronize(stop);
            float t = 0;
            hipEventElapsedTime(&t, start, stop);
            //times[sizeIndex] = t;

            // Convert to GB/sec
            if (p_verbose)
            {
                std::cerr << "size " <<sizes[sizeIndex] << "k took " << t <<
                        " ms\n";
            }

            double speed = (double(sizes[sizeIndex]) * 1024. / (1000*1000)) / t;
            char sizeStr[256];
            sprintf(sizeStr, "% 7dkB", sizes[sizeIndex]);
            resultDB.AddResult("D2H_Bandwidth", sizeStr, "GB/sec", speed);
            resultDB.AddResult("D2H_Time", sizeStr, "ms", t);
        }
	//resultDB.AddResult("ReadbackLatencyEstimate", "1-2kb", "ms", times[0]-(times[1]-times[0])/1.);
	//resultDB.AddResult("ReadbackLatencyEstimate", "1-4kb", "ms", times[0]-(times[2]-times[0])/3.);
	//resultDB.AddResult("ReadbackLatencyEstimate", "2-4kb", "ms", times[1]-(times[2]-times[1])/1.);
    }

    // Cleanup
    hipFree((void*)device);
    CHECK_HIP_ERROR();
    if (p_pinned)
    {
        hipFreeHost((void*)hostMem1);
        CHECK_HIP_ERROR();
        hipFreeHost((void*)hostMem2);
        CHECK_HIP_ERROR();
    }
    else
    {
        delete[] hostMem1;
        delete[] hostMem2;
        hipEventDestroy(start);
	    hipEventDestroy(stop);
    }
}

#define failed(...) \
    printf ("error: ");\
    printf (__VA_ARGS__);\
    printf ("\n");\
    exit(EXIT_FAILURE);

int parseInt(const char *str, int *output)
{
    char *next;
    *output = strtol(str, &next, 0);
    return !strlen(next);
}

void help() {
};

int parseStandardArguments(int argc, char *argv[])
{
    for (int i = 1; i < argc; i++) {
        const char *arg = argv[i];

        if (!strcmp(arg, " ")) {
            // skip NULL args.
        } else if (!strcmp(arg, "--iterations") || (!strcmp(arg, "-i"))) {
            if (++i >= argc || !parseInt(argv[i], &p_iterations)) {
               failed("Bad iterations argument");
            }
        } else if (!strcmp(arg, "--device") || (!strcmp(arg, "-d"))) {
            if (++i >= argc || !parseInt(argv[i], &p_device)) {
               failed("Bad device argument");
            }
        } else if (!strcmp(arg, "--unpinned")) {
            p_pinned = 0;
        } else if (!strcmp(arg, "--h2d")) {
            p_h2d = true;
            p_d2h = false;

        } else if (!strcmp(arg, "--d2h")) {
            p_h2d = false;
            p_d2h = true;

        } else if (!strcmp(arg, "--help")  || (!strcmp(arg, "-h"))) {
            help();

        } else if (!strcmp(arg, "--verbose")) {
            p_verbose = 1;
        } else if (!strcmp(arg, "--detailed")) {
            p_detailed = 1;
        } else {
            failed("Bad argument '%s'", arg);
        }
    }

    return 0;
};

int main(int argc, char *argv[])
{
    parseStandardArguments(argc, argv);

    if (p_h2d) {
        ResultDatabase resultDB;
        RunBenchmark_H2D(resultDB);

        resultDB.DumpSummary(std::cout);

        if (p_detailed) {
            resultDB.DumpDetailed(std::cout);
        }
    }

    if (p_d2h) {
        ResultDatabase resultDB;
        RunBenchmark_D2H(resultDB);

        resultDB.DumpSummary(std::cout);

        if (p_detailed) {
            resultDB.DumpDetailed(std::cout);
        }
    }
}
<|endoftext|>