<commit_before>//=== - llvm/unittest/Support/Alignment.cpp - Alignment utility tests -----===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//

#include "llvm/Support/Alignment.h"
#include "gtest/gtest.h"

#include <vector>

using namespace llvm;

namespace {

std::vector<uint64_t> getValidAlignments() {
  std::vector<uint64_t> Out;
  for (size_t Shift = 0; Shift < 64; ++Shift)
    Out.push_back(1ULL << Shift);
  return Out;
}

// We use a subset of valid alignments for DEATH_TESTs as they are particularly
// slow.
std::vector<uint64_t> getValidAlignmentsForDeathTest() {
  return {1, 1ULL << 31, 1ULL << 63};
}

std::vector<uint64_t> getNonPowerOfTwo() { return {3, 10, 15}; }

TEST(Alignment, AlignDefaultCTor) { EXPECT_EQ(Align().value(), 1ULL); }

TEST(Alignment, MaybeAlignDefaultCTor) {
  EXPECT_FALSE(MaybeAlign().hasValue());
}

TEST(Alignment, ValidCTors) {
  for (size_t Value : getValidAlignments()) {
    EXPECT_EQ(Align(Value).value(), Value);
    EXPECT_EQ((*MaybeAlign(Value)).value(), Value);
  }
}

TEST(Alignment, InvalidCTors) {
  EXPECT_DEATH((Align(0)), "Value must not be 0");
  for (size_t Value : getNonPowerOfTwo()) {
    EXPECT_DEATH((Align(Value)), "Alignment is not a power of 2");
    EXPECT_DEATH((MaybeAlign(Value)), "Alignment is not 0 or a power of 2");
  }
}

TEST(Alignment, CheckMaybeAlignHasValue) {
  EXPECT_TRUE(MaybeAlign(1));
  EXPECT_TRUE(MaybeAlign(1).hasValue());
  EXPECT_FALSE(MaybeAlign(0));
  EXPECT_FALSE(MaybeAlign(0).hasValue());
  EXPECT_FALSE(MaybeAlign());
  EXPECT_FALSE(MaybeAlign().hasValue());
}

TEST(Alignment, CantConvertUnsetMaybe) {
  EXPECT_DEATH((MaybeAlign(0).getValue()), ".*");
}

TEST(Alignment, Division) {
  for (size_t Value : getValidAlignments()) {
    if (Value == 1) {
      EXPECT_DEATH(Align(Value) / 2, "Can't halve byte alignment");
      EXPECT_DEATH(MaybeAlign(Value) / 2, "Can't halve byte alignment");
    } else {
      EXPECT_EQ(Align(Value) / 2, Value / 2);
      EXPECT_EQ(MaybeAlign(Value) / 2, Value / 2);
    }
  }
  EXPECT_EQ(MaybeAlign(0) / 2, MaybeAlign(0));

  EXPECT_DEATH(Align(8) / 0, "Divisor must be positive and a power of 2");
  EXPECT_DEATH(Align(8) / 3, "Divisor must be positive and a power of 2");
}

TEST(Alignment, AlignTo) {
  struct {
    uint64_t alignment;
    uint64_t offset;
    uint64_t rounded;
  } kTests[] = {
      // MaybeAlign
      {0, 0, 0},
      {0, 1, 1},
      {0, 5, 5},
      // MaybeAlign / Align
      {1, 0, 0},
      {1, 1, 1},
      {1, 5, 5},
      {2, 0, 0},
      {2, 1, 2},
      {2, 2, 2},
      {2, 7, 8},
      {2, 16, 16},
      {4, 0, 0},
      {4, 1, 4},
      {4, 4, 4},
      {4, 6, 8},
  };
  for (const auto &T : kTests) {
    MaybeAlign A(T.alignment);
    // Test MaybeAlign
    EXPECT_EQ(alignTo(T.offset, A), T.rounded);
    // Test Align
    if (A)
      EXPECT_EQ(alignTo(T.offset, A.getValue()), T.rounded);
  }
}

TEST(Alignment, Log2) {
  for (size_t Value : getValidAlignments()) {
    EXPECT_EQ(Log2(Align(Value)), Log2_64(Value));
    EXPECT_EQ(Log2(MaybeAlign(Value)), Log2_64(Value));
  }
  EXPECT_DEATH(Log2(MaybeAlign(0)), ".* should be defined");
}

TEST(Alignment, MinAlign) {
  struct {
    uint64_t A;
    uint64_t B;
    uint64_t MinAlign;
  } kTests[] = {
      // MaybeAlign
      {0, 0, 0},
      {0, 8, 8},
      {2, 0, 2},
      // MaybeAlign / Align
      {1, 2, 1},
      {8, 4, 4},
  };
  for (const auto &T : kTests) {
    EXPECT_EQ(commonAlignment(MaybeAlign(T.A), MaybeAlign(T.B)), T.MinAlign);
    EXPECT_EQ(MinAlign(T.A, T.B), T.MinAlign);
    if (T.A)
      EXPECT_EQ(commonAlignment(Align(T.A), MaybeAlign(T.B)), T.MinAlign);
    if (T.B)
      EXPECT_EQ(commonAlignment(MaybeAlign(T.A), Align(T.B)), T.MinAlign);
    if (T.A && T.B)
      EXPECT_EQ(commonAlignment(Align(T.A), Align(T.B)), T.MinAlign);
  }
}

TEST(Alignment, Encode_Decode) {
  for (size_t Value : getValidAlignments()) {
    {
      Align Actual(Value);
      Align Expected = decodeMaybeAlign(encode(Actual)).getValue();
      EXPECT_EQ(Expected, Actual);
    }
    {
      MaybeAlign Actual(Value);
      MaybeAlign Expected = decodeMaybeAlign(encode(Actual));
      EXPECT_EQ(Expected, Actual);
    }
  }
  MaybeAlign Actual(0);
  MaybeAlign Expected = decodeMaybeAlign(encode(Actual));
  EXPECT_EQ(Expected, Actual);
}

TEST(Alignment, isAligned) {
  struct {
    uint64_t alignment;
    uint64_t offset;
    bool isAligned;
  } kTests[] = {
      // MaybeAlign / Align
      {1, 0, true},  {1, 1, true},  {1, 5, true},  {2, 0, true},
      {2, 1, false}, {2, 2, true},  {2, 7, false}, {2, 16, true},
      {4, 0, true},  {4, 1, false}, {4, 4, true},  {4, 6, false},
  };
  for (const auto &T : kTests) {
    MaybeAlign A(T.alignment);
    // Test MaybeAlign
    EXPECT_EQ(isAligned(A, T.offset), T.isAligned);
    // Test Align
    if (A)
      EXPECT_EQ(isAligned(A.getValue(), T.offset), T.isAligned);
  }
}

TEST(Alignment, AlignComparisons) {
  std::vector<uint64_t> ValidAlignments = getValidAlignments();
  std::sort(ValidAlignments.begin(), ValidAlignments.end());
  for (size_t I = 1; I < ValidAlignments.size(); ++I) {
    assert(I >= 1);
    const Align A(ValidAlignments[I - 1]);
    const Align B(ValidAlignments[I]);
    EXPECT_EQ(A, A);
    EXPECT_NE(A, B);
    EXPECT_LT(A, B);
    EXPECT_GT(B, A);
    EXPECT_LE(A, B);
    EXPECT_GE(B, A);
    EXPECT_LE(A, A);
    EXPECT_GE(A, A);

    EXPECT_EQ(A, A.value());
    EXPECT_NE(A, B.value());
    EXPECT_LT(A, B.value());
    EXPECT_GT(B, A.value());
    EXPECT_LE(A, B.value());
    EXPECT_GE(B, A.value());
    EXPECT_LE(A, A.value());
    EXPECT_GE(A, A.value());

    EXPECT_EQ(std::max(A, B), B);
    EXPECT_EQ(std::min(A, B), A);

    const MaybeAlign MA(ValidAlignments[I - 1]);
    const MaybeAlign MB(ValidAlignments[I]);
    EXPECT_EQ(MA, MA);
    EXPECT_NE(MA, MB);
    EXPECT_LT(MA, MB);
    EXPECT_GT(MB, MA);
    EXPECT_LE(MA, MB);
    EXPECT_GE(MB, MA);
    EXPECT_LE(MA, MA);
    EXPECT_GE(MA, MA);

    EXPECT_EQ(MA, MA ? (*MA).value() : 0);
    EXPECT_NE(MA, MB ? (*MB).value() : 0);
    EXPECT_LT(MA, MB ? (*MB).value() : 0);
    EXPECT_GT(MB, MA ? (*MA).value() : 0);
    EXPECT_LE(MA, MB ? (*MB).value() : 0);
    EXPECT_GE(MB, MA ? (*MA).value() : 0);
    EXPECT_LE(MA, MA ? (*MA).value() : 0);
    EXPECT_GE(MA, MA ? (*MA).value() : 0);

    EXPECT_EQ(std::max(A, B), B);
    EXPECT_EQ(std::min(A, B), A);
  }
}

TEST(Alignment, AssumeAligned) {
  EXPECT_EQ(assumeAligned(0), Align(1));
  EXPECT_EQ(assumeAligned(0), Align());
  EXPECT_EQ(assumeAligned(1), Align(1));
  EXPECT_EQ(assumeAligned(1), Align());
}

TEST(Alignment, ComparisonsWithZero) {
  for (size_t Value : getValidAlignmentsForDeathTest()) {
    EXPECT_DEATH((void)(Align(Value) == 0), ".* should be defined");
    EXPECT_DEATH((void)(Align(Value) != 0), ".* should be defined");
    EXPECT_DEATH((void)(Align(Value) >= 0), ".* should be defined");
    EXPECT_DEATH((void)(Align(Value) <= 0), ".* should be defined");
    EXPECT_DEATH((void)(Align(Value) > 0), ".* should be defined");
    EXPECT_DEATH((void)(Align(Value) < 0), ".* should be defined");
  }
}

TEST(Alignment, CompareMaybeAlignToZero) {
  for (size_t Value : getValidAlignmentsForDeathTest()) {
    // MaybeAlign is allowed to be == or != 0
    (void)(MaybeAlign(Value) == 0);
    (void)(MaybeAlign(Value) != 0);
    EXPECT_DEATH((void)(MaybeAlign(Value) >= 0), ".* should be defined");
    EXPECT_DEATH((void)(MaybeAlign(Value) <= 0), ".* should be defined");
    EXPECT_DEATH((void)(MaybeAlign(Value) > 0), ".* should be defined");
    EXPECT_DEATH((void)(MaybeAlign(Value) < 0), ".* should be defined");
  }
}

TEST(Alignment, CompareAlignToUndefMaybeAlign) {
  for (size_t Value : getValidAlignmentsForDeathTest()) {
    EXPECT_DEATH((void)(Align(Value) == MaybeAlign(0)), ".* should be defined");
    EXPECT_DEATH((void)(Align(Value) != MaybeAlign(0)), ".* should be defined");
    EXPECT_DEATH((void)(Align(Value) >= MaybeAlign(0)), ".* should be defined");
    EXPECT_DEATH((void)(Align(Value) <= MaybeAlign(0)), ".* should be defined");
    EXPECT_DEATH((void)(Align(Value) > MaybeAlign(0)), ".* should be defined");
    EXPECT_DEATH((void)(Align(Value) < MaybeAlign(0)), ".* should be defined");
  }
}

} // end anonymous namespace
<commit_msg>[LLVM] Fix Alignment death tests in Release Mode<commit_after>//=== - llvm/unittest/Support/Alignment.cpp - Alignment utility tests -----===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//

#include "llvm/Support/Alignment.h"
#include "gtest/gtest.h"

#include <vector>

using namespace llvm;

