<commit_before>#include "allocator.h"

#include <cstring>

namespace nvds {

void Allocator::Format() {
  ModificationList modifications;
  set_modifications(&modifications);

  memset(flm_, 0, kSize);
  uint32_t blk = sizeof(FreeListManager);
  Write(GetLastFreeList(), blk);

  // 'The block before first block' is not free
  // The last 4 bytes is kept for the free tag
  uint32_t blk_size = (kSize - blk - sizeof(uint32_t)) &
                      ~static_cast<uint32_t>(0x0f);
  Write(blk, blk_size & ~BlockHeader::kFreeMask);
  Write(blk + blk_size - sizeof(uint32_t), blk_size);
  SetTheFreeTag(blk, blk_size);
  // TODO(wgtdkp): setting `next` and `prev` nullptr(unnecessary if called `memset`)p
}

uint32_t Allocator::AllocBlock(uint32_t blk_size) {
  auto free_list = GetFreeListByBlockSize(blk_size);
  uint32_t head;
  while (free_list < kNumFreeLists * sizeof(uint32_t) &&
         (head = Read<uint32_t>(free_list)) == 0) {
    free_list += sizeof(uint32_t);
  }
  if (head == 0) {
    return 0;
  }
  auto head_size = ReadTheSizeTag(head);
  assert(ReadTheFreeTag(head, head_size) != 0);
  assert(head_size >= blk_size);
  if (head_size == blk_size) {
    auto next_blk = Read<uint32_t>(head + offsetof(BlockHeader, next));
    ResetTheFreeTag(head, head_size);
    Write(free_list, next_blk);
    Write(next_blk + offsetof(BlockHeader, prev),
          static_cast<uint32_t>(0));
    return head;
  }
  return SplitBlock(head, head_size, blk_size);
}

void Allocator::FreeBlock(uint32_t blk) {
  auto blk_size      = ReadTheSizeTag(blk);
  auto blk_size_old  = blk_size;
  auto prev_blk_size = Read<uint32_t>(blk - sizeof(uint32_t));
  auto prev_blk      = blk - prev_blk_size;
  auto next_blk      = blk + blk_size;
  auto next_blk_size = ReadTheSizeTag(next_blk);

  if (ReadThePrevFreeTag(blk) &&
      blk_size <= kMaxBlockSize &&
      prev_blk_size <= kMaxBlockSize) {
    RemoveBlock(prev_blk, prev_blk_size);
    blk = prev_blk;
    blk_size += prev_blk_size;
  }
  if (ReadTheFreeTag(next_blk, next_blk_size) &&
      blk_size <= kMaxBlockSize &&
      next_blk_size <= kMaxBlockSize) {
    RemoveBlock(next_blk, next_blk_size);
    blk_size += next_blk_size;
  }

  // If the blk_size changed, write it.
  if (blk_size != blk_size_old) {
    Write(blk, ReadThePrevFreeTag(blk) | blk_size);
    Write(blk + blk_size - sizeof(uint32_t), blk_size);
  }
  SetTheFreeTag(blk, blk_size);

  auto free_list = GetFreeListByBlockSize(blk_size);
  auto head = Read<uint32_t>(free_list);
  Write(free_list, blk);
  Write(blk + offsetof(BlockHeader, prev), static_cast<uint32_t>(0));
  Write(blk + offsetof(BlockHeader, next), head);
  if (head != 0) {
    Write(head + offsetof(BlockHeader, prev), blk);
  }
}

void Allocator::RemoveBlock(uint32_t blk, uint32_t blk_size) {
  assert(ReadTheFreeTag(blk, blk_size) != 0);
  auto prev_blk = Read<uint32_t>(blk + offsetof(BlockHeader, prev));
  auto next_blk = Read<uint32_t>(blk + offsetof(BlockHeader, next));
  if (prev_blk != 0) {
    Write(prev_blk + offsetof(BlockHeader, next),
          Read<uint32_t>(blk + offsetof(BlockHeader, next)));
  } else {
    auto free_list = GetFreeListByBlockSize(blk_size);
    Write(free_list, Read<uint32_t>(blk + offsetof(BlockHeader, next)));
  }
  if (next_blk != 0) {
    Write(next_blk + offsetof(BlockHeader, prev),
          Read<uint32_t>(blk + offsetof(BlockHeader, prev)));
  }
}

uint32_t Allocator::SplitBlock(uint32_t blk, uint32_t blk_size,
                               uint32_t needed_size) {
  auto next_blk  = Read<uint32_t>(blk + offsetof(BlockHeader, next));
  auto free_list = GetFreeListByBlockSize(blk_size);
  assert(blk_size > needed_size);
  auto new_size  = blk_size - needed_size;

  Write(free_list, next_blk);
  if (next_blk != 0) {
    Write(next_blk + offsetof(BlockHeader, prev), static_cast<uint32_t>(0));
  }

  // Update size
  Write(blk, ReadThePrevFreeTag(blk) | new_size);
  Write(blk + new_size - sizeof(uint32_t), new_size);

  free_list = GetFreeListByBlockSize(new_size);
  auto head = Read<uint32_t>(free_list);
  Write(blk + offsetof(BlockHeader, prev), static_cast<uint32_t>(0));
  Write(blk + offsetof(BlockHeader, next), head);
  Write(free_list, blk);
  if (head != 0) {
    Write(head + offsetof(BlockHeader, prev), blk);
  }

  // The rest smaller block is still free
  Write(blk + new_size, BlockHeader::kFreeMask | needed_size);
  Write(blk + blk_size - sizeof(uint32_t), needed_size);

  // Piece splitted is not free now.
  ResetTheFreeTag(blk + new_size, needed_size);
  return blk + new_size;
}

} // namespace nvds
<commit_msg>fix typo in comment<commit_after>#include "allocator.h"

#include <cstring>

namespace nvds {

void Allocator::Format() {
  ModificationList modifications;
  set_modifications(&modifications);

  memset(flm_, 0, kSize);
  uint32_t blk = sizeof(FreeListManager);
  Write(GetLastFreeList(), blk);

  // 'The block before first block' is not free
  // The last 4 bytes is kept for the free tag
  uint32_t blk_size = (kSize - blk - sizeof(uint32_t)) &
                      ~static_cast<uint32_t>(0x0f);
  Write(blk, blk_size & ~BlockHeader::kFreeMask);
  Write(blk + blk_size - sizeof(uint32_t), blk_size);
  SetTheFreeTag(blk, blk_size);
  // TODO(wgtdkp): setting `next` and `prev` nullptr.(unnecessary if called `memset`)
}

uint32_t Allocator::AllocBlock(uint32_t blk_size) {
  auto free_list = GetFreeListByBlockSize(blk_size);
  uint32_t head;
  while (free_list < kNumFreeLists * sizeof(uint32_t) &&
         (head = Read<uint32_t>(free_list)) == 0) {
    free_list += sizeof(uint32_t);
  }
  if (head == 0) {
    return 0;
  }
  auto head_size = ReadTheSizeTag(head);
  assert(ReadTheFreeTag(head, head_size) != 0);
  assert(head_size >= blk_size);
  if (head_size == blk_size) {
    auto next_blk = Read<uint32_t>(head + offsetof(BlockHeader, next));
    ResetTheFreeTag(head, head_size);
    Write(free_list, next_blk);
    Write(next_blk + offsetof(BlockHeader, prev),
          static_cast<uint32_t>(0));
    return head;
  }
  return SplitBlock(head, head_size, blk_size);
}

void Allocator::FreeBlock(uint32_t blk) {
  auto blk_size      = ReadTheSizeTag(blk);
  auto blk_size_old  = blk_size;
  auto prev_blk_size = Read<uint32_t>(blk - sizeof(uint32_t));
  auto prev_blk      = blk - prev_blk_size;
  auto next_blk      = blk + blk_size;
  auto next_blk_size = ReadTheSizeTag(next_blk);

  if (ReadThePrevFreeTag(blk) &&
      blk_size <= kMaxBlockSize &&
      prev_blk_size <= kMaxBlockSize) {
    RemoveBlock(prev_blk, prev_blk_size);
    blk = prev_blk;
    blk_size += prev_blk_size;
  }
  if (ReadTheFreeTag(next_blk, next_blk_size) &&
      blk_size <= kMaxBlockSize &&
      next_blk_size <= kMaxBlockSize) {
    RemoveBlock(next_blk, next_blk_size);
    blk_size += next_blk_size;
  }

  // If the blk_size changed, write it.
  if (blk_size != blk_size_old) {
    Write(blk, ReadThePrevFreeTag(blk) | blk_size);
    Write(blk + blk_size - sizeof(uint32_t), blk_size);
  }
  SetTheFreeTag(blk, blk_size);

  auto free_list = GetFreeListByBlockSize(blk_size);
  auto head = Read<uint32_t>(free_list);
  Write(free_list, blk);
  Write(blk + offsetof(BlockHeader, prev), static_cast<uint32_t>(0));
  Write(blk + offsetof(BlockHeader, next), head);
  if (head != 0) {
    Write(head + offsetof(BlockHeader, prev), blk);
  }
}

void Allocator::RemoveBlock(uint32_t blk, uint32_t blk_size) {
  assert(ReadTheFreeTag(blk, blk_size) != 0);
  auto prev_blk = Read<uint32_t>(blk + offsetof(BlockHeader, prev));
  auto next_blk = Read<uint32_t>(blk + offsetof(BlockHeader, next));
  if (prev_blk != 0) {
    Write(prev_blk + offsetof(BlockHeader, next),
          Read<uint32_t>(blk + offsetof(BlockHeader, next)));
  } else {
    auto free_list = GetFreeListByBlockSize(blk_size);
    Write(free_list, Read<uint32_t>(blk + offsetof(BlockHeader, next)));
  }
  if (next_blk != 0) {
    Write(next_blk + offsetof(BlockHeader, prev),
          Read<uint32_t>(blk + offsetof(BlockHeader, prev)));
  }
}

uint32_t Allocator::SplitBlock(uint32_t blk, uint32_t blk_size,
                               uint32_t needed_size) {
  auto next_blk  = Read<uint32_t>(blk + offsetof(BlockHeader, next));
  auto free_list = GetFreeListByBlockSize(blk_size);
  assert(blk_size > needed_size);
  auto new_size  = blk_size - needed_size;

  Write(free_list, next_blk);
  if (next_blk != 0) {
    Write(next_blk + offsetof(BlockHeader, prev), static_cast<uint32_t>(0));
  }

  // Update size
  Write(blk, ReadThePrevFreeTag(blk) | new_size);
  Write(blk + new_size - sizeof(uint32_t), new_size);

  free_list = GetFreeListByBlockSize(new_size);
  auto head = Read<uint32_t>(free_list);
  Write(blk + offsetof(BlockHeader, prev), static_cast<uint32_t>(0));
  Write(blk + offsetof(BlockHeader, next), head);
  Write(free_list, blk);
  if (head != 0) {
    Write(head + offsetof(BlockHeader, prev), blk);
  }

  // The rest smaller block is still free
  Write(blk + new_size, BlockHeader::kFreeMask | needed_size);
  Write(blk + blk_size - sizeof(uint32_t), needed_size);

  // Piece splitted is not free now.
  ResetTheFreeTag(blk + new_size, needed_size);
  return blk + new_size;
}

} // namespace nvds
<|endoftext|>


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

#ifndef CRIMILD_
#define CRIMILD_

