//===- AArch64LegalizerInfo.cpp ----------------------------------*- C++ -*-==//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
/// \file
/// This file implements the targeting of the Machinelegalizer class for
/// AArch64.
/// \todo This should be generated by TableGen.
//===----------------------------------------------------------------------===//

#include "AArch64LegalizerInfo.h"
#include "llvm/CodeGen/GlobalISel/MachineIRBuilder.h"
#include "llvm/CodeGen/MachineInstr.h"
#include "llvm/CodeGen/MachineRegisterInfo.h"
#include "llvm/CodeGen/ValueTypes.h"
#include "llvm/IR/DerivedTypes.h"
#include "llvm/IR/Type.h"
#include "llvm/Target/TargetOpcodes.h"

using namespace llvm;

#ifndef LLVM_BUILD_GLOBAL_ISEL
#error "You shouldn't build this"
#endif

AArch64LegalizerInfo::AArch64LegalizerInfo() {
  using namespace TargetOpcode;
  const LLT p0 = LLT::pointer(0, 64);
  const LLT s1 = LLT::scalar(1);
  const LLT s8 = LLT::scalar(8);
  const LLT s16 = LLT::scalar(16);
  const LLT s32 = LLT::scalar(32);
  const LLT s64 = LLT::scalar(64);
  const LLT v2s32 = LLT::vector(2, 32);
  const LLT v4s32 = LLT::vector(4, 32);
  const LLT v2s64 = LLT::vector(2, 64);

  for (auto Ty : {p0, s1, s8, s16, s32, s64})
    setAction({G_IMPLICIT_DEF, Ty}, Legal);

  for (unsigned BinOp : {G_ADD, G_SUB, G_MUL, G_AND, G_OR, G_XOR, G_SHL}) {
    // These operations naturally get the right answer when used on
    // GPR32, even if the actual type is narrower.
    for (auto Ty : {s32, s64, v2s32, v4s32, v2s64})
      setAction({BinOp, Ty}, Legal);

    for (auto Ty : {s1, s8, s16})
      setAction({BinOp, Ty}, WidenScalar);
  }

  setAction({G_GEP, p0}, Legal);
  setAction({G_GEP, 1, s64}, Legal);

  for (auto Ty : {s1, s8, s16, s32})
    setAction({G_GEP, 1, Ty}, WidenScalar);

  setAction({G_PTR_MASK, p0}, Legal);

  for (unsigned BinOp : {G_LSHR, G_ASHR, G_SDIV, G_UDIV}) {
    for (auto Ty : {s32, s64})
      setAction({BinOp, Ty}, Legal);

    for (auto Ty : {s1, s8, s16})
      setAction({BinOp, Ty}, WidenScalar);
  }

  for (unsigned BinOp : {G_SREM, G_UREM})
    for (auto Ty : { s1, s8, s16, s32, s64 })
      setAction({BinOp, Ty}, Lower);

  for (unsigned Op : {G_SMULO, G_UMULO})
      setAction({Op, s64}, Lower);

  for (unsigned Op : {G_UADDE, G_USUBE, G_SADDO, G_SSUBO, G_SMULH, G_UMULH}) {
    for (auto Ty : { s32, s64 })
      setAction({Op, Ty}, Legal);

    setAction({Op, 1, s1}, Legal);
  }

  for (unsigned BinOp : {G_FADD, G_FSUB, G_FMA, G_FMUL, G_FDIV})
    for (auto Ty : {s32, s64})
      setAction({BinOp, Ty}, Legal);

  for (unsigned BinOp : {G_FREM, G_FPOW}) {
    setAction({BinOp, s32}, Libcall);
    setAction({BinOp, s64}, Libcall);
  }

  for (auto Ty : {s32, s64, p0}) {
    setAction({G_INSERT, Ty}, Legal);
    setAction({G_INSERT, 1, Ty}, Legal);
  }
  for (auto Ty : {s1, s8, s16}) {
    setAction({G_INSERT, Ty}, WidenScalar);
    setAction({G_INSERT, 1, Ty}, Legal);
    // FIXME: Can't widen the sources because that violates the constraints on
    // G_INSERT (It seems entirely reasonable that inputs shouldn't overlap).
  }

  for (auto Ty : {s1, s8, s16, s32, s64, p0})
    setAction({G_EXTRACT, Ty}, Legal);

  for (auto Ty : {s32, s64})
    setAction({G_EXTRACT, 1, Ty}, Legal);

  for (unsigned MemOp : {G_LOAD, G_STORE}) {
    for (auto Ty : {s8, s16, s32, s64, p0, v2s32})
      setAction({MemOp, Ty}, Legal);

    setAction({MemOp, s1}, WidenScalar);

    // And everything's fine in addrspace 0.
    setAction({MemOp, 1, p0}, Legal);
  }

  // Constants
  for (auto Ty : {s32, s64}) {
    setAction({TargetOpcode::G_CONSTANT, Ty}, Legal);
    setAction({TargetOpcode::G_FCONSTANT, Ty}, Legal);
  }

  setAction({G_CONSTANT, p0}, Legal);

  for (auto Ty : {s1, s8, s16})
    setAction({TargetOpcode::G_CONSTANT, Ty}, WidenScalar);

  setAction({TargetOpcode::G_FCONSTANT, s16}, WidenScalar);

  setAction({G_ICMP, s1}, Legal);
  setAction({G_ICMP, 1, s32}, Legal);
  setAction({G_ICMP, 1, s64}, Legal);
  setAction({G_ICMP, 1, p0}, Legal);

  for (auto Ty : {s1, s8, s16}) {
    setAction({G_ICMP, 1, Ty}, WidenScalar);
  }

  setAction({G_FCMP, s1}, Legal);
  setAction({G_FCMP, 1, s32}, Legal);
  setAction({G_FCMP, 1, s64}, Legal);

  // Extensions
  for (auto Ty : { s1, s8, s16, s32, s64 }) {
    setAction({G_ZEXT, Ty}, Legal);
    setAction({G_SEXT, Ty}, Legal);
    setAction({G_ANYEXT, Ty}, Legal);
  }

  for (auto Ty : { s1, s8, s16, s32 }) {
    setAction({G_ZEXT, 1, Ty}, Legal);
    setAction({G_SEXT, 1, Ty}, Legal);
    setAction({G_ANYEXT, 1, Ty}, Legal);
  }

  setAction({G_FPEXT, s64}, Legal);
  setAction({G_FPEXT, 1, s32}, Legal);

  // Truncations
  for (auto Ty : { s16, s32 })
    setAction({G_FPTRUNC, Ty}, Legal);

  for (auto Ty : { s32, s64 })
    setAction({G_FPTRUNC, 1, Ty}, Legal);

  for (auto Ty : { s1, s8, s16, s32 })
    setAction({G_TRUNC, Ty}, Legal);

  for (auto Ty : { s8, s16, s32, s64 })
    setAction({G_TRUNC, 1, Ty}, Legal);

  // Conversions
  for (auto Ty : { s32, s64 }) {
    setAction({G_FPTOSI, 0, Ty}, Legal);
    setAction({G_FPTOUI, 0, Ty}, Legal);
    setAction({G_SITOFP, 1, Ty}, Legal);
    setAction({G_UITOFP, 1, Ty}, Legal);
  }
  for (auto Ty : { s1, s8, s16 }) {
    setAction({G_FPTOSI, 0, Ty}, WidenScalar);
    setAction({G_FPTOUI, 0, Ty}, WidenScalar);
    setAction({G_SITOFP, 1, Ty}, WidenScalar);
    setAction({G_UITOFP, 1, Ty}, WidenScalar);
  }

  for (auto Ty : { s32, s64 }) {
    setAction({G_FPTOSI, 1, Ty}, Legal);
    setAction({G_FPTOUI, 1, Ty}, Legal);
    setAction({G_SITOFP, 0, Ty}, Legal);
    setAction({G_UITOFP, 0, Ty}, Legal);
  }

  // Control-flow
  for (auto Ty : {s1, s8, s16, s32})
    setAction({G_BRCOND, Ty}, Legal);
  setAction({G_BRINDIRECT, p0}, Legal);

  // Select
  for (auto Ty : {s1, s8, s16})
    setAction({G_SELECT, Ty}, WidenScalar);

  for (auto Ty : {s32, s64, p0})
    setAction({G_SELECT, Ty}, Legal);

  setAction({G_SELECT, 1, s1}, Legal);

  // Pointer-handling
  setAction({G_FRAME_INDEX, p0}, Legal);
  setAction({G_GLOBAL_VALUE, p0}, Legal);

  for (auto Ty : {s1, s8, s16, s32, s64})
    setAction({G_PTRTOINT, 0, Ty}, Legal);

  setAction({G_PTRTOINT, 1, p0}, Legal);

  setAction({G_INTTOPTR, 0, p0}, Legal);
  setAction({G_INTTOPTR, 1, s64}, Legal);

  // Casts for 32 and 64-bit width type are just copies.
  for (auto Ty : {s1, s8, s16, s32, s64}) {
    setAction({G_BITCAST, 0, Ty}, Legal);
    setAction({G_BITCAST, 1, Ty}, Legal);
  }

  // For the sake of copying bits around, the type does not really
  // matter as long as it fits a register.
  for (int EltSize = 8; EltSize <= 64; EltSize *= 2) {
    setAction({G_BITCAST, 0, LLT::vector(128/EltSize, EltSize)}, Legal);
    setAction({G_BITCAST, 1, LLT::vector(128/EltSize, EltSize)}, Legal);
    if (EltSize >= 64)
      continue;

    setAction({G_BITCAST, 0, LLT::vector(64/EltSize, EltSize)}, Legal);
    setAction({G_BITCAST, 1, LLT::vector(64/EltSize, EltSize)}, Legal);
    if (EltSize >= 32)
      continue;

    setAction({G_BITCAST, 0, LLT::vector(32/EltSize, EltSize)}, Legal);
    setAction({G_BITCAST, 1, LLT::vector(32/EltSize, EltSize)}, Legal);
  }

  setAction({G_VASTART, p0}, Legal);

  // va_list must be a pointer, but most sized types are pretty easy to handle
  // as the destination.
  setAction({G_VAARG, 1, p0}, Legal);

  for (auto Ty : {s8, s16, s32, s64, p0})
    setAction({G_VAARG, Ty}, Custom);

  computeTables();
}

bool AArch64LegalizerInfo::legalizeCustom(MachineInstr &MI,
                                          MachineRegisterInfo &MRI,
                                          MachineIRBuilder &MIRBuilder) const {
  switch (MI.getOpcode()) {
  default:
    // No idea what to do.
    return false;
  case TargetOpcode::G_VAARG:
    return legalizeVaArg(MI, MRI, MIRBuilder);
  }

  llvm_unreachable("expected switch to return");
}

bool AArch64LegalizerInfo::legalizeVaArg(MachineInstr &MI,
                                         MachineRegisterInfo &MRI,
                                         MachineIRBuilder &MIRBuilder) const {
  MIRBuilder.setInstr(MI);
  MachineFunction &MF = MIRBuilder.getMF();
  unsigned Align = MI.getOperand(2).getImm();
  unsigned Dst = MI.getOperand(0).getReg();
  unsigned ListPtr = MI.getOperand(1).getReg();

  LLT PtrTy = MRI.getType(ListPtr);
  LLT IntPtrTy = LLT::scalar(PtrTy.getSizeInBits());

  const unsigned PtrSize = PtrTy.getSizeInBits() / 8;
  unsigned List = MRI.createGenericVirtualRegister(PtrTy);
  MIRBuilder.buildLoad(
      List, ListPtr,
      *MF.getMachineMemOperand(MachinePointerInfo(), MachineMemOperand::MOLoad,
                               PtrSize, /* Align = */ PtrSize));

  unsigned DstPtr;
  if (Align > PtrSize) {
    // Realign the list to the actual required alignment.
    auto AlignMinus1 = MIRBuilder.buildConstant(IntPtrTy, Align - 1);

    unsigned ListTmp = MRI.createGenericVirtualRegister(PtrTy);
    MIRBuilder.buildGEP(ListTmp, List, AlignMinus1->getOperand(0).getReg());

    DstPtr = MRI.createGenericVirtualRegister(PtrTy);
    MIRBuilder.buildPtrMask(DstPtr, ListTmp, Log2_64(Align));
  } else
    DstPtr = List;

  uint64_t ValSize = MRI.getType(Dst).getSizeInBits() / 8;
  MIRBuilder.buildLoad(
      Dst, DstPtr,
      *MF.getMachineMemOperand(MachinePointerInfo(), MachineMemOperand::MOLoad,
                               ValSize, std::max(Align, PtrSize)));

  unsigned SizeReg = MRI.createGenericVirtualRegister(IntPtrTy);
  MIRBuilder.buildConstant(SizeReg, alignTo(ValSize, PtrSize));

  unsigned NewList = MRI.createGenericVirtualRegister(PtrTy);
  MIRBuilder.buildGEP(NewList, DstPtr, SizeReg);

  MIRBuilder.buildStore(
      NewList, ListPtr,
      *MF.getMachineMemOperand(MachinePointerInfo(), MachineMemOperand::MOStore,
                               PtrSize, /* Align = */ PtrSize));

  MI.eraseFromParent();
  return true;
}