namespace {

std::vector<uint64_t> getValidAlignments() {
  std::vector<uint64_t> Out;
  for (size_t Shift = 0; Shift < 64; ++Shift)
    Out.push_back(1ULL << Shift);
  return Out;
}

TEST(AlignmentTest, AlignDefaultCTor) { EXPECT_EQ(Align().value(), 1ULL); }

TEST(AlignmentTest, MaybeAlignDefaultCTor) {
  EXPECT_FALSE(MaybeAlign().hasValue());
}

TEST(AlignmentTest, ValidCTors) {
  for (size_t Value : getValidAlignments()) {
    EXPECT_EQ(Align(Value).value(), Value);
    EXPECT_EQ((*MaybeAlign(Value)).value(), Value);
  }
}

TEST(AlignmentTest, CheckMaybeAlignHasValue) {
  EXPECT_TRUE(MaybeAlign(1));
  EXPECT_TRUE(MaybeAlign(1).hasValue());
  EXPECT_FALSE(MaybeAlign(0));
  EXPECT_FALSE(MaybeAlign(0).hasValue());
  EXPECT_FALSE(MaybeAlign());
  EXPECT_FALSE(MaybeAlign().hasValue());
}

TEST(AlignmentTest, Division) {
  for (size_t Value : getValidAlignments()) {
    if (Value > 1) {
      EXPECT_EQ(Align(Value) / 2, Value / 2);
      EXPECT_EQ(MaybeAlign(Value) / 2, Value / 2);
    }
  }
  EXPECT_EQ(MaybeAlign(0) / 2, MaybeAlign(0));
}

TEST(AlignmentTest, AlignTo) {
  struct {
    uint64_t alignment;
    uint64_t offset;
    uint64_t rounded;
  } kTests[] = {
      // MaybeAlign
      {0, 0, 0},
      {0, 1, 1},
      {0, 5, 5},
      // MaybeAlign / Align
      {1, 0, 0},
      {1, 1, 1},
      {1, 5, 5},
      {2, 0, 0},
      {2, 1, 2},
      {2, 2, 2},
      {2, 7, 8},
      {2, 16, 16},
      {4, 0, 0},
      {4, 1, 4},
      {4, 4, 4},
      {4, 6, 8},
  };
  for (const auto &T : kTests) {
    MaybeAlign A(T.alignment);
    // Test MaybeAlign
    EXPECT_EQ(alignTo(T.offset, A), T.rounded);
    // Test Align
    if (A)
      EXPECT_EQ(alignTo(T.offset, A.getValue()), T.rounded);
  }
}

TEST(AlignmentTest, Log2) {
  for (size_t Value : getValidAlignments()) {
    EXPECT_EQ(Log2(Align(Value)), Log2_64(Value));
    EXPECT_EQ(Log2(MaybeAlign(Value)), Log2_64(Value));
  }
}

TEST(AlignmentTest, MinAlign) {
  struct {
    uint64_t A;
    uint64_t B;
    uint64_t MinAlign;
  } kTests[] = {
      // MaybeAlign
      {0, 0, 0},
      {0, 8, 8},
      {2, 0, 2},
      // MaybeAlign / Align
      {1, 2, 1},
      {8, 4, 4},
  };
  for (const auto &T : kTests) {
    EXPECT_EQ(commonAlignment(MaybeAlign(T.A), MaybeAlign(T.B)), T.MinAlign);
    EXPECT_EQ(MinAlign(T.A, T.B), T.MinAlign);
    if (T.A)
      EXPECT_EQ(commonAlignment(Align(T.A), MaybeAlign(T.B)), T.MinAlign);
    if (T.B)
      EXPECT_EQ(commonAlignment(MaybeAlign(T.A), Align(T.B)), T.MinAlign);
    if (T.A && T.B)
      EXPECT_EQ(commonAlignment(Align(T.A), Align(T.B)), T.MinAlign);
  }
}

TEST(AlignmentTest, Encode_Decode) {
  for (size_t Value : getValidAlignments()) {
    {
      Align Actual(Value);
      Align Expected = decodeMaybeAlign(encode(Actual)).getValue();
      EXPECT_EQ(Expected, Actual);
    }
    {
      MaybeAlign Actual(Value);
      MaybeAlign Expected = decodeMaybeAlign(encode(Actual));
      EXPECT_EQ(Expected, Actual);
    }
  }
  MaybeAlign Actual(0);
  MaybeAlign Expected = decodeMaybeAlign(encode(Actual));
  EXPECT_EQ(Expected, Actual);
}

TEST(AlignmentTest, isAligned) {
  struct {
    uint64_t alignment;
    uint64_t offset;
    bool isAligned;
  } kTests[] = {
      // MaybeAlign / Align
      {1, 0, true},  {1, 1, true},  {1, 5, true},  {2, 0, true},
      {2, 1, false}, {2, 2, true},  {2, 7, false}, {2, 16, true},
      {4, 0, true},  {4, 1, false}, {4, 4, true},  {4, 6, false},
  };
  for (const auto &T : kTests) {
    MaybeAlign A(T.alignment);
    // Test MaybeAlign
    EXPECT_EQ(isAligned(A, T.offset), T.isAligned);
    // Test Align
    if (A)
      EXPECT_EQ(isAligned(A.getValue(), T.offset), T.isAligned);
  }
}

TEST(AlignmentTest, AlignComparisons) {
  std::vector<uint64_t> ValidAlignments = getValidAlignments();
  std::sort(ValidAlignments.begin(), ValidAlignments.end());
  for (size_t I = 1; I < ValidAlignments.size(); ++I) {
    assert(I >= 1);
    const Align A(ValidAlignments[I - 1]);
    const Align B(ValidAlignments[I]);
    EXPECT_EQ(A, A);
    EXPECT_NE(A, B);
    EXPECT_LT(A, B);
    EXPECT_GT(B, A);
    EXPECT_LE(A, B);
    EXPECT_GE(B, A);
    EXPECT_LE(A, A);
    EXPECT_GE(A, A);

    EXPECT_EQ(A, A.value());
    EXPECT_NE(A, B.value());
    EXPECT_LT(A, B.value());
    EXPECT_GT(B, A.value());
    EXPECT_LE(A, B.value());
    EXPECT_GE(B, A.value());
    EXPECT_LE(A, A.value());
    EXPECT_GE(A, A.value());

    EXPECT_EQ(std::max(A, B), B);
    EXPECT_EQ(std::min(A, B), A);

    const MaybeAlign MA(ValidAlignments[I - 1]);
    const MaybeAlign MB(ValidAlignments[I]);
    EXPECT_EQ(MA, MA);
    EXPECT_NE(MA, MB);
    EXPECT_LT(MA, MB);
    EXPECT_GT(MB, MA);
    EXPECT_LE(MA, MB);
    EXPECT_GE(MB, MA);
    EXPECT_LE(MA, MA);
    EXPECT_GE(MA, MA);

    EXPECT_EQ(MA, MA ? (*MA).value() : 0);
    EXPECT_NE(MA, MB ? (*MB).value() : 0);
    EXPECT_LT(MA, MB ? (*MB).value() : 0);
    EXPECT_GT(MB, MA ? (*MA).value() : 0);
    EXPECT_LE(MA, MB ? (*MB).value() : 0);
    EXPECT_GE(MB, MA ? (*MA).value() : 0);
    EXPECT_LE(MA, MA ? (*MA).value() : 0);
    EXPECT_GE(MA, MA ? (*MA).value() : 0);

    EXPECT_EQ(std::max(A, B), B);
    EXPECT_EQ(std::min(A, B), A);
  }
}

TEST(AlignmentTest, AssumeAligned) {
  EXPECT_EQ(assumeAligned(0), Align(1));
  EXPECT_EQ(assumeAligned(0), Align());
  EXPECT_EQ(assumeAligned(1), Align(1));
  EXPECT_EQ(assumeAligned(1), Align());
}

// Death tests reply on assert which is disabled in release mode.
#ifndef NDEBUG

// We use a subset of valid alignments for DEATH_TESTs as they are particularly
// slow.
std::vector<uint64_t> getValidAlignmentsForDeathTest() {
  return {1, 1ULL << 31, 1ULL << 63};
}

std::vector<uint64_t> getNonPowerOfTwo() { return {3, 10, 15}; }

TEST(AlignmentDeathTest, Log2) {
  EXPECT_DEATH(Log2(MaybeAlign(0)), ".* should be defined");
}

TEST(AlignmentDeathTest, CantConvertUnsetMaybe) {
  EXPECT_DEATH((MaybeAlign(0).getValue()), ".*");
}

TEST(AlignmentDeathTest, Division) {
  EXPECT_DEATH(Align(1) / 2, "Can't halve byte alignment");
  EXPECT_DEATH(MaybeAlign(1) / 2, "Can't halve byte alignment");

  EXPECT_DEATH(Align(8) / 0, "Divisor must be positive and a power of 2");
  EXPECT_DEATH(Align(8) / 3, "Divisor must be positive and a power of 2");
}

TEST(AlignmentDeathTest, InvalidCTors) {
  EXPECT_DEATH((Align(0)), "Value must not be 0");
  for (size_t Value : getNonPowerOfTwo()) {
    EXPECT_DEATH((Align(Value)), "Alignment is not a power of 2");
    EXPECT_DEATH((MaybeAlign(Value)), "Alignment is not 0 or a power of 2");
  }
}

TEST(AlignmentDeathTest, ComparisonsWithZero) {
  for (size_t Value : getValidAlignmentsForDeathTest()) {
    EXPECT_DEATH((void)(Align(Value) == 0), ".* should be defined");
    EXPECT_DEATH((void)(Align(Value) != 0), ".* should be defined");
    EXPECT_DEATH((void)(Align(Value) >= 0), ".* should be defined");
    EXPECT_DEATH((void)(Align(Value) <= 0), ".* should be defined");
    EXPECT_DEATH((void)(Align(Value) > 0), ".* should be defined");
    EXPECT_DEATH((void)(Align(Value) < 0), ".* should be defined");
  }
}

TEST(AlignmentDeathTest, CompareMaybeAlignToZero) {
  for (size_t Value : getValidAlignmentsForDeathTest()) {
    // MaybeAlign is allowed to be == or != 0
    (void)(MaybeAlign(Value) == 0);
    (void)(MaybeAlign(Value) != 0);
    EXPECT_DEATH((void)(MaybeAlign(Value) >= 0), ".* should be defined");
    EXPECT_DEATH((void)(MaybeAlign(Value) <= 0), ".* should be defined");
    EXPECT_DEATH((void)(MaybeAlign(Value) > 0), ".* should be defined");
    EXPECT_DEATH((void)(MaybeAlign(Value) < 0), ".* should be defined");
  }
}

TEST(AlignmentDeathTest, CompareAlignToUndefMaybeAlign) {
  for (size_t Value : getValidAlignmentsForDeathTest()) {
    EXPECT_DEATH((void)(Align(Value) == MaybeAlign(0)), ".* should be defined");
    EXPECT_DEATH((void)(Align(Value) != MaybeAlign(0)), ".* should be defined");
    EXPECT_DEATH((void)(Align(Value) >= MaybeAlign(0)), ".* should be defined");
    EXPECT_DEATH((void)(Align(Value) <= MaybeAlign(0)), ".* should be defined");
    EXPECT_DEATH((void)(Align(Value) > MaybeAlign(0)), ".* should be defined");
    EXPECT_DEATH((void)(Align(Value) < MaybeAlign(0)), ".* should be defined");
  }
}

#endif // NDEBUG

} // end anonymous namespace
<|endoftext|>


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

#include "main.h"
#include <unsupported/Eigen/AlignedVector3>

namespace Eigen {

template<typename T,typename Derived>
T test_relative_error(const AlignedVector3<T> &a, const MatrixBase<Derived> &b)
{
  return test_relative_error(a.coeffs().template head<3>(), b);
}

}

template<typename Scalar>
void alignedvector3()
{
  Scalar s1 = internal::random<Scalar>();
  Scalar s2 = internal::random<Scalar>();
  typedef Matrix<Scalar,3,1> RefType;
  typedef Matrix<Scalar,3,3> Mat33;
  typedef AlignedVector3<Scalar> FastType;
  RefType  r1(RefType::Random()), r2(RefType::Random()), r3(RefType::Random()),
           r4(RefType::Random()), r5(RefType::Random()), r6(RefType::Random());
  FastType f1(r1), f2(r2), f3(r3), f4(r4), f5(r5), f6(r6);
  Mat33 m1(Mat33::Random());

  VERIFY_IS_APPROX(f1,r1);
  VERIFY_IS_APPROX(f4,r4);

  VERIFY_IS_APPROX(f4+f1,r4+r1);
  VERIFY_IS_APPROX(f4-f1,r4-r1);
  VERIFY_IS_APPROX(f4+f1-f2,r4+r1-r2);
  VERIFY_IS_APPROX(f4+=f3,r4+=r3);
  VERIFY_IS_APPROX(f4-=f5,r4-=r5);
  VERIFY_IS_APPROX(f4-=f5+f1,r4-=r5+r1);
  VERIFY_IS_APPROX(f5+f1-s1*f2,r5+r1-s1*r2);
  VERIFY_IS_APPROX(f5+f1/s2-s1*f2,r5+r1/s2-s1*r2);

  VERIFY_IS_APPROX(m1*f4,m1*r4);
  VERIFY_IS_APPROX(f4.transpose()*m1,r4.transpose()*m1);

  VERIFY_IS_APPROX(f2.dot(f3),r2.dot(r3));
  VERIFY_IS_APPROX(f2.cross(f3),r2.cross(r3));
  VERIFY_IS_APPROX(f2.norm(),r2.norm());

  VERIFY_IS_APPROX(f2.normalized(),r2.normalized());

  VERIFY_IS_APPROX((f2+f1).normalized(),(r2+r1).normalized());

  f2.normalize();
  r2.normalize();
  VERIFY_IS_APPROX(f2,r2);

  std::stringstream ss1, ss2;
  ss1 << f1;
  ss2 << r1;
  VERIFY(ss1.str()==ss2.str());
}