#include "Animation/Animation.hpp"
#include "Animation/ChannelImpl.hpp"
#include "Animation/Clip.hpp"
#include "Animation/Skeleton.hpp"
#include "Audio/AudioListener.hpp"
#include "Audio/AudioSource.hpp"
#include "Behaviors/Actions/AnimateContextValue.hpp"
#include "Behaviors/Actions/AnimateParticleSystem.hpp"
#include "Behaviors/Actions/AnimateSettingValue.hpp"
#include "Behaviors/Actions/ClearTargets.hpp"
#include "Behaviors/Actions/CopyTransformFromTarget.hpp"
#include "Behaviors/Actions/EnableNode.hpp"
#include "Behaviors/Actions/ExecuteBehavior.hpp"
#include "Behaviors/Actions/ExecuteBehaviorOnTarget.hpp"
#include "Behaviors/Actions/FindTarget.hpp"
#include "Behaviors/Actions/LoadScene.hpp"
#include "Behaviors/Actions/LookAt.hpp"
#include "Behaviors/Actions/MotionApply.hpp"
#include "Behaviors/Actions/MotionAvoidOthers.hpp"
#include "Behaviors/Actions/MotionAvoidWalls.hpp"
#include "Behaviors/Actions/MotionComputePathToTarget.hpp"
#include "Behaviors/Actions/MotionReset.hpp"
#include "Behaviors/Actions/MotionSeek.hpp"
#include "Behaviors/Actions/PrintMessage.hpp"
#include "Behaviors/Actions/ResetNavigation.hpp"
#include "Behaviors/Actions/Rotate.hpp"
#include "Behaviors/Actions/SetContextValue.hpp"
#include "Behaviors/Actions/SetSettingValue.hpp"
#include "Behaviors/Actions/Success.hpp"
#include "Behaviors/Actions/Transform.hpp"
#include "Behaviors/Actions/Trigger.hpp"
#include "Behaviors/Actions/Wait.hpp"
#include "Behaviors/Behavior.hpp"
#include "Behaviors/BehaviorContext.hpp"
#include "Behaviors/BehaviorController.hpp"
#include "Behaviors/BehaviorTree.hpp"
#include "Behaviors/Composites/Composite.hpp"
#include "Behaviors/Composites/Parallel.hpp"
#include "Behaviors/Composites/Selector.hpp"
#include "Behaviors/Composites/Sequence.hpp"
#include "Behaviors/Conditions/DistanceToTarget.hpp"
#include "Behaviors/Conditions/HasTargets.hpp"
#include "Behaviors/Conditions/IsAtTarget.hpp"
#include "Behaviors/Conditions/TestContextValue.hpp"
#include "Behaviors/Conditions/TestInputAxis.hpp"
#include "Behaviors/Conditions/TestSettingValue.hpp"
#include "Behaviors/Decorators/Decorator.hpp"
#include "Behaviors/Decorators/Inverter.hpp"
#include "Behaviors/Decorators/Repeat.hpp"
#include "Behaviors/Decorators/RepeatUntilFail.hpp"
#include "Behaviors/Decorators/RepeatUntilSuccess.hpp"
#include "Behaviors/Decorators/Succeeder.hpp"
#include "Behaviors/Decorators/Throttle.hpp"
#include "Behaviors/withBehavior.hpp"
#include "Boundings/AABBBoundingVolume.hpp"
#include "Boundings/BoundingVolume.hpp"
#include "Boundings/PlaneBoundingVolume.hpp"
#include "Boundings/SphereBoundingVolume.hpp"
#include "Coding/Codable.hpp"
#include "Coding/Decoder.hpp"
#include "Coding/EncodedData.hpp"
#include "Coding/Encoder.hpp"
#include "Coding/FileDecoder.hpp"
#include "Coding/FileEncoder.hpp"
#include "Coding/MemoryDecoder.hpp"
#include "Coding/MemoryEncoder.hpp"
#include "Coding/Tags.hpp"
#include "Components/AnimatorComponent.hpp"
#include "Components/AudioListenerComponent.hpp"
#include "Components/AudioSourceComponent.hpp"
#include "Components/BillboardComponent.hpp"
#include "Components/FreeLookCameraComponent.hpp"
#include "Components/LambdaComponent.hpp"
#include "Components/MaterialComponent.hpp"
#include "Components/NodeComponent.hpp"
#include "Components/NodeComponentCatalog.hpp"
#include "Components/OrbitComponent.hpp"
#include "Components/RenderStateComponent.hpp"
#include "Components/RotationComponent.hpp"
#include "Components/SingleValueComponent.hpp"
#include "Components/SkinnedMeshComponent.hpp"
#include "Components/TimerComponent.hpp"
#include "Components/UIResponder.hpp"
#include "Concurrency/Async.hpp"
#include "Concurrency/Job.hpp"
#include "Concurrency/JobScheduler.hpp"
#include "Concurrency/WorkStealingDeque.hpp"
#include "Debug/DebugRenderComponent.hpp"
#include "Debug/DebugRenderHelper.hpp"
#include "Debug/SceneDebugDump.hpp"
#include "Exceptions/Exception.hpp"
#include "Exceptions/FileNotFoundException.hpp"
#include "Exceptions/HasParentException.hpp"
#include "Exceptions/RuntimeException.hpp"
#include "Foundation/Containers/Array.hpp"
#include "Foundation/Containers/Map.hpp"
#include "Foundation/Containers/PriorityQueue.hpp"
#include "Foundation/Containers/Queue.hpp"
#include "Foundation/Containers/Stack.hpp"
#include "Foundation/FilePath.hpp"
#include "Foundation/Log.hpp"
#include "Foundation/Macros.hpp"
#include "Foundation/Memory.hpp"
#include "Foundation/NamedObject.hpp"
#include "Foundation/ObjectFactory.hpp"
#include "Foundation/Policies/ThreadingPolicy.hpp"
#include "Foundation/Profiler.hpp"
#include "Foundation/SharedObject.hpp"
#include "Foundation/Singleton.hpp"
#include "Foundation/StringUtils.hpp"
#include "Foundation/Version.hpp"
#include "Loaders/OBJLoader.hpp"
#include "Mathematics/Clock.hpp"
#include "Mathematics/ColorRGB.hpp"
#include "Mathematics/ColorRGBA.hpp"
#include "Mathematics/ColorRGBAOps.hpp"
#include "Mathematics/ColorRGBOps.hpp"
#include "Mathematics/Frustum.hpp"
#include "Mathematics/Interpolation.hpp"
#include "Mathematics/Intersection.hpp"
#include "Mathematics/Matrix3.hpp"
#include "Mathematics/Matrix3_equality.hpp"
#include "Mathematics/Matrix4.hpp"
#include "Mathematics/Matrix4_equality.hpp"
#include "Mathematics/Numeric.hpp"
#include "Mathematics/Plane3.hpp"
#include "Mathematics/Quaternion.hpp"
#include "Mathematics/Random.hpp"
#include "Mathematics/Ray3.hpp"
#include "Mathematics/Rect.hpp"
#include "Mathematics/Root.hpp"
#include "Mathematics/Series.hpp"
#include "Mathematics/Sphere.hpp"
#include "Mathematics/Transformation.hpp"
#include "Mathematics/Transformation_apply.hpp"
#include "Mathematics/Transformation_inverse.hpp"
#include "Mathematics/Transformation_lookAt.hpp"
#include "Mathematics/Transformation_operators.hpp"
#include "Mathematics/Transformation_rotation.hpp"
#include "Mathematics/Transformation_scale.hpp"
#include "Mathematics/Transformation_translation.hpp"
#include "Mathematics/Vector2.hpp"
#include "Mathematics/Vector2Ops.hpp"
#include "Mathematics/Vector3.hpp"
#include "Mathematics/Vector3Ops.hpp"
#include "Mathematics/Vector4.hpp"
#include "Mathematics/Vector_equality.hpp"
#include "Mathematics/io.hpp"
#include "Mathematics/ortho.hpp"
#include "Mathematics/perspective.hpp"
#include "Mathematics/trigonometry.hpp"
#include "Messaging/MessageQueue.hpp"
#include "Navigation/NavigationCell.hpp"
#include "Navigation/NavigationCellEdge.hpp"
#include "Navigation/NavigationController.hpp"
#include "Navigation/NavigationMesh.hpp"
#include "Navigation/NavigationMeshContainer.hpp"
#include "Navigation/NavigationMeshOBJ.hpp"
#include "ParticleSystem/Generators/AccelerationParticleGenerator.hpp"
#include "ParticleSystem/Generators/BoxPositionParticleGenerator.hpp"
#include "ParticleSystem/Generators/ColorParticleGenerator.hpp"
#include "ParticleSystem/Generators/DefaultValueParticleGenerator.hpp"
#include "ParticleSystem/Generators/EulerAnglesParticleGenerator.hpp"
#include "ParticleSystem/Generators/GridPositionParticleGenerator.hpp"
#include "ParticleSystem/Generators/NodePositionParticleGenerator.hpp"
#include "ParticleSystem/Generators/OrbitPositionParticleGenerator.hpp"
#include "ParticleSystem/Generators/RandomValueParticleGenerator.hpp"
#include "ParticleSystem/Generators/SpherePositionParticleGenerator.hpp"
#include "ParticleSystem/Generators/SphereVelocityParticleGenerator.hpp"
#include "ParticleSystem/Generators/TimeParticleGenerator.hpp"
#include "ParticleSystem/Generators/UniformScaleParticleGenerator.hpp"
#include "ParticleSystem/Generators/VelocityParticleGenerator.hpp"
#include "ParticleSystem/ParticleData.hpp"
#include "ParticleSystem/ParticleSystemComponent.hpp"
#include "ParticleSystem/Renderers/AnimatedSpriteParticleRenderer.hpp"
#include "ParticleSystem/Renderers/InstancedParticleRenderer.hpp"
#include "ParticleSystem/Renderers/NodeParticleRenderer.hpp"
#include "ParticleSystem/Renderers/OrientedQuadParticleRenderer.hpp"
#include "ParticleSystem/Renderers/PointSpriteParticleRenderer.hpp"
#include "ParticleSystem/Updaters/AttractorParticleUpdater.hpp"
#include "ParticleSystem/Updaters/CameraSortParticleUpdater.hpp"
#include "ParticleSystem/Updaters/ColorParticleUpdater.hpp"
#include "ParticleSystem/Updaters/EulerParticleUpdater.hpp"
#include "ParticleSystem/Updaters/FloorParticleUpdater.hpp"
#include "ParticleSystem/Updaters/PositionVelocityParticleUpdater.hpp"
#include "ParticleSystem/Updaters/SetAttribValueParticleUpdater.hpp"
#include "ParticleSystem/Updaters/TimeParticleUpdater.hpp"
#include "ParticleSystem/Updaters/UniformScaleParticleUpdater.hpp"
#include "ParticleSystem/Updaters/ZSortParticleUpdater.hpp"
#include "Primitives/ArcPrimitive.hpp"
#include "Primitives/ArrowPrimitive.hpp"
#include "Primitives/BoxPrimitive.hpp"
#include "Primitives/ConePrimitive.hpp"
#include "Primitives/CylinderPrimitive.hpp"
#include "Primitives/KleinBottlePrimitive.hpp"
#include "Primitives/MobiusStripPrimitive.hpp"
#include "Primitives/NewellTeapotPrimitive.hpp"
#include "Primitives/ParametricPrimitive.hpp"
#include "Primitives/ParametricSpherePrimitive.hpp"
#include "Primitives/Primitive.hpp"
#include "Primitives/QuadPrimitive.hpp"
#include "Primitives/SpherePrimitive.hpp"
#include "Primitives/TorusPrimitive.hpp"
#include "Primitives/TrefoilKnotPrimitive.hpp"
#include "Rendering/Buffer.hpp"
#include "Rendering/Catalog.hpp"
#include "Rendering/ColorMaskState.hpp"
#include "Rendering/CommandBuffer.hpp"
#include "Rendering/ComputePass.hpp"
#include "Rendering/DescriptorSet.hpp"
#include "Rendering/Font.hpp"
#include "Rendering/Image.hpp"
#include "Rendering/ImageManager.hpp"
#include "Rendering/ImageTGA.hpp"
#include "Rendering/IndexBuffer.hpp"
#include "Rendering/Material.hpp"
#include "Rendering/Materials/LitMaterial.hpp"
#include "Rendering/Materials/PrincipledBSDFMaterial.hpp"
#include "Rendering/Materials/SkyboxMaterial.hpp"
#include "Rendering/Materials/UnlitMaterial.hpp"
#include "Rendering/Operations/OperationUtils.hpp"
#include "Rendering/Operations/Operations.hpp"
#include "Rendering/Operations/Operations_softRT.hpp"
#include "Rendering/Pipeline.hpp"
#include "Rendering/Programs/UnlitShaderProgram.hpp"
#include "Rendering/RenderPass.hpp"
#include "Rendering/RenderResource.hpp"
#include "Rendering/RenderState.hpp"
#include "Rendering/Renderer.hpp"
#include "Rendering/Sampler.hpp"
#include "Rendering/Shader.hpp"
#include "Rendering/ShaderLibrary.hpp"
#include "Rendering/ShaderLocation.hpp"
#include "Rendering/ShaderProgram.hpp"
#include "Rendering/ShaderProgramLibrary.hpp"
#include "Rendering/ShaderUniform.hpp"
#include "Rendering/ShaderUniformImpl.hpp"
#include "Rendering/ShadowMap.hpp"
#include "Rendering/SkinnedMesh.hpp"
#include "Rendering/Swapchain.hpp"
#include "Rendering/Texture.hpp"
#include "Rendering/UniformBuffer.hpp"
#include "Rendering/Uniforms/CallbackUniformBuffer.hpp"
#include "Rendering/Uniforms/CameraViewProjectionUniformBuffer.hpp"
#include "Rendering/Uniforms/LightingUniform.hpp"
#include "Rendering/Uniforms/ModelUniformBuffer.hpp"
#include "Rendering/Uniforms/ModelViewProjectionUniformBuffer.hpp"
#include "Rendering/VertexBuffer.hpp"
#include "SceneGraph/Camera.hpp"
#include "SceneGraph/Geometry.hpp"
#include "SceneGraph/Group.hpp"
#include "SceneGraph/Light.hpp"
#include "SceneGraph/Node.hpp"
#include "SceneGraph/Skybox.hpp"
#include "SceneGraph/Switch.hpp"
#include "SceneGraph/Text.hpp"
#include "Simulation/Console/Console.hpp"
#include "Simulation/FileSystem.hpp"
#include "Simulation/Input.hpp"
#include "Simulation/Simulation.hpp"
#include "Simulation/Systems/AudioSystem.hpp"
#include "Simulation/Systems/DebugSystem.hpp"
#include "Simulation/Systems/RenderSystem.hpp"
#include "Simulation/Systems/StreamingSystem.hpp"
#include "Simulation/Systems/UISystem.hpp"
#include "Simulation/Systems/UpdateSystem.hpp"
#include "UI/UIBackground.hpp"
#include "UI/UIButton.hpp"
#include "UI/UICanvas.hpp"
#include "UI/UIFrame.hpp"
#include "UI/UIFrameConstraint.hpp"
#include "UI/UIFrameConstraintMaker.hpp"
#include "UI/UILabel.hpp"
#include "Visitors/Apply.hpp"
#include "Visitors/ApplyToGeometries.hpp"
#include "Visitors/ComputeRenderQueue.hpp"
#include "Visitors/FetchCameras.hpp"
#include "Visitors/FetchLights.hpp"
#include "Visitors/NodeVisitor.hpp"
#include "Visitors/Picking.hpp"
#include "Visitors/SelectNodes.hpp"
#include "Visitors/ShallowCopy.hpp"
#include "Visitors/StartComponents.hpp"
#include "Visitors/UpdateComponents.hpp"
#include "Visitors/UpdateRenderState.hpp"
#include "Visitors/UpdateWorldState.hpp"