@import url("https://fonts.googleapis.com/css?family=Roboto+Mono|Source+Sans+Pro:300,400,600");
* {
  -webkit-font-smoothing: antialiased;
  -webkit-overflow-scrolling: touch;
  -webkit-tap-highlight-color: rgba(0,0,0,0);
  -webkit-text-size-adjust: none;
  -webkit-touch-callout: none;
  box-sizing: border-box;
}
body:not(.ready) {
  overflow: hidden;
}
body:not(.ready) [data-cloak],
body:not(.ready) .app-nav,
body:not(.ready) > nav {
  display: none;
}
div#app {
  font-size: 30px;
  font-weight: lighter;
  margin: 40vh auto;
  text-align: center;
}
div#app:empty::before {
  content: 'Loading...';
}
.emoji {
  height: 1.2rem;
  vertical-align: middle;
}
.progress {
  background-color: var(--theme-color, #42b983);
  height: 2px;
  left: 0px;
  position: fixed;
  right: 0px;
  top: 0px;
  transition: width 0.2s, opacity 0.4s;
  width: 0%;
  z-index: 999999;
}
.search a:hover {
  color: var(--theme-color, #42b983);
}
.search .search-keyword {
  color: var(--theme-color, #42b983);
  font-style: normal;
  font-weight: bold;
}
html,
body {
  height: 100%;
}
body {
  -moz-osx-font-smoothing: grayscale;
  -webkit-font-smoothing: antialiased;
  color: #34495e;
  font-family: 'Source Sans Pro', 'Helvetica Neue', Arial, sans-serif;
  font-size: 15px;
  letter-spacing: 0;
  margin: 0;
  overflow-x: hidden;
}
img {
  max-width: 100%;
}
a[disabled] {
  cursor: not-allowed;
  opacity: 0.6;
}
kbd {
  border: solid 1px #ccc;
  border-radius: 3px;
  display: inline-block;
  font-size: 12px !important;
  line-height: 12px;
  margin-bottom: 3px;
  padding: 3px 5px;
  vertical-align: middle;
}
li input[type='checkbox'] {
  margin: 0 0.2em 0.25em 0;
  vertical-align: middle;
}
.app-nav {
  margin: 25px 60px 0 0;
  position: absolute;
  right: 0;
  text-align: right;
  z-index: 10;
/* navbar dropdown */
}
.app-nav.no-badge {
  margin-right: 25px;
}
.app-nav p {
  margin: 0;
}
.app-nav > a {
  margin: 0 1rem;
  padding: 5px 0;
}
.app-nav ul,
.app-nav li {
  display: inline-block;
  list-style: none;
  margin: 0;
}
.app-nav a {
  color: inherit;
  font-size: 16px;
  text-decoration: none;
  transition: color 0.3s;
}
.app-nav a:hover {
  color: var(--theme-color, #42b983);
}
.app-nav a.active {
  border-bottom: 2px solid var(--theme-color, #42b983);
  color: var(--theme-color, #42b983);
}
.app-nav li {
  display: inline-block;
  margin: 0 1rem;
  padding: 5px 0;
  position: relative;
  cursor: pointer;
}
.app-nav li ul {
  background-color: #fff;
  border: 1px solid #ddd;
  border-bottom-color: #ccc;
  border-radius: 4px;
  box-sizing: border-box;
  display: none;
  max-height: calc(100vh - 61px);
  overflow-y: auto;
  padding: 10px 0;
  position: absolute;
  right: -15px;
  text-align: left;
  top: 100%;
  white-space: nowrap;
}
.app-nav li ul li {
  display: block;
  font-size: 14px;
  line-height: 1rem;
  margin: 0;
  margin: 8px 14px;
  white-space: nowrap;
}
.app-nav li ul a {
  display: block;
  font-size: inherit;
  margin: 0;
  padding: 0;
}
.app-nav li ul a.active {
  border-bottom: 0;
}
.app-nav li:hover ul {
  display: block;
}
.github-corner {
  border-bottom: 0;
  position: fixed;
  right: 0;
  text-decoration: none;
  top: 0;
  z-index: 1;
}
.github-corner:hover .octo-arm {
  -webkit-animation: octocat-wave 560ms ease-in-out;
          animation: octocat-wave 560ms ease-in-out;
}
.github-corner svg {
  color: #fff;
  fill: var(--theme-color, #42b983);
  height: 80px;
  width: 80px;
}
main {
  display: block;
  position: relative;
  width: 100vw;
  height: 100%;
  z-index: 0;
}
main.hidden {
  display: none;
}
.anchor {
  display: inline-block;
  text-decoration: none;
  transition: all 0.3s;
}
.anchor span {
  color: #34495e;
}
.anchor:hover {
  text-decoration: underline;
}
.sidebar {
  border-right: 1px solid rgba(0,0,0,0.07);
  overflow-y: auto;
  padding: 40px 0 0;
  position: absolute;
  top: 0;
  bottom: 0;
  left: 0;
  transition: transform 250ms ease-out;
  width: 300px;
  z-index: 20;
}
.sidebar > h1 {
  margin: 0 auto 1rem;
  font-size: 1.5rem;
  font-weight: 300;
  text-align: center;
}
.sidebar > h1 a {
  color: inherit;
  text-decoration: none;
}
.sidebar > h1 .app-nav {
  display: block;
  position: static;
}
.sidebar .sidebar-nav {
  line-height: 2em;
  padding-bottom: 40px;
}
.sidebar li.collapse .app-sub-sidebar {
  display: none;
}
.sidebar ul {
  margin: 0 0 0 15px;
  padding: 0;
}
.sidebar li > p {
  font-weight: 700;
  margin: 0;
}
.sidebar ul,
.sidebar ul li {
  list-style: none;
}
.sidebar ul li a {
  border-bottom: none;
  display: block;
}
.sidebar ul li ul {
  padding-left: 20px;
}
.sidebar::-webkit-scrollbar {
  width: 4px;
}
.sidebar::-webkit-scrollbar-thumb {
  background: transparent;
  border-radius: 4px;
}
.sidebar:hover::-webkit-scrollbar-thumb {
  background: rgba(136,136,136,0.4);
}
.sidebar:hover::-webkit-scrollbar-track {
  background: rgba(136,136,136,0.1);
}
.sidebar-toggle {
  background-color: transparent;
  background-color: rgba(255,255,255,0.8);
  border: 0;
  outline: none;
  padding: 10px;
  position: absolute;
  bottom: 0;
  left: 0;
  text-align: center;
  transition: opacity 0.3s;
  width: 284px;
  z-index: 30;
  cursor: pointer;
}
.sidebar-toggle:hover .sidebar-toggle-button {
  opacity: 0.4;
}
.sidebar-toggle span {
  background-color: var(--theme-color, #42b983);
  display: block;
  margin-bottom: 4px;
  width: 16px;
  height: 2px;
}
body.sticky .sidebar,
body.sticky .sidebar-toggle {
  position: fixed;
}
.content {
  padding-top: 60px;
  position: absolute;
  top: 0;
  right: 0;
  bottom: 0;
  left: 300px;
  transition: left 250ms ease;
}
.markdown-section {
  margin: 0 auto;
  max-width: 80%;
  padding: 30px 15px 40px 15px;
  position: relative;
}
.markdown-section > * {
  box-sizing: border-box;
  font-size: inherit;
}
.markdown-section > :first-child {
  margin-top: 0 !important;
}
.markdown-section hr {
  border: none;
  border-bottom: 1px solid #eee;
  margin: 2em 0;
}
.markdown-section iframe {
  border: 1px solid #eee;
/* fix horizontal overflow on iOS Safari */
  width: 1px;
  min-width: 100%;
}
.markdown-section table {
  border-collapse: collapse;
  border-spacing: 0;
  display: block;
  margin-bottom: 1rem;
  overflow: auto;
  width: 100%;
}
.markdown-section th {
  border: 1px solid #ddd;
  font-weight: bold;
  padding: 6px 13px;
}
.markdown-section td {
  border: 1px solid #ddd;
  padding: 6px 13px;
}
.markdown-section tr {
  border-top: 1px solid #ccc;
}
.markdown-section tr:nth-child(2n) {
  background-color: #f8f8f8;
}
.markdown-section p.tip {
  background-color: #f8f8f8;
  border-bottom-right-radius: 2px;
  border-left: 4px solid #f66;
  border-top-right-radius: 2px;
  margin: 2em 0;
  padding: 12px 24px 12px 30px;
  position: relative;
}
.markdown-section p.tip:before {
  background-color: #f66;
  border-radius: 100%;
  color: #fff;
  content: '!';
  font-family: 'Dosis', 'Source Sans Pro', 'Helvetica Neue', Arial, sans-serif;
  font-size: 14px;
  font-weight: bold;
  left: -12px;
  line-height: 20px;
  position: absolute;
  height: 20px;
  width: 20px;
  text-align: center;
  top: 14px;
}
.markdown-section p.tip code {
  background-color: #efefef;
}
.markdown-section p.tip em {
  color: #34495e;
}
.markdown-section p.warn {
  background: rgba(66,185,131,0.1);
  border-radius: 2px;
  padding: 1rem;
}
.markdown-section ul.task-list > li {
  list-style-type: none;
}
body.close .sidebar {
  transform: translateX(-300px);
}
body.close .sidebar-toggle {
  width: auto;
}
body.close .content {
  left: 0;
}
@media print {
  .github-corner,
  .sidebar-toggle,
  .sidebar,
  .app-nav {
    display: none;
  }
}
@media screen and (max-width: 768px) {
  .github-corner,
  .sidebar-toggle,
  .sidebar {
    position: fixed;
  }
  .app-nav {
    margin-top: 16px;
  }
  .app-nav li ul {
    top: 30px;
  }
  main {
    height: auto;
    overflow-x: hidden;
  }
  .sidebar {
    left: -300px;
    transition: transform 250ms ease-out;
  }
  .content {
    left: 0;
    max-width: 100vw;
    position: static;
    padding-top: 20px;
    transition: transform 250ms ease;
  }
  .app-nav,
  .github-corner {
    transition: transform 250ms ease-out;
  }
  .sidebar-toggle {
    background-color: transparent;
    width: auto;
    padding: 30px 30px 10px 10px;
  }
  body.close .sidebar {
    transform: translateX(300px);
  }
  body.close .sidebar-toggle {
    background-color: rgba(255,255,255,0.8);
    transition: 1s background-color;
    width: 284px;
    padding: 10px;
  }
  body.close .content {
    transform: translateX(300px);
  }
  body.close .app-nav,
  body.close .github-corner {
    display: none;
  }
  .github-corner:hover .octo-arm {
    -webkit-animation: none;
            animation: none;
  }
  .github-corner .octo-arm {
    -webkit-animation: octocat-wave 560ms ease-in-out;
            animation: octocat-wave 560ms ease-in-out;
  }
}
@-webkit-keyframes octocat-wave {
  0%, 100% {
    transform: rotate(0);
  }
  20%, 60% {
    transform: rotate(-25deg);
  }
  40%, 80% {
    transform: rotate(10deg);
  }
}
@keyframes octocat-wave {
  0%, 100% {
    transform: rotate(0);
  }
  20%, 60% {
    transform: rotate(-25deg);
  }
  40%, 80% {
    transform: rotate(10deg);
  }
}
section.cover {
  align-items: center;
  background-position: center center;
  background-repeat: no-repeat;
  background-size: cover;
  height: 100vh;
  display: none;
}
section.cover.show {
  display: flex;
}
section.cover.has-mask .mask {
  background-color: #fff;
  opacity: 0.8;
  position: absolute;
  top: 0;
  height: 100%;
  width: 100%;
}
section.cover .cover-main {
  flex: 1;
  margin: -20px 16px 0;
  text-align: center;
  z-index: 1;
}
section.cover a {
  color: inherit;
  text-decoration: none;
}
section.cover a:hover {
  text-decoration: none;
}
section.cover p {
  line-height: 1.5rem;
  margin: 1em 0;
}
section.cover h1 {
  color: inherit;
  font-size: 2.5rem;
  font-weight: 300;
  margin: 0.625rem 0 2.5rem;
  position: relative;
  text-align: center;
}
section.cover h1 a {
  display: block;
}
section.cover h1 small {
  bottom: -0.4375rem;
  font-size: 1rem;
  position: absolute;
}
section.cover blockquote {
  font-size: 1.5rem;
  text-align: center;
}
section.cover ul {
  line-height: 1.8;
  list-style-type: none;
  margin: 1em auto;
  max-width: 500px;
  padding: 0;
}
section.cover .cover-main > p:last-child a {
  border-color: var(--theme-color, #42b983);
  border-radius: 2rem;
  border-style: solid;
  border-width: 1px;
  box-sizing: border-box;
  color: var(--theme-color, #42b983);
  display: inline-block;
  font-size: 1.05rem;
  letter-spacing: 0.1rem;
  margin: 0.5rem 1rem;
  padding: 0.75em 2rem;
  text-decoration: none;
  transition: all 0.15s ease;
}
section.cover .cover-main > p:last-child a:last-child {
  background-color: var(--theme-color, #42b983);
  color: #fff;
}
section.cover .cover-main > p:last-child a:last-child:hover {
  color: inherit;
  opacity: 0.8;
}
section.cover .cover-main > p:last-child a:hover {
  color: inherit;
}
section.cover blockquote > p > a {
  border-bottom: 2px solid var(--theme-color, #42b983);
  transition: color 0.3s;
}
section.cover blockquote > p > a:hover {
  color: var(--theme-color, #42b983);
}
body {
  background-color: #fff;
}
/* sidebar */
.sidebar {
  background-color: #fff;
  color: #364149;
}
.sidebar li {
  margin: 6px 0 6px 0;
}
.sidebar ul li a {
  color: #505d6b;
  font-size: 14px;
  font-weight: normal;
  overflow: hidden;
  text-decoration: none;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.sidebar ul li a:hover {
  text-decoration: underline;
}
.sidebar ul li ul {
  padding: 0;
}
.sidebar ul li.active > a {
  border-right: 2px solid;
  color: var(--theme-color, #42b983);
  font-weight: 600;
}
.app-sub-sidebar li::before {
  content: '-';
  padding-right: 4px;
  float: left;
}
/* markdown content found on pages */
.markdown-section h1,
.markdown-section h2,
.markdown-section h3,
.markdown-section h4,
.markdown-section strong {
  color: #2c3e50;
  font-weight: 600;
}
.markdown-section a {
  color: var(--theme-color, #42b983);
  font-weight: 600;
}
.markdown-section h1 {
  font-size: 2rem;
  margin: 0 0 1rem;
}
.markdown-section h2 {
  font-size: 1.75rem;
  margin: 45px 0 0.8rem;
}
.markdown-section h3 {
  font-size: 1.5rem;
  margin: 40px 0 0.6rem;
}
.markdown-section h4 {
  font-size: 1.25rem;
}
.markdown-section h5 {
  font-size: 1rem;
}
.markdown-section h6 {
  color: #777;
  font-size: 1rem;
}
.markdown-section figure,
.markdown-section p {
  margin: 1.2em 0;
}
.markdown-section p,
.markdown-section ul,
.markdown-section ol {
  line-height: 1.6rem;
  word-spacing: 0.05rem;
}
.markdown-section ul,
.markdown-section ol {
  padding-left: 1.5rem;
}
.markdown-section blockquote {
  border-left: 4px solid var(--theme-color, #42b983);
  color: #858585;
  margin: 2em 0;
  padding-left: 20px;
}
.markdown-section blockquote p {
  font-weight: 600;
  margin-left: 0;
}
.markdown-section iframe {
  margin: 1em 0;
}
.markdown-section em {
  color: #7f8c8d;
}
.markdown-section code {
  background-color: #f8f8f8;
  border-radius: 2px;
  color: #e96900;
  font-family: 'Roboto Mono', Monaco, courier, monospace;
  font-size: 0.8rem;
  margin: 0 2px;
  padding: 3px 5px;
  white-space: pre-wrap;
}
.markdown-section pre {
  -moz-osx-font-smoothing: initial;
  -webkit-font-smoothing: initial;
  background-color: #f8f8f8;
  font-family: 'Roboto Mono', Monaco, courier, monospace;
  line-height: 1.5rem;
  margin: 1.2em 0;
  overflow: auto;
  padding: 0 1.4rem;
  position: relative;
  word-wrap: normal;
}
/* code highlight */
.token.comment,
.token.prolog,
.token.doctype,
.token.cdata {
  color: #8e908c;
}
.token.namespace {
  opacity: 0.7;
}
.token.boolean,
.token.number {
  color: #c76b29;
}
.token.punctuation {
  color: #525252;
}
.token.property {
  color: #c08b30;
}
.token.tag {
  color: #2973b7;
}
.token.string {
  color: var(--theme-color, #42b983);
}
.token.selector {
  color: #6679cc;
}
.token.attr-name {
  color: #2973b7;
}
.token.entity,
.token.url,
.language-css .token.string,
.style .token.string {
  color: #22a2c9;
}
.token.attr-value,
.token.control,
.token.directive,
.token.unit {
  color: var(--theme-color, #42b983);
}
.token.keyword,
.token.function {
  color: #e96900;
}
.token.statement,
.token.regex,
.token.atrule {
  color: #22a2c9;
}
.token.placeholder,
.token.variable {
  color: #3d8fd1;
}
.token.deleted {
  text-decoration: line-through;
}
.token.inserted {
  border-bottom: 1px dotted #202746;
  text-decoration: none;
}
.token.italic {
  font-style: italic;
}
.token.important,
.token.bold {
  font-weight: bold;
}
.token.important {
  color: #c94922;
}
.token.entity {
  cursor: help;
}
.markdown-section pre > code {
  -moz-osx-font-smoothing: initial;
  -webkit-font-smoothing: initial;
  background-color: #f8f8f8;
  border-radius: 2px;
  color: #525252;
  display: block;
  font-family: 'Roboto Mono', Monaco, courier, monospace;
  font-size: 0.8rem;
  line-height: inherit;
  margin: 0 2px;
  max-width: inherit;
  overflow: inherit;
  padding: 2.2em 5px;
  white-space: inherit;
}
.markdown-section code::after,
.markdown-section code::before {
  letter-spacing: 0.05rem;
}
code .token {
  -moz-osx-font-smoothing: initial;
  -webkit-font-smoothing: initial;
  min-height: 1.5rem;
  position: relative;
  left: auto;
}
pre::after {
  color: #ccc;
  content: attr(data-lang);
  font-size: 0.6rem;
  font-weight: 600;
  height: 15px;
  line-height: 15px;
  padding: 5px 10px 0;
  position: absolute;
  right: 0;
  text-align: right;
  top: 0;
}


'use strict';
var weak = require('./_collection-weak');

// 23.4 WeakSet Objects
require('./_collection')('WeakSet', function(get){
  return function WeakSet(){ return get(this, arguments.length > 0 ? arguments[0] : undefined); };
}, {
  // 23.4.3.1 WeakSet.prototype.add(value)
  add: function add(value){
    return weak.def(this, value, true);
  }
}, weak, false, true);


// Copyright (c) 2012, Suryandaru Triandana <syndtr@gmail.com>
// All rights reserved.
//
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

package filter

import (
	"encoding/binary"
	"github.com/syndtr/goleveldb/leveldb/util"
	"testing"
)

type harness struct {
	t *testing.T

	bloom     Filter
	generator FilterGenerator
	filter    []byte
}

func newHarness(t *testing.T) *harness {
	bloom := NewBloomFilter(10)
	return &harness{
		t:         t,
		bloom:     bloom,
		generator: bloom.NewGenerator(),
	}
}

func (h *harness) add(key []byte) {
	h.generator.Add(key)
}

func (h *harness) addNum(key uint32) {
	var b [4]byte
	binary.LittleEndian.PutUint32(b[:], key)
	h.add(b[:])
}

func (h *harness) build() {
	b := &util.Buffer{}
	h.generator.Generate(b)
	h.filter = b.Bytes()
}

func (h *harness) reset() {
	h.filter = nil
}

func (h *harness) filterLen() int {
	return len(h.filter)
}

func (h *harness) assert(key []byte, want, silent bool) bool {
	got := h.bloom.Contains(h.filter, key)
	if !silent && got != want {
		h.t.Errorf("assert on '%v' failed got '%v', want '%v'", key, got, want)
	}
	return got
}

func (h *harness) assertNum(key uint32, want, silent bool) bool {
	var b [4]byte
	binary.LittleEndian.PutUint32(b[:], key)
	return h.assert(b[:], want, silent)
}

func TestBloomFilter_Empty(t *testing.T) {
	h := newHarness(t)
	h.build()
	h.assert([]byte("hello"), false, false)
	h.assert([]byte("world"), false, false)
}

func TestBloomFilter_Small(t *testing.T) {
	h := newHarness(t)
	h.add([]byte("hello"))
	h.add([]byte("world"))
	h.build()
	h.assert([]byte("hello"), true, false)
	h.assert([]byte("world"), true, false)
	h.assert([]byte("x"), false, false)
	h.assert([]byte("foo"), false, false)
}

func nextN(n int) int {
	switch {
	case n < 10:
		n += 1
	case n < 100:
		n += 10
	case n < 1000:
		n += 100
	default:
		n += 1000
	}
	return n
}

func TestBloomFilter_VaryingLengths(t *testing.T) {
	h := newHarness(t)
	var mediocre, good int
	for n := 1; n < 10000; n = nextN(n) {
		h.reset()
		for i := 0; i < n; i++ {
			h.addNum(uint32(i))
		}
		h.build()

		got := h.filterLen()
		want := (n * 10 / 8) + 40
		if got > want {
			t.Errorf("filter len test failed, '%d' > '%d'", got, want)
		}

		for i := 0; i < n; i++ {
			h.assertNum(uint32(i), true, false)
		}

		var rate float32
		for i := 0; i < 10000; i++ {
			if h.assertNum(uint32(i+1000000000), true, true) {
				rate++
			}
		}
		rate /= 10000
		if rate > 0.02 {
			t.Errorf("false positive rate is more than 2%%, got %v, at len %d", rate, n)
		}
		if rate > 0.0125 {
			mediocre++
		} else {
			good++
		}
	}
	t.Logf("false positive rate: %d good, %d mediocre", good, mediocre)
	if mediocre > good/5 {
		t.Error("mediocre false positive rate is more than expected")
	}
}


<?php

namespace Foo\DataProviderIssue2833;

use PHPUnit\Framework\TestCase;

class FirstTest extends TestCase
{
    /**
     * @dataProvider provide
     */
    public function testFirst($x)
    {
        $this->assertTrue(true);
    }

    public function provide()
    {
        SecondTest::DUMMY;

        return [[true]];
    }
}


package ${content.dao.classPackage};
import java.util.List;

import ${content.assist.classPackage}.${content.assist.className};
import ${content.entity.classPackage}.${content.entity.className};

import org.apache.ibatis.annotations.Param;
/**
 * ${content.entity.className}的Dao接口
 *
 * @author
 *
 */
public interface ${content.dao.className} {

	/**
	 * 获得${content.entity.className}数据的总行数,可以通过辅助工具Assist进行条件查询,如果没有条件则传入null
	 *
	 * @param assist
	 * @return
	 */
	long ${content.dao.item.count.value!}(Assist assist);

	/**
	 * 获得${content.entity.className}数据集合,可以通过辅助工具Assist进行条件查询,如果没有条件则传入null
	 *
	 * @param assist
	 * @return
	 */
	List<${content.entity.className}> ${content.dao.item.select.value!}(Assist assist);
	<#if content.entity.primaryKeyAttr??>
	/**
	 * 通过${content.entity.className}的id获得${content.entity.className}对象
	 *
	 * @param id
	 * @return
	 */
	${content.entity.className} ${content.dao.item.selectById.value!}(${content.entity.primaryKeyAttr.javaType} id);
	</#if>

	/**
	 * 获得一个${content.entity.className}对象,以参数${content.entity.className}对象中不为空的属性作为条件进行查询,返回符合条件的第一条
	 *
	 * @param obj
	 * @return
	 */
	${content.entity.className} ${content.dao.item.selectByObjSingle.value!}(${content.entity.className} obj);

	/**
	 * 获得一个${content.entity.className}对象,以参数${content.entity.className}对象中不为空的属性作为条件进行查询
	 *
	 * @param obj
	 * @return
	 */
	List<${content.entity.className}> ${content.dao.item.selectByObj.value!}(${content.entity.className} obj);

	/**
	 * 插入${content.entity.className}到数据库,包括null值
	 *
	 * @param value
	 * @return
	 */
	int ${content.dao.item.insertAll.value!}(${content.entity.className} value);

	/**
	 * 插入${content.entity.className}中属性值不为null的数据到数据库
	 *
	 * @param value
	 * @return
	 */
	int ${content.dao.item.insertNotNull.value!}(${content.entity.className} value);

	/**
	 * 批量插入${content.entity.className}到数据库,包括null值
	 *
	 * @param value
	 * @return
	 */
	int ${content.dao.item.insertBatch.value!}(List<${content.entity.className}> value);
	<#if content.entity.primaryKeyAttr??>
	/**
	 * 通过${content.entity.className}的id删除${content.entity.className}
	 *
	 * @param id
	 * @return
	 */
	int ${content.dao.item.deleteById.value!}(${content.entity.primaryKeyAttr.javaType} id);
	</#if>

	/**
	 * 通过辅助工具Assist的条件删除${content.entity.className}
	 *
	 * @param assist
	 * @return
	 */
	int ${content.dao.item.deleteByAssist.value!}(Assist assist);

	<#if content.entity.primaryKeyAttr??>
	/**
	 * 通过${content.entity.className}的id更新${content.entity.className}中的数据,包括null值
	 *
	 * @param enti
	 * @return
	 */
	int ${content.dao.item.updateAllById.value!}(${content.entity.className} enti);

	/**
	 * 通过${content.entity.className}的id更新${content.entity.className}中属性不为null的数据
	 *
	 * @param enti
	 * @return
	 */
	int ${content.dao.item.updateNotNullById.value!}(${content.entity.className} enti);
	</#if>

	/**
	 * 通过辅助工具Assist的条件更新${content.entity.className}中的数据,包括null值
	 *
	 * @param value
	 * @param assist
	 * @return
	 */
	int ${content.dao.item.updateAllByAssist.value!}(@Param("enti") ${content.entity.className} value, @Param("assist") Assist assist);

	/**
	 * 通过辅助工具Assist的条件更新${content.entity.className}中属性不为null的数据
	 *
	 * @param value
	 * @param assist
	 * @return
	 */
	int ${content.dao.item.updateNotNullByAssist.value!}(@Param("enti") ${content.entity.className} value, @Param("assist") Assist assist);
}


# CNCF年度报告解读

CNCF成立于2015年12月11日，自2018年开始每年年初都会发布一次 CNCF Annual Report（CNCF 年度报告），总结 CNCF 去年一年里在推广云原生技术和理念上付出的行动和取得的进展，这一章节将从2018年的年度报告开始每年都会解读一次 CNCF 年度报告，2018年的年度报告延续了2017年年度报告的大体分类，但2017年的报告过于精简（只列举了一些活动与数字），本章不对其解读，而是从2018年的年度报告开始，感兴趣的读者可以下载其报告自行阅览。

## 参考

- [CNCF Annual Report 2017 pdf](https://www.cncf.io/wp-content/uploads/2018/03/CNCF-Annual-Report-2017.pdf)
- [CNCF Annual Report 2018 pdf](https://www.cncf.io/wp-content/uploads/2019/02/CNCF_Annual_Report_2018_FInal.pdf)
- [CNCF Annual Report 2019 pdf](https://www.cncf.io/wp-content/uploads/2020/02/CNCF-Annual-Report-2019.pdf)


/*
 * Copyright © 2018  Google, Inc.
 *
 *  This is part of HarfBuzz, a text shaping library.
 *
 * Permission is hereby granted, without written agreement and without
 * license or royalty fees, to use, copy, modify, and distribute this
 * software and its documentation for any purpose, provided that the
 * above copyright notice and the following two paragraphs appear in
 * all copies of this software.
 *
 * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
 * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
 * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
 * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
 * DAMAGE.
 *
 * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
 * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
 * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
 * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
 * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
 *
 * Google Author(s): Garret Rieger
 */

#ifndef HB_SUBSET_TEST_H
#define HB_SUBSET_TEST_H

#include <stdio.h>

#include "hb-test.h"
#include "hb-subset.h"

#ifdef HAVE_STDBOOL_H
# include <stdbool.h>
#else
typedef short bool;
# ifndef true
#  define true 1
# endif
# ifndef false
#  define false 0
# endif
#endif

HB_BEGIN_DECLS

static inline hb_subset_input_t *
hb_subset_test_create_input (const hb_set_t *codepoints)
{
  hb_subset_input_t *input = hb_subset_input_create_or_fail ();
  hb_set_t * input_codepoints = hb_subset_input_unicode_set (input);
  hb_set_union (input_codepoints, codepoints);
  return input;
}

static inline hb_subset_input_t *
hb_subset_test_create_input_from_glyphs (const hb_set_t *glyphs)
{
  hb_subset_input_t *input = hb_subset_input_create_or_fail ();
  hb_set_t * input_glyphs  = hb_subset_input_glyph_set (input);
  hb_set_union (input_glyphs, glyphs);
  return input;
}

static inline hb_subset_input_t *
hb_subset_test_create_input_from_nameids (const hb_set_t *name_ids)
{
  hb_subset_input_t *input = hb_subset_input_create_or_fail ();
  hb_set_t * input_name_ids  = hb_subset_input_nameid_set (input);
  hb_set_set (input_name_ids, name_ids);
  return input;
}

static inline hb_face_t *
hb_subset_test_create_subset (hb_face_t *source,
			      hb_subset_input_t *input)
{
  hb_face_t *subset = hb_subset (source, input);
  g_assert (subset);

  hb_subset_input_destroy (input);
  return subset;
}

static inline void
hb_subset_test_check (hb_face_t *expected,
		      hb_face_t *actual,
		      hb_tag_t   table)
{
  hb_blob_t *expected_blob, *actual_blob;
  expected_blob = hb_face_reference_table (expected, table);
  actual_blob = hb_face_reference_table (actual, table);
  fprintf(stderr, "comparing %c%c%c%c, expected %d bytes, actual %d bytes\n", HB_UNTAG(table), hb_blob_get_length(expected_blob), hb_blob_get_length (actual_blob));
  hb_test_assert_blobs_equal (expected_blob, actual_blob);
  hb_blob_destroy (expected_blob);
  hb_blob_destroy (actual_blob);
}

HB_END_DECLS

#endif /* HB_SUBSET_TEST_H */


server {

    listen {{ Arr::get($config, 'ports.http', 80) }};

    # server hostnames
    server_name {{ $hostname->fqdn }};

    # allow cross origin access
    add_header Access-Control-Allow-Origin *;
    add_header Access-Control-Request-Method GET;

    # root path of website; serve files from here
    root {{ public_path() }};
    index index.php;

    # logging
    access_log {{ storage_path('logs/')  }}{{ $hostname->fqdn }}.access.log;
    error_log {{ storage_path('logs/')  }}{{ $hostname->fqdn }}.error.log notice;

    @if($media)
    location ~* ^/media/(.+)$ {
        alias {{ $media }}/$1;
    }
    @endif

    location / {
        index index.php;
        try_files $uri $uri/ $uri/index.php?$args /index.php?$args;
    }

    # pass the PHP scripts to FastCGI server from upstream phpfcgi
    location ~ \.php(/|$) {
        fastcgi_pass {{ Arr::get($config, 'php-sock') }};
        include fastcgi_params;

        fastcgi_split_path_info ^(.+\.php)(/.*)$;

        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
    }
}


Dataframes are used for statistics, machine-learning, and data manipulation/exploration. You can think of a Dataframe as an excel spreadsheet.
This package is designed to be light-weight and intuitive.

⚠ The package is production ready but the API is not stable yet. Once stability is reached, version `1.0.0` will be tagged.
It is recommended your package manager locks to a commit id instead of the master branch directly. ⚠

⭐ **the project to show your appreciation.**

# Features

1. Importing from CSV, JSONL, MySQL & PostgreSQL
2. Exporting to CSV, JSONL, Excel, Parquet, MySQL & PostgreSQL
3. Developer Friendly
4. Flexible - Create custom Series (custom data types)
5. Performant
6. Interoperability with [gonum package](https://godoc.org/gonum.org/v1/gonum).
7. [pandas sub-package](https://pandas.pydata.org/pandas-docs/stable/reference/frame.html) ![Help Required](https://img.shields.io/badge/help-required-blueviolet)
8. Fake data generation
9. Interpolation (ForwardFill, BackwardFill, Linear, Spline, Lagrange)
10. Time-series Forecasting (SES, Holt-Winters)
11. Math functions
12. Plotting (cross-platform)

See [Tutorial](https://github.com/rocketlaunchr/dataframe-go#tutorial) here.

## Installation

```
go get -u github.com/rocketlaunchr/dataframe-go
```

```go
import dataframe "github.com/rocketlaunchr/dataframe-go"
```

# DataFrames

## Creating a DataFrame

```go

s1 := dataframe.NewSeriesInt64("day", nil, 1, 2, 3, 4, 5, 6, 7, 8)
s2 := dataframe.NewSeriesFloat64("sales", nil, 50.3, 23.4, 56.2, nil, nil, 84.2, 72, 89)
df := dataframe.NewDataFrame(s1, s2)

fmt.Print(df.Table())

OUTPUT:
+-----+-------+---------+
|     |  DAY  |  SALES  |
+-----+-------+---------+
| 0:  |   1   |  50.3   |
| 1:  |   2   |  23.4   |
| 2:  |   3   |  56.2   |
| 3:  |   4   |   NaN   |
| 4:  |   5   |   NaN   |
| 5:  |   6   |  84.2   |
| 6:  |   7   |   72    |
| 7:  |   8   |   89    |
+-----+-------+---------+
| 8X2 | INT64 | FLOAT64 |
+-----+-------+---------+

```
[![Go Playground](https://img.shields.io/badge/Go-Playground-5593c7.svg?labelColor=41c3f3&style=for-the-badge)](https://play.golang.org/p/eC5HYAEHjNI)

## Insert and Remove Row

```go

df.Append(nil, 9, 123.6)

df.Append(nil, map[string]interface{}{
	"day":   10,
	"sales": nil,
})

df.Remove(0)

OUTPUT:
+-----+-------+---------+
|     |  DAY  |  SALES  |
+-----+-------+---------+
| 0:  |   2   |  23.4   |
| 1:  |   3   |  56.2   |
| 2:  |   4   |   NaN   |
| 3:  |   5   |   NaN   |
| 4:  |   6   |  84.2   |
| 5:  |   7   |   72    |
| 6:  |   8   |   89    |
| 7:  |   9   |  123.6  |
| 8:  |  10   |   NaN   |
+-----+-------+---------+
| 9X2 | INT64 | FLOAT64 |
+-----+-------+---------+
```
[![Go Playground](https://img.shields.io/badge/Go-Playground-5593c7.svg?labelColor=41c3f3&style=for-the-badge)](https://play.golang.org/p/xwW_410vQ2p)

## Update Row

```go

df.UpdateRow(0, nil, map[string]interface{}{
	"day":   3,
	"sales": 45,
})

```

## Sorting

```go

sks := []dataframe.SortKey{
	{Key: "sales", Desc: true},
	{Key: "day", Desc: true},
}

df.Sort(ctx, sks)

OUTPUT:
+-----+-------+---------+
|     |  DAY  |  SALES  |
+-----+-------+---------+
| 0:  |   9   |  123.6  |
| 1:  |   8   |   89    |
| 2:  |   6   |  84.2   |
| 3:  |   7   |   72    |
| 4:  |   3   |  56.2   |
| 5:  |   2   |  23.4   |
| 6:  |  10   |   NaN   |
| 7:  |   5   |   NaN   |
| 8:  |   4   |   NaN   |
+-----+-------+---------+
| 9X2 | INT64 | FLOAT64 |
+-----+-------+---------+
```
[![Go Playground](https://img.shields.io/badge/Go-Playground-5593c7.svg?labelColor=41c3f3&style=for-the-badge)](https://play.golang.org/p/lsJkKw3ZUJq)

## Iterating

You can change the step and starting row. It may be wise to lock the DataFrame before iterating.

The returned value is a map containing the name of the series (`string`) and the index of the series (`int`) as keys.

```go

iterator := df.ValuesIterator(dataframe.ValuesOptions{0, 1, true}) // Don't apply read lock because we are write locking from outside.

df.Lock()
for {
	row, vals, _ := iterator()
	if row == nil {
		break
	}
	fmt.Println(*row, vals)
}
df.Unlock()

OUTPUT:
0 map[day:1 0:1 sales:50.3 1:50.3]
1 map[sales:23.4 1:23.4 day:2 0:2]
2 map[day:3 0:3 sales:56.2 1:56.2]
3 map[1:<nil> day:4 0:4 sales:<nil>]
4 map[day:5 0:5 sales:<nil> 1:<nil>]
5 map[sales:84.2 1:84.2 day:6 0:6]
6 map[day:7 0:7 sales:72 1:72]
7 map[day:8 0:8 sales:89 1:89]
```
[![Go Playground](https://img.shields.io/badge/Go-Playground-5593c7.svg?labelColor=41c3f3&style=for-the-badge)](https://play.golang.org/p/eqjvu-vO8sr)

## Statistics

You can easily calculate statistics for a Series using the [gonum](https://godoc.org/gonum.org/v1/gonum/stat) or [montanaflynn/stats](https://godoc.org/github.com/montanaflynn/stats) package.

`SeriesFloat64` and `SeriesTime` provide access to the exported `Values` field to seamlessly interoperate with external math-based packages.

### Example

Some series provide easy conversion using the `ToSeriesFloat64` method.

```go
import "gonum.org/v1/gonum/stat"

s := dataframe.NewSeriesInt64("random", nil, 1, 2, 3, 4, 5, 6, 7, 8)
sf, _ := s.ToSeriesFloat64(ctx)
```

### Mean

```go
mean := stat.Mean(sf.Values, nil)
```

### Median

```go
import "github.com/montanaflynn/stats"
median, _ := stats.Median(sf.Values)
```

### Standard Deviation

```go
std := stat.StdDev(sf.Values, nil)
```

## Plotting (cross-platform)

```go
import (
	chart "github.com/wcharczuk/go-chart"
	"github.com/rocketlaunchr/dataframe-go/plot"
	wc "github.com/rocketlaunchr/dataframe-go/plot/wcharczuk/go-chart"
)

sales := dataframe.NewSeriesFloat64("sales", nil, 50.3, nil, 23.4, 56.2, 89, 32, 84.2, 72, 89)
cs, _ := wc.S(ctx, sales, nil, nil)

graph := chart.Chart{Series: []chart.Series{cs}}

plt, _ := plot.Open("Monthly sales", 450, 300)
graph.Render(chart.SVG, plt)
plt.Display(plot.None)
<-plt.Closed

```

Output:

## Math Functions

```go
import "github.com/rocketlaunchr/dataframe-go/math/funcs"

res := 24
sx := dataframe.NewSeriesFloat64("x", nil, utils.Float64Seq(1, float64(res), 1))
sy := dataframe.NewSeriesFloat64("y", &dataframe.SeriesInit{Size: res})
df := dataframe.NewDataFrame(sx, sy)

fn := funcs.RegFunc("sin(2*𝜋*x/24)")
funcs.Evaluate(ctx, df, fn, 1)
```
[![Go Playground](https://img.shields.io/badge/Go-Playground-5593c7.svg?labelColor=41c3f3&style=for-the-badge)](https://play.golang.org/p/f4GfS2rUjaM)

Output:

## Importing Data

The `imports` sub-package has support for importing csv, jsonl and directly from a SQL database. The `DictateDataType` option can be set to specify the true underlying data type. Alternatively, `InferDataTypes` option can be set.

### CSV

```go
csvStr := `
Country,Date,Age,Amount,Id
"United States",2012-02-01,50,112.1,01234
"United States",2012-02-01,32,321.31,54320
"United Kingdom",2012-02-01,17,18.2,12345
"United States",2012-02-01,32,321.31,54320
"United Kingdom",2012-05-07,NA,18.2,12345
"United States",2012-02-01,32,321.31,54320
"United States",2012-02-01,32,321.31,54320
Spain,2012-02-01,66,555.42,00241
`
df, err := imports.LoadFromCSV(ctx, strings.NewReader(csvStr))

OUTPUT:
+-----+----------------+------------+-------+---------+-------+
|     |    COUNTRY     |    DATE    |  AGE  | AMOUNT  |  ID   |
+-----+----------------+------------+-------+---------+-------+
| 0:  | United States  | 2012-02-01 |  50   |  112.1  | 1234  |
| 1:  | United States  | 2012-02-01 |  32   | 321.31  | 54320 |
| 2:  | United Kingdom | 2012-02-01 |  17   |  18.2   | 12345 |
| 3:  | United States  | 2012-02-01 |  32   | 321.31  | 54320 |
| 4:  | United Kingdom | 2015-05-07 |  NaN  |  18.2   | 12345 |
| 5:  | United States  | 2012-02-01 |  32   | 321.31  | 54320 |
| 6:  | United States  | 2012-02-01 |  32   | 321.31  | 54320 |
| 7:  |     Spain      | 2012-02-01 |  66   | 555.42  |  241  |
+-----+----------------+------------+-------+---------+-------+
| 8X5 |     STRING     |    TIME    | INT64 | FLOAT64 | INT64 |
+-----+----------------+------------+-------+---------+-------+
```
[![Go Playground](https://img.shields.io/badge/Go-Playground-5593c7.svg?labelColor=41c3f3&style=for-the-badge)](https://play.golang.org/p/7hyUXnRy1pR)

## Exporting Data

The `exports` sub-package has support for exporting to csv, jsonl, parquet, Excel and directly to a SQL database.

## Optimizations

* If you know the number of rows in advance, you can set the capacity of the underlying slice of a series using `SeriesInit{}`. This will preallocate memory and provide speed improvements.

# Generic Series

Out of the box, there is support for `string`, `time.Time`, `float64` and `int64`. Automatic support exists for `float32` and all types of integers. There is a convenience function provided for dealing with `bool`. There is also support for `complex128` inside the `xseries` subpackage.

There may be times that you want to use your own custom data types. You can either implement your own `Series` type (more performant) or use the **Generic Series** (more convenient).

## civil.Date

```go
import "time"
import "cloud.google.com/go/civil"

sg := dataframe.NewSeriesGeneric("date", civil.Date{}, nil, civil.Date{2018, time.May, 01}, civil.Date{2018, time.May, 02}, civil.Date{2018, time.May, 03})
s2 := dataframe.NewSeriesFloat64("sales", nil, 50.3, 23.4, 56.2)

df := dataframe.NewDataFrame(sg, s2)

OUTPUT:
+-----+------------+---------+
|     |    DATE    |  SALES  |
+-----+------------+---------+
| 0:  | 2018-05-01 |  50.3   |
| 1:  | 2018-05-02 |  23.4   |
| 2:  | 2018-05-03 |  56.2   |
+-----+------------+---------+
| 3X2 | CIVIL DATE | FLOAT64 |
+-----+------------+---------+

```

# Tutorial

## Create some fake data

Let's create a list of 8 "fake" employees with a name, title and base hourly wage rate.

```go
import "golang.org/x/exp/rand"
import "rocketlaunchr/dataframe-go/utils/faker"

ctx := context.Background()
src := rand.NewSource(uint64(time.Now().UTC().UnixNano()))
df := faker.NewDataFrame(8, src, faker.S("name", 0, "Name"), faker.S("title", 0.5, "JobTitle"), faker.S("base rate", 0, "Number", 15, 50))
```

```go
+-----+----------------+----------------+-----------+
|     |      NAME      |     TITLE      | BASE RATE |
+-----+----------------+----------------+-----------+
| 0:  | Cordia Jacobi  |   Consultant   |    42     |
| 1:  | Nickolas Emard |      NaN       |    22     |
| 2:  | Hollis Dickens | Representative |    22     |
| 3:  | Stacy Dietrich |      NaN       |    43     |
| 4:  |  Aleen Legros  |    Officer     |    21     |
| 5:  |  Adelia Metz   |   Architect    |    18     |
| 6:  | Sunny Gerlach  |      NaN       |    28     |
| 7:  | Austin Hackett |      NaN       |    39     |
+-----+----------------+----------------+-----------+
| 8X3 |     STRING     |     STRING     |   INT64   |
+-----+----------------+----------------+-----------+
```

## Apply Function

Let's give a promotion to everyone by doubling their salary.

```go
s := df.Series[2]

applyFn := dataframe.ApplySeriesFn(func(val interface{}, row, nRows int) interface{} {
	return 2 * val.(int64)
})

dataframe.Apply(ctx, s, applyFn, dataframe.FilterOptions{InPlace: true})
```

```go
+-----+----------------+----------------+-----------+
|     |      NAME      |     TITLE      | BASE RATE |
+-----+----------------+----------------+-----------+
| 0:  | Cordia Jacobi  |   Consultant   |    84     |
| 1:  | Nickolas Emard |      NaN       |    44     |
| 2:  | Hollis Dickens | Representative |    44     |
| 3:  | Stacy Dietrich |      NaN       |    86     |
| 4:  |  Aleen Legros  |    Officer     |    42     |
| 5:  |  Adelia Metz   |   Architect    |    36     |
| 6:  | Sunny Gerlach  |      NaN       |    56     |
| 7:  | Austin Hackett |      NaN       |    78     |
+-----+----------------+----------------+-----------+
| 8X3 |     STRING     |     STRING     |   INT64   |
+-----+----------------+----------------+-----------+
```

## Create a Time series

Let's inform all employees separately on sequential days.

```go
import "rocketlaunchr/dataframe-go/utils/utime"

mts, _ := utime.NewSeriesTime(ctx, "meeting time", "1D", time.Now().UTC(), false, utime.NewSeriesTimeOptions{Size: &[]int{8}[0]})
df.AddSeries(mts, nil)
```

```go
+-----+----------------+----------------+-----------+--------------------------------+
|     |      NAME      |     TITLE      | BASE RATE |          MEETING TIME          |
+-----+----------------+----------------+-----------+--------------------------------+
| 0:  | Cordia Jacobi  |   Consultant   |    84     |   2020-02-02 23:13:53.015324   |
|     |                |                |           |           +0000 UTC            |
| 1:  | Nickolas Emard |      NaN       |    44     |   2020-02-03 23:13:53.015324   |
|     |                |                |           |           +0000 UTC            |
| 2:  | Hollis Dickens | Representative |    44     |   2020-02-04 23:13:53.015324   |
|     |                |                |           |           +0000 UTC            |
| 3:  | Stacy Dietrich |      NaN       |    86     |   2020-02-05 23:13:53.015324   |
|     |                |                |           |           +0000 UTC            |
| 4:  |  Aleen Legros  |    Officer     |    42     |   2020-02-06 23:13:53.015324   |
|     |                |                |           |           +0000 UTC            |
| 5:  |  Adelia Metz   |   Architect    |    36     |   2020-02-07 23:13:53.015324   |
|     |                |                |           |           +0000 UTC            |
| 6:  | Sunny Gerlach  |      NaN       |    56     |   2020-02-08 23:13:53.015324   |
|     |                |                |           |           +0000 UTC            |
| 7:  | Austin Hackett |      NaN       |    78     |   2020-02-09 23:13:53.015324   |
|     |                |                |           |           +0000 UTC            |
+-----+----------------+----------------+-----------+--------------------------------+
| 8X4 |     STRING     |     STRING     |   INT64   |              TIME              |
+-----+----------------+----------------+-----------+--------------------------------+
```

## Filtering

Let's filter out our senior employees (they have titles) for no reason.

```go
filterFn := dataframe.FilterDataFrameFn(func(vals map[interface{}]interface{}, row, nRows int) (dataframe.FilterAction, error) {
	if vals["title"] == nil {
		return dataframe.DROP, nil
	}
	return dataframe.KEEP, nil
})

seniors, _ := dataframe.Filter(ctx, df, filterFn)
```

```go
+-----+----------------+----------------+-----------+--------------------------------+
|     |      NAME      |     TITLE      | BASE RATE |          MEETING TIME          |
+-----+----------------+----------------+-----------+--------------------------------+
| 0:  | Cordia Jacobi  |   Consultant   |    84     |   2020-02-02 23:13:53.015324   |
|     |                |                |           |           +0000 UTC            |
| 1:  | Hollis Dickens | Representative |    44     |   2020-02-04 23:13:53.015324   |
|     |                |                |           |           +0000 UTC            |
| 2:  |  Aleen Legros  |    Officer     |    42     |   2020-02-06 23:13:53.015324   |
|     |                |                |           |           +0000 UTC            |
| 3:  |  Adelia Metz   |   Architect    |    36     |   2020-02-07 23:13:53.015324   |
|     |                |                |           |           +0000 UTC            |
+-----+----------------+----------------+-----------+--------------------------------+
| 4X4 |     STRING     |     STRING     |   INT64   |              TIME              |
+-----+----------------+----------------+-----------+--------------------------------+
```

## Other useful packages

- [dbq](https://github.com/rocketlaunchr/dbq) - Zero boilerplate database operations for Go
- [electron-alert](https://github.com/rocketlaunchr/electron-alert) - SweetAlert2 for Electron Applications
- [igo](https://github.com/rocketlaunchr/igo) - A Go transpiler with cool new syntax such as fordefer (defer for for-loops)
- [mysql-go](https://github.com/rocketlaunchr/mysql-go) - Properly cancel slow MySQL queries
- [react](https://github.com/rocketlaunchr/react) - Build front end applications using Go
- [remember-go](https://github.com/rocketlaunchr/remember-go) - Cache slow database queries

#

### Legal Information

The license is a modified MIT license. Refer to `LICENSE` file for more details.

**© 2018-20 PJ Engineering and Business Solutions Pty. Ltd.**


// test_parser_constructs_module_basic1_test.v
module f1_test;
endmodule

// test_parser_constructs_param_basic0_test.v
module f2_test #( parameter v2kparam = 5)
(in, out, io, vin, vout, vio);
input in;
output out;
inout io;
input [3:0] vin;
output [v2kparam:0] vout;
inout [0:3] vio;
parameter myparam = 10;
endmodule

// test_parser_constructs_port_basic0_test.v
module f3_test(in, out, io, vin, vout, vio);
input in;
output out;
inout io;
input [3:0] vin;
output [3:0] vout;
inout [0:3] vio;
endmodule

// test_parser_directives_define_simpledef_test.v
`define parvez ahmad
`define  WIRE wire
`define TEN 10

module f4_`parvez();
parameter param = `TEN;
`WIRE w;
assign w = `TEN;
endmodule

// test_parser_misc_operators_test.v
module f5_test(out, i0, i1, i2, i3, s1, s0);
output out;
input i0, i1, i2, i3;
input s1, s0;

assign out = (~s1 & s0 & i0) |
			 (~s1 & s0 & i1) |
			 (s1 & ~s0 & i2) |
			 (s1 & s0 & i3);

endmodule

module f5_ternaryop(out, i0, i1, i2, i3, s1, s0);
output out;
input i0, i1, i2, i3;
input s1, s0;

assign out = s1 ? (s0 ? i3 : i2) : (s0 ? i1 : i0);

endmodule

module f5_fulladd4(sum, c_out, a, b, c_in);
output [3:0] sum;
output c_out;
input [3:0] a, b;
input c_in;

assign {c_out, sum} = a + b + c_in;
endmodule

// test_parser_v2k_comb_port_data_type_test.v
module f6_adder(sum , co, a, b, ci);
output	reg		[31:0]	sum;
output	reg				co;
input	wire	[31:0]	a, b;
input wire				ci;
endmodule

// test_parser_v2k_comma_sep_sens_list_test.v
module f7_test(q, d, clk, reset);
output reg q;
input d, clk, reset;

always @ (posedge clk, negedge reset)
	if(!reset) q <= 0;
	else q <= d;

endmodule


# -*- coding: utf-8 -*-
#
# Copyright (C) 2019 Chris Caron <lead2gold@gmail.com>
# All rights reserved.
#
# This code is licensed under the MIT License.
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files(the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and / or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions :
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.

# To use this plugin, you need to first generate a webhook.

# When you're complete, you will recieve a URL that looks something like this:
#                https://apprise.ryver.com/application/webhook/ckhrjW8w672m6HG
#                          ^                                        ^
#                          |                                        |
#  These are important <---^----------------------------------------^
#
import re
import six
import requests
from json import dumps

from .NotifyBase import NotifyBase
from ..common import NotifyImageSize
from ..common import NotifyType
from ..utils import parse_bool
from ..utils import validate_regex
from ..AppriseLocale import gettext_lazy as _

class RyverWebhookMode(object):
    """
    Ryver supports to webhook modes
    """
    SLACK = 'slack'
    RYVER = 'ryver'

# Define the types in a list for validation purposes
RYVER_WEBHOOK_MODES = (
    RyverWebhookMode.SLACK,
    RyverWebhookMode.RYVER,
)

class NotifyRyver(NotifyBase):
    """
    A wrapper for Ryver Notifications
    """

    # The default descriptive name associated with the Notification
    service_name = 'Ryver'

    # The services URL
    service_url = 'https://ryver.com/'

    # The default secure protocol
    secure_protocol = 'ryver'

    # A URL that takes you to the setup/help of the specific protocol
    setup_url = 'https://github.com/caronc/apprise/wiki/Notify_ryver'

    # Allows the user to specify the NotifyImageSize object
    image_size = NotifyImageSize.XY_72

    # The maximum allowable characters allowed in the body per message
    body_maxlen = 1000

    # Define object templates
    templates = (
        '{schema}://{organization}/{token}',
        '{schema}://{user}@{organization}/{token}',
    )

    # Define our template tokens
    template_tokens = dict(NotifyBase.template_tokens, **{
        'organization': {
            'name': _('Organization'),
            'type': 'string',
            'required': True,
            'regex': (r'^[A-Z0-9_-]{3,32}$', 'i'),
        },
        'token': {
            'name': _('Token'),
            'type': 'string',
            'required': True,
            'private': True,
            'regex': (r'^[A-Z0-9]{15}$', 'i'),
        },
        'user': {
            'name': _('Bot Name'),
            'type': 'string',
        },
    })

    # Define our template arguments
    template_args = dict(NotifyBase.template_args, **{
        'mode': {
            'name': _('Webhook Mode'),
            'type': 'choice:string',
            'values': RYVER_WEBHOOK_MODES,
            'default': RyverWebhookMode.RYVER,
        },
        'image': {
            'name': _('Include Image'),
            'type': 'bool',
            'default': True,
            'map_to': 'include_image',
        },
    })

    def __init__(self, organization, token, mode=RyverWebhookMode.RYVER,
                 include_image=True, **kwargs):
        """
        Initialize Ryver Object
        """
        super(NotifyRyver, self).__init__(**kwargs)

        # API Token (associated with project)
        self.token = validate_regex(
            token, *self.template_tokens['token']['regex'])
        if not self.token:
            msg = 'An invalid Ryver API Token ' \
                  '({}) was specified.'.format(token)
            self.logger.warning(msg)
            raise TypeError(msg)

        # Organization (associated with project)
        self.organization = validate_regex(
            organization, *self.template_tokens['organization']['regex'])
        if not self.organization:
            msg = 'An invalid Ryver Organization ' \
                  '({}) was specified.'.format(organization)
            self.logger.warning(msg)
            raise TypeError(msg)

        # Store our webhook mode
        self.mode = None \
            if not isinstance(mode, six.string_types) else mode.lower()

        if self.mode not in RYVER_WEBHOOK_MODES:
            msg = 'The Ryver webhook mode specified ({}) is invalid.' \
                .format(mode)
            self.logger.warning(msg)
            raise TypeError(msg)

        # Place an image inline with the message body
        self.include_image = include_image

        # Slack formatting requirements are defined here which Ryver supports:
        # https://api.slack.com/docs/message-formatting
        self._re_formatting_map = {
            # New lines must become the string version
            r'\r\*\n': '\\n',
            # Escape other special characters
            r'&': '&',
            r'<': '<',
            r'>': '>',
        }

        # Iterate over above list and store content accordingly
        self._re_formatting_rules = re.compile(
            r'(' + '|'.join(self._re_formatting_map.keys()) + r')',
            re.IGNORECASE,
        )

        return

    def send(self, body, title='', notify_type=NotifyType.INFO, **kwargs):
        """
        Perform Ryver Notification
        """

        headers = {
            'User-Agent': self.app_id,
            'Content-Type': 'application/json',
        }

        if self.mode == RyverWebhookMode.SLACK:
            # Perform Slack formatting
            title = self._re_formatting_rules.sub(  # pragma: no branch
                lambda x: self._re_formatting_map[x.group()], title,
            )
            body = self._re_formatting_rules.sub(  # pragma: no branch
                lambda x: self._re_formatting_map[x.group()], body,
            )

        url = 'https://{}.ryver.com/application/webhook/{}'.format(
            self.organization,
            self.token,
        )

        # prepare JSON Object
        payload = {
            'body': body if not title else '**{}**\r\n{}'.format(title, body),
            'createSource': {
                'displayName': self.user,
                'avatar': None,
            },
        }

        # Acquire our image url if configured to do so
        image_url = None if not self.include_image else \
            self.image_url(notify_type)

        if image_url:
            payload['createSource']['avatar'] = image_url

        self.logger.debug('Ryver POST URL: %s (cert_verify=%r)' % (
            url, self.verify_certificate,
        ))
        self.logger.debug('Ryver Payload: %s' % str(payload))

        # Always call throttle before any remote server i/o is made
        self.throttle()

        try:
            r = requests.post(
                url,
                data=dumps(payload),
                headers=headers,
                verify=self.verify_certificate,
            )

            if r.status_code != requests.codes.ok:
                # We had a problem
                status_str = \
                    NotifyBase.http_response_code_lookup(r.status_code)

                self.logger.warning(
                    'Failed to send Ryver notification: '
                    '{}{}error={}.'.format(
                        status_str,
                        ', ' if status_str else '',
                        r.status_code))

                self.logger.debug('Response Details:\r\n{}'.format(r.content))

                # Return; we're done
                return False

            else:
                self.logger.info('Sent Ryver notification.')

        except requests.RequestException as e:
            self.logger.warning(
                'A Connection error occured sending Ryver:%s ' % (
                    self.organization) + 'notification.'
            )
            self.logger.debug('Socket Exception: %s' % str(e))
            return False

        return True

    def url(self, privacy=False, *args, **kwargs):
        """
        Returns the URL built dynamically based on specified arguments.
        """

        # Define any arguments set
        args = {
            'format': self.notify_format,
            'overflow': self.overflow_mode,
            'image': 'yes' if self.include_image else 'no',
            'mode': self.mode,
            'verify': 'yes' if self.verify_certificate else 'no',
        }

        # Determine if there is a botname present
        botname = ''
        if self.user:
            botname = '{botname}@'.format(
                botname=NotifyRyver.quote(self.user, safe=''),
            )

        return '{schema}://{botname}{organization}/{token}/?{args}'.format(
            schema=self.secure_protocol,
            botname=botname,
            organization=NotifyRyver.quote(self.organization, safe=''),
            token=self.pprint(self.token, privacy, safe=''),
            args=NotifyRyver.urlencode(args),
        )

    @staticmethod
    def parse_url(url):
        """
        Parses the URL and returns enough arguments that can allow
        us to substantiate this object.

        """

        results = NotifyBase.parse_url(url)

        if not results:
            # We're done early as we couldn't load the results
            return results

        # The first token is stored in the hostname
        results['organization'] = NotifyRyver.unquote(results['host'])

        # Now fetch the remaining tokens
        try:
            results['token'] = \
                NotifyRyver.split_path(results['fullpath'])[0]

        except IndexError:
            # no token
            results['token'] = None

        if 'webhook' in results['qsd']:
            # Deprication Notice issued for v0.7.5
            NotifyRyver.logger.deprecate(
                'The Ryver URL contains the parameter '
                '"webhook=" which will be deprecated in an upcoming '
                'release. Please use "mode=" instead.'
            )

        # use mode= for consistency with the other plugins but we also
        # support webhook= for backwards compatibility.
        results['mode'] = results['qsd'].get(
            'mode', results['qsd'].get(
                'webhook', RyverWebhookMode.RYVER))

        # use image= for consistency with the other plugins
        results['include_image'] = \
            parse_bool(results['qsd'].get('image', True))

        return results

    @staticmethod
    def parse_native_url(url):
        """
        Support https://RYVER_ORG.ryver.com/application/webhook/TOKEN
        """

        result = re.match(
            r'^https?://(?P<org>[A-Z0-9_-]+)\.ryver\.com/application/webhook/'
            r'(?P<webhook_token>[A-Z0-9]+)/?'
            r'(?P<args>\?.+)?$', url, re.I)

        if result:
            return NotifyRyver.parse_url(
                '{schema}://{org}/{webhook_token}/{args}'.format(
                    schema=NotifyRyver.secure_protocol,
                    org=result.group('org'),
                    webhook_token=result.group('webhook_token'),
                    args='' if not result.group('args')
                    else result.group('args')))

        return None


#filter WebSafe
<?xml version="1.0" encoding="UTF-8"?>
<e2servicelist>
	#for $service in $services
	<e2service>
		<e2servicereference>$service.servicereference</e2servicereference>
		<e2servicename>$service.servicename</e2servicename>
	</e2service>
	#end for
</e2servicelist>
#end filter


// Run: %dxc -T cs_6_0 -E main -O3

// CHECK:      [[ptr:%\d+]] = OpAccessChain %_ptr_Uniform_S %gSBuffer
// CHECK-NEXT: [[val:%\d+]] = OpLoad %S [[ptr]]
// CHECK-NEXT: [[ptr:%\d+]] = OpAccessChain %_ptr_Uniform_S %gRWSBuffer
// CHECK-NEXT:                OpStore [[ptr]] [[val]]

struct S {
  float4 f;
};

int i;

StructuredBuffer<S> gSBuffer;
RWStructuredBuffer<S> gRWSBuffer;

void foo(RWStructuredBuffer<S> pRWSBuffer) {
  pRWSBuffer[i] = gSBuffer[i];
}

[numthreads(1,1,1)]
void main() {
  foo(gRWSBuffer);
}


# ===========================================================================
#      http://www.gnu.org/software/autoconf-archive/ax_lib_readline.html
# ===========================================================================
#
# SYNOPSIS
#
#   AX_LIB_READLINE
#
# DESCRIPTION
#
#   Searches for a readline compatible library. If found, defines
#   `HAVE_LIBREADLINE'. If the found library has the `add_history' function,
#   sets also `HAVE_READLINE_HISTORY'. Also checks for the locations of the
#   necessary include files and sets `HAVE_READLINE_H' or
#   `HAVE_READLINE_READLINE_H' and `HAVE_READLINE_HISTORY_H' or
#   'HAVE_HISTORY_H' if the corresponding include files exists.
#
#   The libraries that may be readline compatible are `libedit',
#   `libeditline' and `libreadline'. Sometimes we need to link a termcap
#   library for readline to work, this macro tests these cases too by trying
#   to link with `libtermcap', `libcurses' or `libncurses' before giving up.
#
#   Here is an example of how to use the information provided by this macro
#   to perform the necessary includes or declarations in a C file:
#
#     #ifdef HAVE_LIBREADLINE
#     #  if defined(HAVE_READLINE_READLINE_H)
#     #    include <readline/readline.h>
#     #  elif defined(HAVE_READLINE_H)
#     #    include <readline.h>
#     #  else /* !defined(HAVE_READLINE_H) */
#     extern char *readline ();
#     extern int rl_insert_text(const char*);
#     extern void rl_forced_update_display(void);
#     extern int rl_bind_key(int, int(*f)(int, int));
#     #  endif /* !defined(HAVE_READLINE_H) */
#     char *cmdline = NULL;
#     #else /* !defined(HAVE_READLINE_READLINE_H) */
#       /* no readline */
#     #endif /* HAVE_LIBREADLINE */
#
#     #ifdef HAVE_READLINE_HISTORY
#     #  if defined(HAVE_READLINE_HISTORY_H)
#     #    include <readline/history.h>
#     #  elif defined(HAVE_HISTORY_H)
#     #    include <history.h>
#     #  else /* !defined(HAVE_HISTORY_H) */
#     extern void add_history ();
#     extern int write_history ();
#     extern int read_history ();
#     #  endif /* defined(HAVE_READLINE_HISTORY_H) */
#       /* no history */
#     #endif /* HAVE_READLINE_HISTORY */
#
# LICENSE
#
#   Copyright (c) 2008 Ville Laurikari <vl@iki.fi>
#
#   Copying and distribution of this file, with or without modification, are
#   permitted in any medium without royalty provided the copyright notice
#   and this notice are preserved. This file is offered as-is, without any
#   warranty.

# Modified version. Original version is available here:
#  http://www.gnu.org/software/autoconf-archive/ax_lib_readline.html

#serial 6

AU_ALIAS([VL_LIB_READLINE], [AX_LIB_READLINE])
AC_DEFUN([AX_LIB_READLINE], [
  AC_CACHE_CHECK([for a readline compatible library],
                 ax_cv_lib_readline, [
    _save_LIBS="$LIBS"
    for readline_lib in readline edit editline; do
      for termcap_lib in "" termcap curses ncurses; do
        if test -z "$termcap_lib"; then
          TRY_LIB="-l$readline_lib"
        else
          TRY_LIB="-l$readline_lib -l$termcap_lib"
        fi
        LIBS="$ORIG_LIBS $TRY_LIB"
        for readline_func in readline rl_insert_text rl_forced_update_display; do
          AC_TRY_LINK_FUNC($readline_func, ax_cv_lib_readline="$TRY_LIB", ax_cv_lib_readline="")
          if test -z "$ax_cv_lib_readline"; then
            break
          fi
        done
        if test -n "$ax_cv_lib_readline"; then
          break
        fi
      done
      if test -n "$ax_cv_lib_readline"; then
        break
      fi
    done
    if test -z "$ax_cv_lib_readline"; then
      ax_cv_lib_readline="no"
    fi
    LIBS="$_save_LIBS"
  ])

  if test "$ax_cv_lib_readline" != "no"; then
    READLINE_LIBS="$ax_cv_lib_readline"
    AC_SUBST(READLINE_LIBS)

    _save_LIBS="$LIBS"
    LIBS="$LIBS $READLINE_LIBS"
    AC_DEFINE(HAVE_LIBREADLINE, 1,
              [Define if you have a readline compatible library])
    AC_CHECK_HEADERS(readline.h readline/readline.h)
    AC_CACHE_CHECK([whether readline supports history],
                   ax_cv_lib_readline_history, [
      ax_cv_lib_readline_history="no"
      AC_TRY_LINK_FUNC(add_history, ax_cv_lib_readline_history="yes")
    ])
    if test "$ax_cv_lib_readline_history" = "yes"; then
      AC_DEFINE(HAVE_READLINE_HISTORY, 1,
                [Define if your readline library has \`add_history'])
      AC_CHECK_HEADERS(history.h readline/history.h)
    fi

    LIBS="$_save_LIBS"
  fi
])dnl


---
Title: Bundesreisekostengesetz
jurabk: BRKG 2005
layout: default
origslug: brkg_2005
slug: brkg_2005

---

# Bundesreisekostengesetz (BRKG 2005)

Ausfertigungsdatum
:   2005-05-26

Fundstelle
:   BGBl I: 2005, 1418

Zuletzt geändert durch
:   Art. 15 Abs. 51 G v. 5.2.2009 I 160

## § 1 Geltungsbereich

(1) Dieses Gesetz regelt Art und Umfang der Reisekostenvergütung der
Beamtinnen, Beamten, Richterinnen und Richter des Bundes sowie der
Soldatinnen und Soldaten und der in den Bundesdienst abgeordneten
Beamtinnen, Beamten, Richterinnen und Richter.

(2) Die Reisekostenvergütung umfasst

1.  die Fahrt- und Flugkostenerstattung (§ 4),

2.  die Wegstreckenentschädigung (§ 5),

3.  das Tagegeld (§ 6),

4.  das Übernachtungsgeld (§ 7),

5.  die Auslagenerstattung bei längerem Aufenthalt am Geschäftsort (§ 8),

6.  die Aufwands- und Pauschvergütung (§ 9) sowie

7.  die Erstattung sonstiger Kosten (§ 10).

## § 2 Dienstreisen

(1) Dienstreisen sind Reisen zur Erledigung von Dienstgeschäften
außerhalb der Dienststätte. Sie müssen, mit Ausnahme von Dienstreisen
am Dienst- oder Wohnort, schriftlich oder elektronisch angeordnet oder
genehmigt worden sein, es sei denn, dass eine Anordnung oder
Genehmigung nach dem Amt der Dienstreisenden oder dem Wesen des
Dienstgeschäfts nicht in Betracht kommt. Dienstreisen sollen nur
durchgeführt werden, wenn sie aus dienstlichen Gründen notwendig sind.
Dienstreisen sind auch Reisen aus Anlass der Versetzung, Abordnung
oder Kommandierung.

(2) Die Dauer der Dienstreise bestimmt sich nach der Abreise und
Ankunft an der Wohnung, es sei denn, die Dienstreise beginnt oder
endet an der Dienststätte.

## § 3 Anspruch auf Reisekostenvergütung

(1) Dienstreisende erhalten auf Antrag eine Vergütung der dienstlich
veranlassten notwendigen Reisekosten. Der Anspruch auf
Reisekostenvergütung erlischt, wenn sie nicht innerhalb einer
Ausschlussfrist von sechs Monaten nach Beendigung der Dienstreise
schriftlich oder elektronisch beantragt wird. Die zuständigen Stellen
können bis zum Ablauf von sechs Monaten nach Antragstellung die
Vorlage der maßgeblichen Kostenbelege verlangen. Werden diese Belege
auf Anforderung nicht innerhalb von drei Monaten vorgelegt, kann der
Vergütungsantrag insoweit abgelehnt werden.

(2) Leistungen, die Dienstreisende ihres Amtes wegen von dritter Seite
aus Anlass einer Dienstreise erhalten, sind auf die
Reisekostenvergütung anzurechnen.

(3) Bei Dienstreisen für eine auf Veranlassung der zuständigen Behörde
ausgeübte Nebentätigkeit haben Dienstreisende nur Anspruch auf
Reisekostenvergütung, die nicht von anderer Stelle zu übernehmen ist.
Das gilt auch dann, wenn Dienstreisende auf ihren Anspruch gegen diese
Stelle verzichtet haben.

## § 4 Fahrt- und Flugkostenerstattung

(1) Entstandene Kosten für Fahrten auf dem Land- oder Wasserweg mit
regelmäßig verkehrenden Beförderungsmitteln werden bis zur Höhe der
niedrigsten Beförderungsklasse erstattet. Für Bahnfahrten von
mindestens zwei Stunden können die entstandenen Fahrtkosten der
nächsthöheren Klasse erstattet werden. Wurde aus dienstlichen oder
wirtschaftlichen Gründen ein Flugzeug benutzt, werden die Kosten der
niedrigsten Flugklasse erstattet. Kosten einer höheren Klasse
regelmäßig verkehrender Beförderungsmittel können erstattet werden,
wenn dienstliche Gründe dies im Einzelfall oder allgemein erfordern.

(2) Mögliche Fahrpreisermäßigungen sind zu berücksichtigen.
Fahrtkosten werden nicht erstattet, wenn eine unentgeltliche
Beförderungsmöglichkeit genutzt werden kann.

(3) Dienstreisenden, denen für Bahnfahrten die Kosten der niedrigsten
Beförderungsklasse zu erstatten wären, werden bei einem Grad der
Behinderung von mindestens 50 die Kosten der nächsthöheren Klasse
erstattet.

(4) Wurde aus triftigem Grund ein Mietwagen oder ein Taxi benutzt,
werden die entstandenen notwendigen Kosten erstattet.

## § 5 Wegstreckenentschädigung

(1) Für Fahrten mit anderen als den in § 4 genannten
Beförderungsmitteln wird eine Wegstreckenentschädigung gewährt. Sie
beträgt bei Benutzung eines Kraftfahrzeuges oder eines anderen
motorbetriebenen Fahrzeuges 20 Cent je Kilometer zurückgelegter
Strecke, höchstens jedoch 130 Euro. Die oberste Bundesbehörde kann den
Höchstbetrag auf 150 Euro festsetzen, wenn dienstliche Gründe dies im
Einzelfall oder allgemein erfordern.

(2) Besteht an der Benutzung eines Kraftwagens ein erhebliches
dienstliches Interesse, beträgt die Wegstreckenentschädigung 30 Cent
je Kilometer zurückgelegter Strecke. Das erhebliche dienstliche
Interesse muss vor Antritt der Dienstreise in der Anordnung oder
Genehmigung schriftlich oder elektronisch festgestellt werden.

(3) Benutzen Dienstreisende zur Erledigung von Dienstgeschäften
regelmäßig ein Fahrrad, wird Wegstreckenentschädigung nach Maßgabe
einer allgemeinen Verwaltungsvorschrift gemäß § 16 gewährt.

(4) Eine Wegstreckenentschädigung wird Dienstreisenden nicht gewährt,
wenn sie

1.  eine vom Dienstherrn unentgeltlich zur Verfügung gestellte
    Beförderungsmöglichkeit nutzen konnten oder

2.  von anderen Dienstreisenden des Bundes oder eines anderen Dienstherrn
    in einem Kraftwagen mitgenommen wurden.

## § 6 Tagegeld

(1) Als Ersatz von Mehraufwendungen für Verpflegung erhalten
Dienstreisende ein Tagegeld. Die Höhe des Tagegeldes bemisst sich nach
§ 4 Abs. 5 Satz 1 Nr. 5 Satz 2 des Einkommensteuergesetzes. Besteht
zwischen der Dienststätte oder der Wohnung und der Stelle, an der das
Dienstgeschäft erledigt wird, nur eine geringe Entfernung, wird
Tagegeld nicht gewährt.

(2) Erhalten Dienstreisende ihres Amtes wegen unentgeltlich
Verpflegung, werden von dem zustehenden Tagegeld für das Frühstück 20
Prozent und für das Mittag- und Abendessen je 40 Prozent des
Tagegeldes für einen vollen Kalendertag einbehalten. Gleiches gilt,
wenn das Entgelt für Verpflegung in den erstattungsfähigen Fahrt-,
Übernachtungs- oder Nebenkosten enthalten ist. Die Sätze 1 und 2 sind
auch dann anzuwenden, wenn Dienstreisende ihres Amtes wegen
unentgeltlich bereitgestellte Verpflegung ohne triftigen Grund nicht
in Anspruch nehmen. Die oberste Dienstbehörde kann in besonderen
Fällen niedrigere Einbehaltungssätze zulassen.

## § 7 Übernachtungsgeld

(1) Für eine notwendige Übernachtung erhalten Dienstreisende pauschal
20 Euro. Höhere Übernachtungskosten werden erstattet, soweit sie
notwendig sind.

(2) Übernachtungsgeld wird nicht gewährt

1.  für die Dauer der Benutzung von Beförderungsmitteln,

2.  bei Dienstreisen am oder zum Wohnort für die Dauer des Aufenthalts an
    diesem Ort,

3.  bei unentgeltlicher Bereitstellung einer Unterkunft des Amtes wegen,
    auch wenn diese Unterkunft ohne triftigen Grund nicht genutzt wird,
    und

4.  in den Fällen, in denen das Entgelt für die Unterkunft in den
    erstattungsfähigen Fahrt- oder sonstigen Kosten enthalten ist, es sei
    denn, dass eine Übernachtung aufgrund einer zu frühen Ankunft am
    Geschäftsort oder einer zu späten Abfahrt von diesem zusätzlich
    erforderlich wird.

## § 8 Auslagenerstattung bei längerem Aufenthalt am Geschäftsort

Dauert der dienstlich veranlasste Aufenthalt an demselben auswärtigen
Geschäftsort länger als 14 Tage, wird vom 15. Tag an ein um 50 Prozent
ermäßigtes Tagegeld gewährt; in besonderen Fällen kann die oberste
Dienstbehörde oder die von ihr ermächtigte Behörde auf eine Ermäßigung
des Tagegeldes verzichten. Notwendige Übernachtungskosten werden
erstattet; ein pauschales Übernachtungsgeld nach § 7 Abs. 1 wird nicht
gewährt. Als Reisebeihilfe für Heimfahrten werden für jeweils 14 Tage
des Aufenthalts am Geschäftsort je nach benutztem Beförderungsmittel
Fahrt- oder Flugkosten bis zur Höhe des in § 4 Abs. 1 Satz 1 oder 3
oder in § 5 Abs. 1 genannten Betrages gewährt. Wird der Geschäftsort
aufgrund von Heimfahrten verlassen, wird für die Zeit des Aufenthalts
in der Wohnung Tagegeld nicht gewährt.

## § 9 Aufwands- und Pauschvergütung

(1) Dienstreisende, denen erfahrungsgemäß geringerer Aufwand für
Verpflegung oder Unterkunft als allgemein üblich entsteht, erhalten
nach näherer Bestimmung der obersten Dienstbehörde oder der von ihr
ermächtigten Behörde anstelle von Tagegeld, Übernachtungsgeld und
Auslagenerstattung nach § 8 Satz 1 und 2 eine entsprechende
Aufwandsvergütung. Diese kann auch nach Stundensätzen bemessen werden.

(2) Die oberste Dienstbehörde oder die von ihr ermächtigte Behörde
kann für regelmäßige oder gleichartige Dienstreisen anstelle der
Reisekostenvergütung oder einzelner ihrer Bestandteile eine
Pauschvergütung gewähren, die nach dem Durchschnitt der in einem
bestimmten Zeitraum sonst anfallenden Reisekostenvergütungen zu
bemessen ist.

## § 10 Erstattung sonstiger Kosten

(1) Zur Erledigung des Dienstgeschäfts notwendige Auslagen, die nicht
nach den §§ 4 bis 9 zu erstatten sind, werden als Nebenkosten
erstattet.

(2) Entfällt eine Dienstreise aus einem von der oder dem Bediensteten
nicht zu vertretenden Grund, werden durch die Vorbereitung
entstandene, nach diesem Gesetz abzugeltende Auslagen erstattet.

## § 11 Bemessung der Reisekostenvergütung in besonderen Fällen

(1) Für Dienstreisen aus Anlass der Versetzung, Abordnung oder
Kommandierung wird das Tagegeld für die Zeit bis zur Ankunft am neuen
Dienstort gewährt; im Übrigen gilt § 2 Abs. 2. Das Tagegeld wird für
die Zeit bis zum Ablauf des Ankunftstages gewährt, wenn den
Dienstreisenden vom nächsten Tag an Trennungsreise- oder
Trennungstagegeld zusteht; daneben wird Übernachtungsgeld (§ 7)
gewährt. Für Dienstreisen im Sinne des Satzes 1 wird das Tagegeld vom
Beginn des Abfahrtstages an gewährt, wenn für den vorhergehenden Tag
Trennungsreise- oder Trennungstagegeld gewährt wird. Für ein- und
zweitägige Abordnungen oder Kommandierungen ist bei der Festsetzung
der Reisekostenvergütung abweichend von den Sätzen 1 bis 3 die gesamte
Dauer der Abwesenheit von der Wohnung oder bisherigen Dienststätte
zugrunde zu legen.

(2) Für Reisen aus Anlass der Einstellung kann Reisekostenvergütung
wie für Dienstreisen gewährt werden; Absatz 1 ist entsprechend
anzuwenden. Die Reisekostenvergütung darf dabei nicht höher sein als
der Betrag, der für eine Dienstreise von der Wohnung zur Dienststätte
zu erstatten wäre.

(3) Reisekostenvergütung kann ferner gewährt werden

1.  für Einstellungsreisen vor dem Wirksamwerden der Ernennung zur
    Beamtin, zum Beamten, zur Richterin, zum Richter, zur Soldatin oder
    zum Soldaten und

2.  für Reisen aus Anlass des Ausscheidens aus dem Dienst wegen Ablaufs
    der Dienstzeit oder wegen Dienstunfähigkeit von Beamtinnen und Beamten
    auf Widerruf, von Soldatinnen und Soldaten auf Zeit oder von Soldaten,
    die aufgrund der Wehrpflicht Wehrdienst leisten; dies gilt für Reisen
    in das Ausland nur bis zum inländischen Grenzort oder dem inländischen
    Flughafen, von dem die Flugreise angetreten wird.

Die Absätze 1 und 2 Satz 2 gelten entsprechend.

(4) Für Reisen zum Zwecke der Ausbildung oder Fortbildung, die
teilweise im dienstlichen Interesse liegen, können mit Zustimmung der
obersten Dienstbehörde oder der von ihr ermächtigten Behörde
entstandene Kosten bis zur Höhe der für Dienstreisen zustehenden
Reisekostenvergütung erstattet werden.

(5) Übernachten Dienstreisende in ihrer außerhalb des Geschäftsorts
gelegenen Wohnung, wird für jede Hin- und Rückfahrt aus Anlass einer
Übernachtung als Ersatz der Fahrtauslagen ein Betrag in Höhe der
Übernachtungspauschale nach § 7 gewährt.

## § 12 Erkrankung während einer Dienstreise

Erkranken Dienstreisende und werden sie in ein Krankenhaus
aufgenommen, werden für jeden vollen Kalendertag des
Krankenhausaufenthalts die notwendigen Auslagen für die Unterkunft am
Geschäftsort erstattet. Für eine Besuchsreise einer oder eines
Angehörigen aus Anlass einer durch ärztliche Bescheinigung
nachgewiesenen lebensgefährlichen Erkrankung der oder des
Dienstreisenden werden Fahrtauslagen gemäß § 4 Abs. 1 Satz 1 und 3
oder § 5 Abs. 1 erstattet.

## § 13 Verbindung von Dienstreisen mit privaten Reisen

(1) Werden Dienstreisen mit privaten Reisen verbunden, wird die
Reisekostenvergütung so bemessen, als ob nur die Dienstreise
durchgeführt worden wäre. Die Reisekostenvergütung nach Satz 1 darf
die sich nach dem tatsächlichen Reiseverlauf ergebende nicht
übersteigen. Werden Dienstreisen mit einem Urlaub von mehr als fünf
Arbeitstagen verbunden, werden nur die zusätzlich für die Erledigung
des Dienstgeschäfts entstehenden Kosten als Fahrtauslagen entsprechend
den §§ 4 und 5 erstattet; Tage- und Übernachtungsgeld wird für die
Dauer des Dienstgeschäfts sowie für die zusätzliche Reisezeit gewährt.

(2) Wird in besonderen Fällen angeordnet oder genehmigt, dass die
Dienstreise an einem vorübergehenden Aufenthaltsort anzutreten oder zu
beenden ist, wird die Reisekostenvergütung abweichend von Absatz 1
nach der Abreise von oder der Ankunft an diesem Ort bemessen.
Entsprechendes gilt, wenn in diesen Fällen die Dienstreise an der
Wohnung oder Dienststätte beginnt oder endet. Absatz 1 Satz 2 ist
entsprechend anzuwenden.

(3) Wird aus dienstlichen Gründen die vorzeitige Beendigung einer
Urlaubsreise angeordnet, gilt die Rückreise vom Urlaubsort unmittelbar
oder über den Geschäftsort zur Dienststätte als Dienstreise, für die
Reisekostenvergütung gewährt wird. Außerdem werden die Fahrtauslagen
für die kürzeste Reisestrecke von der Wohnung zum Urlaubsort, an dem
die Bediensteten die Anordnung erreicht, im Verhältnis des nicht
ausgenutzten Teils der Urlaubsreise zur vorgesehenen Dauer der
Urlaubsreise erstattet.

(4) Aufwendungen der Dienstreisenden und der sie begleitenden
Personen, die durch die Unterbrechung oder vorzeitige Beendigung einer
Urlaubsreise verursacht worden sind, werden in angemessenem Umfang
erstattet. Dies gilt auch für Aufwendungen, die aus diesen Gründen
nicht ausgenutzt werden konnten; hinsichtlich der Erstattung von
Aufwendungen für die Hin- und Rückfahrt ist Absatz 3 Satz 2 sinngemäß
anzuwenden.

## § 14 Auslandsdienstreisen

(1) Auslandsdienstreisen sind Dienstreisen im oder ins Ausland sowie
vom Ausland ins Inland.

(2) Nicht als Auslandsdienstreisen gelten Dienstreisen der im
Grenzverkehr tätigen Beamtinnen und Beamten im Bereich ausländischer
Lokalgrenzbehörden, zwischen solchen Bereichen und zwischen diesen und
dem Inland.

(3) Das Bundesministerium des Innern wird ermächtigt, durch
Rechtsverordnung wegen der besonderen Verhältnisse abweichende
Vorschriften über die Reisekostenvergütung für Auslandsdienstreisen
bezüglich der Anordnung und Genehmigung von Dienstreisen, der Fahrt-
und Flugkosten, des Auslandstage- und Auslandsübernachtungsgeldes, der
Reisebeihilfen, der Kriterien der Erstattung klimabedingter Bekleidung
und anderer Nebenkosten zu erlassen.

## § 15 Trennungsgeld

(1) Beamtinnen, Beamte, Richterinnen und Richter, die an einen Ort
außerhalb des Dienst- und Wohnortes ohne Zusage der
Umzugskostenvergütung abgeordnet werden, erhalten für die ihnen
dadurch entstehenden notwendigen Aufwendungen unter Berücksichtigung
der häuslichen Ersparnis ein Trennungsgeld nach einer
Rechtsverordnung, die für Abordnungen im Inland das Bundesministerium
des Innern erlässt. Diese Verordnung ist auch anzuwenden für
Abordnungen im oder ins Ausland sowie vom Ausland ins Inland, soweit
aufgrund der Ermächtigung des Absatzes 2 keine Sonderregelungen
ergangen sind. Dasselbe gilt für Kommandierungen von Soldatinnen und
Soldaten und die vorübergehende dienstliche Tätigkeit bei einer
anderen Stelle als einer Dienststelle. Der Abordnung stehen die
Zuweisung nach § 29 des Bundesbeamtengesetzes oder nach § 20 des
Beamtenstatusgesetzes gleich.

(2) Absatz 1 Satz 1 und 3 gilt entsprechend für Abordnungen ohne
Zusage der Umzugskostenvergütung im oder ins Ausland sowie vom Ausland
ins Inland, soweit die besonderen Bedürfnisse des Auslandsdienstes und
die besonderen Verhältnisse im Ausland es erfordern mit der Maßgabe,
dass das Auswärtige Amt die Rechtsverordnung im Einvernehmen mit dem
Bundesministerium des Innern, dem Bundesministerium der Verteidigung
und dem Bundesministerium der Finanzen erlässt.

(3) Werden Beamtinnen oder Beamte auf Widerruf im Vorbereitungsdienst
zum Zwecke ihrer Ausbildung einer Ausbildungsstelle an einem anderen
Ort als dem bisherigen Dienst- und Wohnort zugewiesen, können ihnen
die dadurch entstehenden notwendigen Mehrauslagen ganz oder teilweise
erstattet werden.

## § 16 Verwaltungsvorschriften

Allgemeine Verwaltungsvorschriften zu diesem Gesetz erlässt das
Bundesministerium des Innern. Verwaltungsvorschriften zu den
Sondervorschriften für die Reisekostenvergütung für
Auslandsdienstreisen erlässt das Bundesministerium des Innern im
Einvernehmen mit dem Auswärtigen Amt.


/*
PluginPy
Copyright (C) 2018 Samson Wang

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

This program 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 General Public License
along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/

#include "PluginMgr.h"
#include <QDebug>
#include <pybind11/embed.h>
#include <pybind11/eval.h>
#include <pybind11/pytypes.h>
#include "ExportPyPlugin.h"
#include "PluginWrapper.h"
#include "InputData.h"

namespace py = pybind11;

namespace pluginpy {

pluginpy::PluginMgr& PluginMgr::instance() {
    static PluginMgr s_mgr;
    return s_mgr;
}

launchy::PluginInterface* PluginMgr::loadPlugin(const QString& pluginName, const QString& pluginPath) {
    qDebug() << "pluginpy::PluginMgr::loadPlugin, name:" << pluginName
        << "path:" << pluginPath;

    uint pluginId = qHash(pluginName);
    if (m_pluginInterface.contains(pluginId)) {
        qDebug() << "pluginpy::PluginMgr::loadPlugin, plugin alread loaded, name:" << pluginName
            << "path:" << pluginPath;
        return m_pluginInterface[pluginId];
    }

    if (!m_pluginObject.contains(pluginId)) {
        py::list pathObj = py::module::import("sys").attr("path").cast<py::list>();
        pathObj.append(qUtf8Printable(QDir::toNativeSeparators(pluginPath)));
        py::object module = py::module::import(qUtf8Printable(pluginName));
        py::object pluginClass = module.attr("getPlugin")();

        m_pluginObject.insert(pluginId, pluginClass());
    }

    py::object& pluginObject = m_pluginObject[pluginId];

    if (py::isinstance<exportpy::Plugin>(pluginObject)) {
        qDebug() << "pluginpy::PluginMgr::loadPlugin, plugin load succeed";
        exportpy::Plugin* pluginPtr = pluginObject.cast<exportpy::Plugin*>();
        if (pluginPtr) {
            std::string name = pluginPtr->getName();
            qDebug() << "pluginpy::PluginMgr::loadPlugin, plugin name:" << name.c_str();
            launchy::PluginInterface* intf = new pluginpy::PluginWrapper(pluginPtr);
            // store this pointer in manager
            m_pluginInterface.insert(pluginId, intf);
            return intf;
        }
    }

    return nullptr;
}

bool PluginMgr::unloadPlugin(uint pluginId) {
    qDebug() << "pluginpy::PluginMgr::unloadPlugin, id:" << pluginId;

    launchy::PluginInterface* plugin = m_pluginInterface[pluginId];
    if (plugin) {
        delete plugin;
        plugin = nullptr;
    }

    m_pluginInterface.remove(pluginId);
    m_pluginObject.remove(pluginId);

    return true;
}

void PluginMgr::initSettings(QSettings* setting) {
    if (!setting) {
        qWarning("PluginMgr::initSettings, setting is nullptr");
        return;
    }

    // avoid multiple pybind11 import
    if (setting == m_pSettings) {
        qDebug("PluginMgr::initSettings, setting is already set");
        return;
    }
    m_pSettings = setting;

    try {
        // init qsetting
        py::object launchyModule = py::module::import("launchy");
        py::object launchyDict = launchyModule.attr("__dict__");
        PyObject* settingPyObj = PyLong_FromVoidPtr(m_pSettings);
        launchyDict["__settings"] = py::handle(settingPyObj);

        // run setQSetting from launchy_util
        py::object launchyUtilModule = py::module::import("launchy_util");
        launchyUtilModule.attr("setSettingsObject")();
    }
    catch (const py::error_already_set& e) {
        PyErr_Print();
        PyErr_Clear();
        const char* errInfo = e.what();
        qWarning() << "pluginpy::PluginMgr::initSettings,"
            << "fail to init QSetting," << errInfo;
    }
}

void PluginMgr::registerPlugin(py::object pluginClass) {
    qDebug() << "pluginpy::PluginMgr::registerPlugin, register plugin called";
    //m_pluginClass.push_back(pluginClass);

}

PluginMgr::PluginMgr()
    : m_pSettings(nullptr) {

    py::initialize_interpreter();

    QString pythonLibPath = qApp->applicationDirPath() + "/python";
    py::list pathObj = py::module::import("sys").attr("path").cast<py::list>();
    pathObj.append(qUtf8Printable(QDir::toNativeSeparators(pythonLibPath)));

    try {
        // import pluginconf.py
        py::module::import("launchy_util");
    }
    catch (const py::error_already_set& e) {
        PyErr_Print();
        PyErr_Clear();
        const char* errInfo = e.what();
        qDebug() << "pluginpy::PluginMgr::PluginMgr, launchy_util module not imported," << errInfo;
    }
}

PluginMgr::~PluginMgr() {
    QHashIterator<uint, launchy::PluginInterface*> it1(m_pluginInterface);
    while (it1.hasNext()) {
        it1.next();
        delete it1.value();
    }
    m_pSettings = nullptr;
    m_pluginInterface.clear();
    m_pluginObject.clear();
    py::finalize_interpreter();
}

}


. /lib/functions.sh
. /lib/functions/migrations.sh

board=$(board_name)

case "$board" in
lenovo,newifi-y1)
	migrate_leds "^y1:=newifi-y1:"
	;;
lenovo,newifi-y1s)
	migrate_leds "^y1s:=newifi-y1s:"
	;;
netgear,wn3000rp-v3)
	migrate_leds "^wn3000rpv3:=wn3000rp-v3:"
	;;
tplink,archer-c2-v1)
	migrate_leds "^c2-v1:=archer-c2-v1:"
	;;
tplink,archer-c20-v1)
	migrate_leds "^c20-v1:=archer-c20-v1:"
	;;
tplink,archer-c20i)
	migrate_leds "^c20i:=archer-c20i:"
	;;
tplink,archer-c50-v1)
	migrate_leds "^c50:=archer-c50-v1:"
	;;
tplink,archer-mr200)
	migrate_leds "^mr200:=archer-mr200:"
	;;
youku,yk1)
	migrate_leds "^youku-yk1:=yk1:"
	;;
zyxel,keenetic-omni)
	migrate_leds "^kn_rc:=keenetic-omni:"
	;;
zyxel,keenetic-omni-ii)
	migrate_leds "^kn_rc:=keenetic-omni-ii:"
	;;
zyxel,keenetic-viva)
	migrate_leds "^kng_rc:=keenetic-viva:"
	;;
esac

migrations_apply system

exit 0


<!-- SPDX-License-Identifier: CC-BY-4.0 -->
<!-- Copyright Contributors to the ODPi Egeria project. -->

# OCF Metadata Management - Client-side

OCF Metadata management client-side provides common client-side beans for managing the paging used when
retrieving metadata about an asset and its related elements (such as connections and schema)
from the open metadata repositories where the API is based on the
[Open Connector Framework (OCF)](../../../frameworks/open-connector-framework) beans.

----
License: [CC BY 4.0](https://creativecommons.org/licenses/by/4.0/),
Copyright Contributors to the ODPi Egeria project.


/**
 Copyright (c) 2014-present, Facebook, Inc.
 All rights reserved.

 This source code is licensed under the BSD-style license found in the
 LICENSE file in the root directory of this source tree. An additional grant
 of patent rights can be found in the PATENTS file in the same directory.
 */

#import "POPDecayAnimation.h"
#import "POPPropertyAnimationInternal.h"

// minimal velocity factor before decay animation is considered complete, in units / s
static CGFloat kPOPAnimationDecayMinimalVelocityFactor = 5.;

// default decay animation deceleration
static CGFloat kPOPAnimationDecayDecelerationDefault = 0.998;

static void decay_position(CGFloat *x, CGFloat *v, NSUInteger count, CFTimeInterval dt, CGFloat deceleration)
{
  dt *= 1000;

  // v0 = v / 1000
  // v = v0 * powf(deceleration, dt);
  // v = v * 1000;

  // x0 = x;
  // x = x0 + v0 * deceleration * (1 - powf(deceleration, dt)) / (1 - deceleration)
  float v0[count];
  float kv = powf(deceleration, dt);
  float kx = deceleration * (1 - kv) / (1 - deceleration);

  for (NSUInteger idx = 0; idx < count; idx++) {
    v0[idx] = v[idx] / 1000.;
    v[idx] = v0[idx] * kv * 1000.;
    x[idx] = x[idx] + v0[idx] * kx;
  }
}

struct _POPDecayAnimationState : _POPPropertyAnimationState
{
  double deceleration;
  CFTimeInterval duration;

  _POPDecayAnimationState(id __unsafe_unretained anim) :
  _POPPropertyAnimationState(anim),
  duration(0),
  deceleration(kPOPAnimationDecayDecelerationDefault) {
    type = kPOPAnimationDecay;
  }

  bool isDone() {
    if (_POPPropertyAnimationState::isDone()) {
      return true;
    }

    CGFloat f = dynamicsThreshold * kPOPAnimationDecayMinimalVelocityFactor;
    const CGFloat *velocityValues = vec_data(velocityVec);
    for (NSUInteger idx = 0; idx < valueCount; idx++) {
      if (fabsf(velocityValues[idx]) >= f)
        return false;
    }
    return true;

  }

  void computeDestinationValues() {
    // to value assuming final velocity as a factor of dynamics threshold
    // derived from v' = v * d^dt used in decay_position
    // to compute the to value with maximal dt, p' = p + (v * d) / (1 - d)
    VectorRef fromValue = NULL != currentVec ? currentVec : fromVec;
    if (!fromValue) {
      return;
    }

    VectorRef toValue(Vector::new_vector(fromValue.get()));

    // compute duration till threshold velocity
    Vector4r scaledVelocity = vector4(velocityVec) / 1000.;

    double k = dynamicsThreshold * kPOPAnimationDecayMinimalVelocityFactor / 1000.;
    double vx = k / scaledVelocity.x;
    double vy = k / scaledVelocity.y;
    double vz = k / scaledVelocity.z;
    double vw = k / scaledVelocity.w;
    double d = log(deceleration) * 1000.;
    duration = MAX(MAX(MAX(log(fabs(vx)) / d, log(fabs(vy)) / d), log(fabs(vz)) / d), log(fabs(vw)) / d);

    // ensure velocity threshold is exceeded
    if (isnan(duration) || duration < 0) {
      duration = 0;
    } else {
      // compute to value
      Vector4r velocity = velocityVec->vector4r();
      decay_position(toValue->data(), velocity.data(), valueCount, duration, deceleration);
    }

    toVec = toValue;
  }

  bool advance(CFTimeInterval time, CFTimeInterval dt, id obj) {
    // advance past not yet initialized animations
    if (NULL == currentVec) {
      return false;
    }

    decay_position(currentVec->data(), velocityVec->data(), valueCount, dt, deceleration);

    // clamp to compute end value; avoid possibility of decaying past
    clampCurrentValue(kPOPAnimationClampEnd | clampMode);

    return true;
  }

};

typedef struct _POPDecayAnimationState POPDecayAnimationState;