void test_alignedvector3()
{
  for(int i = 0; i < g_repeat; i++) {
    CALL_SUBTEST( alignedvector3<float>() );
  }
}
<commit_msg>add regression unit test for previous changeset<commit_after>// This file is part of Eigen, a lightweight C++ template library
// for linear algebra.
//
// Copyright (C) 2009 Gael Guennebaud <g.gael@free.fr>
//
// This Source Code Form is subject to the terms of the Mozilla
// Public License v. 2.0. If a copy of the MPL was not distributed
// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.

#include "main.h"
#include <unsupported/Eigen/AlignedVector3>

namespace Eigen {

template<typename T,typename Derived>
T test_relative_error(const AlignedVector3<T> &a, const MatrixBase<Derived> &b)
{
  return test_relative_error(a.coeffs().template head<3>(), b);
}

}

template<typename Scalar>
void alignedvector3()
{
  Scalar s1 = internal::random<Scalar>();
  Scalar s2 = internal::random<Scalar>();
  typedef Matrix<Scalar,3,1> RefType;
  typedef Matrix<Scalar,3,3> Mat33;
  typedef AlignedVector3<Scalar> FastType;
  RefType  r1(RefType::Random()), r2(RefType::Random()), r3(RefType::Random()),
           r4(RefType::Random()), r5(RefType::Random()), r6(RefType::Random());
  FastType f1(r1), f2(r2), f3(r3), f4(r4), f5(r5), f6(r6);
  Mat33 m1(Mat33::Random());

  VERIFY_IS_APPROX(f1,r1);
  VERIFY_IS_APPROX(f4,r4);

  VERIFY_IS_APPROX(f4+f1,r4+r1);
  VERIFY_IS_APPROX(f4-f1,r4-r1);
  VERIFY_IS_APPROX(f4+f1-f2,r4+r1-r2);
  VERIFY_IS_APPROX(f4+=f3,r4+=r3);
  VERIFY_IS_APPROX(f4-=f5,r4-=r5);
  VERIFY_IS_APPROX(f4-=f5+f1,r4-=r5+r1);
  VERIFY_IS_APPROX(f5+f1-s1*f2,r5+r1-s1*r2);
  VERIFY_IS_APPROX(f5+f1/s2-s1*f2,r5+r1/s2-s1*r2);

  VERIFY_IS_APPROX(m1*f4,m1*r4);
  VERIFY_IS_APPROX(f4.transpose()*m1,r4.transpose()*m1);

  VERIFY_IS_APPROX(f2.dot(f3),r2.dot(r3));
  VERIFY_IS_APPROX(f2.cross(f3),r2.cross(r3));
  VERIFY_IS_APPROX(f2.norm(),r2.norm());

  VERIFY_IS_APPROX(f2.normalized(),r2.normalized());

  VERIFY_IS_APPROX((f2+f1).normalized(),(r2+r1).normalized());

  f2.normalize();
  r2.normalize();
  VERIFY_IS_APPROX(f2,r2);

  {
    FastType f6 = RefType::Zero();
    FastType f7 = FastType::Zero();
    VERIFY_IS_APPROX(f6,f7);
    f6 = r4+r1;
    VERIFY_IS_APPROX(f6,r4+r1);
    f6 -= Scalar(2)*r4;
    VERIFY_IS_APPROX(f6,r1-r4);
  }

  std::stringstream ss1, ss2;
  ss1 << f1;
  ss2 << r1;
  VERIFY(ss1.str()==ss2.str());
}

void test_alignedvector3()
{
  for(int i = 0; i < g_repeat; i++) {
    CALL_SUBTEST( alignedvector3<float>() );
  }
}
<|endoftext|>


<commit_before>/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */

#include <windows.ui.notifications.h>
#include <windows.data.xml.dom.h>
#include <wrl.h>
#include <wchar.h>
#include <vector>

#pragma comment(lib, "delayimp")
#pragma comment(lib, "runtimeobject")

using namespace ABI::Windows::Data::Xml::Dom;
using namespace ABI::Windows::Foundation;
using namespace ABI::Windows::UI::Notifications;
using namespace Microsoft::WRL;
using namespace Microsoft::WRL::Wrappers;

class ToastNotificationHandler;

static wchar_t* sAppId = nullptr;
static std::vector<ToastNotificationHandler*> sNotifications;

typedef bool (STDAPICALLTYPE *EventCallback)();

class ToastNotificationHandler {
	typedef ABI::Windows::UI::Notifications::IToastNotification IToastNotification;
	typedef ABI::Windows::UI::Notifications::IToastDismissedEventArgs IToastDismissedEventArgs;
	typedef ABI::Windows::UI::Notifications::IToastNotificationManagerStatics IToastNotificationManagerStatics;
	typedef ABI::Windows::UI::Notifications::ToastTemplateType ToastTemplateType;
	typedef ABI::Windows::Data::Xml::Dom::IXmlNode IXmlNode;
	typedef ABI::Windows::Data::Xml::Dom::IXmlDocument IXmlDocument;

	typedef __FITypedEventHandler_2_Windows__CUI__CNotifications__CToastNotification_IInspectable_t ToastActivationHandler;
	typedef __FITypedEventHandler_2_Windows__CUI__CNotifications__CToastNotification_Windows__CUI__CNotifications__CToastDismissedEventArgs ToastDismissHandler;

public:
	ToastNotificationHandler() : mTitle(nullptr), mMessage(nullptr), mName(nullptr), mActivateCallback(nullptr), mDismissCallback(nullptr)
	{
	}

	~ToastNotificationHandler();

	bool Init(const wchar_t* aTitle, const wchar_t* aMessage, const wchar_t* aName);
	bool DisplayNotification(EventCallback aActivate, EventCallback aDismiss);
	bool CloseNotification();

	const wchar_t* GetName() const { return mName; }

private:
	ComPtr<IXmlDocument> ToastNotificationHandler::InitializeXmlForTemplate(ToastTemplateType templateType);
	bool CreateWindowsNotificationFromXml(IXmlDocument* aXml);

	HRESULT OnActivate(IToastNotification* aNotification, IInspectable* aInspectable);
	HRESULT OnDismiss(IToastNotification* aNotification, IToastDismissedEventArgs* aInspectable);

	ComPtr<IToastNotificationManagerStatics> mToastNotificationManagerStatics;
	ComPtr<IToastNotification> mNotification;
	ComPtr<IToastNotifier> mNotifier;
	HSTRING mTitle;
	HSTRING mMessage;
	wchar_t* mName;
	DWORD mThreadId;

	EventCallback mActivateCallback;
	EventCallback mDismissCallback;
};

ToastNotificationHandler::~ToastNotificationHandler()
{
	std::vector<ToastNotificationHandler*>::iterator iter = sNotifications.begin();
	while (sNotifications.end() != iter) {
		if (*iter == this) {
			sNotifications.erase(iter);
			break;
		}
		iter++;
	}

	if (mTitle) {
		WindowsDeleteString(mTitle);
	}
	if (mMessage) {
		WindowsDeleteString(mMessage);
	}
	if (mName) {
		free(mName);
	}
}

bool
ToastNotificationHandler::Init(const wchar_t* aTitle, const wchar_t* aMessage, const wchar_t* aName)
{
	HRESULT hr;
	hr = WindowsCreateString(aTitle, (UINT32)wcslen(aTitle), &mTitle);
	if (FAILED(hr)) {
		return false;
	}
	hr = WindowsCreateString(aMessage, (UINT32)wcslen(aMessage), &mMessage);
	if (FAILED(hr)) {
		return false;
	}
	if (aName) {
		mName = _wcsdup(aName);
		if (!mName) {
			return false;
		}
	}

	mThreadId = GetCurrentThreadId();

	return true;
}

static bool
SetNodeValueString(HSTRING inputString, ComPtr<IXmlNode> node, ComPtr<IXmlDocument> xml)
{
	ComPtr<IXmlText> inputText;
	HRESULT hr;
	hr = xml->CreateTextNode(inputString, &inputText);
	if (FAILED(hr)) {
		return false;
	}
	ComPtr<IXmlNode> inputTextNode;
	hr = inputText.As(&inputTextNode);
	if (FAILED(hr)) {
		return false;
	}
	ComPtr<IXmlNode> appendedChild;
	hr = node->AppendChild(inputTextNode.Get(), &appendedChild);
	if (FAILED(hr)) {
		return false;
	}

	return true;
}

ComPtr<IXmlDocument>
ToastNotificationHandler::InitializeXmlForTemplate(ToastTemplateType templateType)
{
	HRESULT hr;
	hr = GetActivationFactory(HStringReference(RuntimeClass_Windows_UI_Notifications_ToastNotificationManager).Get(), mToastNotificationManagerStatics.GetAddressOf());
	if (FAILED(hr)) {
		return nullptr;
	}

	ComPtr<IXmlDocument> toastXml;
	mToastNotificationManagerStatics->GetTemplateContent(templateType, &toastXml);
	return toastXml;
}

bool
ToastNotificationHandler::CreateWindowsNotificationFromXml(IXmlDocument* aXml)
{
	ComPtr<IToastNotificationFactory> factory;
	HRESULT hr;
	hr = GetActivationFactory(HStringReference(RuntimeClass_Windows_UI_Notifications_ToastNotification).Get(), factory.GetAddressOf());
	if (FAILED(hr)) {
		return false;
	}

	hr = factory->CreateToastNotification(aXml, &mNotification);
	if (FAILED(hr)) {
		return false;
	}

	if (mActivateCallback) {
		EventRegistrationToken activatedToken;
		hr = mNotification->add_Activated(Callback<ToastActivationHandler>(this, &ToastNotificationHandler::OnActivate).Get(), &activatedToken);
		if (FAILED(hr)) {
			return false;
		}
	}

	EventRegistrationToken dismissedToken;
	hr = mNotification->add_Dismissed(Callback<ToastDismissHandler>(this, &ToastNotificationHandler::OnDismiss).Get(), &dismissedToken);
	if (FAILED(hr)) {
		return false;
	}

	hr = mToastNotificationManagerStatics->CreateToastNotifierWithId(HStringReference(sAppId).Get(), mNotifier.GetAddressOf());
	if (FAILED(hr)) {
		return false;
	}
	hr = mNotifier->Show(mNotification.Get());
	if (FAILED(hr)) {
		return false;
	}

	return true;
}

bool
ToastNotificationHandler::DisplayNotification(EventCallback aActivate, EventCallback aDismiss)
{
	ComPtr<IXmlDocument> toastXml = InitializeXmlForTemplate(ToastTemplateType::ToastTemplateType_ToastText03);
	HRESULT hr;

	ComPtr<IXmlNodeList> toastTextElements;
	hr = toastXml->GetElementsByTagName(HStringReference(L"text").Get(), &toastTextElements);
	if (FAILED(hr)) {
		return false;
	}

	ComPtr<IXmlNode> titleTextNodeRoot;
	hr = toastTextElements->Item(0, &titleTextNodeRoot);
	if (FAILED(hr)) {
		return false;
	}
	ComPtr<IXmlNode> msgTextNodeRoot;
	hr = toastTextElements->Item(1, &msgTextNodeRoot);
	if (FAILED(hr)) {
		return false;
	}

	SetNodeValueString(mTitle, titleTextNodeRoot.Get(), toastXml.Get());
	SetNodeValueString(mMessage, msgTextNodeRoot.Get(), toastXml.Get());

	mActivateCallback = aActivate;
	mDismissCallback = aDismiss;

	return CreateWindowsNotificationFromXml(toastXml.Get());
}

bool
ToastNotificationHandler::CloseNotification()
{
	if (mNotifier && mNotification) {
		mNotifier->Hide(mNotification.Get());
	}
	return true;
}

HRESULT
ToastNotificationHandler::OnActivate(IToastNotification* aNotification, IInspectable* aInspectable)
{
	if (mThreadId != GetCurrentThreadId()) {
		return E_FAIL;
	}
	if (mActivateCallback) {
		mActivateCallback();
	}
	return S_OK;
}

HRESULT
ToastNotificationHandler::OnDismiss(IToastNotification* aNotification, IToastDismissedEventArgs* aArgs)
{
	if (mThreadId != GetCurrentThreadId()) {
		return E_FAIL;
	}
	if (mDismissCallback) {
		mDismissCallback();
	}
	delete this;
	return S_OK;
}

extern "C"
bool WINAPI
SetAppId()
{
	if (!sAppId) {
		WCHAR wszFilename[MAX_PATH];
		GetModuleFileNameW(NULL, wszFilename, MAX_PATH);
		wchar_t* slash = wcsrchr(wszFilename, '\\');
		if (slash) {
			*slash = '\0';
		}

		HKEY key;
		if (RegOpenKeyExW(HKEY_CURRENT_USER, L"Software\\Mozilla\\Firefox\\TaskBarIDs", 0, KEY_QUERY_VALUE, &key) == ERROR_SUCCESS) {
			WCHAR value[MAX_PATH];
			DWORD type = REG_SZ;
			DWORD len = sizeof(value);
			if (RegQueryValueExW(key, wszFilename, NULL, &type, (LPBYTE) value, &len) == ERROR_SUCCESS) {
				sAppId = _wcsdup(value);
			}
			RegCloseKey(key);
		}
	}

	return !!sAppId;
}