namespace crimild {

    void init( void );

}

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

#ifndef CRIMILD_
#define CRIMILD_

#include "Animation/Animation.hpp"
#include "Animation/ChannelImpl.hpp"
#include "Animation/Clip.hpp"
#include "Animation/Skeleton.hpp"
#include "Audio/AudioListener.hpp"
#include "Audio/AudioSource.hpp"
#include "Behaviors/Actions/AnimateContextValue.hpp"
#include "Behaviors/Actions/AnimateParticleSystem.hpp"
#include "Behaviors/Actions/AnimateSettingValue.hpp"
#include "Behaviors/Actions/ClearTargets.hpp"
#include "Behaviors/Actions/CopyTransformFromTarget.hpp"
#include "Behaviors/Actions/EnableNode.hpp"
#include "Behaviors/Actions/ExecuteBehavior.hpp"
#include "Behaviors/Actions/ExecuteBehaviorOnTarget.hpp"
#include "Behaviors/Actions/FindTarget.hpp"
#include "Behaviors/Actions/LoadScene.hpp"
#include "Behaviors/Actions/LookAt.hpp"
#include "Behaviors/Actions/MotionApply.hpp"
#include "Behaviors/Actions/MotionAvoidOthers.hpp"
#include "Behaviors/Actions/MotionAvoidWalls.hpp"
#include "Behaviors/Actions/MotionComputePathToTarget.hpp"
#include "Behaviors/Actions/MotionReset.hpp"
#include "Behaviors/Actions/MotionSeek.hpp"
#include "Behaviors/Actions/PrintMessage.hpp"
#include "Behaviors/Actions/ResetNavigation.hpp"
#include "Behaviors/Actions/Rotate.hpp"
#include "Behaviors/Actions/SetContextValue.hpp"
#include "Behaviors/Actions/SetSettingValue.hpp"
#include "Behaviors/Actions/Success.hpp"
#include "Behaviors/Actions/Transform.hpp"
#include "Behaviors/Actions/Trigger.hpp"
#include "Behaviors/Actions/Wait.hpp"
#include "Behaviors/Behavior.hpp"
#include "Behaviors/BehaviorContext.hpp"
#include "Behaviors/BehaviorController.hpp"
#include "Behaviors/BehaviorTree.hpp"
#include "Behaviors/Composites/Composite.hpp"
#include "Behaviors/Composites/Parallel.hpp"
#include "Behaviors/Composites/Selector.hpp"
#include "Behaviors/Composites/Sequence.hpp"
#include "Behaviors/Conditions/DistanceToTarget.hpp"
#include "Behaviors/Conditions/HasTargets.hpp"
#include "Behaviors/Conditions/IsAtTarget.hpp"
#include "Behaviors/Conditions/TestContextValue.hpp"
#include "Behaviors/Conditions/TestInputAxis.hpp"
#include "Behaviors/Conditions/TestSettingValue.hpp"
#include "Behaviors/Decorators/Decorator.hpp"
#include "Behaviors/Decorators/Inverter.hpp"
#include "Behaviors/Decorators/Repeat.hpp"
#include "Behaviors/Decorators/RepeatUntilFail.hpp"
#include "Behaviors/Decorators/RepeatUntilSuccess.hpp"
#include "Behaviors/Decorators/Succeeder.hpp"
#include "Behaviors/Decorators/Throttle.hpp"
#include "Behaviors/withBehavior.hpp"
#include "Boundings/AABBBoundingVolume.hpp"
#include "Boundings/BoundingVolume.hpp"
#include "Boundings/PlaneBoundingVolume.hpp"
#include "Boundings/SphereBoundingVolume.hpp"
#include "Coding/Codable.hpp"
#include "Coding/Decoder.hpp"
#include "Coding/EncodedData.hpp"
#include "Coding/Encoder.hpp"
#include "Coding/FileDecoder.hpp"
#include "Coding/FileEncoder.hpp"
#include "Coding/MemoryDecoder.hpp"
#include "Coding/MemoryEncoder.hpp"
#include "Coding/Tags.hpp"
#include "Components/AnimatorComponent.hpp"
#include "Components/AudioListenerComponent.hpp"
#include "Components/AudioSourceComponent.hpp"
#include "Components/BillboardComponent.hpp"
#include "Components/FreeLookCameraComponent.hpp"
#include "Components/LambdaComponent.hpp"
#include "Components/MaterialComponent.hpp"
#include "Components/NodeComponent.hpp"
#include "Components/NodeComponentCatalog.hpp"
#include "Components/OrbitComponent.hpp"
#include "Components/RenderStateComponent.hpp"
#include "Components/RotationComponent.hpp"
#include "Components/SingleValueComponent.hpp"
#include "Components/SkinnedMeshComponent.hpp"
#include "Components/TimerComponent.hpp"
#include "Components/UIResponder.hpp"
#include "Concurrency/Async.hpp"
#include "Concurrency/Job.hpp"
#include "Concurrency/JobScheduler.hpp"
#include "Concurrency/WorkStealingDeque.hpp"
#include "Debug/DebugRenderComponent.hpp"
#include "Debug/DebugRenderHelper.hpp"
#include "Debug/SceneDebugDump.hpp"
#include "Exceptions/Exception.hpp"
#include "Exceptions/FileNotFoundException.hpp"
#include "Exceptions/HasParentException.hpp"
#include "Exceptions/RuntimeException.hpp"
#include "Foundation/Containers/Array.hpp"
#include "Foundation/Containers/Map.hpp"
#include "Foundation/Containers/PriorityQueue.hpp"
#include "Foundation/Containers/Queue.hpp"
#include "Foundation/Containers/Stack.hpp"
#include "Foundation/FilePath.hpp"
#include "Foundation/Log.hpp"
#include "Foundation/Macros.hpp"
#include "Foundation/Memory.hpp"
#include "Foundation/NamedObject.hpp"
#include "Foundation/ObjectFactory.hpp"
#include "Foundation/Policies/ThreadingPolicy.hpp"
#include "Foundation/Profiler.hpp"
#include "Foundation/SharedObject.hpp"
#include "Foundation/Singleton.hpp"
#include "Foundation/StringUtils.hpp"
#include "Foundation/Version.hpp"
#include "Loaders/OBJLoader.hpp"
#include "Mathematics/Clock.hpp"
#include "Mathematics/ColorRGB.hpp"
#include "Mathematics/ColorRGBA.hpp"
#include "Mathematics/ColorRGBAOps.hpp"
#include "Mathematics/ColorRGBOps.hpp"
#include "Mathematics/Frustum.hpp"
#include "Mathematics/Interpolation.hpp"
#include "Mathematics/Intersection.hpp"
#include "Mathematics/Matrix3.hpp"
#include "Mathematics/Matrix3_equality.hpp"
#include "Mathematics/Matrix4.hpp"
#include "Mathematics/Matrix4_equality.hpp"
#include "Mathematics/Numeric.hpp"
#include "Mathematics/Plane3.hpp"
#include "Mathematics/Quaternion.hpp"
#include "Mathematics/Random.hpp"
#include "Mathematics/Ray3.hpp"
#include "Mathematics/Rect.hpp"
#include "Mathematics/Root.hpp"
#include "Mathematics/Series.hpp"
#include "Mathematics/Sphere.hpp"
#include "Mathematics/Transformation.hpp"
#include "Mathematics/Transformation_apply.hpp"
#include "Mathematics/Transformation_inverse.hpp"
#include "Mathematics/Transformation_lookAt.hpp"
#include "Mathematics/Transformation_operators.hpp"
#include "Mathematics/Transformation_rotation.hpp"
#include "Mathematics/Transformation_scale.hpp"
#include "Mathematics/Transformation_translation.hpp"
#include "Mathematics/Vector2.hpp"
#include "Mathematics/Vector2Ops.hpp"
#include "Mathematics/Vector3.hpp"
#include "Mathematics/Vector3Ops.hpp"
#include "Mathematics/Vector4.hpp"
#include "Mathematics/Vector_equality.hpp"
#include "Mathematics/easing.hpp"
#include "Mathematics/io.hpp"
#include "Mathematics/ortho.hpp"
#include "Mathematics/perspective.hpp"
#include "Mathematics/trigonometry.hpp"
#include "Messaging/MessageQueue.hpp"
#include "Navigation/NavigationCell.hpp"
#include "Navigation/NavigationCellEdge.hpp"
#include "Navigation/NavigationController.hpp"
#include "Navigation/NavigationMesh.hpp"
#include "Navigation/NavigationMeshContainer.hpp"
#include "Navigation/NavigationMeshOBJ.hpp"
#include "ParticleSystem/Generators/AccelerationParticleGenerator.hpp"
#include "ParticleSystem/Generators/BoxPositionParticleGenerator.hpp"
#include "ParticleSystem/Generators/ColorParticleGenerator.hpp"
#include "ParticleSystem/Generators/DefaultValueParticleGenerator.hpp"
#include "ParticleSystem/Generators/EulerAnglesParticleGenerator.hpp"
#include "ParticleSystem/Generators/GridPositionParticleGenerator.hpp"
#include "ParticleSystem/Generators/NodePositionParticleGenerator.hpp"
#include "ParticleSystem/Generators/OrbitPositionParticleGenerator.hpp"
#include "ParticleSystem/Generators/RandomValueParticleGenerator.hpp"
#include "ParticleSystem/Generators/SpherePositionParticleGenerator.hpp"
#include "ParticleSystem/Generators/SphereVelocityParticleGenerator.hpp"
#include "ParticleSystem/Generators/TimeParticleGenerator.hpp"
#include "ParticleSystem/Generators/UniformScaleParticleGenerator.hpp"
#include "ParticleSystem/Generators/VelocityParticleGenerator.hpp"
#include "ParticleSystem/ParticleData.hpp"
#include "ParticleSystem/ParticleSystemComponent.hpp"
#include "ParticleSystem/Renderers/AnimatedSpriteParticleRenderer.hpp"
#include "ParticleSystem/Renderers/InstancedParticleRenderer.hpp"
#include "ParticleSystem/Renderers/NodeParticleRenderer.hpp"
#include "ParticleSystem/Renderers/OrientedQuadParticleRenderer.hpp"
#include "ParticleSystem/Renderers/PointSpriteParticleRenderer.hpp"
#include "ParticleSystem/Updaters/AttractorParticleUpdater.hpp"
#include "ParticleSystem/Updaters/CameraSortParticleUpdater.hpp"
#include "ParticleSystem/Updaters/ColorParticleUpdater.hpp"
#include "ParticleSystem/Updaters/EulerParticleUpdater.hpp"
#include "ParticleSystem/Updaters/FloorParticleUpdater.hpp"
#include "ParticleSystem/Updaters/PositionVelocityParticleUpdater.hpp"
#include "ParticleSystem/Updaters/SetAttribValueParticleUpdater.hpp"
#include "ParticleSystem/Updaters/TimeParticleUpdater.hpp"
#include "ParticleSystem/Updaters/UniformScaleParticleUpdater.hpp"
#include "ParticleSystem/Updaters/ZSortParticleUpdater.hpp"
#include "Primitives/ArcPrimitive.hpp"
#include "Primitives/ArrowPrimitive.hpp"
#include "Primitives/BoxPrimitive.hpp"
#include "Primitives/ConePrimitive.hpp"
#include "Primitives/CylinderPrimitive.hpp"
#include "Primitives/KleinBottlePrimitive.hpp"
#include "Primitives/MobiusStripPrimitive.hpp"
#include "Primitives/NewellTeapotPrimitive.hpp"
#include "Primitives/ParametricPrimitive.hpp"
#include "Primitives/ParametricSpherePrimitive.hpp"
#include "Primitives/Primitive.hpp"
#include "Primitives/QuadPrimitive.hpp"
#include "Primitives/SpherePrimitive.hpp"
#include "Primitives/TorusPrimitive.hpp"
#include "Primitives/TrefoilKnotPrimitive.hpp"
#include "Rendering/Buffer.hpp"
#include "Rendering/Catalog.hpp"
#include "Rendering/ColorMaskState.hpp"
#include "Rendering/CommandBuffer.hpp"
#include "Rendering/ComputePass.hpp"
#include "Rendering/DescriptorSet.hpp"
#include "Rendering/Font.hpp"
#include "Rendering/Image.hpp"
#include "Rendering/ImageManager.hpp"
#include "Rendering/ImageTGA.hpp"
#include "Rendering/IndexBuffer.hpp"
#include "Rendering/Material.hpp"
#include "Rendering/Materials/LitMaterial.hpp"
#include "Rendering/Materials/PrincipledBSDFMaterial.hpp"
#include "Rendering/Materials/SkyboxMaterial.hpp"
#include "Rendering/Materials/UnlitMaterial.hpp"
#include "Rendering/Operations/OperationUtils.hpp"
#include "Rendering/Operations/Operations.hpp"
#include "Rendering/Operations/Operations_softRT.hpp"
#include "Rendering/Pipeline.hpp"
#include "Rendering/Programs/UnlitShaderProgram.hpp"
#include "Rendering/RenderPass.hpp"
#include "Rendering/RenderResource.hpp"
#include "Rendering/RenderState.hpp"
#include "Rendering/Renderer.hpp"
#include "Rendering/Sampler.hpp"
#include "Rendering/Shader.hpp"
#include "Rendering/ShaderLibrary.hpp"
#include "Rendering/ShaderLocation.hpp"
#include "Rendering/ShaderProgram.hpp"
#include "Rendering/ShaderProgramLibrary.hpp"
#include "Rendering/ShaderUniform.hpp"
#include "Rendering/ShaderUniformImpl.hpp"
#include "Rendering/ShadowMap.hpp"
#include "Rendering/SkinnedMesh.hpp"
#include "Rendering/Swapchain.hpp"
#include "Rendering/Texture.hpp"
#include "Rendering/UniformBuffer.hpp"
#include "Rendering/Uniforms/CallbackUniformBuffer.hpp"
#include "Rendering/Uniforms/CameraViewProjectionUniformBuffer.hpp"
#include "Rendering/Uniforms/LightingUniform.hpp"
#include "Rendering/Uniforms/ModelUniformBuffer.hpp"
#include "Rendering/Uniforms/ModelViewProjectionUniformBuffer.hpp"
#include "Rendering/VertexBuffer.hpp"
#include "SceneGraph/Camera.hpp"
#include "SceneGraph/Geometry.hpp"
#include "SceneGraph/Group.hpp"
#include "SceneGraph/Light.hpp"
#include "SceneGraph/Node.hpp"
#include "SceneGraph/Skybox.hpp"
#include "SceneGraph/Switch.hpp"
#include "SceneGraph/Text.hpp"
#include "Simulation/Console/Console.hpp"
#include "Simulation/FileSystem.hpp"
#include "Simulation/Input.hpp"
#include "Simulation/Simulation.hpp"
#include "Simulation/Systems/AudioSystem.hpp"
#include "Simulation/Systems/DebugSystem.hpp"
#include "Simulation/Systems/RenderSystem.hpp"
#include "Simulation/Systems/StreamingSystem.hpp"
#include "Simulation/Systems/UISystem.hpp"
#include "Simulation/Systems/UpdateSystem.hpp"
#include "UI/UIBackground.hpp"
#include "UI/UIButton.hpp"
#include "UI/UICanvas.hpp"
#include "UI/UIFrame.hpp"
#include "UI/UIFrameConstraint.hpp"
#include "UI/UIFrameConstraintMaker.hpp"
#include "UI/UILabel.hpp"
#include "Visitors/Apply.hpp"
#include "Visitors/ApplyToGeometries.hpp"
#include "Visitors/ComputeRenderQueue.hpp"
#include "Visitors/FetchCameras.hpp"
#include "Visitors/FetchLights.hpp"
#include "Visitors/NodeVisitor.hpp"
#include "Visitors/Picking.hpp"
#include "Visitors/SelectNodes.hpp"
#include "Visitors/ShallowCopy.hpp"
#include "Visitors/StartComponents.hpp"
#include "Visitors/UpdateComponents.hpp"
#include "Visitors/UpdateRenderState.hpp"
#include "Visitors/UpdateWorldState.hpp"