// external API to show toast notification via JS-CTYPES
extern "C"
bool WINAPI
DisplayToastNotification(const wchar_t* aTitle, const wchar_t* aMessage, const wchar_t* aName, void* aCallbackActive, void* aCallbackDismiss)
{
	if (!sAppId) {
		return false;
	}

	ToastNotificationHandler* handler = new ToastNotificationHandler();

	if (!handler->Init(aTitle, aMessage, aName)) {
		delete handler;
		return false;
	}

	if (!handler->DisplayNotification((EventCallback) aCallbackActive, (EventCallback) aCallbackDismiss)) {
		delete handler;
		return false;
	}

	sNotifications.push_back(handler);

	return true;
}

extern "C"
bool WINAPI
CloseToastNotification(const wchar_t* aName)
{
	if (!aName) {
		return false;
	}
	std::vector<ToastNotificationHandler*>::iterator iter = sNotifications.begin();
	while (sNotifications.end() != iter) {
		ToastNotificationHandler* handler = *iter;
		if (handler) {
			if (!wcscmp(handler->GetName(), aName)) {
				sNotifications.erase(iter);
				handler->CloseNotification();
				delete handler;
				return true;
			}
		}
		iter++;
	}

	return false;
}
<commit_msg>Change logic of remove handler<commit_after>/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */

#include <windows.ui.notifications.h>
#include <windows.data.xml.dom.h>
#include <wrl.h>
#include <wchar.h>
#include <vector>

#pragma comment(lib, "delayimp")
#pragma comment(lib, "runtimeobject")

using namespace ABI::Windows::Data::Xml::Dom;
using namespace ABI::Windows::Foundation;
using namespace ABI::Windows::UI::Notifications;
using namespace Microsoft::WRL;
using namespace Microsoft::WRL::Wrappers;

class ToastNotificationHandler;

static wchar_t* sAppId = nullptr;
static std::vector<ToastNotificationHandler*> sNotifications;

typedef bool (STDAPICALLTYPE *EventCallback)();

class ToastNotificationHandler {
	typedef ABI::Windows::UI::Notifications::IToastNotification IToastNotification;
	typedef ABI::Windows::UI::Notifications::IToastDismissedEventArgs IToastDismissedEventArgs;
	typedef ABI::Windows::UI::Notifications::IToastNotificationManagerStatics IToastNotificationManagerStatics;
	typedef ABI::Windows::UI::Notifications::ToastTemplateType ToastTemplateType;
	typedef ABI::Windows::Data::Xml::Dom::IXmlNode IXmlNode;
	typedef ABI::Windows::Data::Xml::Dom::IXmlDocument IXmlDocument;

	typedef __FITypedEventHandler_2_Windows__CUI__CNotifications__CToastNotification_IInspectable_t ToastActivationHandler;
	typedef __FITypedEventHandler_2_Windows__CUI__CNotifications__CToastNotification_Windows__CUI__CNotifications__CToastDismissedEventArgs ToastDismissHandler;

public:
	ToastNotificationHandler() : mTitle(nullptr), mMessage(nullptr), mName(nullptr), mActivateCallback(nullptr), mDismissCallback(nullptr)
	{
	}

	~ToastNotificationHandler();

	bool Init(const wchar_t* aTitle, const wchar_t* aMessage, const wchar_t* aName);
	bool DisplayNotification(EventCallback aActivate, EventCallback aDismiss);
	bool CloseNotification();

	const wchar_t* GetName() const { return mName; }

private:
	ComPtr<IXmlDocument> ToastNotificationHandler::InitializeXmlForTemplate(ToastTemplateType templateType);
	bool CreateWindowsNotificationFromXml(IXmlDocument* aXml);

	HRESULT OnActivate(IToastNotification* aNotification, IInspectable* aInspectable);
	HRESULT OnDismiss(IToastNotification* aNotification, IToastDismissedEventArgs* aInspectable);

	ComPtr<IToastNotificationManagerStatics> mToastNotificationManagerStatics;
	ComPtr<IToastNotification> mNotification;
	ComPtr<IToastNotifier> mNotifier;
	HSTRING mTitle;
	HSTRING mMessage;
	wchar_t* mName;
	DWORD mThreadId;

	EventCallback mActivateCallback;
	EventCallback mDismissCallback;
};

ToastNotificationHandler::~ToastNotificationHandler()
{
	if (mTitle) {
		WindowsDeleteString(mTitle);
	}
	if (mMessage) {
		WindowsDeleteString(mMessage);
	}
	if (mName) {
		free(mName);
	}
}

bool
ToastNotificationHandler::Init(const wchar_t* aTitle, const wchar_t* aMessage, const wchar_t* aName)
{
	HRESULT hr;
	hr = WindowsCreateString(aTitle, static_cast<UINT32>(wcslen(aTitle)), &mTitle);
	if (FAILED(hr)) {
		return false;
	}
	hr = WindowsCreateString(aMessage, static_cast<UINT32>(wcslen(aMessage)), &mMessage);
	if (FAILED(hr)) {
		return false;
	}
	if (aName) {
		mName = _wcsdup(aName);
		if (!mName) {
			return false;
		}
	}

	mThreadId = GetCurrentThreadId();

	return true;
}

static bool
SetNodeValueString(HSTRING inputString, ComPtr<IXmlNode> node, ComPtr<IXmlDocument> xml)
{
	ComPtr<IXmlText> inputText;
	HRESULT hr;
	hr = xml->CreateTextNode(inputString, &inputText);
	if (FAILED(hr)) {
		return false;
	}
	ComPtr<IXmlNode> inputTextNode;
	hr = inputText.As(&inputTextNode);
	if (FAILED(hr)) {
		return false;
	}
	ComPtr<IXmlNode> appendedChild;
	hr = node->AppendChild(inputTextNode.Get(), &appendedChild);
	if (FAILED(hr)) {
		return false;
	}

	return true;
}

ComPtr<IXmlDocument>
ToastNotificationHandler::InitializeXmlForTemplate(ToastTemplateType templateType)
{
	HRESULT hr;
	hr = GetActivationFactory(
		HStringReference(RuntimeClass_Windows_UI_Notifications_ToastNotificationManager).Get(),
		mToastNotificationManagerStatics.GetAddressOf());
	if (FAILED(hr)) {
		return nullptr;
	}

	ComPtr<IXmlDocument> toastXml;
	mToastNotificationManagerStatics->GetTemplateContent(templateType, &toastXml);
	return toastXml;
}

bool
ToastNotificationHandler::CreateWindowsNotificationFromXml(IXmlDocument* aXml)
{
	ComPtr<IToastNotificationFactory> factory;
	HRESULT hr;
	hr = GetActivationFactory(
		HStringReference(RuntimeClass_Windows_UI_Notifications_ToastNotification).Get(),
		factory.GetAddressOf());
	if (FAILED(hr)) {
		return false;
	}

	hr = factory->CreateToastNotification(aXml, &mNotification);
	if (FAILED(hr)) {
		return false;
	}

	if (mActivateCallback) {
		EventRegistrationToken activatedToken;
		hr = mNotification->add_Activated(
			Callback<ToastActivationHandler>(this, &ToastNotificationHandler::OnActivate).Get(),
			&activatedToken);
		if (FAILED(hr)) {
			return false;
		}
	}

	EventRegistrationToken dismissedToken;
	hr = mNotification->add_Dismissed(
		Callback<ToastDismissHandler>(this, &ToastNotificationHandler::OnDismiss).Get(),
		&dismissedToken);
	if (FAILED(hr)) {
		return false;
	}

	hr = mToastNotificationManagerStatics->CreateToastNotifierWithId(
		HStringReference(sAppId).Get(),
		mNotifier.GetAddressOf());
	if (FAILED(hr)) {
		return false;
	}
	hr = mNotifier->Show(mNotification.Get());
	if (FAILED(hr)) {
		return false;
	}

	return true;
}

bool
ToastNotificationHandler::DisplayNotification(EventCallback aActivate, EventCallback aDismiss)
{
	ComPtr<IXmlDocument> toastXml = InitializeXmlForTemplate(ToastTemplateType::ToastTemplateType_ToastText03);
	HRESULT hr;

	ComPtr<IXmlNodeList> toastTextElements;
	hr = toastXml->GetElementsByTagName(HStringReference(L"text").Get(), &toastTextElements);
	if (FAILED(hr)) {
		return false;
	}

	ComPtr<IXmlNode> titleTextNodeRoot;
	hr = toastTextElements->Item(0, &titleTextNodeRoot);
	if (FAILED(hr)) {
		return false;
	}
	ComPtr<IXmlNode> msgTextNodeRoot;
	hr = toastTextElements->Item(1, &msgTextNodeRoot);
	if (FAILED(hr)) {
		return false;
	}

	SetNodeValueString(mTitle, titleTextNodeRoot.Get(), toastXml.Get());
	SetNodeValueString(mMessage, msgTextNodeRoot.Get(), toastXml.Get());

	mActivateCallback = aActivate;
	mDismissCallback = aDismiss;

	return CreateWindowsNotificationFromXml(toastXml.Get());
}

bool
ToastNotificationHandler::CloseNotification()
{
	if (mNotifier && mNotification) {
		mNotifier->Hide(mNotification.Get());
	}
	return true;
}

HRESULT
ToastNotificationHandler::OnActivate(IToastNotification* aNotification, IInspectable* aInspectable)
{
	if (mThreadId != GetCurrentThreadId()) {
		return E_FAIL;
	}
	if (mActivateCallback) {
		mActivateCallback();
	}
	return S_OK;
}

HRESULT
ToastNotificationHandler::OnDismiss(IToastNotification* aNotification, IToastDismissedEventArgs* aArgs)
{
	if (mThreadId != GetCurrentThreadId()) {
		return E_FAIL;
	}
	if (mDismissCallback) {
		mDismissCallback();
	}

	auto iter = sNotifications.begin();
	while (sNotifications.end() != iter) {
		if (*iter == this) {
			sNotifications.erase(iter);
			break;
		}
		iter++;
	}

	delete this;
	return S_OK;
}

extern "C"
bool WINAPI
SetAppId()
{
	// If having -no-remote option, Firefox doesn't start DDE.
	if (_wgetenv(L"MOZ_NO_REMOTE")) {
		return false;
	}

	if (!sAppId) {
		WCHAR wszFilename[MAX_PATH];
		GetModuleFileNameW(NULL, wszFilename, MAX_PATH);
		wchar_t* slash = wcsrchr(wszFilename, '\\');
		if (slash) {
			*slash = '\0';
		}

		HKEY key;
		if (RegOpenKeyExW(HKEY_CURRENT_USER, L"Software\\Mozilla\\Firefox\\TaskBarIDs", 0, KEY_QUERY_VALUE, &key) == ERROR_SUCCESS) {
			WCHAR value[MAX_PATH];
			DWORD type = REG_SZ;
			DWORD len = sizeof(value);
			if (RegQueryValueExW(key, wszFilename, NULL, &type, (LPBYTE) value, &len) == ERROR_SUCCESS) {
				sAppId = _wcsdup(value);
			}
			RegCloseKey(key);
		}
	}

	return !!sAppId;
}

// external API to show toast notification via JS-CTYPES
extern "C"
bool WINAPI
DisplayToastNotification(const wchar_t* aTitle, const wchar_t* aMessage, const wchar_t* aName, void* aCallbackActive, void* aCallbackDismiss)
{
	if (!sAppId) {
		return false;
	}

	ToastNotificationHandler* handler = new ToastNotificationHandler();

	if (!handler->Init(aTitle, aMessage, aName)) {
		delete handler;
		return false;
	}

	if (!handler->DisplayNotification((EventCallback) aCallbackActive, (EventCallback) aCallbackDismiss)) {
		delete handler;
		return false;
	}

	sNotifications.push_back(handler);

	return true;
}

extern "C"
bool WINAPI
CloseToastNotification(const wchar_t* aName)
{
	if (!aName || !*aName) {
		return false;
	}
	auto iter = sNotifications.begin();
	while (sNotifications.end() != iter) {
		ToastNotificationHandler* handler = *iter;
		if (handler) {
			if (!wcscmp(handler->GetName(), aName)) {
				handler->CloseNotification();
				return true;
			}
		}
		iter++;
	}

	return false;
}
<|endoftext|>


<commit_before>//* This file is part of the MOOSE framework
//* https://www.mooseframework.org
//*
//* All rights reserved, see COPYRIGHT for full restrictions
//* https://github.com/idaholab/moose/blob/master/COPYRIGHT
//*
//* Licensed under LGPL 2.1, please see LICENSE for details
//* https://www.gnu.org/licenses/lgpl-2.1.html

// StochasticTools includes
#include "SamplerTransientMultiApp.h"
#include "Sampler.h"
#include "StochasticToolsTransfer.h"

registerMooseObject("StochasticToolsApp", SamplerTransientMultiApp);

InputParameters
SamplerTransientMultiApp::validParams()
{
  InputParameters params = TransientMultiApp::validParams();
  params += SamplerInterface::validParams();
  params.addClassDescription("Creates a sub-application for each row of each Sampler matrix.");
  params.addParam<SamplerName>("sampler", "The Sampler object to utilize for creating MultiApps.");
  params.suppressParameter<std::vector<Point>>("positions");
  params.suppressParameter<bool>("output_in_position");
  params.suppressParameter<std::vector<FileName>>("positions_file");
  params.suppressParameter<Real>("move_time");
  params.suppressParameter<std::vector<Point>>("move_positions");
  params.suppressParameter<std::vector<unsigned int>>("move_apps");
  params.set<bool>("use_positions") = false;

  // use "batch-restore=2" to be consistent with SamplerFullSolveMultiApp and use the
  // allow_out_of_range flag to allow the StochasticToolsTransfer object to inspect the MultiApp
  // object parameters without triggering an assert.
  MooseEnum modes("normal=0 batch-reset=1 batch-restore=2", "normal");
  params.addParam<MooseEnum>(
      "mode",
      modes,
      "The operation mode, 'normal' creates one sub-application for each row in the Sampler and "
      "'batch' creates on sub-application for each processor and re-executes for each row.");

  return params;
}

SamplerTransientMultiApp::SamplerTransientMultiApp(const InputParameters & parameters)
  : TransientMultiApp(parameters),
    SamplerInterface(this),
    _sampler(SamplerInterface::getSampler("sampler")),
    _mode(getParam<MooseEnum>("mode").getEnum<StochasticTools::MultiAppMode>()),
    _number_of_sampler_rows(_sampler.getNumberOfRows()),
    _perf_solve_step(registerTimedSection("solveStep", 1)),
    _perf_solve_batch_step(registerTimedSection("solveStepBatch", 1)),
    _perf_initial_setup(registerTimedSection("initialSetup", 2))
{
  if (_mode == StochasticTools::MultiAppMode::BATCH_RESTORE)
  {
    if (n_processors() > _sampler.getNumberOfRows())
      paramError(
          "mode",
          "There appears to be more available processors (",
          n_processors(),
          ") than samples (",
          _sampler.getNumberOfRows(),
          "), this is not supported in "
          "batch mode. Consider switching to \'normal\' to allow multiple processors per sample.");
    init(n_processors());
  }
  else if (_mode == StochasticTools::MultiAppMode::NORMAL)
    init(_sampler.getNumberOfRows());
  else
    paramError("mode",
               "The supplied mode, '",
               getParam<MooseEnum>("mode"),
               "', currently is not implemented for the SamplerTransientMultiApp, the available "
               "options are 'normal' or 'batch-restore'.");
}

void
SamplerTransientMultiApp::initialSetup()
{
  TIME_SECTION(_perf_initial_setup);

  TransientMultiApp::initialSetup();

  // Perform initial backup for the batch sub-applications
  if (_mode == StochasticTools::MultiAppMode::BATCH_RESTORE)
  {
    dof_id_type n = _sampler.getNumberOfLocalRows();
    _batch_backup.resize(n);
    for (MooseIndex(n) i = 0; i < n; ++i)
      for (MooseIndex(_my_num_apps) j = 0; j < _my_num_apps; j++)
        _batch_backup[i].emplace_back(_apps[j]->backup());
  }
}

bool
SamplerTransientMultiApp::solveStep(Real dt, Real target_time, bool auto_advance)
{
  TIME_SECTION(_perf_solve_step);

  if (_sampler.getNumberOfRows() != _number_of_sampler_rows)
    mooseError("The size of the sampler has changed; SamplerTransientMultiApp object do not "
               "support dynamic Sampler output.");

  bool last_solve_converged = true;
  if (_mode == StochasticTools::MultiAppMode::BATCH_RESTORE)
    last_solve_converged = solveStepBatch(dt, target_time, auto_advance);
  else
    last_solve_converged = TransientMultiApp::solveStep(dt, target_time, auto_advance);
  return last_solve_converged;
}

bool
SamplerTransientMultiApp::solveStepBatch(Real dt, Real target_time, bool auto_advance)
{
  TIME_SECTION(_perf_solve_batch_step);

  // Value to return
  bool last_solve_converged = true;

  // List of active relevant Transfer objects
  std::vector<std::shared_ptr<StochasticToolsTransfer>> to_transfers =
      getActiveStochasticToolsTransfers(MultiAppTransfer::TO_MULTIAPP);
  std::vector<std::shared_ptr<StochasticToolsTransfer>> from_transfers =
      getActiveStochasticToolsTransfers(MultiAppTransfer::FROM_MULTIAPP);

  // Initialize to/from transfers
  for (auto transfer : to_transfers)
    transfer->initializeToMultiapp();
  for (auto transfer : from_transfers)
    transfer->initializeFromMultiapp();

  // Perform batch MultiApp solves
  dof_id_type num_items = _sampler.getNumberOfLocalRows();
  for (MooseIndex(num_items) i = 0; i < num_items; ++i)
  {
    if (_mode == StochasticTools::MultiAppMode::BATCH_RESTORE)
      for (MooseIndex(_my_num_apps) j = 0; j < _my_num_apps; j++)
        _apps[j]->restore(_batch_backup[i][j]);

    for (auto transfer : to_transfers)
      transfer->executeToMultiapp();

    last_solve_converged = TransientMultiApp::solveStep(dt, target_time, auto_advance);

    for (auto transfer : from_transfers)
      transfer->executeFromMultiapp();

    if (_mode == StochasticTools::MultiAppMode::BATCH_RESTORE)
      for (MooseIndex(_my_num_apps) j = 0; j < _my_num_apps; j++)
        _batch_backup[i][j] = _apps[j]->backup();
  }

  // Finalize to/from transfers
  for (auto transfer : to_transfers)
    transfer->finalizeToMultiapp();
  for (auto transfer : from_transfers)
    transfer->finalizeFromMultiapp();

  return last_solve_converged;
}

std::vector<std::shared_ptr<StochasticToolsTransfer>>
SamplerTransientMultiApp::getActiveStochasticToolsTransfers(Transfer::DIRECTION direction)
{
  std::vector<std::shared_ptr<StochasticToolsTransfer>> output;
  const ExecuteMooseObjectWarehouse<Transfer> & warehouse =
      _fe_problem.getMultiAppTransferWarehouse(direction);
  for (std::shared_ptr<Transfer> transfer : warehouse.getActiveObjects())
  {
    std::shared_ptr<StochasticToolsTransfer> ptr =
        std::dynamic_pointer_cast<StochasticToolsTransfer>(transfer);
    if (ptr && ptr->getMultiApp()->name() == this->name())
      output.push_back(ptr);
  }
  return output;
}
<commit_msg>Update modules/stochastic_tools/src/multiapps/SamplerTransientMultiApp.C<commit_after>//* This file is part of the MOOSE framework
//* https://www.mooseframework.org
//*
//* All rights reserved, see COPYRIGHT for full restrictions
//* https://github.com/idaholab/moose/blob/master/COPYRIGHT
//*
//* Licensed under LGPL 2.1, please see LICENSE for details
//* https://www.gnu.org/licenses/lgpl-2.1.html

// StochasticTools includes
#include "SamplerTransientMultiApp.h"
#include "Sampler.h"
#include "StochasticToolsTransfer.h"

registerMooseObject("StochasticToolsApp", SamplerTransientMultiApp);

InputParameters
SamplerTransientMultiApp::validParams()
{
  InputParameters params = TransientMultiApp::validParams();
  params += SamplerInterface::validParams();
  params.addClassDescription("Creates a sub-application for each row of each Sampler matrix.");
  params.addParam<SamplerName>("sampler", "The Sampler object to utilize for creating MultiApps.");
  params.suppressParameter<std::vector<Point>>("positions");
  params.suppressParameter<bool>("output_in_position");
  params.suppressParameter<std::vector<FileName>>("positions_file");
  params.suppressParameter<Real>("move_time");
  params.suppressParameter<std::vector<Point>>("move_positions");
  params.suppressParameter<std::vector<unsigned int>>("move_apps");
  params.set<bool>("use_positions") = false;

  // use "batch-restore=2" to be consistent with SamplerFullSolveMultiApp and use the
  // allow_out_of_range flag to allow the StochasticToolsTransfer object to inspect the MultiApp
  // object parameters without triggering an assert.
  MooseEnum modes("normal=0 batch-reset=1 batch-restore=2", "normal");
  params.addParam<MooseEnum>(
      "mode",
      modes,
      "The operation mode, 'normal' creates one sub-application for each row in the Sampler and "
      "'batch' creates on sub-application for each processor and re-executes for each row.");

  return params;
}

SamplerTransientMultiApp::SamplerTransientMultiApp(const InputParameters & parameters)
  : TransientMultiApp(parameters),
    SamplerInterface(this),
    _sampler(SamplerInterface::getSampler("sampler")),
    _mode(getParam<MooseEnum>("mode").getEnum<StochasticTools::MultiAppMode>()),
    _number_of_sampler_rows(_sampler.getNumberOfRows()),
    _perf_solve_step(registerTimedSection("solveStep", 1)),
    _perf_solve_batch_step(registerTimedSection("solveStepBatch", 1)),
    _perf_initial_setup(registerTimedSection("initialSetup", 2))
{
  if (_mode == StochasticTools::MultiAppMode::BATCH_RESTORE)
  {
    if (n_processors() > _sampler.getNumberOfRows())
      paramError(
          "mode",
          "There appears to be more available processors (",
          n_processors(),
          ") than samples (",
          _sampler.getNumberOfRows(),
          "), this is not supported in "
          "batch mode. Consider switching to \'normal\' to allow multiple processors per sample.");
    init(n_processors());
  }
  else if (_mode == StochasticTools::MultiAppMode::NORMAL)
    init(_sampler.getNumberOfRows());
  else
    paramError("mode",
               "The supplied mode, '",
               getParam<MooseEnum>("mode"),
               "', currently is not implemented for the SamplerTransientMultiApp, the available "
               "options are 'normal' or 'batch-restore'.");
}

void
SamplerTransientMultiApp::initialSetup()
{
  TIME_SECTION(_perf_initial_setup);

  TransientMultiApp::initialSetup();

  // Perform initial backup for the batch sub-applications
  if (_mode == StochasticTools::MultiAppMode::BATCH_RESTORE)
  {
    dof_id_type n = _sampler.getNumberOfLocalRows();
    _batch_backup.resize(n);
    for (MooseIndex(n) i = 0; i < n; ++i)
      for (MooseIndex(_my_num_apps) j = 0; j < _my_num_apps; j++)
        _batch_backup[i].emplace_back(_apps[j]->backup());
  }
}

bool
SamplerTransientMultiApp::solveStep(Real dt, Real target_time, bool auto_advance)
{
  TIME_SECTION(_perf_solve_step);

  if (_sampler.getNumberOfRows() != _number_of_sampler_rows)
    mooseError("The size of the sampler has changed; SamplerTransientMultiApp object do not "
               "support dynamic Sampler output.");

  bool last_solve_converged = true;
  if (_mode == StochasticTools::MultiAppMode::BATCH_RESTORE)
    last_solve_converged = solveStepBatch(dt, target_time, auto_advance);
  else
    last_solve_converged = TransientMultiApp::solveStep(dt, target_time, auto_advance);
  return last_solve_converged;
}

bool
SamplerTransientMultiApp::solveStepBatch(Real dt, Real target_time, bool auto_advance)
{
  TIME_SECTION(_perf_solve_batch_step);

  // Value to return
  bool last_solve_converged = true;

  // List of active relevant Transfer objects
  std::vector<std::shared_ptr<StochasticToolsTransfer>> to_transfers =
      getActiveStochasticToolsTransfers(MultiAppTransfer::TO_MULTIAPP);
  std::vector<std::shared_ptr<StochasticToolsTransfer>> from_transfers =
      getActiveStochasticToolsTransfers(MultiAppTransfer::FROM_MULTIAPP);

  // Initialize to/from transfers
  for (auto transfer : to_transfers)
    transfer->initializeToMultiapp();
  for (auto transfer : from_transfers)
    transfer->initializeFromMultiapp();

  // Perform batch MultiApp solves
  dof_id_type num_items = _sampler.getNumberOfLocalRows();
  for (MooseIndex(num_items) i = 0; i < num_items; ++i)
  {
    if (_mode == StochasticTools::MultiAppMode::BATCH_RESTORE)
      for (MooseIndex(_my_num_apps) j = 0; j < _my_num_apps; j++)
        _apps[j]->restore(_batch_backup[i][j]);

    for (auto transfer : to_transfers)
      transfer->executeToMultiapp();

    last_solve_converged = TransientMultiApp::solveStep(dt, target_time, auto_advance);

    for (auto transfer : from_transfers)
      transfer->executeFromMultiapp();

    if (_mode == StochasticTools::MultiAppMode::BATCH_RESTORE)
      for (MooseIndex(_my_num_apps) j = 0; j < _my_num_apps; j++)
        _batch_backup[i][j] = _apps[j]->backup();
  }

  // Finalize to/from transfers
  for (auto transfer : to_transfers)
    transfer->finalizeToMultiapp();
  for (auto transfer : from_transfers)
    transfer->finalizeFromMultiapp();

  return last_solve_converged;
}