namespace crimild {

    void init( void );

}

#endif
<|endoftext|>


<commit_before>/*************** <auto-copyright.pl BEGIN do not edit this line> **************
 *
 * VR Juggler is (C) Copyright 1998-2005 by Iowa State University
 *
 * Original Authors:
 *   Allen Bierbaum, Christopher Just,
 *   Patrick Hartling, Kevin Meinert,
 *   Carolina Cruz-Neira, Albert Baker
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Library General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Library General Public License for more details.
 *
 * You should have received a copy of the GNU Library General Public
 * License along with this library; if not, write to the
 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
 * Boston, MA 02111-1307, USA.
 *
 * -----------------------------------------------------------------
 * File:          $RCSfile$
 * Date modified: $Date$
 * Version:       $Revision$
 * -----------------------------------------------------------------
 *
 *************** <auto-copyright.pl END do not edit this line> ***************/

#include <gadget/Devices/DriverConfig.h>

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <errno.h>
#include <sys/ioctl.h>
#include <fcntl.h>

#include <linux/joystick.h>      // Get the joystick abilities

#include <vpr/Util/Debug.h>
#include <jccl/Config/ConfigElement.h>
#include <gadget/Type/DeviceConstructor.h>
#include <gadget/Util/Debug.h>
#include <gadget/gadgetParam.h>

#include <drivers/Open/LinuxJoydev/LinuxJoydev.h>

extern "C"
{

GADGET_DRIVER_EXPORT(vpr::Uint32) getGadgeteerVersion()
{
   return __GADGET_version;
}

GADGET_DRIVER_EXPORT(void) initDevice(gadget::InputManager* inputMgr)
{
   new gadget::DeviceConstructor<gadget::LinuxJoydev>(inputMgr);
}

}

namespace gadget
{

// Constructor.
LinuxJoydev::LinuxJoydev()
{
   /* Do nothing. */ ;
}

// Destructor.
LinuxJoydev::~LinuxJoydev() throw ()
{
   /* Do nothing. */ ;
}

std::string LinuxJoydev::getElementType()
{
   return "linux_joydev";
}

bool LinuxJoydev::config(jccl::ConfigElementPtr e)
{
   if(! (Input::config(e) && Digital::config(e) && Analog::config(e)))
   {
      return false;
   }

   // The joydev driver returns axis values in the range [-32767, 32767].
   // Hence, we ignore whatever the user provided through the config element.
   setMin(-32767.0f);
   setMax(32767.0f);

   mJsLabel = e->getName();
   mPortName = e->getProperty<std::string>("port_name");

   unsigned int num_axis_buttons = e->getNum("axis_buttons");
   for ( unsigned int i = 0; i < num_axis_buttons; ++i )
   {
      unsigned int idx = e->getProperty<unsigned int>("axis_buttons", i);
      mAxisButtonIndices.push_back(idx);
   }

   return true;
}

// Begins sampling.  Connects to the joystick and prepares to read.
bool LinuxJoydev::startSampling()
{
   vprDEBUG(gadgetDBG_INPUT_MGR, vprDBG_CONFIG_STATUS_LVL)
      << "Opening Linux Joystick driver on port: " << mPortName << std::endl
      << vprDEBUG_FLUSH;

   // Open the joystick non-blocking.
   mJsFD = open(mPortName.c_str(), O_RDONLY | O_NONBLOCK);

   if(mJsFD < 0)
   {
      vprDEBUG(gadgetDBG_INPUT_MGR, vprDBG_CRITICAL_LVL)
         << "ERROR: Failed to open Linux Joystick: " << mPortName << std::endl
         << vprDEBUG_FLUSH;
      return false;
   }

   // Read in the settings
   int version;
   unsigned char num_axes, num_buttons;
   char js_name[255];

   ioctl(mJsFD, JSIOCGVERSION, &version);

   const unsigned int version_major(version >> 16);
   const unsigned int version_minor((version >> 8) & 0xff);
   const unsigned int version_patch(version & 0xff);
   char version_str[256];
   snprintf(version_str, sizeof(version_str), "%d.%d.%d", version_major,
            version_minor, version_patch);

   // Verify that the version is new enough.
   if ( version_major < 1 )
   {
      vprDEBUG(gadgetDBG_INPUT_MGR, vprDBG_CRITICAL_LVL)
         << "ERROR: Linux Joystick API Version is too old.  The LinuxJoydev "
         << "driver requires version 1.0 or greater, but found version "
         << version_str << std::endl << vprDEBUG_FLUSH;
      return false;
   }

   ioctl(mJsFD, JSIOCGAXES, &num_axes);
   ioctl(mJsFD, JSIOCGBUTTONS, &num_buttons);

   mNumAxes = num_axes;
   mNumButtons = num_buttons;

   // Get joystick name
   if ( ioctl(mJsFD, JSIOCGNAME(sizeof(js_name)), js_name) < 0 )
   {
      mPhysicalJsName = std::string("Unknown");
   }
   else
   {
      mPhysicalJsName = js_name;
   }

   // Output joystick description
   vprDEBUG(gadgetDBG_INPUT_MGR, vprDBG_CONFIG_LVL)
         << "  Joystick Label: " << mJsLabel << std::endl
         << "   Joystick Name: " << mPhysicalJsName << std::endl
         << "            Axes: " << mNumAxes << std::endl
         << "         Buttons: " << mNumButtons << std::endl
         << "  Driver version: " << version_str << std::endl
         << "    Axis buttons: ";

   for ( unsigned int i = 0; i < mAxisButtonIndices.size(); ++i )
   {
      vprDEBUG_CONTnl(gadgetDBG_INPUT_MGR, vprDBG_CONFIG_LVL)
         << mAxisButtonIndices[i] << " ";
   }
   vprDEBUG_CONTnl(gadgetDBG_INPUT_MGR, vprDBG_CONFIG_LVL) << std::endl
                                                           << vprDEBUG_FLUSH;

   // Allocate initial device data
   // - By default this will clear them out
   mCurAxes.resize(mNumAxes);
   mCurAxesRanges.resize(mNumAxes, axis_range_t(getMin(), getMax()));
   mCurButtons.resize(mNumButtons + mAxisButtonIndices.size());

   // Setup axis as button stuff
   mAxisToButtonIndexLookup.clear();
   mAxisToButtonIndexLookup.resize(mNumAxes, -1);            // Default to -1, meaning no axis button
   for ( unsigned int i = 0; i < mAxisButtonIndices.size(); ++i )       // For each configured axis index
   {
      unsigned int virtual_btn_index = (mNumButtons + i); // Index of the virtual button from the axis
      vprASSERT(virtual_btn_index < mCurButtons.size() &&
                "Virtual button index out of range");
      unsigned int axis_index = mAxisButtonIndices[i];                      // Index of the axis we are mapping
      mAxisToButtonIndexLookup[axis_index] = int(virtual_btn_index);    // Setup the mapping
   }

   return true;
}

// Stops sampling.  Drops the connection to joystick and clears everything.
bool LinuxJoydev::stopSampling()
{
   if(mJsFD > 0)
   {
      close(mJsFD);     // Close the joystick device
   }

   return true;
}

// Updates to the sampled data.
void LinuxJoydev::updateData()
{
   // -- Read in any new pending events
   js_event cur_event;

   // While events pending
   while (read(mJsFD, &cur_event, sizeof(struct js_event)) > 0)
   {
      if(cur_event.type & JS_EVENT_BUTTON)
      {
         //std::cout << "ljs: btn: " << unsigned(cur_event.number) << " val:"
         //          << cur_event.value << std::endl;
         const unsigned int btn_number(cur_event.number);
         vprASSERT(btn_number < mCurButtons.size() && "Button out of range");
         mCurButtons[btn_number] = cur_event.value;         // Assign the new button value (0,1)
         mCurButtons[btn_number].setTime();                 // Set timestamp to now
      }
      else if(cur_event.type & JS_EVENT_AXIS)
      {
         //std::cout << "ljs: axis: " << unsigned(cur_event.number) << " val:"
         //          << cur_event.value << std::endl;
         const unsigned int axis_number(cur_event.number);
         vprASSERT(axis_number < mCurAxes.size() && "Axis out of range");
         vprASSERT(axis_number < mCurAxesRanges.size() && "Axis out of range");

         float norm_value(0.0f);
         normalizeMinToMax(cur_event.value, norm_value);
         mCurAxes[axis_number] = norm_value;
         mCurAxes[axis_number].setTime();

         // Check for axis buttons
         // - If we have a mapping
         // - If axis is gt 0.5, then btn is down
         if(mAxisToButtonIndexLookup[axis_number] != -1)    // If we map to a virtual button
         {
            unsigned vir_btn_index = mAxisToButtonIndexLookup[axis_number];
            vprASSERT(vir_btn_index < mCurButtons.size() &&
                      "Virtual button index out of range");
            mCurButtons[vir_btn_index] = ( (norm_value > 0.5f) ? 1 : 0);
            mCurButtons[vir_btn_index].setTime();
         }
      }
   }

   // Check to make sure error was just no-pending events
   if(errno != EAGAIN)
   {
      vprDEBUG(vprDBG_ALL, vprDBG_CRITICAL_LVL)
         << "ERROR: Error reading linux joystick.\n" << vprDEBUG_FLUSH;
      return;
   }

   addDigitalSample(mCurButtons);
   swapDigitalBuffers();

   addAnalogSample(mCurAxes);
   swapAnalogBuffers();
}

} // End of gadget namespace
<commit_msg>Bug fixed:	Axis buttons now provide two digital data sources: one for 		the axis' low value and one for its high value. Prior to 		this change, only one digital data source per analog axis 		was available.<commit_after>/*************** <auto-copyright.pl BEGIN do not edit this line> **************
 *
 * VR Juggler is (C) Copyright 1998-2005 by Iowa State University
 *
 * Original Authors:
 *   Allen Bierbaum, Christopher Just,
 *   Patrick Hartling, Kevin Meinert,
 *   Carolina Cruz-Neira, Albert Baker
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Library General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Library General Public License for more details.
 *
 * You should have received a copy of the GNU Library General Public
 * License along with this library; if not, write to the
 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
 * Boston, MA 02111-1307, USA.
 *
 * -----------------------------------------------------------------
 * File:          $RCSfile$
 * Date modified: $Date$
 * Version:       $Revision$
 * -----------------------------------------------------------------
 *
 *************** <auto-copyright.pl END do not edit this line> ***************/