std::vector<std::shared_ptr<StochasticToolsTransfer>>
SamplerTransientMultiApp::getActiveStochasticToolsTransfers(Transfer::DIRECTION direction)
{
  std::vector<std::shared_ptr<StochasticToolsTransfer>> output;
  const ExecuteMooseObjectWarehouse<Transfer> & warehouse =
      _fe_problem.getMultiAppTransferWarehouse(direction);
  for (std::shared_ptr<Transfer> transfer : warehouse.getActiveObjects())
  {
    std::shared_ptr<StochasticToolsTransfer> ptr =
        std::dynamic_pointer_cast<StochasticToolsTransfer>(transfer);
    if (ptr && ptr->getMultiApp().get() == this)
      output.push_back(ptr);
  }
  return output;
}
<|endoftext|>


<commit_before>/*
    Copyright (c) 2010 Michael Jansen <kde@michael-jansen>

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

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

    You should have received a copy of the GNU Library General Public License
    along with this library; see the file COPYING.LIB.  If not, write to the
    Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
    02110-1301, USA.
*/

#include "notificationsource.h"
#include <akdebug.h>

#include "notificationsourceadaptor.h"
#include "notificationmanager.h"
#include "collectionreferencemanager.h"
#include <libs/notificationmessagev2_p_p.h>

using namespace Akonadi;
using namespace Akonadi::Server;

template<typename T>
QVector<T> setToVector( const QSet<T> &set )
{
  QVector<T> v( set.size() );
  std::copy( set.constBegin(), set.constEnd(), v.begin() );
  return v;
}

NotificationSource::NotificationSource( const QString &identifier, const QString &clientServiceName, NotificationManager *parent )
  : QObject( parent )
  , mManager( parent )
  , mIdentifier( identifier )
  , mDBusIdentifier( identifier )
  , mClientWatcher( 0 )
  , mServerSideMonitorEnabled( false )
  , mAllMonitored( false )
  , mExclusive( false )
{
  new NotificationSourceAdaptor( this );

  // Clean up for dbus usage: any non-alphanumeric char should be turned into '_'
  const int len = mDBusIdentifier.length();
  for ( int i = 0; i < len; ++i ) {
    if ( !mDBusIdentifier[i].isLetterOrNumber() ) {
      mDBusIdentifier[i] = QLatin1Char( '_' );
    }
  }

  QDBusConnection::sessionBus().registerObject(
      dbusPath().path(),
      this,
      QDBusConnection::ExportAdaptors );

  mClientWatcher = new QDBusServiceWatcher( clientServiceName, QDBusConnection::sessionBus(), QDBusServiceWatcher::WatchForUnregistration, this );
  connect( mClientWatcher, SIGNAL(serviceUnregistered(QString)), SLOT(serviceUnregistered(QString)) );
}

NotificationSource::~NotificationSource()
{
}

QDBusObjectPath NotificationSource::dbusPath() const
{
  return QDBusObjectPath( QLatin1String( "/subscriber/" ) + mDBusIdentifier );
}

void NotificationSource::emitNotification( const NotificationMessage::List &notifications )
{
  Q_EMIT notify( notifications );
}

void NotificationSource::emitNotification( const NotificationMessageV2::List &notifications )
{
  Q_EMIT notifyV2( notifications );
}

void NotificationSource::emitNotification( const NotificationMessageV3::List &notifications )
{
  Q_EMIT notifyV3( notifications );
}

QString NotificationSource::identifier() const
{
  return mIdentifier;
}

void NotificationSource::unsubscribe()
{
  mManager->unsubscribe( mIdentifier );
}

bool NotificationSource::isServerSideMonitorEnabled() const
{
  return mServerSideMonitorEnabled;
}

void NotificationSource::setServerSideMonitorEnabled( bool enabled )
{
  mServerSideMonitorEnabled = enabled;
}

bool NotificationSource::isExclusive() const
{
  return mExclusive;
}

void NotificationSource::setExclusive( bool enabled )
{
  mExclusive = enabled;
}

void NotificationSource::addClientServiceName( const QString &clientServiceName )
{
  if ( mClientWatcher->watchedServices().contains( clientServiceName ) ) {
    return;
  }

  mClientWatcher->addWatchedService( clientServiceName );
  akDebug() << Q_FUNC_INFO << "Notification source" << mIdentifier << "now serving:" << mClientWatcher->watchedServices();
}

void NotificationSource::serviceUnregistered( const QString &serviceName )
{
  mClientWatcher->removeWatchedService( serviceName );
  akDebug() << Q_FUNC_INFO << "Notification source" << mIdentifier << "now serving:" << mClientWatcher->watchedServices();

  if ( mClientWatcher->watchedServices().isEmpty() ) {
    unsubscribe();
  }
}

void NotificationSource::setMonitoredCollection( Entity::Id id, bool monitored )
{
  if ( id < 0 || !isServerSideMonitorEnabled() ) {
    return;
  }

  if ( monitored && !mMonitoredCollections.contains( id ) ) {
    mMonitoredCollections.insert( id );
    Q_EMIT monitoredCollectionsChanged();
  } else if ( !monitored ) {
    mMonitoredCollections.remove( id );
    Q_EMIT monitoredCollectionsChanged();
  }
}

QVector<Entity::Id> NotificationSource::monitoredCollections() const
{
  return setToVector<Entity::Id>( mMonitoredCollections );
}

void NotificationSource::setMonitoredItem( Entity::Id id, bool monitored )
{
  if ( id < 0 || !isServerSideMonitorEnabled() ) {
    return;
  }

  if ( monitored && !mMonitoredItems.contains( id ) ) {
    mMonitoredItems.insert( id );
    Q_EMIT monitoredItemsChanged();
  } else if ( !monitored ) {
    mMonitoredItems.remove( id );
    Q_EMIT monitoredItemsChanged();
  }
}

QVector<Entity::Id> NotificationSource::monitoredItems() const
{
  return setToVector<Entity::Id>( mMonitoredItems );
}

void NotificationSource::setMonitoredTag( Entity::Id id, bool monitored )
{
  if ( id < 0 || !isServerSideMonitorEnabled() ) {
    return;
  }

  if ( monitored && !mMonitoredTags.contains( id ) ) {
    mMonitoredTags.insert( id );
    Q_EMIT monitoredTagsChanged();
  } else if ( !monitored ) {
    mMonitoredTags.remove( id );
    Q_EMIT monitoredTagsChanged();
  }
}

QVector<Entity::Id> NotificationSource::monitoredTags() const
{
  return setToVector<Entity::Id>( mMonitoredTags );
}

void NotificationSource::setMonitoredResource( const QByteArray &resource, bool monitored )
{
  if ( !isServerSideMonitorEnabled() ) {
    return;
  }

  if ( monitored && !mMonitoredResources.contains( resource ) ) {
    mMonitoredResources.insert( resource );
    Q_EMIT monitoredResourcesChanged();
  } else if ( !monitored ) {
    mMonitoredResources.remove( resource );
    Q_EMIT monitoredResourcesChanged();
  }
}

QVector<QByteArray> NotificationSource::monitoredResources() const
{
  return setToVector<QByteArray>( mMonitoredResources );
}

void NotificationSource::setMonitoredMimeType( const QString &mimeType, bool monitored )
{
  if ( mimeType.isEmpty() || !isServerSideMonitorEnabled() ) {
    return;
  }

  if ( monitored && !mMonitoredMimeTypes.contains( mimeType ) ) {
    mMonitoredMimeTypes.insert( mimeType );
    Q_EMIT monitoredMimeTypesChanged();
  } else if ( !monitored ) {
    mMonitoredMimeTypes.remove( mimeType );
    Q_EMIT monitoredMimeTypesChanged();
  }
}

QStringList NotificationSource::monitoredMimeTypes() const
{
  return mMonitoredMimeTypes.toList();
}

void NotificationSource::setAllMonitored( bool allMonitored )
{
  if ( !isServerSideMonitorEnabled() ) {
    return;
  }

  if ( allMonitored && !mAllMonitored ) {
    mAllMonitored = true;
    Q_EMIT isAllMonitoredChanged();
  } else if ( !allMonitored ) {
    mAllMonitored = false;
    Q_EMIT isAllMonitoredChanged();
  }
}

bool NotificationSource::isAllMonitored() const
{
  return mAllMonitored;
}

void NotificationSource::setIgnoredSession( const QByteArray &sessionId, bool ignored )
{
  if ( !isServerSideMonitorEnabled() ) {
    return;
  }

  if ( ignored && !mIgnoredSessions.contains( sessionId ) ) {
    mIgnoredSessions.insert( sessionId );
    Q_EMIT ignoredSessionsChanged();
  } else if ( !ignored ) {
    mIgnoredSessions.remove( sessionId );
    Q_EMIT ignoredSessionsChanged();
  }
}

QVector<QByteArray> NotificationSource::ignoredSessions() const
{
  return setToVector<QByteArray>( mIgnoredSessions );
}

bool NotificationSource::isCollectionMonitored( Entity::Id id ) const
{
  if ( id < 0 ) {
    return false;
  } else if ( mMonitoredCollections.contains( id ) ) {
    return true;
  } else if ( mMonitoredCollections.contains( 0 ) ) {
    return true;
  }
  return false;
}

bool NotificationSource::isMimeTypeMonitored( const QString &mimeType ) const
{
  return mMonitoredMimeTypes.contains( mimeType );

  // FIXME: Handle mimetype aliases
}

bool NotificationSource::isMoveDestinationResourceMonitored( const NotificationMessageV3 &msg ) const
{
  if ( msg.operation() != NotificationMessageV2::Move ) {
    return false;
  }
  return mMonitoredResources.contains( msg.destinationResource() );
}

void NotificationSource::setMonitoredType( NotificationMessageV2::Type type, bool monitored )
{
  if ( !isServerSideMonitorEnabled() ) {
    return;
  }

  if ( monitored && !mMonitoredTypes.contains( type ) ) {
    mMonitoredTypes.insert( type );
    Q_EMIT monitoredTypesChanged();
  } else if ( !monitored ) {
    mMonitoredTypes.remove( type );
    Q_EMIT monitoredTypesChanged();
  }
}

QVector<NotificationMessageV2::Type> NotificationSource::monitoredTypes() const
{
  return setToVector<NotificationMessageV2::Type>( mMonitoredTypes );
}

bool NotificationSource::acceptsNotification( const NotificationMessageV3 &notification )
{
  // session is ignored
  if ( mIgnoredSessions.contains( notification.sessionId() ) ) {
    return false;
  }

  if (notification.entities().count() == 0 && notification.type() != NotificationMessageV2::Relations) {
    return false;
  }

  //Only emit notifications for referenced collections if the subscriber is exclusive or monitors the collection
  if ( notification.type() == NotificationMessageV2::Collections ) {
    // HACK: We need to dispatch notifications about disabled collections to SOME
    // agents (that's what we have the exclusive subscription for) - but because
    // querying each Collection from database would be expensive, we use the
    // metadata hack to transfer this information from NotificationCollector
    if ( notification.d->metadata.contains("DISABLED") ) {
        // Exclusive subscriber always gets it
        if ( mExclusive ) {
            return true;
        }

        // Now let's see if the collection is referenced - then we still might need
        // to accept it
        Q_FOREACH ( const NotificationMessageV2::Entity &entity, notification.entities() ) {
          if ( CollectionReferenceManager::instance()->isReferenced( entity.id ) ) {
            return ( mExclusive || isCollectionMonitored( entity.id ) );
          }
        }

        // If the collection is not referenced, monitored or the subscriber is not
        // exclusive (i.e. if we got here), then the subscriber does not care about
        // this one, so drop it
        return false;
    }
  } else if ( notification.type() == NotificationMessageV2::Items ) {
      if ( CollectionReferenceManager::instance()->isReferenced( notification.parentCollection() ) ) {
        return ( mExclusive || isCollectionMonitored( notification.parentCollection() ) || isMoveDestinationResourceMonitored( notification ) );
      }
  }

  // user requested everything
  if ( mAllMonitored && notification.type() != NotificationMessageV2::InvalidType ) {
    return true;
  }

  switch ( notification.type() ) {
  case NotificationMessageV2::InvalidType:
    akDebug() << "Received invalid change notification!";
    return false;

  case NotificationMessageV2::Items:
    if ( !mMonitoredTypes.isEmpty() && !mMonitoredTypes.contains( NotificationMessageV2::Items ) ) {
      return false;
    }
    // we have a resource or mimetype filter
    if ( !mMonitoredResources.isEmpty() || !mMonitoredMimeTypes.isEmpty() ) {
      if ( mMonitoredResources.contains( notification.resource() ) ) {
        return true;
      }

      if ( isMoveDestinationResourceMonitored( notification ) ) {
        return true;
      }

      Q_FOREACH ( const NotificationMessageV2::Entity &entity, notification.entities() ) {
        if ( isMimeTypeMonitored( entity.mimeType ) ) {
          return true;
        }
      }

      return false;
    }

    // we explicitly monitor that item or the collections it's in
    Q_FOREACH ( const NotificationMessageV2::Entity &entity, notification.entities() ) {
      if ( mMonitoredItems.contains( entity.id ) ) {
        return true;
      }
    }

    return isCollectionMonitored( notification.parentCollection() )
        || isCollectionMonitored( notification.parentDestCollection() );

  case NotificationMessageV2::Collections:
    if ( !mMonitoredTypes.isEmpty() && !mMonitoredTypes.contains( NotificationMessageV2::Collections ) ) {
      return false;
    }

    // we have a resource filter
    if ( !mMonitoredResources.isEmpty() ) {
      const bool resourceMatches = mMonitoredResources.contains( notification.resource() )
                                  || isMoveDestinationResourceMonitored( notification );

      // a bit hacky, but match the behaviour from the item case,
      // if resource is the only thing we are filtering on, stop here, and if the resource filter matched, of course
      if ( mMonitoredMimeTypes.isEmpty() || resourceMatches ) {
        return resourceMatches;
      }
      // else continue
    }

    // we explicitly monitor that colleciton, or all of them
    Q_FOREACH ( const NotificationMessageV2::Entity &entity, notification.entities() ) {
      if ( isCollectionMonitored( entity.id ) ) {
        return true;
      }
    }

    return isCollectionMonitored( notification.parentCollection() )
        || isCollectionMonitored( notification.parentDestCollection() );

  case NotificationMessageV2::Tags:
    if ( !mMonitoredTypes.isEmpty() && !mMonitoredTypes.contains( NotificationMessageV2::Tags ) ) {
      return false;
    }

    if ( mMonitoredTags.isEmpty() ) {
      return true;
    }

    Q_FOREACH ( const NotificationMessageV2::Entity &entity, notification.entities() ) {
      if ( mMonitoredTags.contains( entity.id ) ) {
        return true;
      }
    }

    return false;

    case NotificationMessageV2::Relations:
        if (!mMonitoredTypes.isEmpty() && !mMonitoredTypes.contains(NotificationMessageV2::Relations)) {
            return false;
        }
        return true;

  }

  return false;
}
<commit_msg>NotificationSource: Don't drop unsubscribe or enabled notifications<commit_after>/*
    Copyright (c) 2010 Michael Jansen <kde@michael-jansen>

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

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

    You should have received a copy of the GNU Library General Public License
    along with this library; see the file COPYING.LIB.  If not, write to the
    Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
    02110-1301, USA.
*/

#include "notificationsource.h"
#include <akdebug.h>

#include "notificationsourceadaptor.h"
#include "notificationmanager.h"
#include "collectionreferencemanager.h"
#include <libs/notificationmessagev2_p_p.h>

using namespace Akonadi;
using namespace Akonadi::Server;

template<typename T>
QVector<T> setToVector( const QSet<T> &set )
{
  QVector<T> v( set.size() );
  std::copy( set.constBegin(), set.constEnd(), v.begin() );
  return v;
}

NotificationSource::NotificationSource( const QString &identifier, const QString &clientServiceName, NotificationManager *parent )
  : QObject( parent )
  , mManager( parent )
  , mIdentifier( identifier )
  , mDBusIdentifier( identifier )
  , mClientWatcher( 0 )
  , mServerSideMonitorEnabled( false )
  , mAllMonitored( false )
  , mExclusive( false )
{
  new NotificationSourceAdaptor( this );

  // Clean up for dbus usage: any non-alphanumeric char should be turned into '_'
  const int len = mDBusIdentifier.length();
  for ( int i = 0; i < len; ++i ) {
    if ( !mDBusIdentifier[i].isLetterOrNumber() ) {
      mDBusIdentifier[i] = QLatin1Char( '_' );
    }
  }

  QDBusConnection::sessionBus().registerObject(
      dbusPath().path(),
      this,
      QDBusConnection::ExportAdaptors );

  mClientWatcher = new QDBusServiceWatcher( clientServiceName, QDBusConnection::sessionBus(), QDBusServiceWatcher::WatchForUnregistration, this );
  connect( mClientWatcher, SIGNAL(serviceUnregistered(QString)), SLOT(serviceUnregistered(QString)) );
}

NotificationSource::~NotificationSource()
{
}

QDBusObjectPath NotificationSource::dbusPath() const
{
  return QDBusObjectPath( QLatin1String( "/subscriber/" ) + mDBusIdentifier );
}

void NotificationSource::emitNotification( const NotificationMessage::List &notifications )
{
  Q_EMIT notify( notifications );
}

void NotificationSource::emitNotification( const NotificationMessageV2::List &notifications )
{
  Q_EMIT notifyV2( notifications );
}

void NotificationSource::emitNotification( const NotificationMessageV3::List &notifications )
{
  Q_EMIT notifyV3( notifications );
}

QString NotificationSource::identifier() const
{
  return mIdentifier;
}

void NotificationSource::unsubscribe()
{
  mManager->unsubscribe( mIdentifier );
}

bool NotificationSource::isServerSideMonitorEnabled() const
{
  return mServerSideMonitorEnabled;
}

void NotificationSource::setServerSideMonitorEnabled( bool enabled )
{
  mServerSideMonitorEnabled = enabled;
}

bool NotificationSource::isExclusive() const
{
  return mExclusive;
}

void NotificationSource::setExclusive( bool enabled )
{
  mExclusive = enabled;
}

void NotificationSource::addClientServiceName( const QString &clientServiceName )
{
  if ( mClientWatcher->watchedServices().contains( clientServiceName ) ) {
    return;
  }

  mClientWatcher->addWatchedService( clientServiceName );
  akDebug() << Q_FUNC_INFO << "Notification source" << mIdentifier << "now serving:" << mClientWatcher->watchedServices();
}

void NotificationSource::serviceUnregistered( const QString &serviceName )
{
  mClientWatcher->removeWatchedService( serviceName );
  akDebug() << Q_FUNC_INFO << "Notification source" << mIdentifier << "now serving:" << mClientWatcher->watchedServices();

  if ( mClientWatcher->watchedServices().isEmpty() ) {
    unsubscribe();
  }
}

void NotificationSource::setMonitoredCollection( Entity::Id id, bool monitored )
{
  if ( id < 0 || !isServerSideMonitorEnabled() ) {
    return;
  }

  if ( monitored && !mMonitoredCollections.contains( id ) ) {
    mMonitoredCollections.insert( id );
    Q_EMIT monitoredCollectionsChanged();
  } else if ( !monitored ) {
    mMonitoredCollections.remove( id );
    Q_EMIT monitoredCollectionsChanged();
  }
}

QVector<Entity::Id> NotificationSource::monitoredCollections() const
{
  return setToVector<Entity::Id>( mMonitoredCollections );
}

void NotificationSource::setMonitoredItem( Entity::Id id, bool monitored )
{
  if ( id < 0 || !isServerSideMonitorEnabled() ) {
    return;
  }

  if ( monitored && !mMonitoredItems.contains( id ) ) {
    mMonitoredItems.insert( id );
    Q_EMIT monitoredItemsChanged();
  } else if ( !monitored ) {
    mMonitoredItems.remove( id );
    Q_EMIT monitoredItemsChanged();
  }
}

QVector<Entity::Id> NotificationSource::monitoredItems() const
{
  return setToVector<Entity::Id>( mMonitoredItems );
}

void NotificationSource::setMonitoredTag( Entity::Id id, bool monitored )
{
  if ( id < 0 || !isServerSideMonitorEnabled() ) {
    return;
  }

  if ( monitored && !mMonitoredTags.contains( id ) ) {
    mMonitoredTags.insert( id );
    Q_EMIT monitoredTagsChanged();
  } else if ( !monitored ) {
    mMonitoredTags.remove( id );
    Q_EMIT monitoredTagsChanged();
  }
}

QVector<Entity::Id> NotificationSource::monitoredTags() const
{
  return setToVector<Entity::Id>( mMonitoredTags );
}

void NotificationSource::setMonitoredResource( const QByteArray &resource, bool monitored )
{
  if ( !isServerSideMonitorEnabled() ) {
    return;
  }

  if ( monitored && !mMonitoredResources.contains( resource ) ) {
    mMonitoredResources.insert( resource );
    Q_EMIT monitoredResourcesChanged();
  } else if ( !monitored ) {
    mMonitoredResources.remove( resource );
    Q_EMIT monitoredResourcesChanged();
  }
}

QVector<QByteArray> NotificationSource::monitoredResources() const
{
  return setToVector<QByteArray>( mMonitoredResources );
}

void NotificationSource::setMonitoredMimeType( const QString &mimeType, bool monitored )
{
  if ( mimeType.isEmpty() || !isServerSideMonitorEnabled() ) {
    return;
  }

  if ( monitored && !mMonitoredMimeTypes.contains( mimeType ) ) {
    mMonitoredMimeTypes.insert( mimeType );
    Q_EMIT monitoredMimeTypesChanged();
  } else if ( !monitored ) {
    mMonitoredMimeTypes.remove( mimeType );
    Q_EMIT monitoredMimeTypesChanged();
  }
}

QStringList NotificationSource::monitoredMimeTypes() const
{
  return mMonitoredMimeTypes.toList();
}

void NotificationSource::setAllMonitored( bool allMonitored )
{
  if ( !isServerSideMonitorEnabled() ) {
    return;
  }

  if ( allMonitored && !mAllMonitored ) {
    mAllMonitored = true;
    Q_EMIT isAllMonitoredChanged();
  } else if ( !allMonitored ) {
    mAllMonitored = false;
    Q_EMIT isAllMonitoredChanged();
  }
}

bool NotificationSource::isAllMonitored() const
{
  return mAllMonitored;
}

void NotificationSource::setIgnoredSession( const QByteArray &sessionId, bool ignored )
{
  if ( !isServerSideMonitorEnabled() ) {
    return;
  }

  if ( ignored && !mIgnoredSessions.contains( sessionId ) ) {
    mIgnoredSessions.insert( sessionId );
    Q_EMIT ignoredSessionsChanged();
  } else if ( !ignored ) {
    mIgnoredSessions.remove( sessionId );
    Q_EMIT ignoredSessionsChanged();
  }
}

QVector<QByteArray> NotificationSource::ignoredSessions() const
{
  return setToVector<QByteArray>( mIgnoredSessions );
}

bool NotificationSource::isCollectionMonitored( Entity::Id id ) const
{
  if ( id < 0 ) {
    return false;
  } else if ( mMonitoredCollections.contains( id ) ) {
    return true;
  } else if ( mMonitoredCollections.contains( 0 ) ) {
    return true;
  }
  return false;
}

bool NotificationSource::isMimeTypeMonitored( const QString &mimeType ) const
{
  return mMonitoredMimeTypes.contains( mimeType );

  // FIXME: Handle mimetype aliases
}

bool NotificationSource::isMoveDestinationResourceMonitored( const NotificationMessageV3 &msg ) const
{
  if ( msg.operation() != NotificationMessageV2::Move ) {
    return false;
  }
  return mMonitoredResources.contains( msg.destinationResource() );
}

void NotificationSource::setMonitoredType( NotificationMessageV2::Type type, bool monitored )
{
  if ( !isServerSideMonitorEnabled() ) {
    return;
  }

  if ( monitored && !mMonitoredTypes.contains( type ) ) {
    mMonitoredTypes.insert( type );
    Q_EMIT monitoredTypesChanged();
  } else if ( !monitored ) {
    mMonitoredTypes.remove( type );
    Q_EMIT monitoredTypesChanged();
  }
}

QVector<NotificationMessageV2::Type> NotificationSource::monitoredTypes() const
{
  return setToVector<NotificationMessageV2::Type>( mMonitoredTypes );
}