#include <gadget/Devices/DriverConfig.h>

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <errno.h>
#include <sys/ioctl.h>
#include <fcntl.h>

#include <linux/joystick.h>      // Get the joystick abilities

#include <vpr/Util/Debug.h>
#include <jccl/Config/ConfigElement.h>
#include <gadget/Type/DeviceConstructor.h>
#include <gadget/Util/Debug.h>
#include <gadget/gadgetParam.h>

#include <drivers/Open/LinuxJoydev/LinuxJoydev.h>

extern "C"
{

GADGET_DRIVER_EXPORT(vpr::Uint32) getGadgeteerVersion()
{
   return __GADGET_version;
}

GADGET_DRIVER_EXPORT(void) initDevice(gadget::InputManager* inputMgr)
{
   new gadget::DeviceConstructor<gadget::LinuxJoydev>(inputMgr);
}

}

namespace gadget
{

// Constructor.
LinuxJoydev::LinuxJoydev()
{
   /* Do nothing. */ ;
}

// Destructor.
LinuxJoydev::~LinuxJoydev() throw ()
{
   /* Do nothing. */ ;
}

std::string LinuxJoydev::getElementType()
{
   return "linux_joydev";
}

bool LinuxJoydev::config(jccl::ConfigElementPtr e)
{
   if(! (Input::config(e) && Digital::config(e) && Analog::config(e)))
   {
      return false;
   }

   // The joydev driver returns axis values in the range [-32767, 32767].
   // Hence, we ignore whatever the user provided through the config element.
   setMin(-32767.0f);
   setMax(32767.0f);

   mJsLabel = e->getName();
   mPortName = e->getProperty<std::string>("port_name");

   unsigned int num_axis_buttons = e->getNum("axis_buttons");
   for ( unsigned int i = 0; i < num_axis_buttons; ++i )
   {
      unsigned int idx = e->getProperty<unsigned int>("axis_buttons", i);
      mAxisButtonIndices.push_back(idx);
   }

   return true;
}

// Begins sampling.  Connects to the joystick and prepares to read.
bool LinuxJoydev::startSampling()
{
   vprDEBUG(gadgetDBG_INPUT_MGR, vprDBG_CONFIG_STATUS_LVL)
      << "Opening Linux Joystick driver on port: " << mPortName << std::endl
      << vprDEBUG_FLUSH;

   // Open the joystick non-blocking.
   mJsFD = open(mPortName.c_str(), O_RDONLY | O_NONBLOCK);

   if(mJsFD < 0)
   {
      vprDEBUG(gadgetDBG_INPUT_MGR, vprDBG_CRITICAL_LVL)
         << "ERROR: Failed to open Linux Joystick: " << mPortName << std::endl
         << vprDEBUG_FLUSH;
      return false;
   }

   // Read in the settings
   int version;
   unsigned char num_axes, num_buttons;
   char js_name[255];

   ioctl(mJsFD, JSIOCGVERSION, &version);

   const unsigned int version_major(version >> 16);
   const unsigned int version_minor((version >> 8) & 0xff);
   const unsigned int version_patch(version & 0xff);
   char version_str[256];
   snprintf(version_str, sizeof(version_str), "%d.%d.%d", version_major,
            version_minor, version_patch);

   // Verify that the version is new enough.
   if ( version_major < 1 )
   {
      vprDEBUG(gadgetDBG_INPUT_MGR, vprDBG_CRITICAL_LVL)
         << "ERROR: Linux Joystick API Version is too old.  The LinuxJoydev "
         << "driver requires version 1.0 or greater, but found version "
         << version_str << std::endl << vprDEBUG_FLUSH;
      return false;
   }

   ioctl(mJsFD, JSIOCGAXES, &num_axes);
   ioctl(mJsFD, JSIOCGBUTTONS, &num_buttons);

   mNumAxes = num_axes;
   mNumButtons = num_buttons;

   // Get joystick name
   if ( ioctl(mJsFD, JSIOCGNAME(sizeof(js_name)), js_name) < 0 )
   {
      mPhysicalJsName = std::string("Unknown");
   }
   else
   {
      mPhysicalJsName = js_name;
   }

   // Output joystick description
   vprDEBUG(gadgetDBG_INPUT_MGR, vprDBG_CONFIG_LVL)
         << "  Joystick Label: " << mJsLabel << std::endl
         << "   Joystick Name: " << mPhysicalJsName << std::endl
         << "            Axes: " << mNumAxes << std::endl
         << "         Buttons: " << mNumButtons << std::endl
         << "  Driver version: " << version_str << std::endl
         << "    Axis buttons: ";

   for ( unsigned int i = 0; i < mAxisButtonIndices.size(); ++i )
   {
      vprDEBUG_CONTnl(gadgetDBG_INPUT_MGR, vprDBG_CONFIG_LVL)
         << mAxisButtonIndices[i] << " ";
   }
   vprDEBUG_CONTnl(gadgetDBG_INPUT_MGR, vprDBG_CONFIG_LVL) << std::endl
                                                           << vprDEBUG_FLUSH;

   // Allocate initial device data
   // - By default this will clear them out
   mCurAxes.resize(mNumAxes);
   mCurAxesRanges.resize(mNumAxes, axis_range_t(getMin(), getMax()));
   // We use double the number of axis button indices because each axis has
   // to map to two buttons (high and low).
   mCurButtons.resize(mNumButtons + mAxisButtonIndices.size() * 2);

   // Setup axis as button stuff
   mAxisToButtonIndexLookup.clear();
   mAxisToButtonIndexLookup.resize(mNumAxes, -1);            // Default to -1, meaning no axis button
   for ( unsigned int i = 0; i < mAxisButtonIndices.size(); ++i )       // For each configured axis index
   {
      // Define the index of the virtual button from the axis. Each axis
      // provides two virtual buttons: one for its low value and one for its
      // high value. These virtual buttons are paired up in the digital
      // sample buffers as [low0, high0, low1, high1, ..., lowN, highN] for
      // axes 0 through N.
      const unsigned int virtual_btn_index = mNumButtons + i * 2;
      vprASSERT(virtual_btn_index < mCurButtons.size() &&
                "Virtual button index out of range");
      unsigned int axis_index = mAxisButtonIndices[i];                      // Index of the axis we are mapping
      mAxisToButtonIndexLookup[axis_index] = int(virtual_btn_index);    // Setup the mapping
   }

   return true;
}

// Stops sampling.  Drops the connection to joystick and clears everything.
bool LinuxJoydev::stopSampling()
{
   if(mJsFD > 0)
   {
      close(mJsFD);     // Close the joystick device
   }

   return true;
}

// Updates to the sampled data.
void LinuxJoydev::updateData()
{
   // -- Read in any new pending events
   js_event cur_event;

   // While events pending
   while (read(mJsFD, &cur_event, sizeof(struct js_event)) > 0)
   {
      if(cur_event.type & JS_EVENT_BUTTON)
      {
         //std::cout << "ljs: btn: " << unsigned(cur_event.number) << " val:"
         //          << cur_event.value << std::endl;
         const unsigned int btn_number(cur_event.number);
         vprASSERT(btn_number < mCurButtons.size() && "Button out of range");
         mCurButtons[btn_number] = cur_event.value;         // Assign the new button value (0,1)
         mCurButtons[btn_number].setTime();                 // Set timestamp to now
      }
      else if(cur_event.type & JS_EVENT_AXIS)
      {
         //std::cout << "ljs: axis: " << unsigned(cur_event.number) << " val:"
         //          << cur_event.value << std::endl;
         const unsigned int axis_number(cur_event.number);
         vprASSERT(axis_number < mCurAxes.size() && "Axis out of range");
         vprASSERT(axis_number < mCurAxesRanges.size() && "Axis out of range");

         float norm_value(0.0f);
         normalizeMinToMax(cur_event.value, norm_value);
         mCurAxes[axis_number] = norm_value;
         mCurAxes[axis_number].setTime();

         // Check for axis buttons. If we have a mapping for axis_number,
         // then we map the value of the analog axis to two buttons (high and
         // low). If the analog value is greater than 0.5, then we map the
         // high button to 1 and the low button to 0. If the analog value is
         // less than 0.5, then we map the high button to 0 and the low button
         // to 0. Otherwise, both buttons are 0.
         if ( mAxisToButtonIndexLookup[axis_number] != -1 )    // If we map to a virtual button
         {
            const unsigned int low_btn_index =
               mAxisToButtonIndexLookup[axis_number];
            const unsigned int high_btn_index = low_btn_index + 1;
            vprASSERT(high_btn_index < mCurButtons.size() &&
                      "Virtual high button index out of range");
            vprASSERT(low_btn_index < mCurButtons.size() &&
                      "Virtual low button index out of range");

            // Record the high button as pressed and the low button as not
            // pressed.
            if ( norm_value > 0.5f )
            {
               mCurButtons[low_btn_index]  = 0;
               mCurButtons[high_btn_index] = 1;
            }
            // Record the high button as not pressed and the low button as
            // pressed.
            else if ( norm_value < 0.5f )
            {
               mCurButtons[low_btn_index]  = 1;
               mCurButtons[high_btn_index] = 0;
            }
            // Record both buttons as not pressed.
            else
            {
               mCurButtons[low_btn_index]  = 0;
               mCurButtons[high_btn_index] = 0;
            }

            mCurButtons[low_btn_index].setTime();
            mCurButtons[high_btn_index].setTime();
         }
      }
   }

   // Check to make sure error was just no-pending events
   if(errno != EAGAIN)
   {
      vprDEBUG(vprDBG_ALL, vprDBG_CRITICAL_LVL)
         << "ERROR: Error reading linux joystick.\n" << vprDEBUG_FLUSH;
      return;
   }

   addDigitalSample(mCurButtons);
   swapDigitalBuffers();

   addAnalogSample(mCurAxes);
   swapAnalogBuffers();
}

} // End of gadget namespace
<|endoftext|>


<commit_before>#include "bitcoinamountfield.h"
#include "qvaluecombobox.h"
#include "bitcoinunits.h"

#include "guiconstants.h"

#include <QLabel>
#include <QLineEdit>
#include <QRegExpValidator>
#include <QHBoxLayout>
#include <QKeyEvent>
#include <QDoubleSpinBox>
#include <QComboBox>
#include <QApplication>
#include <qmath.h>