bool NotificationSource::acceptsNotification( const NotificationMessageV3 &notification )
{
  // session is ignored
  if ( mIgnoredSessions.contains( notification.sessionId() ) ) {
    return false;
  }

  if (notification.entities().count() == 0 && notification.type() != NotificationMessageV2::Relations) {
    return false;
  }

  //Only emit notifications for referenced collections if the subscriber is exclusive or monitors the collection
  if ( notification.type() == NotificationMessageV2::Collections ) {
    // HACK: We need to dispatch notifications about disabled collections to SOME
    // agents (that's what we have the exclusive subscription for) - but because
    // querying each Collection from database would be expensive, we use the
    // metadata hack to transfer this information from NotificationCollector
    if ( notification.d->metadata.contains("DISABLED") && (notification.operation() != NotificationMessageV2::Unsubscribe) && !notification.itemParts().contains("ENABLED") ) {
        // Exclusive subscriber always gets it
        if ( mExclusive ) {
            return true;
        }

        // Now let's see if the collection is referenced - then we still might need
        // to accept it
        Q_FOREACH ( const NotificationMessageV2::Entity &entity, notification.entities() ) {
          if ( CollectionReferenceManager::instance()->isReferenced( entity.id ) ) {
            return ( mExclusive || isCollectionMonitored( entity.id ) );
          }
        }

        // If the collection is not referenced, monitored or the subscriber is not
        // exclusive (i.e. if we got here), then the subscriber does not care about
        // this one, so drop it
        return false;
    }
  } else if ( notification.type() == NotificationMessageV2::Items ) {
      if ( CollectionReferenceManager::instance()->isReferenced( notification.parentCollection() ) ) {
        return ( mExclusive || isCollectionMonitored( notification.parentCollection() ) || isMoveDestinationResourceMonitored( notification ) );
      }
  }

  // user requested everything
  if ( mAllMonitored && notification.type() != NotificationMessageV2::InvalidType ) {
    return true;
  }

  switch ( notification.type() ) {
  case NotificationMessageV2::InvalidType:
    akDebug() << "Received invalid change notification!";
    return false;

  case NotificationMessageV2::Items:
    if ( !mMonitoredTypes.isEmpty() && !mMonitoredTypes.contains( NotificationMessageV2::Items ) ) {
      return false;
    }
    // we have a resource or mimetype filter
    if ( !mMonitoredResources.isEmpty() || !mMonitoredMimeTypes.isEmpty() ) {
      if ( mMonitoredResources.contains( notification.resource() ) ) {
        return true;
      }

      if ( isMoveDestinationResourceMonitored( notification ) ) {
        return true;
      }

      Q_FOREACH ( const NotificationMessageV2::Entity &entity, notification.entities() ) {
        if ( isMimeTypeMonitored( entity.mimeType ) ) {
          return true;
        }
      }

      return false;
    }

    // we explicitly monitor that item or the collections it's in
    Q_FOREACH ( const NotificationMessageV2::Entity &entity, notification.entities() ) {
      if ( mMonitoredItems.contains( entity.id ) ) {
        return true;
      }
    }

    return isCollectionMonitored( notification.parentCollection() )
        || isCollectionMonitored( notification.parentDestCollection() );

  case NotificationMessageV2::Collections:
    if ( !mMonitoredTypes.isEmpty() && !mMonitoredTypes.contains( NotificationMessageV2::Collections ) ) {
      return false;
    }

    // we have a resource filter
    if ( !mMonitoredResources.isEmpty() ) {
      const bool resourceMatches = mMonitoredResources.contains( notification.resource() )
                                  || isMoveDestinationResourceMonitored( notification );

      // a bit hacky, but match the behaviour from the item case,
      // if resource is the only thing we are filtering on, stop here, and if the resource filter matched, of course
      if ( mMonitoredMimeTypes.isEmpty() || resourceMatches ) {
        return resourceMatches;
      }
      // else continue
    }

    // we explicitly monitor that colleciton, or all of them
    Q_FOREACH ( const NotificationMessageV2::Entity &entity, notification.entities() ) {
      if ( isCollectionMonitored( entity.id ) ) {
        return true;
      }
    }

    return isCollectionMonitored( notification.parentCollection() )
        || isCollectionMonitored( notification.parentDestCollection() );

  case NotificationMessageV2::Tags:
    if ( !mMonitoredTypes.isEmpty() && !mMonitoredTypes.contains( NotificationMessageV2::Tags ) ) {
      return false;
    }

    if ( mMonitoredTags.isEmpty() ) {
      return true;
    }

    Q_FOREACH ( const NotificationMessageV2::Entity &entity, notification.entities() ) {
      if ( mMonitoredTags.contains( entity.id ) ) {
        return true;
      }
    }

    return false;

    case NotificationMessageV2::Relations:
        if (!mMonitoredTypes.isEmpty() && !mMonitoredTypes.contains(NotificationMessageV2::Relations)) {
            return false;
        }
        return true;

  }

  return false;
}
<|endoftext|>


<commit_before>/*VRP*********************************************************************
 *
 * vehicle routing problems
 *      A collection of C++ classes for developing VRP solutions
 *      and specific solutions developed using these classes.
 *
 * Copyright 2014 Stephen Woodbridge <woodbri@imaptools.com>
 * Copyright 2014 Vicky Vergara <vicky_vergara@hotmail.com>
 *
 * This is free software; you can redistribute and/or modify it under
 * the terms of the MIT License. Please file LICENSE for details.
 *
 ********************************************************************VRP*/

#include <stdexcept>
#include <algorithm>
#include <iostream>
#include <fstream>
#include <sstream>
#include <string>
#include <math.h>
#include <stdio.h>

#ifdef DOVRPLOG
#include "logger.h"
#endif

#ifdef DOSTATS
#include "timer.h"
#include "stats.h"
#endif

#include "trashconfig.h"
#include "truckManyVisitsDump.h"
#include "tabuopt.h"

void Usage()
{
  std::cout << "Usage: trash file (no extension)\n";
}

/* Logging Severity Levels
    0   INFO
    1   WARNING
    2   ERROR
    3   FATAL  NOTE FATAL is converted to ERROR when NDEBUG is defined

    DLOG(<level>) << "message";
    DLOG_IF(<level>, <cond>) << "message";
    DLOG_EVERY_N(<level>, <n>) << "message";
    CHECK(<cond>) << "message";  // print "message" and FATAL if false

    http://google-glog.googlecode.com/svn/trunk/doc/glog.html

    GLOG_logtostderr=1 ./bin/trash ...  // to get output to terminal
*/

int main(int argc, char **argv)
{

#ifdef DOVRPLOG
  if ( not google::IsGoogleLoggingInitialized() ) {
    FLAGS_log_dir = "./logs/";
    google::InitGoogleLogging( "vrp_trash_collection" );
    FLAGS_logtostderr = 0;
    FLAGS_stderrthreshold = google::FATAL;
    FLAGS_minloglevel = google::INFO;
  }
#endif

  if (argc < 2) {
    Usage();
    return 1;
  }

  std::string infile = argv[1];

  try {
#ifdef DOSTATS
    Timer starttime;
#endif

#ifdef VRPMINTRACE
    //CONFIG->dump("CONFIG");
#endif

#ifdef OSRMCLIENT
    osrmi->useOsrm(true);
    bool testResult = osrmi->testOsrmClient(
          -34.905113, -56.157043,
          -34.906807, -56.158463,
          -34.9076,   -56.157028);
   // remove the following comment when testing OSRM only
   // assert(true==false);
#ifdef VRPMINTRACE
    if (testResult)
     DLOG(INFO) << "osrm test passed";
   else
     DLOG(INFO) << "osrm test FAIL";
#endif  // VRPMINTRACE
#endif  // OSRMCLIENT

    int iteration = 3;
    double best_cost = 9999999;

    TruckManyVisitsDump tp(infile);
    tp.process(0);
    DLOG(INFO) << "Initial solution: 0 is best";

    Solution best_sol(tp);
    best_cost = best_sol.getCostOsrm();

    TabuOpt tsi(tp, iteration);
    Solution opt_sol = tsi.getBestSolution();

    if (best_cost < opt_sol.getCostOsrm()) {
      DLOG(INFO) << "Optimization: 0 is best";
      best_cost = opt_sol.getCost();
      best_sol = opt_sol;
    }

    for (int icase = 1; icase < 2; ++icase) {
      DLOG(INFO) << "initial solution: " << icase;
      tp.process(icase);
      if (best_cost < tp.getCostOsrm()) {
        DLOG(INFO) << "initial solution: " << icase << " is best";
        best_cost = tp.getCost();
        best_sol = tp;
      }

      TabuOpt ts(tp, iteration);

      DLOG(INFO) << "optimization: " << icase;

      if (best_cost < ts.getBestSolution().getCostOsrm()) {
        DLOG(INFO) << "Optimization: " << icase << " is best";
        best_cost = ts.getBestSolution().getCost();
        best_sol = ts.getBestSolution();
      }
assert(true==false);
    }

#ifdef VRPMINTRACE
    best_sol.dumpCostValues();
    best_sol.tau();
#endif

    best_sol.dumpSolutionForPg();
    twc->cleanUp();

  } catch (const std::exception &e) {
    std::cerr << e.what() << std::endl;
    return 1;
  }

  return 0;
}

<commit_msg>fixed condition<commit_after>/*VRP*********************************************************************
 *
 * vehicle routing problems
 *      A collection of C++ classes for developing VRP solutions
 *      and specific solutions developed using these classes.
 *
 * Copyright 2014 Stephen Woodbridge <woodbri@imaptools.com>
 * Copyright 2014 Vicky Vergara <vicky_vergara@hotmail.com>
 *
 * This is free software; you can redistribute and/or modify it under
 * the terms of the MIT License. Please file LICENSE for details.
 *
 ********************************************************************VRP*/

#include <stdexcept>
#include <algorithm>
#include <iostream>
#include <fstream>
#include <sstream>
#include <string>
#include <math.h>
#include <stdio.h>

#ifdef DOVRPLOG
#include "logger.h"
#endif

#ifdef DOSTATS
#include "timer.h"
#include "stats.h"
#endif

#include "trashconfig.h"
#include "truckManyVisitsDump.h"
#include "tabuopt.h"

void Usage()
{
  std::cout << "Usage: trash file (no extension)\n";
}

/* Logging Severity Levels
    0   INFO
    1   WARNING
    2   ERROR
    3   FATAL  NOTE FATAL is converted to ERROR when NDEBUG is defined

    DLOG(<level>) << "message";
    DLOG_IF(<level>, <cond>) << "message";
    DLOG_EVERY_N(<level>, <n>) << "message";
    CHECK(<cond>) << "message";  // print "message" and FATAL if false

    http://google-glog.googlecode.com/svn/trunk/doc/glog.html

    GLOG_logtostderr=1 ./bin/trash ...  // to get output to terminal
*/

int main(int argc, char **argv)
{

#ifdef DOVRPLOG
  if ( not google::IsGoogleLoggingInitialized() ) {
    FLAGS_log_dir = "./logs/";
    google::InitGoogleLogging( "vrp_trash_collection" );
    FLAGS_logtostderr = 0;
    FLAGS_stderrthreshold = google::FATAL;
    FLAGS_minloglevel = google::INFO;
  }
#endif

  if (argc < 2) {
    Usage();
    return 1;
  }

  std::string infile = argv[1];

  try {
#ifdef DOSTATS
    Timer starttime;
#endif

#ifdef VRPMINTRACE
    //CONFIG->dump("CONFIG");
#endif

#ifdef OSRMCLIENT
    osrmi->useOsrm(true);
    bool testResult = osrmi->testOsrmClient(
          -34.905113, -56.157043,
          -34.906807, -56.158463,
          -34.9076,   -56.157028);
   // remove the following comment when testing OSRM only
   // assert(true==false);
#ifdef VRPMINTRACE
    if (testResult)
     DLOG(INFO) << "osrm test passed";
   else
     DLOG(INFO) << "osrm test FAIL";
#endif  // VRPMINTRACE
#endif  // OSRMCLIENT

    int iteration = 3;
    double best_cost = 9999999;

    TruckManyVisitsDump tp(infile);
    tp.process(0);
    DLOG(INFO) << "Initial solution: 0 is best";

    Solution best_sol(tp);
    best_cost = best_sol.getCostOsrm();

    TabuOpt tsi(tp, iteration);
    Solution opt_sol = tsi.getBestSolution();

    if (best_cost > opt_sol.getCostOsrm()) {
      DLOG(INFO) << "Optimization: 0 is best";
      best_cost = opt_sol.getCost();
      best_sol = opt_sol;
    }

    for (int icase = 1; icase < 2; ++icase) {
      DLOG(INFO) << "initial solution: " << icase;
      tp.process(icase);
      if (best_cost < tp.getCostOsrm()) {
        DLOG(INFO) << "initial solution: " << icase << " is best";
        best_cost = tp.getCost();
        best_sol = tp;
      }

      TabuOpt ts(tp, iteration);

      DLOG(INFO) << "optimization: " << icase;

      if (best_cost > ts.getBestSolution().getCostOsrm()) {
        DLOG(INFO) << "Optimization: " << icase << " is best";
        best_cost = ts.getBestSolution().getCost();
        best_sol = ts.getBestSolution();
      }
assert(true==false);
    }

#ifdef VRPMINTRACE
    best_sol.dumpCostValues();
    best_sol.tau();
#endif

    best_sol.dumpSolutionForPg();
    twc->cleanUp();

  } catch (const std::exception &e) {
    std::cerr << e.what() << std::endl;
    return 1;
  }

  return 0;
}

<|endoftext|>