BitcoinAmountField::BitcoinAmountField(QWidget *parent):
        QWidget(parent), amount(0), currentUnit(-1)
{
    amount = new QDoubleSpinBox(this);
    amount->setLocale(QLocale::c());
    amount->setDecimals(8);
    amount->installEventFilter(this);
    amount->setMaximumWidth(170);
    amount->setSingleStep(0.001);

    QHBoxLayout *layout = new QHBoxLayout(this);
    layout->addWidget(amount);
    unit = new QValueComboBox(this);
    unit->setModel(new BitcoinUnits(this));
    layout->addWidget(unit);
    layout->addStretch(1);
    layout->setContentsMargins(0,0,0,0);

    setLayout(layout);

    setFocusPolicy(Qt::TabFocus);
    setFocusProxy(amount);

    // If one if the widgets changes, the combined content changes as well
    connect(amount, SIGNAL(valueChanged(QString)), this, SIGNAL(textChanged()));
    connect(unit, SIGNAL(currentIndexChanged(int)), this, SLOT(unitChanged(int)));

    // Set default based on configuration
    unitChanged(unit->currentIndex());
}

void BitcoinAmountField::setText(const QString &text)
{
    if (text.isEmpty())
        amount->clear();
    else
        amount->setValue(text.toDouble());
}

void BitcoinAmountField::clear()
{
    amount->clear();
    unit->setCurrentIndex(0);
}

bool BitcoinAmountField::validate()
{
    bool valid = true;
    if (amount->value() == 0.0)
        valid = false;
    if (valid && !BitcoinUnits::parse(currentUnit, text(), 0))
        valid = false;

    setValid(valid);

    return valid;
}

void BitcoinAmountField::setValid(bool valid)
{
    if (valid)
        amount->setStyleSheet("");
    else
        amount->setStyleSheet(STYLE_INVALID);
}

QString BitcoinAmountField::text() const
{
    if (amount->text().isEmpty())
        return QString();
    else
        return amount->text();
}

bool BitcoinAmountField::eventFilter(QObject *object, QEvent *event)
{
    if (event->type() == QEvent::FocusIn)
    {
        // Clear invalid flag on focus
        setValid(true);
    }
    else if (event->type() == QEvent::KeyPress || event->type() == QEvent::KeyRelease)
    {
        QKeyEvent *keyEvent = static_cast<QKeyEvent *>(event);
        if (keyEvent->key() == Qt::Key_Comma)
        {
            // Translate a comma into a period
            QKeyEvent periodKeyEvent(event->type(), Qt::Key_Period, keyEvent->modifiers(), ".", keyEvent->isAutoRepeat(), keyEvent->count());
            qApp->sendEvent(object, &periodKeyEvent);
            return true;
        }
    }
    return QWidget::eventFilter(object, event);
}

QWidget *BitcoinAmountField::setupTabChain(QWidget *prev)
{
    QWidget::setTabOrder(prev, amount);
    return amount;
}

qint64 BitcoinAmountField::value(bool *valid_out) const
{
    qint64 val_out = 0;
    bool valid = BitcoinUnits::parse(currentUnit, text(), &val_out);
    if(valid_out)
    {
        *valid_out = valid;
    }
    return val_out;
}

void BitcoinAmountField::setValue(qint64 value)
{
    setText(BitcoinUnits::format(currentUnit, value));
}

void BitcoinAmountField::unitChanged(int idx)
{
    // Use description tooltip for current unit for the combobox
    unit->setToolTip(unit->itemData(idx, Qt::ToolTipRole).toString());

    // Determine new unit ID
    int newUnit = unit->itemData(idx, BitcoinUnits::UnitRole).toInt();

    // Parse current value and convert to new unit
    bool valid = false;
    qint64 currentValue = value(&valid);

    currentUnit = newUnit;

    // Set max length after retrieving the value, to prevent truncation
    amount->setDecimals(BitcoinUnits::decimals(currentUnit));
    amount->setMaximum(qPow(10, BitcoinUnits::amountDigits(currentUnit)) - qPow(10, -amount->decimals()));

    if(valid)
    {
        // If value was valid, re-place it in the widget with the new unit
        setValue(currentValue);
    }
    else
    {
        // If current value is invalid, just clear field
        setText("");
    }
    setValid(true);
}

void BitcoinAmountField::setDisplayUnit(int newUnit)
{
    unit->setValue(newUnit);
}
<commit_msg>Removed restricting stretching of nebls units as it doesn't necessarily fit its combo box in high dpi screens.<commit_after>#include "bitcoinamountfield.h"
#include "qvaluecombobox.h"
#include "bitcoinunits.h"

#include "guiconstants.h"

#include <QLabel>
#include <QLineEdit>
#include <QRegExpValidator>
#include <QHBoxLayout>
#include <QKeyEvent>
#include <QDoubleSpinBox>
#include <QComboBox>
#include <QApplication>
#include <qmath.h>

BitcoinAmountField::BitcoinAmountField(QWidget *parent):
        QWidget(parent), amount(0), currentUnit(-1)
{
    amount = new QDoubleSpinBox(this);
    amount->setLocale(QLocale::c());
    amount->setDecimals(8);
    amount->installEventFilter(this);
    amount->setMaximumWidth(170);
    amount->setSingleStep(0.001);

    QHBoxLayout *layout = new QHBoxLayout(this);
    layout->addWidget(amount);
    unit = new QValueComboBox(this);
    unit->setModel(new BitcoinUnits(this));
    layout->addWidget(unit);
//    layout->addStretch(1);
    layout->setContentsMargins(0,0,0,0);

    setLayout(layout);

    setFocusPolicy(Qt::TabFocus);
    setFocusProxy(amount);

    // If one if the widgets changes, the combined content changes as well
    connect(amount, SIGNAL(valueChanged(QString)), this, SIGNAL(textChanged()));
    connect(unit, SIGNAL(currentIndexChanged(int)), this, SLOT(unitChanged(int)));

    // Set default based on configuration
    unitChanged(unit->currentIndex());
}

void BitcoinAmountField::setText(const QString &text)
{
    if (text.isEmpty())
        amount->clear();
    else
        amount->setValue(text.toDouble());
}

void BitcoinAmountField::clear()
{
    amount->clear();
    unit->setCurrentIndex(0);
}

bool BitcoinAmountField::validate()
{
    bool valid = true;
    if (amount->value() == 0.0)
        valid = false;
    if (valid && !BitcoinUnits::parse(currentUnit, text(), 0))
        valid = false;

    setValid(valid);

    return valid;
}

void BitcoinAmountField::setValid(bool valid)
{
    if (valid)
        amount->setStyleSheet("");
    else
        amount->setStyleSheet(STYLE_INVALID);
}

QString BitcoinAmountField::text() const
{
    if (amount->text().isEmpty())
        return QString();
    else
        return amount->text();
}

bool BitcoinAmountField::eventFilter(QObject *object, QEvent *event)
{
    if (event->type() == QEvent::FocusIn)
    {
        // Clear invalid flag on focus
        setValid(true);
    }
    else if (event->type() == QEvent::KeyPress || event->type() == QEvent::KeyRelease)
    {
        QKeyEvent *keyEvent = static_cast<QKeyEvent *>(event);
        if (keyEvent->key() == Qt::Key_Comma)
        {
            // Translate a comma into a period
            QKeyEvent periodKeyEvent(event->type(), Qt::Key_Period, keyEvent->modifiers(), ".", keyEvent->isAutoRepeat(), keyEvent->count());
            qApp->sendEvent(object, &periodKeyEvent);
            return true;
        }
    }
    return QWidget::eventFilter(object, event);
}

QWidget *BitcoinAmountField::setupTabChain(QWidget *prev)
{
    QWidget::setTabOrder(prev, amount);
    return amount;
}

qint64 BitcoinAmountField::value(bool *valid_out) const
{
    qint64 val_out = 0;
    bool valid = BitcoinUnits::parse(currentUnit, text(), &val_out);
    if(valid_out)
    {
        *valid_out = valid;
    }
    return val_out;
}

void BitcoinAmountField::setValue(qint64 value)
{
    setText(BitcoinUnits::format(currentUnit, value));
}

void BitcoinAmountField::unitChanged(int idx)
{
    // Use description tooltip for current unit for the combobox
    unit->setToolTip(unit->itemData(idx, Qt::ToolTipRole).toString());

    // Determine new unit ID
    int newUnit = unit->itemData(idx, BitcoinUnits::UnitRole).toInt();

    // Parse current value and convert to new unit
    bool valid = false;
    qint64 currentValue = value(&valid);

    currentUnit = newUnit;

    // Set max length after retrieving the value, to prevent truncation
    amount->setDecimals(BitcoinUnits::decimals(currentUnit));
    amount->setMaximum(qPow(10, BitcoinUnits::amountDigits(currentUnit)) - qPow(10, -amount->decimals()));

    if(valid)
    {
        // If value was valid, re-place it in the widget with the new unit
        setValue(currentValue);
    }
    else
    {
        // If current value is invalid, just clear field
        setText("");
    }
    setValid(true);
}

void BitcoinAmountField::setDisplayUnit(int newUnit)
{
    unit->setValue(newUnit);
}
<|endoftext|>


<commit_before>/*
This file is part of Bohrium and copyright (c) 2012 the Bohrium
team <http://www.bh107.org>.

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

Bohrium is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the
GNU Lesser General Public License along with Bohrium.

If not, see <http://www.gnu.org/licenses/>.
*/

#include <cassert>

#include <bh_component.hpp>
#include <bh_extmethod.hpp>
#include <bh_idmap.hpp>

#include "kernel.hpp"
#include "block.hpp"
#include "instruction.hpp"
#include "type.hpp"
#include "store.hpp"

using namespace bohrium;
using namespace component;
using namespace std;

namespace {
class Impl : public ComponentImpl {
  private:
    Store _store;
    map<bh_opcode, extmethod::ExtmethodFace> extmethods;
  public:
    Impl(int stack_level) : ComponentImpl(stack_level), _store(config) {}
    ~Impl() {}; // NB: a destructor implementation must exist
    void execute(bh_ir *bhir);
    void extmethod(const string &name, bh_opcode opcode) {
        // ExtmethodFace does not have a default or copy constructor thus
        // we have to use its move constructor.
        extmethods.insert(make_pair(opcode, extmethod::ExtmethodFace(config, name)));
    }
};
}

extern "C" ComponentImpl* create(int stack_level) {
    return new Impl(stack_level);
}
extern "C" void destroy(ComponentImpl* self) {
    delete self;
}

namespace {
void spaces(stringstream &out, int num) {
    for (int i = 0; i < num; ++i) {
        out << " ";
    }
}
}

void write_block(const IdMap<bh_base*> &base_ids, const Block &block, stringstream &out) {
    if (block.isInstr()) {
        if (block._instr != NULL) {
            spaces(out, 4 + block.rank*4);
            write_instr(base_ids, *block._instr, out);
        }
    } else {
        spaces(out, 4 + block.rank*4);
        // If this block is sweeped, we will "peel" the for-loop such that the
        // sweep instruction is replaced with BH_IDENTITY in the first iteration
        if (block._sweeps.size() > 0) {
            Block peeled_block(block);
            vector<bh_instruction> sweep_instr_list(block._sweeps.size());
            {
                size_t i = 0;
                for (const bh_instruction *instr: block._sweeps) {
                    Block *sweep_instr_block = peeled_block.findInstrBlock(instr);
                    assert(sweep_instr_block != NULL);
                    bh_instruction *sweep_instr = &sweep_instr_list[i++];
                    sweep_instr->opcode = BH_IDENTITY;
                    sweep_instr->operand[1] = instr->operand[1]; // The input is the same as in the sweep
                    sweep_instr->operand[0] = instr->operand[0];
                    // But the output needs an extra dimension when we are reducing to a non-scalar
                    if (bh_opcode_is_reduction(instr->opcode) and instr->operand[1].ndim > 1) {
                        sweep_instr->operand[0].insert_dim(instr->constant.get_int64(), 1, 0);
                    }
                    sweep_instr_block->_instr = sweep_instr;
                }
            }
            string itername;
            {stringstream t; t << "i" << block.rank; itername = t.str();}
            out << "{ // Peeled loop, 1. iteration" << endl;
            spaces(out, 8 + block.rank*4);
            out << "uint64_t " << itername << " = 0;" << endl;
            for (const Block &b: peeled_block._block_list) {
                write_block(base_ids, b, out);
            }
            spaces(out, 4 + block.rank*4);
            out << "}" << endl;
            spaces(out, 4 + block.rank*4);
        }

        string itername;
        {stringstream t; t << "i" << block.rank; itername = t.str();}
        out << "for(uint64_t " << itername;
        if (block._sweeps.size() > 0) // If the for-loop has been peeled, we should that at 1
            out << "=1; ";
        else
            out << "=0; ";
        out << itername << " < " << block.size << "; ++" << itername << ") {" << endl;
        for (const Block &b: block._block_list) {
            write_block(base_ids, b, out);
        }
        spaces(out, 4 + block.rank*4);
        out << "}" << endl;
    }
}

vector<Block> fuser_singleton(vector<bh_instruction> &instr_list) {

    set<bh_base*> bases; // Set of all known bases
    set<bh_base*> syncs; // Set of all sync'ed bases

    // Creates the block_list based on the instr_list
    vector<Block> block_list;
    for (auto instr=instr_list.begin(); instr != instr_list.end(); ++instr) {
        int nop = bh_noperands(instr->opcode);
        if (nop == 0)
            continue; // Ignore noop instructions such as BH_NONE or BH_TALLY

        bh_base *created_array = NULL; // Is this instruction creating a new array?
        bh_base *destroyed_array = NULL;// Is this instruction destroying an array?

        // Add inputs to 'bases'
        for (int i=1; i<nop; ++i) {
            bh_view &v = instr->operand[i];
            if (not bh_is_constant(&v)) {
                bases.insert(v.base);
            }
        }
        // Add output to 'bases' and check if 'instr' creates a new array
        {
            bh_view &v = instr->operand[0];
            if (bases.find(v.base) == bases.end()) { // TODO: check if writing to whole array
                created_array = v.base;
            }
            bases.insert(v.base);
        }
        if (instr->opcode == BH_SYNC) {
            assert(nop == 1);
            syncs.insert(instr->operand[0].base);
        } else if (instr->opcode == BH_FREE) {
            assert(nop == 1);
            if (syncs.find(instr->operand[0].base) == syncs.end()) {
                // If the array is free'ed and not sync'ed, it can be destroyed
                destroyed_array = instr->operand[0].base;
            }
        }
        set<bh_base*> news, frees, tmps;
        if (created_array != NULL)
            news.insert(created_array);
        if (destroyed_array != NULL)
            frees.insert(destroyed_array);

        // Now that we have the news, frees, and tmps, we can create the single instruction block
        vector<bh_instruction*> single_instr = {&instr[0]};
        block_list.push_back(create_nested_block(single_instr, 0, news, frees, tmps));
    }
    return block_list;
}

// Check if 'a' and 'b' supports data-parallelism when merged
static bool data_parallel_compatible(const bh_instruction *a, const bh_instruction *b)
{
    if(bh_opcode_is_system(a->opcode) || bh_opcode_is_system(b->opcode))
        return true;

    const int a_nop = bh_noperands(a->opcode);
    for(int i=0; i<a_nop; ++i)
    {
        if(not bh_view_disjoint(&b->operand[0], &a->operand[i])
           && not bh_view_aligned(&b->operand[0], &a->operand[i]))
            return false;
    }
    const int b_nop = bh_noperands(b->opcode);
    for(int i=0; i<b_nop; ++i)
    {
        if(not bh_view_disjoint(&a->operand[0], &b->operand[i])
           && not bh_view_aligned(&a->operand[0], &b->operand[i]))
            return false;
    }
    return true;
}

// Check if 'b1' and 'b2' supports data-parallelism when merged
static bool data_parallel_compatible(const Block &b1, const Block &b2) {
    for (const bh_instruction *i1 : b1.getAllInstr()) {
        for (const bh_instruction *i2 : b2.getAllInstr()) {
            if (not data_parallel_compatible(i1, i2))
                return false;
        }
    }
    return true;
}

// Check if 'b1' and 'b2' is fusible.
static bool fusible(const Block &b1, const Block &b2) {
    if (not data_parallel_compatible(b1, b2))
        return false;

    if (b1.rank != b2.rank or b1.size != b2.size)
        return false;

    if (b1._sweeps.size() > 0)
        return false;

    return true;
}

vector<Block> fuser_serial(vector<Block> &block_list) {
    vector<Block> ret;
    for (auto it = block_list.begin(); it != block_list.end(); ) {
        ret.push_back(*it);
        Block &cur = ret.back();
        ++it;
        if (cur.isInstr()) {
            continue; // We should never fuse instruction blocks
        }
        for (; it != block_list.end(); ++it) {
            if ((not it->isInstr()) and fusible(cur, *it)) {
                cur.merge(*it);
            } else {
                break;
            }
        }
        // Let's fuse at the next rank level
        cur._block_list = fuser_serial(cur._block_list);
    }
    return ret;
}

vector<Block> remove_empty_blocks(vector<Block> &block_list) {
    vector<Block> ret;
    for (Block &b: block_list) {
        if (b.getAllInstr().size() > 0)
            ret.push_back(b);
    }
    return ret;
}

void Impl::execute(bh_ir *bhir) {

    // Assign IDs to all base arrays
    IdMap<bh_base *> base_ids;
    // NB: by assigning the IDs in the order they appear in the 'instr_list',
    //     the kernels can better be reused
    for(const bh_instruction &instr: bhir->instr_list) {
        const int nop = bh_noperands(instr.opcode);
        for(int i=0; i<nop; ++i) {
            const bh_view &v = instr.operand[i];
            if (not bh_is_constant(&v)) {
                base_ids.insert(v.base);
            }
        }
    }
    // Do we have anything to do?
    if (base_ids.size() == 0)
        return;

    //Let's create a kernel
    Kernel kernel;
    {
        // Let's fuse the 'instr_list' into blocks
        kernel.block_list = fuser_singleton(bhir->instr_list);
        kernel.block_list = fuser_serial(kernel.block_list);
        kernel.block_list = remove_empty_blocks(kernel.block_list);

        // And fill kernel attributes
        for (bh_instruction &instr: bhir->instr_list) {
            if (instr.opcode == BH_RANDOM) {
                kernel.useRandom = true;
            } else if (instr.opcode == BH_FREE) {
                kernel.frees.insert(instr.operand[0].base);
            }
        }
    }

    // Do we even have any "real" operations to perform?
    if (kernel.block_list.size() == 0) {
        // Finally, let's cleanup
        for(bh_base *base: kernel.frees) {
            bh_data_free(base);
        }
        return;
    }

    // Debug print
    //cout << kernel.block_list;

    // Code generation
    stringstream ss;

    // Make sure all arrays are allocated
    for(bh_base *base: base_ids.getKeys()) {
        bh_data_malloc(base);
    }

    // Write the need includes
    ss << "#include <stdint.h>" << endl;
    ss << "#include <stdlib.h>" << endl;
    ss << "#include <stdbool.h>" << endl;
    ss << "#include <complex.h>" << endl;
    ss << "#include <tgmath.h>" << endl;
    ss << "#include <math.h>" << endl;
    ss << "#include <bh_memory.h>" << endl;
    ss << "#include <bh_type.h>" << endl;
    ss << endl;

    if (kernel.useRandom) { // Write the random function
        ss << "#include <Random123/philox.h>" << endl;
        ss << "uint64_t random123(uint64_t start, uint64_t key, uint64_t index) {" << endl;
        ss << "    union {philox2x32_ctr_t c; uint64_t ul;} ctr, res; " << endl;
        ss << "    ctr.ul = start + index; " << endl;
        ss << "    res.c = philox2x32(ctr.c, (philox2x32_key_t){{key}}); " << endl;
        ss << "    return res.ul; " << endl;
        ss << "} " << endl;
    }
    ss << endl;

    // Write the header of the execute function
    ss << "void execute(";
    for(size_t id=0; id < base_ids.size(); ++id) {
        const bh_base *b = base_ids.getKeys()[id];
        ss << write_type(b->type) << " a" << id << "[]";
        if (id+1 < base_ids.size()) {
            ss << ", ";
        }
    }
    ss << ") {" << endl;

    // Write the blocks that makes up the body of 'execute()'
    for(const Block &block: kernel.block_list) {
        write_block(base_ids, block, ss);
    }

    ss << "}" << endl << endl;

    // Write the launcher function, which will convert the data_list of void pointers
    // to typed arrays and call the execute function
    {
        ss << "void launcher(void* data_list[]) {" << endl;
        size_t i=0;
        for (bh_base *b: base_ids.getKeys()) {
            spaces(ss, 4);
            ss << write_type(b->type) << " *a" << base_ids[b];
            ss << " = data_list[" << i << "];" << endl;
            ++i;
        }
        spaces(ss, 4);
        ss << "execute(";
        for(size_t id=0; id < base_ids.size(); ++id) {
            ss << "a" << id;
            if (id+1 < base_ids.size()) {
                ss << ", ";
            }
        }
        ss << ");" << endl;
        ss << "}" << endl;
    }

  //  cout << ss.str();

    KernelFunction func = _store.getFunction(ss.str());
    assert(func != NULL);

    // Create a 'data_list' of data pointers
    vector<void*> data_list;
    data_list.reserve(base_ids.size());
    for(bh_base *base: base_ids.getKeys()) {
        assert(base->data != NULL);
        data_list.push_back(base->data);
    }

    // Call the launcher function with the 'data_list', which will execute the kernel
    func(&data_list[0]);
    // Finally, let's cleanup
    for(bh_base *base: kernel.frees) {
        bh_data_free(base);
    }
}

<commit_msg>uni: cleanup<commit_after>/*
This file is part of Bohrium and copyright (c) 2012 the Bohrium
team <http://www.bh107.org>.

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

Bohrium is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the
GNU Lesser General Public License along with Bohrium.

If not, see <http://www.gnu.org/licenses/>.
*/

#include <cassert>

#include <bh_component.hpp>
#include <bh_extmethod.hpp>
#include <bh_idmap.hpp>

#include "kernel.hpp"
#include "block.hpp"
#include "instruction.hpp"
#include "type.hpp"
#include "store.hpp"

using namespace bohrium;
using namespace component;
using namespace std;

namespace {
class Impl : public ComponentImpl {
  private:
    Store _store;
    map<bh_opcode, extmethod::ExtmethodFace> extmethods;
  public:
    Impl(int stack_level) : ComponentImpl(stack_level), _store(config) {}
    ~Impl() {}; // NB: a destructor implementation must exist
    void execute(bh_ir *bhir);
    void extmethod(const string &name, bh_opcode opcode) {
        // ExtmethodFace does not have a default or copy constructor thus
        // we have to use its move constructor.
        extmethods.insert(make_pair(opcode, extmethod::ExtmethodFace(config, name)));
    }
};
}

extern "C" ComponentImpl* create(int stack_level) {
    return new Impl(stack_level);
}
extern "C" void destroy(ComponentImpl* self) {
    delete self;
}

namespace {
void spaces(stringstream &out, int num) {
    for (int i = 0; i < num; ++i) {
        out << " ";
    }
}
}

void write_block(const IdMap<bh_base*> &base_ids, const Block &block, stringstream &out) {
    if (block.isInstr()) {
        if (block._instr != NULL) {
            spaces(out, 4 + block.rank*4);
            write_instr(base_ids, *block._instr, out);
        }
    } else {
        spaces(out, 4 + block.rank*4);
        // If this block is sweeped, we will "peel" the for-loop such that the
        // sweep instruction is replaced with BH_IDENTITY in the first iteration
        if (block._sweeps.size() > 0) {
            Block peeled_block(block);
            vector<bh_instruction> sweep_instr_list(block._sweeps.size());
            {
                size_t i = 0;
                for (const bh_instruction *instr: block._sweeps) {
                    Block *sweep_instr_block = peeled_block.findInstrBlock(instr);
                    assert(sweep_instr_block != NULL);
                    bh_instruction *sweep_instr = &sweep_instr_list[i++];
                    sweep_instr->opcode = BH_IDENTITY;
                    sweep_instr->operand[1] = instr->operand[1]; // The input is the same as in the sweep
                    sweep_instr->operand[0] = instr->operand[0];
                    // But the output needs an extra dimension when we are reducing to a non-scalar
                    if (bh_opcode_is_reduction(instr->opcode) and instr->operand[1].ndim > 1) {
                        sweep_instr->operand[0].insert_dim(instr->constant.get_int64(), 1, 0);
                    }
                    sweep_instr_block->_instr = sweep_instr;
                }
            }
            string itername;
            {stringstream t; t << "i" << block.rank; itername = t.str();}
            out << "{ // Peeled loop, 1. iteration" << endl;
            spaces(out, 8 + block.rank*4);
            out << "uint64_t " << itername << " = 0;" << endl;
            for (const Block &b: peeled_block._block_list) {
                write_block(base_ids, b, out);
            }
            spaces(out, 4 + block.rank*4);
            out << "}" << endl;
            spaces(out, 4 + block.rank*4);
        }

        string itername;
        {stringstream t; t << "i" << block.rank; itername = t.str();}
        out << "for(uint64_t " << itername;
        if (block._sweeps.size() > 0) // If the for-loop has been peeled, we should that at 1
            out << "=1; ";
        else
            out << "=0; ";
        out << itername << " < " << block.size << "; ++" << itername << ") {" << endl;
        for (const Block &b: block._block_list) {
            write_block(base_ids, b, out);
        }
        spaces(out, 4 + block.rank*4);
        out << "}" << endl;
    }
}

vector<Block> fuser_singleton(vector<bh_instruction> &instr_list) {

    set<bh_base*> bases; // Set of all known bases
    set<bh_base*> syncs; // Set of all sync'ed bases

    // Creates the block_list based on the instr_list
    vector<Block> block_list;
    for (auto instr=instr_list.begin(); instr != instr_list.end(); ++instr) {
        int nop = bh_noperands(instr->opcode);
        if (nop == 0)
            continue; // Ignore noop instructions such as BH_NONE or BH_TALLY

        bh_base *created_array = NULL; // Is this instruction creating a new array?
        bh_base *destroyed_array = NULL;// Is this instruction destroying an array?

        // Add inputs to 'bases'
        for (int i=1; i<nop; ++i) {
            bh_view &v = instr->operand[i];
            if (not bh_is_constant(&v)) {
                bases.insert(v.base);
            }
        }
        // Add output to 'bases' and check if 'instr' creates a new array
        {
            bh_view &v = instr->operand[0];
            if (bases.find(v.base) == bases.end()) { // TODO: check if writing to whole array
                created_array = v.base;
            }
            bases.insert(v.base);
        }
        if (instr->opcode == BH_SYNC) {
            assert(nop == 1);
            syncs.insert(instr->operand[0].base);
        } else if (instr->opcode == BH_FREE) {
            assert(nop == 1);
            if (syncs.find(instr->operand[0].base) == syncs.end()) {
                // If the array is free'ed and not sync'ed, it can be destroyed
                destroyed_array = instr->operand[0].base;
            }
        }
        set<bh_base*> news, frees, tmps;
        if (created_array != NULL)
            news.insert(created_array);
        if (destroyed_array != NULL)
            frees.insert(destroyed_array);

        // Now that we have the news, frees, and tmps, we can create the single instruction block
        vector<bh_instruction*> single_instr = {&instr[0]};
        block_list.push_back(create_nested_block(single_instr, 0, news, frees, tmps));
    }
    return block_list;
}

// Check if 'a' and 'b' supports data-parallelism when merged
static bool data_parallel_compatible(const bh_instruction *a, const bh_instruction *b)
{
    if(bh_opcode_is_system(a->opcode) || bh_opcode_is_system(b->opcode))
        return true;

    const int a_nop = bh_noperands(a->opcode);
    for(int i=0; i<a_nop; ++i)
    {
        if(not bh_view_disjoint(&b->operand[0], &a->operand[i])
           && not bh_view_aligned(&b->operand[0], &a->operand[i]))
            return false;
    }
    const int b_nop = bh_noperands(b->opcode);
    for(int i=0; i<b_nop; ++i)
    {
        if(not bh_view_disjoint(&a->operand[0], &b->operand[i])
           && not bh_view_aligned(&a->operand[0], &b->operand[i]))
            return false;
    }
    return true;
}

// Check if 'b1' and 'b2' supports data-parallelism when merged
static bool data_parallel_compatible(const Block &b1, const Block &b2) {
    for (const bh_instruction *i1 : b1.getAllInstr()) {
        for (const bh_instruction *i2 : b2.getAllInstr()) {
            if (not data_parallel_compatible(i1, i2))
                return false;
        }
    }
    return true;
}

vector<Block> fuser_serial(vector<Block> &block_list) {
    vector<Block> ret;
    for (auto it = block_list.begin(); it != block_list.end(); ) {
        ret.push_back(*it);
        Block &cur = ret.back();
        ++it;
        if (cur.isInstr()) {
            continue; // We should never fuse instruction blocks
        }
        for (; it != block_list.end(); ++it) {
            // We start with general checks of fusibility
            if (it->isInstr())
                break;
            if (not data_parallel_compatible(cur, *it))
                break;
            if (cur._sweeps.size() > 0) //TODO: support merge of reduction
                break;
            assert(cur.rank == it->rank);

            // And then we check for shape match
            if (cur.size == it->size) { // Perfect match, directly mergeable
                cur.merge(*it);
            } else {
                break; // We couldn't find any shape match
            }
        }
        // Let's fuse at the next rank level
        cur._block_list = fuser_serial(cur._block_list);
    }
    return ret;
}

vector<Block> remove_empty_blocks(vector<Block> &block_list) {
    vector<Block> ret;
    for (Block &b: block_list) {
        if (b.getAllInstr().size() > 0)
            ret.push_back(b);
    }
    return ret;
}

void Impl::execute(bh_ir *bhir) {

    // Assign IDs to all base arrays
    IdMap<bh_base *> base_ids;
    // NB: by assigning the IDs in the order they appear in the 'instr_list',
    //     the kernels can better be reused
    for(const bh_instruction &instr: bhir->instr_list) {
        const int nop = bh_noperands(instr.opcode);
        for(int i=0; i<nop; ++i) {
            const bh_view &v = instr.operand[i];
            if (not bh_is_constant(&v)) {
                base_ids.insert(v.base);
            }
        }
    }
    // Do we have anything to do?
    if (base_ids.size() == 0)
        return;

    //Let's create a kernel
    Kernel kernel;
    {
        // Let's fuse the 'instr_list' into blocks
        kernel.block_list = fuser_singleton(bhir->instr_list);
        kernel.block_list = fuser_serial(kernel.block_list);
        kernel.block_list = remove_empty_blocks(kernel.block_list);

        // And fill kernel attributes
        for (bh_instruction &instr: bhir->instr_list) {
            if (instr.opcode == BH_RANDOM) {
                kernel.useRandom = true;
            } else if (instr.opcode == BH_FREE) {
                kernel.frees.insert(instr.operand[0].base);
            }
        }
    }

    // Do we even have any "real" operations to perform?
    if (kernel.block_list.size() == 0) {
        // Finally, let's cleanup
        for(bh_base *base: kernel.frees) {
            bh_data_free(base);
        }
        return;
    }

    // Debug print
    //cout << kernel.block_list;

    // Code generation
    stringstream ss;

    // Make sure all arrays are allocated
    for(bh_base *base: base_ids.getKeys()) {
        bh_data_malloc(base);
    }

    // Write the need includes
    ss << "#include <stdint.h>" << endl;
    ss << "#include <stdlib.h>" << endl;
    ss << "#include <stdbool.h>" << endl;
    ss << "#include <complex.h>" << endl;
    ss << "#include <tgmath.h>" << endl;
    ss << "#include <math.h>" << endl;
    ss << "#include <bh_memory.h>" << endl;
    ss << "#include <bh_type.h>" << endl;
    ss << endl;

    if (kernel.useRandom) { // Write the random function
        ss << "#include <Random123/philox.h>" << endl;
        ss << "uint64_t random123(uint64_t start, uint64_t key, uint64_t index) {" << endl;
        ss << "    union {philox2x32_ctr_t c; uint64_t ul;} ctr, res; " << endl;
        ss << "    ctr.ul = start + index; " << endl;
        ss << "    res.c = philox2x32(ctr.c, (philox2x32_key_t){{key}}); " << endl;
        ss << "    return res.ul; " << endl;
        ss << "} " << endl;
    }
    ss << endl;

    // Write the header of the execute function
    ss << "void execute(";
    for(size_t id=0; id < base_ids.size(); ++id) {
        const bh_base *b = base_ids.getKeys()[id];
        ss << write_type(b->type) << " a" << id << "[]";
        if (id+1 < base_ids.size()) {
            ss << ", ";
        }
    }
    ss << ") {" << endl;

    // Write the blocks that makes up the body of 'execute()'
    for(const Block &block: kernel.block_list) {
        write_block(base_ids, block, ss);
    }

    ss << "}" << endl << endl;

    // Write the launcher function, which will convert the data_list of void pointers
    // to typed arrays and call the execute function
    {
        ss << "void launcher(void* data_list[]) {" << endl;
        size_t i=0;
        for (bh_base *b: base_ids.getKeys()) {
            spaces(ss, 4);
            ss << write_type(b->type) << " *a" << base_ids[b];
            ss << " = data_list[" << i << "];" << endl;
            ++i;
        }
        spaces(ss, 4);
        ss << "execute(";
        for(size_t id=0; id < base_ids.size(); ++id) {
            ss << "a" << id;
            if (id+1 < base_ids.size()) {
                ss << ", ";
            }
        }
        ss << ");" << endl;
        ss << "}" << endl;
    }

  //  cout << ss.str();

    KernelFunction func = _store.getFunction(ss.str());
    assert(func != NULL);

    // Create a 'data_list' of data pointers
    vector<void*> data_list;
    data_list.reserve(base_ids.size());
    for(bh_base *base: base_ids.getKeys()) {
        assert(base->data != NULL);
        data_list.push_back(base->data);
    }

    // Call the launcher function with the 'data_list', which will execute the kernel
    func(&data_list[0]);
    // Finally, let's cleanup
    for(bh_base *base: kernel.frees) {
        bh_data_free(base);
    }
}

<|endoftext|>


<commit_before>// Time:  O(n)
// Space: O(1)

// DP with rolling window.
class Solution {
public:
    /**
     * @param values: a vector of integers
     * @return: a boolean which equals to true if the first player will win
     */
    bool firstWillWin(vector<int> &values) {
        // For boundary case.
        if (values.size() < 2) {
            return values.size() % 2 == 1;
        }

        vector<int> P(5, 0);
        int sum = 0;
        // P[i] = max(values[i] + min(P[i + 2], P[i + 3]),
        //            values[i] + values[i + 1] + min(P[i + 3], P[i + 4]))
        for (int i = values.size() - 1; i >= 0; --i) {
            sum += values[i];
            int values_i_plus_1 = i + 1 < values.size() ? values[i + 1]: 0;
            int a = i + 2 < values.size() ? P[(i + 2) % 5] : 0;
            int b = i + 3 < values.size() ? P[(i + 3) % 5] : 0;
            int c = i + 4 < values.size() ? P[(i + 4) % 5] : 0;
            P[i % 5] = max(values[i] + min(a, b),
                           values[i] + values_i_plus_1 + min(b, c));
        }

        return P[0] > sum - P[0];
    }
};

// Time:  O(n)
// Space: O(n)
class Solution2 {
public:
    /**
     * @param values: a vector of integers
     * @return: a boolean which equals to true if the first player will win
     */
    bool firstWillWin(vector<int> &values) {
        // For boundary case.
        if (values.size() < 2) {
            return values.size() % 2 == 1;
        }

        vector<int> P(values.size(), 0);
        int sum = 0;
        // P[i] = max(values[i] + min(P[i + 2], P[i + 3]),
        //            values[i] + values[i + 1] + min(P[i + 3], P[i + 4]))
        for (int i = values.size() - 1; i >= 0; --i) {
            sum += values[i];
            int values_i_plus_1 = i + 1 < values.size() ? values[i + 1]: 0;
            int a = i + 2 < values.size() ? P[i + 2] : 0;
            int b = i + 3 < values.size() ? P[i + 3] : 0;
            int c = i + 4 < values.size() ? P[i + 4] : 0;
            P[i] = max(values[i] + min(a, b),
                       values[i] + values_i_plus_1 + min(b, c));
        }

        return P[0] > sum - P[0];
    }
};
<commit_msg>Update coins-in-a-line-ii.cpp<commit_after>// Time:  O(n)
// Space: O(1)

// DP with rolling window.
class Solution {
public:
    /**
     * @param values: a vector of integers
     * @return: a boolean which equals to true if the first player will win
     */
    bool firstWillWin(vector<int> &values) {
        // For boundary case.
        if (values.size() < 2) {
            return values.size() % 2 == 1;
        }

        vector<int> P(5, 0);
        int sum = 0;
        for (int i = values.size() - 1; i >= 0; --i) {
            sum += values[i];
            int values_i_plus_1 = i + 1 < values.size() ? values[i + 1]: 0;
            int a = i + 2 < values.size() ? P[(i + 2) % 5] : 0;
            int b = i + 3 < values.size() ? P[(i + 3) % 5] : 0;
            int c = i + 4 < values.size() ? P[(i + 4) % 5] : 0;
            // P[i] = max(values[i] + min(P[i + 2], P[i + 3]),
            //            values[i] + values[i + 1] + min(P[i + 3], P[i + 4]))
            P[i % 5] = max(values[i] + min(a, b),
                           values[i] + values_i_plus_1 + min(b, c));
        }

        return P[0] > sum - P[0];
    }
};

// Time:  O(n)
// Space: O(n)
class Solution2 {
public:
    /**
     * @param values: a vector of integers
     * @return: a boolean which equals to true if the first player will win
     */
    bool firstWillWin(vector<int> &values) {
        // For boundary case.
        if (values.size() < 2) {
            return values.size() % 2 == 1;
        }

        vector<int> P(values.size(), 0);
        int sum = 0;
        for (int i = values.size() - 1; i >= 0; --i) {
            sum += values[i];
            int values_i_plus_1 = i + 1 < values.size() ? values[i + 1]: 0;
            int a = i + 2 < values.size() ? P[i + 2] : 0;
            int b = i + 3 < values.size() ? P[i + 3] : 0;
            int c = i + 4 < values.size() ? P[i + 4] : 0;
            // P[i] = max(values[i] + min(P[i + 2], P[i + 3]),
            //            values[i] + values[i + 1] + min(P[i + 3], P[i + 4]))
            P[i] = max(values[i] + min(a, b),
                       values[i] + values_i_plus_1 + min(b, c));
        }

        return P[0] > sum - P[0];
    }
};
<|endoftext|>