<commit_before>/* Copyright 2019 The TensorFlow Authors. All Rights Reserved.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==============================================================================*/

#include <cmath>

#include "tensorflow/core/framework/allocator.h"
#include "tensorflow/core/framework/fake_input.h"
#include "tensorflow/core/framework/node_def_builder.h"
#include "tensorflow/core/framework/op_kernel.h"
#include "tensorflow/core/framework/tensor.h"
#include "tensorflow/core/framework/tensor_testutil.h"
#include "tensorflow/core/framework/types.h"
#include "tensorflow/core/framework/types.pb.h"
#include "tensorflow/core/kernels/ops_testutil.h"
#include "tensorflow/core/kernels/ops_util.h"
#include "tensorflow/core/lib/core/status_test_util.h"
#include "tensorflow/core/platform/test.h"
#include "tensorflow/core/platform/test_benchmark.h"

namespace tensorflow {

class MklRequantizatedOpsTest : public OpsTestBase {};

class MklRequantizatedOpsTestHelper : public OpsTestBase {
 public:
  void Setup(Tensor &input_tensor_qint32, float &range_weights_ch1,
             float &range_weights_ch2);
  void TestBody(){};
};

void MklRequantizatedOpsTestHelper::Setup(Tensor &input_tensor_qint32,
                                          float &range_weights_ch1,
                                          float &range_weights_ch2) {
  // Step 1: Input range assumptions
  // -------------------------------
  // Assume input Tensor T (NHWC) in FP32 has range [0, 5.0]   size nt*ht*wt*ct
  // Assume input Filter W (NHWC) with 2 output channels of    size nw*ht*wt*2
  // logically,   Filter W has 2 channels W1 and W2 each of    size nw*ht*wt*1
  // Assume input Filter W1(NHWC) in FP32 has range [-2.0, 2.0]size nw*ht*wt*1
  // Assume input Filter W2(NHWC) in FP32 has range [-3.0, 3.0]size nw*ht*wt*1

  // Step 2: Quantization details (per channel)
  // ------------------------------------------
  // T and W are quantized using a Quantize Op.
  // The input Tensor T (NHWC) is quantized to unsigned int8.
  // Hence T's max value is mapped to ((2^8-1) = 255).
  // The input Filter W (NHWC) is quantized to signed int8.
  // Hence W's max value is mapped to ((2^7)-1 = 127)).

  // Range of Quantized T  in uint8[0  , 255] maps to orig T  in FP32[0   , 5.0]
  // Range of Quantized W1 in int8[-127, 127] maps to orig W1 in FP32[-2.0, 2.0]
  // Range of Quantized W2 in int8[-127, 127] maps to orig W2 in FP32[-3.0, 3.0]

  // Hence the resolution of Quantized T will be 5.0/255
  // Hence the resolution of Quantized W1 will be 2.0/127
  // Hence the resolution of Quantized W2 will be 3.0/127

  // Step 3: Assumption of quantizedconv on quantized input&weights(per channel)
  // ---------------------------------------------------------------------------
  // The input T and weights W1 (or W2) will be convolved.
  // The output Tensor T is in int32 whose range is [-2^31, 2^31).
  // For simplicity, we truncate the range to (-2^31, 2^31) to make it
  // symmetric.
  // The range of the convolved T*W1 is ((2^31)-1) * 5.0/255 * 2.0/127 =
  // 663110.59
  // So the range of convolved T*W1 in int32(-2^31, 2^31) that maps to
  // orig T range in FP32[0, 5.0] * [-2.0, 2.0] is [-663110.59, 663110.59]

  // The range of the convolved T*W2 is (2^31-1) * 5.0/255 * 3.0/127 = 994665.88
  // So the range of convolved T*W1 in int32(-2^31, 2^31) that maps to
  // orig T range in FP32 [0, 5.0] * [-3.0, 3.0]  is [-994665.88, 994665.88]

  // Step 4: Assumption output above is fed to Requantization_range_perchannel
  // --------------------------------------------------------------------------
  // Here we recalculate the new range for convolved T*W so that we
  // make good use in int8 quantization from int32 to int8.

  // We assume the above operations are performed and use these values above
  // as ranges for Requantization_range_perchannel_op.
  range_weights_ch1 = 663110.59;  // For W1 channel
  range_weights_ch2 = 994665.88;  // For W2 Channel

  // We Fill the input Tensor T qint32 with arbitrary int32 values
  test::FillValues<qint32>(
      &input_tensor_qint32,
      {-1000, -2000,  2000,   4000,   -3000,  -6000,  4000,   8000,
       5000,  10000,  -6000,  -12000, 7000,   14000,  8000,   16000,
       9000,  -18000, -10000, -20000, 11000,  22000,  -12000, -24000,
       13000, 26000,  14000,  28000,  -15000, -30000, 16000,  32000});

  // Step 5: Define and run requantization_range_perchannel
  // -------------------------------------------------------
  // See test RequantizationRangePerChannelTest_Basic and/or
  // test RequantizationRangePerChannelTest_ClipMax
}

// Tests the RequantizationRangePerChannel Op wherein the range
// of the weights is calculated per channel.
TEST_F(MklRequantizatedOpsTest, RequantizationRangePerChannelTest_Basic) {
  // Let us set up the tensor and inputs before we run this op.
  float clip_value_max = static_cast<float>((1L << 31) - 1);
  float range_weights_ch1 = 0.0;
  float range_weights_ch2 = 0.0;

  // Create the input tensor
  const int input_height = 4;
  const int input_width = 4;
  const int input_channels = 2;

  // Define the shape of T.
  Tensor input_tensor_qint32(DT_QINT32,
                             {1, input_height, input_width, input_channels});

  // Explanation and setup prior to this Op. Fill T and populate range values.
  MklRequantizatedOpsTestHelper helper;
  helper.Setup(input_tensor_qint32, range_weights_ch1, range_weights_ch2);

  // Step 5: Define and run requantization_range_perchannel
  // -------------------------------------------------------
  // Define, create and initialize the OP in question.
  TF_ASSERT_OK(NodeDefBuilder("requantization_range_per_channel",
                              "RequantizationRangePerChannel")
                   .Input(FakeInput(DT_QINT32))
                   .Input(FakeInput(DT_FLOAT))
                   .Input(FakeInput(DT_FLOAT))
                   .Attr("T", DataTypeToEnum<qint32>::v())
                   .Attr("clip_value_max", clip_value_max)
                   .Finalize(node_def()));
  TF_ASSERT_OK(InitOp());

  // Add the Input Nodes to the Op.
  AddInputFromArray<qint32>(input_tensor_qint32.shape(),
                            input_tensor_qint32.flat<qint32>());

  // Calculate the Min and max from the ranges
  float ch1_min = -range_weights_ch1;
  float ch1_max = range_weights_ch1;
  float ch2_min = -range_weights_ch2;
  float ch2_max = range_weights_ch2;

  // Add the Perchannel range Nodes to the Op.
  AddInputFromArray<float>(TensorShape({input_channels}), {ch1_min, ch2_min});
  AddInputFromArray<float>(TensorShape({input_channels}), {ch1_max, ch2_max});

  // Run the Kernel
  TF_ASSERT_OK(RunOpKernel());

  // Step 6: Verify Output and Store values to test Requantize_perchannel
  // --------------------------------------------------------------------

  // Verify the Expected Outputs
  const float output_min = GetOutput(0)->flat<float>()(0);
  const float output_max = GetOutput(1)->flat<float>()(0);
  EXPECT_NEAR(-14.8217, output_min, 0.002);
  EXPECT_NEAR(14.8217, output_max, 0.002);

  // output range is made use in RequantizePerChannelTest_Basic
}

TEST_F(MklRequantizatedOpsTest, RequantizationRangePerChannelTest_ClipMax) {
  // Let us setup the tensor and inputs before we run this op.
  float clip_value_max = 6;  // Can be used as 6 for Relu 6 activations.
  float range_weights_ch1 = 0.0;
  float range_weights_ch2 = 0.0;

  // Create the input tensor
  const int input_height = 4;
  const int input_width = 4;
  const int input_channels = 2;

  // define and input tensor T shape.
  Tensor input_tensor_qint32(DT_QINT32,
                             {1, input_height, input_width, input_channels});

  // Explanation and setup prior to this Op. Fill T and populate range values.
  MklRequantizatedOpsTestHelper helper;
  helper.Setup(input_tensor_qint32, range_weights_ch1, range_weights_ch2);

  // Step 5: Define and run requantization_range_perchannel
  // -------------------------------------------------------
  // Define, create and initalize the OP in question.
  TF_ASSERT_OK(NodeDefBuilder("requantization_range_per_channel",
                              "RequantizationRangePerChannel")
                   .Input(FakeInput(DT_QINT32))
                   .Input(FakeInput(DT_FLOAT))
                   .Input(FakeInput(DT_FLOAT))
                   .Attr("T", DataTypeToEnum<qint32>::v())
                   .Attr("clip_value_max", clip_value_max)
                   .Finalize(node_def()));
  TF_ASSERT_OK(InitOp());

  // Add the Input Nodes to the Op.
  AddInputFromArray<qint32>(input_tensor_qint32.shape(),
                            input_tensor_qint32.flat<qint32>());

  // Calculate the Min and max from the ranges
  float ch1_min = -range_weights_ch1;
  float ch1_max = range_weights_ch1;
  float ch2_min = -range_weights_ch2;
  float ch2_max = range_weights_ch2;

  // Add the Perchannel range Nodes to the Op.
  AddInputFromArray<float>(TensorShape({input_channels}), {ch1_min, ch2_min});
  AddInputFromArray<float>(TensorShape({input_channels}), {ch1_max, ch2_max});

  // Run the Kernel
  TF_ASSERT_OK(RunOpKernel());

  // Step 6: Verify Output and Store values to test Requantize_perchannel
  // --------------------------------------------------------------------

  // Verify the Expected Outputs
  const float output_min = GetOutput(0)->flat<float>()(0);
  const float output_max = GetOutput(1)->flat<float>()(0);
  EXPECT_NEAR(-6.0, output_min, 0.002);  // Values are Max as with clip_value
  EXPECT_NEAR(6.0, output_max, 0.002);   // Values are Max as with clip_value
}

TEST_F(MklRequantizatedOpsTest, RequantizePerChannelTest_Basic) {
  // Let us setup the tensor and inputs before we run this op.
  float range_weights_ch1 = 0.0;
  float range_weights_ch2 = 0.0;

  // Create the input tensor
  const int input_height = 4;
  const int input_width = 4;
  const int input_channels = 2;

  // define an input tensor T shape.
  Tensor input_tensor_qint32(DT_QINT32,
                             {1, input_height, input_width, input_channels});

  // Explanation and setup prior to this Op. Fill T and populate range values.
  MklRequantizatedOpsTestHelper helper;
  helper.Setup(input_tensor_qint32, range_weights_ch1, range_weights_ch2);

  // Step 7: Define and run requantize_perchannel
  // --------------------------------------------
  // The output of Requantization_range_op_per_channel which calculated the
  // new ranges of int8 is fed to the requantize per channel op.
  // Here the Values of Convolved T*W is converted from int32 to int8.

  TF_ASSERT_OK(NodeDefBuilder("requantize_per_channel", "RequantizePerChannel")
                   .Input(FakeInput(DT_QINT32))
                   .Input(FakeInput(DT_FLOAT))
                   .Input(FakeInput(DT_FLOAT))
                   .Input(FakeInput(DT_FLOAT))
                   .Input(FakeInput(DT_FLOAT))
                   .Attr("T", DataTypeToEnum<qint32>::v())
                   .Attr("out_type", DataTypeToEnum<qint8>::v())
                   .Finalize(node_def()));
  TF_ASSERT_OK(InitOp());

  // Add the Input Nodes to the Op.
  AddInputFromArray<qint32>(input_tensor_qint32.shape(),
                            input_tensor_qint32.flat<qint32>());

  // Calculate the Min and max from the ranges
  float ch1_min = -range_weights_ch1;
  float ch1_max = range_weights_ch1;
  float ch2_min = -range_weights_ch2;
  float ch2_max = range_weights_ch2;

  // Add the Perchannel range Nodes to the Op.
  AddInputFromArray<float>(TensorShape({input_channels}), {ch1_min, ch2_min});
  AddInputFromArray<float>(TensorShape({input_channels}), {ch1_max, ch2_max});

  // Calculate the Min and max from Step 6 above
  // in RequantizationRangePerChannelTest_Basic
  float range_op_output_min = -14.8217;
  float range_op_output_max = 14.8217;

  // Add the Requested_min and requested_max stored from Step 6.
  AddInputFromArray<float>(TensorShape({1}), {range_op_output_min});
  AddInputFromArray<float>(TensorShape({1}), {range_op_output_max});

  // Run the kernel
  TF_ASSERT_OK(RunOpKernel());

  // Verify the output with the expected output
  Tensor output = *GetOutput(0);
  const float output_min = GetOutput(1)->flat<float>()(0);
  const float output_max = GetOutput(2)->flat<float>()(0);
  EXPECT_NEAR(range_op_output_min, output_min, 0.002);
  EXPECT_NEAR(range_op_output_max, output_max, 0.002);
}

}  // namespace tensorflow
<commit_msg>change comments for test 2<commit_after>/* Copyright 2019 The TensorFlow Authors. All Rights Reserved.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==============================================================================*/

#include <cmath>

#include "tensorflow/core/framework/allocator.h"
#include "tensorflow/core/framework/fake_input.h"
#include "tensorflow/core/framework/node_def_builder.h"
#include "tensorflow/core/framework/op_kernel.h"
#include "tensorflow/core/framework/tensor.h"
#include "tensorflow/core/framework/tensor_testutil.h"
#include "tensorflow/core/framework/types.h"
#include "tensorflow/core/framework/types.pb.h"
#include "tensorflow/core/kernels/ops_testutil.h"
#include "tensorflow/core/kernels/ops_util.h"
#include "tensorflow/core/lib/core/status_test_util.h"
#include "tensorflow/core/platform/test.h"
#include "tensorflow/core/platform/test_benchmark.h"

namespace tensorflow {

class MklRequantizatedOpsTest : public OpsTestBase {};

class MklRequantizatedOpsTestHelper : public OpsTestBase {
 public:
  void Setup(Tensor &input_tensor_qint32, float &range_weights_ch1,
             float &range_weights_ch2);
  void TestBody(){};
};

void MklRequantizatedOpsTestHelper::Setup(Tensor &input_tensor_qint32,
                                          float &range_weights_ch1,
                                          float &range_weights_ch2) {
  // Step 1: Input range assumptions
  // -------------------------------
  // Assume input tensor T (NHWC) in FP32 has range [0, 5.0]   size nt*ht*wt*ct
  // Assume input filter W (NHWC) with 2 output channels of    size nw*ht*wt*2
  // logically,   filter W has 2 channels W1 and W2 each of    size nw*ht*wt*1
  // Assume input filter W1(NHWC) in FP32 has range [-2.0, 2.0]size nw*ht*wt*1
  // Assume input filter W2(NHWC) in FP32 has range [-3.0, 3.0]size nw*ht*wt*1

  // Step 2: Quantization details (per channel)
  // ------------------------------------------
  // T and W are quantized using a quantize Op.
  // The input tensor T (NHWC) is quantized to unsigned int8.
  // Hence T's max value is mapped to ((2^8-1) = 255).
  // The input filter W (NHWC) is quantized to signed int8.
  // Hence W's max value is mapped to ((2^7)-1 = 127)).

  // Range of quantized T  in uint8[0  , 255] maps to orig T  in FP32[0   , 5.0]
  // Range of quantized W1 in int8[-127, 127] maps to orig W1 in FP32[-2.0, 2.0]
  // Range of quantized W2 in int8[-127, 127] maps to orig W2 in FP32[-3.0, 3.0]

  // Hence the resolution of quantized T will be 5.0/255
  // Hence the resolution of quantized W1 will be 2.0/127
  // Hence the resolution of quantized W2 will be 3.0/127

  // Step 3: Assumption of quantizedconv on quantized input&weights(per channel)
  // ---------------------------------------------------------------------------
  // The input T and weights W1 (or W2) will be convolved.
  // The output tensor T is in int32 whose range is [-2^31, 2^31).
  // For simplicity, we truncate the range to (-2^31, 2^31) to make it
  // symmetric.
  // The range of the convolved T*W1 is ((2^31)-1) * 5.0/255 * 2.0/127 =
  // 663110.59
  // So the range of convolved T*W1 in int32(-2^31, 2^31) that maps to
  // orig T range in FP32[0, 5.0] * [-2.0, 2.0] is [-663110.59, 663110.59]

  // The range of the convolved T*W2 is (2^31-1) * 5.0/255 * 3.0/127 = 994665.88
  // So the range of convolved T*W1 in int32(-2^31, 2^31) that maps to
  // orig T range in FP32 [0, 5.0] * [-3.0, 3.0]  is [-994665.88, 994665.88]

  // Step 4: Assumption output above is fed to requantization_range_perchannel
  // --------------------------------------------------------------------------
  // Here we recalculate the new range for convolved T*W so that we
  // make good use in int8 quantization from int32 to int8.

  // We assume the above operations are performed and use these values above
  // as ranges for requantization_range_perchannel_op.
  range_weights_ch1 = 663110.59;  // For W1 channel
  range_weights_ch2 = 994665.88;  // For W2 Channel

  // We Fill the input tensor T qint32 with arbitrary int32 values
  test::FillValues<qint32>(
      &input_tensor_qint32,
      {-1000, -2000,  2000,   4000,   -3000,  -6000,  4000,   8000,
       5000,  10000,  -6000,  -12000, 7000,   14000,  8000,   16000,
       9000,  -18000, -10000, -20000, 11000,  22000,  -12000, -24000,
       13000, 26000,  14000,  28000,  -15000, -30000, 16000,  32000});

  // Step 5: Define and run requantization_range_perchannel
  // -------------------------------------------------------
  // See test RequantizationRangePerChannelTest_Basic and/or
  // test RequantizationRangePerChannelTest_ClipMax
}

// Tests the RequantizationRangePerChannel Op wherein the range
// of the weights is calculated per channel.
TEST_F(MklRequantizatedOpsTest, RequantizationRangePerChannelTest_Basic) {
  // Let us set up the tensor and inputs before we run this op.
  float clip_value_max = static_cast<float>((1L << 31) - 1);
  float range_weights_ch1 = 0.0;
  float range_weights_ch2 = 0.0;

  // Create the input tensor
  const int input_height = 4;
  const int input_width = 4;
  const int input_channels = 2;

  // Define the shape of T.
  Tensor input_tensor_qint32(DT_QINT32,
                             {1, input_height, input_width, input_channels});

  // Explanation and setup prior to this Op. Fill T and populate range values.
  MklRequantizatedOpsTestHelper helper;
  helper.Setup(input_tensor_qint32, range_weights_ch1, range_weights_ch2);

  // Step 5: Define and run requantization_range_perchannel
  // -------------------------------------------------------
  // Define, create and initialize the OP in question.
  TF_ASSERT_OK(NodeDefBuilder("requantization_range_per_channel",
                              "RequantizationRangePerChannel")
                   .Input(FakeInput(DT_QINT32))
                   .Input(FakeInput(DT_FLOAT))
                   .Input(FakeInput(DT_FLOAT))
                   .Attr("T", DataTypeToEnum<qint32>::v())
                   .Attr("clip_value_max", clip_value_max)
                   .Finalize(node_def()));
  TF_ASSERT_OK(InitOp());

  // Add the Input Nodes to the Op.
  AddInputFromArray<qint32>(input_tensor_qint32.shape(),
                            input_tensor_qint32.flat<qint32>());

  // Calculate the Min and max from the ranges
  float ch1_min = -range_weights_ch1;
  float ch1_max = range_weights_ch1;
  float ch2_min = -range_weights_ch2;
  float ch2_max = range_weights_ch2;

  // Add the perchannel range Nodes to the Op.
  AddInputFromArray<float>(TensorShape({input_channels}), {ch1_min, ch2_min});
  AddInputFromArray<float>(TensorShape({input_channels}), {ch1_max, ch2_max});

  // Run the kernel
  TF_ASSERT_OK(RunOpKernel());

  // Step 6: Verify output and store values to test requantize_perchannel
  // --------------------------------------------------------------------

  // Verify the Expected Outputs
  const float output_min = GetOutput(0)->flat<float>()(0);
  const float output_max = GetOutput(1)->flat<float>()(0);
  EXPECT_NEAR(-14.8217, output_min, 0.002);
  EXPECT_NEAR(14.8217, output_max, 0.002);

  // output range is made use in requantizePerChannelTest_Basic
}

TEST_F(MklRequantizatedOpsTest, RequantizationRangePerChannelTest_ClipMax) {
  // Let us setup the tensor and inputs before we run this op.
  float clip_value_max = 6;  // Can be used as 6 for Relu 6 activations.
  float range_weights_ch1 = 0.0;
  float range_weights_ch2 = 0.0;

  // Create the input tensor
  const int input_height = 4;
  const int input_width = 4;
  const int input_channels = 2;

  // define and input tensor T shape.
  Tensor input_tensor_qint32(DT_QINT32,
                             {1, input_height, input_width, input_channels});

  // Explanation and setup prior to this Op. Fill T and populate range values.
  MklRequantizatedOpsTestHelper helper;
  helper.Setup(input_tensor_qint32, range_weights_ch1, range_weights_ch2);

  // Step 5: Define and run requantization_range_perchannel
  // -------------------------------------------------------
  // Define, create and initalize the OP in question.
  TF_ASSERT_OK(NodeDefBuilder("requantization_range_per_channel",
                              "RequantizationRangePerChannel")
                   .Input(FakeInput(DT_QINT32))
                   .Input(FakeInput(DT_FLOAT))
                   .Input(FakeInput(DT_FLOAT))
                   .Attr("T", DataTypeToEnum<qint32>::v())
                   .Attr("clip_value_max", clip_value_max)
                   .Finalize(node_def()));
  TF_ASSERT_OK(InitOp());

  // Add the Input Nodes to the Op.
  AddInputFromArray<qint32>(input_tensor_qint32.shape(),
                            input_tensor_qint32.flat<qint32>());

  // Calculate the min and max from the ranges
  float ch1_min = -range_weights_ch1;
  float ch1_max = range_weights_ch1;
  float ch2_min = -range_weights_ch2;
  float ch2_max = range_weights_ch2;

  // Add the perchannel range nodes to the Op.
  AddInputFromArray<float>(TensorShape({input_channels}), {ch1_min, ch2_min});
  AddInputFromArray<float>(TensorShape({input_channels}), {ch1_max, ch2_max});

  // Run the kernel
  TF_ASSERT_OK(RunOpKernel());

  // Step 6: Verify output and store values to test requantize_perchannel
  // --------------------------------------------------------------------

  // Verify the expected outputs
  const float output_min = GetOutput(0)->flat<float>()(0);
  const float output_max = GetOutput(1)->flat<float>()(0);
  EXPECT_NEAR(-6.0, output_min, 0.002);  // Values are Max as with clip_value
  EXPECT_NEAR(6.0, output_max, 0.002);   // Values are Max as with clip_value
}

TEST_F(MklRequantizatedOpsTest, RequantizePerChannelTest_Basic) {
  // Let us setup the tensor and inputs before we run this op.
  float range_weights_ch1 = 0.0;
  float range_weights_ch2 = 0.0;

  // Create the input tensor
  const int input_height = 4;
  const int input_width = 4;
  const int input_channels = 2;

  // define an input tensor T shape.
  Tensor input_tensor_qint32(DT_QINT32,
                             {1, input_height, input_width, input_channels});

  // Explanation and setup prior to this Op. Fill T and populate range values.
  MklRequantizatedOpsTestHelper helper;
  helper.Setup(input_tensor_qint32, range_weights_ch1, range_weights_ch2);

  // Step 7: Define and run requantize_perchannel
  // --------------------------------------------
  // The output of requantization_range_op_per_channel which calculated the
  // new ranges of int8 is fed to the requantize per channel op.
  // Here the Values of Convolved T*W is converted from int32 to int8.

  TF_ASSERT_OK(NodeDefBuilder("requantize_per_channel", "RequantizePerChannel")
                   .Input(FakeInput(DT_QINT32))
                   .Input(FakeInput(DT_FLOAT))
                   .Input(FakeInput(DT_FLOAT))
                   .Input(FakeInput(DT_FLOAT))
                   .Input(FakeInput(DT_FLOAT))
                   .Attr("T", DataTypeToEnum<qint32>::v())
                   .Attr("out_type", DataTypeToEnum<qint8>::v())
                   .Finalize(node_def()));
  TF_ASSERT_OK(InitOp());

  // Add the input Nodes to the Op.
  AddInputFromArray<qint32>(input_tensor_qint32.shape(),
                            input_tensor_qint32.flat<qint32>());

  // Calculate the min and max from the ranges
  float ch1_min = -range_weights_ch1;
  float ch1_max = range_weights_ch1;
  float ch2_min = -range_weights_ch2;
  float ch2_max = range_weights_ch2;

  // Add the perchannel range nodes to the Op.
  AddInputFromArray<float>(TensorShape({input_channels}), {ch1_min, ch2_min});
  AddInputFromArray<float>(TensorShape({input_channels}), {ch1_max, ch2_max});

  // Calculate the min and max from Step 6 above
  // in RequantizationRangePerChannelTest_Basic
  float range_op_output_min = -14.8217;
  float range_op_output_max = 14.8217;

  // Add the requested_min and requested_max stored from Step 6.
  AddInputFromArray<float>(TensorShape({1}), {range_op_output_min});
  AddInputFromArray<float>(TensorShape({1}), {range_op_output_max});

  // Run the kernel
  TF_ASSERT_OK(RunOpKernel());

  // Verify the output with the expected output
  Tensor output = *GetOutput(0);
  const float output_min = GetOutput(1)->flat<float>()(0);
  const float output_max = GetOutput(2)->flat<float>()(0);
  EXPECT_NEAR(range_op_output_min, output_min, 0.002);
  EXPECT_NEAR(range_op_output_max, output_max, 0.002);
}

}  // namespace tensorflow
<|endoftext|>


<commit_before>#if defined(__GNUG__) && __GNUG__ < 3
#define _XOPEN_SOURCE
#endif

#include "datetime.h"
#include "error.h"

#include <ctime>
#include <cctype>

namespace ledger {

std::time_t         now	      = std::time(NULL);
int                 now_year  = std::localtime(&now)->tm_year;

static std::time_t  base      = -1;
static int	    base_year = -1;

static const int    month_days[12] = {
  31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
};

static const char * formats[] = {
  "%Y/%m/%d",
  "%m/%d",
  "%Y.%m.%d",
  "%m.%d",
  "%Y-%m-%d",
  "%m-%d",
  "%a",
  "%A",
  "%b",
  "%B",
  "%Y",
  NULL
};

std::time_t interval_t::first(const std::time_t moment) const
{
  std::time_t quant = begin;

  if (moment && std::difftime(moment, quant) > 0) {
    // Find an efficient starting point for the upcoming while loop.
    // We want a date early enough that the range will be correct, but
    // late enough that we don't spend hundreds of thousands of loops
    // skipping through time.

    struct std::tm * desc = std::gmtime(&moment);
    if (years)
      desc->tm_mon = 0;
    desc->tm_mday = 1;
    desc->tm_hour = 0;
    desc->tm_min  = 0;
    desc->tm_sec  = 0;
    quant = std::mktime(desc);

    std::time_t temp;
    while (std::difftime(moment, temp = increment(quant)) >= 0) {
      if (quant == temp)
	break;
      quant = temp;
    }
  }

  return quant;
}

std::time_t interval_t::increment(const std::time_t moment) const
{
  std::time_t then = moment;

  if (years || months) {
    struct std::tm * desc = std::gmtime(&then);

    if (years)
      desc->tm_year += years;

    if (months) {
      desc->tm_mon += months;

      if (desc->tm_mon > 11) {
	desc->tm_year++;
	desc->tm_mon -= 12;
      }
      else if (desc->tm_mon < 0) {
	desc->tm_year--;
	desc->tm_mon += 12;
      }
    }

    desc->tm_hour = 0;
    desc->tm_min  = 0;
    desc->tm_sec  = 0;

    then = std::mktime(desc);
  }

  return then + seconds;
}

static void parse_inclusion_specifier(const std::string& word,
				      std::time_t *	 begin,
				      std::time_t *	 end)
{
  struct std::tm when;

  if (! parse_date_mask(word.c_str(), &when))
    throw interval_expr_error(std::string("Could not parse date mask: ") +
			      word);

  when.tm_hour = 0;
  when.tm_min  = 0;
  when.tm_sec  = 0;

  bool saw_year = true;
  bool saw_mon  = true;

  if (when.tm_year == -1) {
    when.tm_year = now_year;
    saw_year = false;
  }
  if (when.tm_mon == -1) {
    when.tm_mon = 0;
    saw_mon = false;
  } else {
    saw_year = false;		// don't increment by year if month used
  }
  if (when.tm_mday == -1)
    when.tm_mday = 1;

  if (begin) {
    *begin = std::mktime(&when);
    if (end)
      *end = interval_t(0, saw_mon ? 1 : 0, saw_year ? 1 : 0).increment(*begin);
  }
  else if (end) {
    *end = std::mktime(&when);
  }
}

static inline
void read_lower_word(std::istream& in, std::string& word) {
  in >> word;
  for (int i = 0, l = word.length(); i < l; i++)
    word[i] = std::tolower(word[i]);
}

static void parse_date_words(std::istream& in, std::string& word,
			     std::time_t * begin, std::time_t * end)
{
  std::string type;
  bool	      mon_spec = false;
  char	      buf[32];

  if (word == "this" || word == "last" || word == "next") {
    type = word;
    if (! in.eof())
      read_lower_word(in, word);
    else
      word = "month";
  } else {
    type = "this";
  }

  if (word == "month") {
    std::strftime(buf, 31, "%B", std::localtime(&now));
    word = buf;
    mon_spec = true;
  }
  else if (word == "year") {
    std::strftime(buf, 31, "%Y", std::localtime(&now));
    word = buf;
  }

  parse_inclusion_specifier(word, begin, end);

  if (type == "last") {
    if (mon_spec) {
      if (begin)
	*begin = interval_t(0, -1, 0).increment(*begin);
      if (end)
	*end   = interval_t(0, -1, 0).increment(*end);
    } else {
      if (begin)
	*begin = interval_t(0, 0, -1).increment(*begin);
      if (end)
	*end   = interval_t(0, 0, -1).increment(*end);
    }
  }
  else if (type == "next") {
    if (mon_spec) {
      if (begin)
	*begin = interval_t(0, 1, 0).increment(*begin);
      if (end)
	*end   = interval_t(0, 1, 0).increment(*end);
    } else {
      if (begin)
	*begin = interval_t(0, 0, 1).increment(*begin);
      if (end)
	*end   = interval_t(0, 0, 1).increment(*end);
    }
  }
}

void interval_t::parse(std::istream& in)
{
  std::string word;

  while (! in.eof()) {
    read_lower_word(in, word);
    if (word == "every") {
      read_lower_word(in, word);
      if (std::isdigit(word[0])) {
	int quantity = std::atol(word.c_str());
	read_lower_word(in, word);
	if (word == "days")
	  seconds = 86400 * quantity;
	else if (word == "weeks")
	  seconds = 7 * 86400 * quantity;
	else if (word == "months")
	  months = quantity;
	else if (word == "quarters")
	  months = 3 * quantity;
	else if (word == "years")
	  years = quantity;
      }
      else if (word == "day")
	seconds = 86400;
      else if (word == "week")
	seconds = 7 * 86400;
      else if (word == "monthly")
	months = 1;
      else if (word == "quarter")
	months = 3;
      else if (word == "year")
	years = 1;
    }
    else if (word == "daily")
      seconds = 86400;
    else if (word == "weekly")
      seconds = 7 * 86400;
    else if (word == "biweekly")
      seconds = 14 * 86400;
    else if (word == "monthly")
      months = 1;
    else if (word == "bimonthly")
      months = 2;
    else if (word == "quarterly")
      months = 3;
    else if (word == "yearly")
      years = 1;
    else if (word == "this" || word == "last" || word == "next") {
      parse_date_words(in, word, &begin, &end);
    }
    else if (word == "in") {
      read_lower_word(in, word);
      parse_date_words(in, word, &begin, &end);
    }
    else if (word == "from" || word == "since") {
      read_lower_word(in, word);
      parse_date_words(in, word, &begin, NULL);
    }
    else if (word == "to" || word == "until") {
      read_lower_word(in, word);
      parse_date_words(in, word, NULL, &end);
    }
    else {
      parse_inclusion_specifier(word, &begin, &end);
    }
  }
}

bool parse_date_mask(const char * date_str, struct std::tm * result)
{
  for (const char ** f = formats; *f; f++) {
    memset(result, INT_MAX, sizeof(struct std::tm));
    if (strptime(date_str, *f, result))
      return true;
  }
  return false;
}

bool parse_date(const char * date_str, std::time_t * result, const int year)
{
  struct std::tm when;

  if (! parse_date_mask(date_str, &when))
    return false;

  when.tm_hour = 0;
  when.tm_min  = 0;
  when.tm_sec  = 0;

  if (when.tm_year == -1)
    when.tm_year = ((year == -1) ? now_year : (year - 1900));

  if (when.tm_mon == -1)
    when.tm_mon = 0;

  if (when.tm_mday == -1)
    when.tm_mday = 1;

  *result = std::mktime(&when);

  return true;
}

bool quick_parse_date(const char * date_str, std::time_t * result)
{
  int year = -1, month = -1, day, num = 0;

  for (const char * p = date_str; *p; p++) {
    if (*p == '/' || *p == '-' || *p == '.') {
      if (year == -1)
	year = num;
      else
	month = num;
      num = 0;
    }
    else if (*p < '0' || *p > '9') {
      return false;
    }
    else {
      num *= 10;
      num += *p - '0';
    }
  }

  day = num;

  if (month == -1) {
    month = year;
    year  = now_year + 1900;
  }

  if (base == -1 || year != base_year) {
    struct std::tm when;
    std::memset(&when, 0, sizeof(when));

    base_year    = year == -1 ? now_year + 1900 : year;
    when.tm_year = year == -1 ? now_year : year - 1900;
    when.tm_mday = 1;

    base = std::mktime(&when);
    year = base_year;
  }

  *result = base;

  --month;
  while (--month >= 0) {
    *result += month_days[month] * 24 * 60 * 60;
    if (month == 1 && year % 4 == 0 && year != 2000) // february in leap years
      *result += 24 * 60 * 60;
  }

  if (--day)
    *result += day * 24 * 60 * 60;

  return true;
}

} // namespace ledger

#ifdef USE_BOOST_PYTHON

#include <boost/python.hpp>

using namespace boost::python;
using namespace ledger;

unsigned int interval_len(interval_t& interval)
{
  int periods = 1;
  std::time_t when = interval.first();
  while (interval.end && when < interval.end) {
    when = interval.increment(when);
    if (when < interval.end)
      periods++;
  }
  return periods;
}

std::time_t interval_getitem(interval_t& interval, int i)
{
  static std::time_t last_index = 0;
  static std::time_t last_moment = 0;

  if (i == 0) {
    last_index = 0;
    last_moment = interval.first();
  }
  else {
    last_moment = interval.increment(last_moment);
    if (interval.end && last_moment >= interval.end) {
      PyErr_SetString(PyExc_IndexError, "Index out of range");
      throw_error_already_set();
    }
  }
  return last_moment;
}

void export_datetime()
{
  class_< interval_t >
    ("Interval", init<optional<int, int, int, std::time_t, std::time_t> >())
    .def(init<std::string>())
    .def(! self)

    .def_readwrite("years", &interval_t::years)
    .def_readwrite("months", &interval_t::months)
    .def_readwrite("seconds", &interval_t::seconds)
    .def_readwrite("begin", &interval_t::begin)
    .def_readwrite("end", &interval_t::end)

    .def("__len__", interval_len)
    .def("__getitem__", interval_getitem)

    .def("increment", &interval_t::increment)
    ;
}

#endif // USE_BOOST_PYTHON
<commit_msg>(export_datetime): Exposed "parse_date" function.<commit_after>#if defined(__GNUG__) && __GNUG__ < 3
#define _XOPEN_SOURCE
#endif

#include "datetime.h"
#include "error.h"

#include <ctime>
#include <cctype>

namespace ledger {

std::time_t         now	      = std::time(NULL);
int                 now_year  = std::localtime(&now)->tm_year;

static std::time_t  base      = -1;
static int	    base_year = -1;

static const int    month_days[12] = {
  31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
};

static const char * formats[] = {
  "%Y/%m/%d",
  "%m/%d",
  "%Y.%m.%d",
  "%m.%d",
  "%Y-%m-%d",
  "%m-%d",
  "%a",
  "%A",
  "%b",
  "%B",
  "%Y",
  NULL
};

std::time_t interval_t::first(const std::time_t moment) const
{
  std::time_t quant = begin;

  if (moment && std::difftime(moment, quant) > 0) {
    // Find an efficient starting point for the upcoming while loop.
    // We want a date early enough that the range will be correct, but
    // late enough that we don't spend hundreds of thousands of loops
    // skipping through time.

    struct std::tm * desc = std::gmtime(&moment);
    if (years)
      desc->tm_mon = 0;
    desc->tm_mday = 1;
    desc->tm_hour = 0;
    desc->tm_min  = 0;
    desc->tm_sec  = 0;
    quant = std::mktime(desc);

    std::time_t temp;
    while (std::difftime(moment, temp = increment(quant)) >= 0) {
      if (quant == temp)
	break;
      quant = temp;
    }
  }

  return quant;
}

std::time_t interval_t::increment(const std::time_t moment) const
{
  std::time_t then = moment;

  if (years || months) {
    struct std::tm * desc = std::gmtime(&then);

    if (years)
      desc->tm_year += years;

    if (months) {
      desc->tm_mon += months;

      if (desc->tm_mon > 11) {
	desc->tm_year++;
	desc->tm_mon -= 12;
      }
      else if (desc->tm_mon < 0) {
	desc->tm_year--;
	desc->tm_mon += 12;
      }
    }

    desc->tm_hour = 0;
    desc->tm_min  = 0;
    desc->tm_sec  = 0;

    then = std::mktime(desc);
  }

  return then + seconds;
}

static void parse_inclusion_specifier(const std::string& word,
				      std::time_t *	 begin,
				      std::time_t *	 end)
{
  struct std::tm when;

  if (! parse_date_mask(word.c_str(), &when))
    throw interval_expr_error(std::string("Could not parse date mask: ") +
			      word);

  when.tm_hour = 0;
  when.tm_min  = 0;
  when.tm_sec  = 0;

  bool saw_year = true;
  bool saw_mon  = true;

  if (when.tm_year == -1) {
    when.tm_year = now_year;
    saw_year = false;
  }
  if (when.tm_mon == -1) {
    when.tm_mon = 0;
    saw_mon = false;
  } else {
    saw_year = false;		// don't increment by year if month used
  }
  if (when.tm_mday == -1)
    when.tm_mday = 1;

  if (begin) {
    *begin = std::mktime(&when);
    if (end)
      *end = interval_t(0, saw_mon ? 1 : 0, saw_year ? 1 : 0).increment(*begin);
  }
  else if (end) {
    *end = std::mktime(&when);
  }
}

static inline
void read_lower_word(std::istream& in, std::string& word) {
  in >> word;
  for (int i = 0, l = word.length(); i < l; i++)
    word[i] = std::tolower(word[i]);
}

static void parse_date_words(std::istream& in, std::string& word,
			     std::time_t * begin, std::time_t * end)
{
  std::string type;
  bool	      mon_spec = false;
  char	      buf[32];

  if (word == "this" || word == "last" || word == "next") {
    type = word;
    if (! in.eof())
      read_lower_word(in, word);
    else
      word = "month";
  } else {
    type = "this";
  }

  if (word == "month") {
    std::strftime(buf, 31, "%B", std::localtime(&now));
    word = buf;
    mon_spec = true;
  }
  else if (word == "year") {
    std::strftime(buf, 31, "%Y", std::localtime(&now));
    word = buf;
  }

  parse_inclusion_specifier(word, begin, end);

  if (type == "last") {
    if (mon_spec) {
      if (begin)
	*begin = interval_t(0, -1, 0).increment(*begin);
      if (end)
	*end   = interval_t(0, -1, 0).increment(*end);
    } else {
      if (begin)
	*begin = interval_t(0, 0, -1).increment(*begin);
      if (end)
	*end   = interval_t(0, 0, -1).increment(*end);
    }
  }
  else if (type == "next") {
    if (mon_spec) {
      if (begin)
	*begin = interval_t(0, 1, 0).increment(*begin);
      if (end)
	*end   = interval_t(0, 1, 0).increment(*end);
    } else {
      if (begin)
	*begin = interval_t(0, 0, 1).increment(*begin);
      if (end)
	*end   = interval_t(0, 0, 1).increment(*end);
    }
  }
}

void interval_t::parse(std::istream& in)
{
  std::string word;

  while (! in.eof()) {
    read_lower_word(in, word);
    if (word == "every") {
      read_lower_word(in, word);
      if (std::isdigit(word[0])) {
	int quantity = std::atol(word.c_str());
	read_lower_word(in, word);
	if (word == "days")
	  seconds = 86400 * quantity;
	else if (word == "weeks")
	  seconds = 7 * 86400 * quantity;
	else if (word == "months")
	  months = quantity;
	else if (word == "quarters")
	  months = 3 * quantity;
	else if (word == "years")
	  years = quantity;
      }
      else if (word == "day")
	seconds = 86400;
      else if (word == "week")
	seconds = 7 * 86400;
      else if (word == "monthly")
	months = 1;
      else if (word == "quarter")
	months = 3;
      else if (word == "year")
	years = 1;
    }
    else if (word == "daily")
      seconds = 86400;
    else if (word == "weekly")
      seconds = 7 * 86400;
    else if (word == "biweekly")
      seconds = 14 * 86400;
    else if (word == "monthly")
      months = 1;
    else if (word == "bimonthly")
      months = 2;
    else if (word == "quarterly")
      months = 3;
    else if (word == "yearly")
      years = 1;
    else if (word == "this" || word == "last" || word == "next") {
      parse_date_words(in, word, &begin, &end);
    }
    else if (word == "in") {
      read_lower_word(in, word);
      parse_date_words(in, word, &begin, &end);
    }
    else if (word == "from" || word == "since") {
      read_lower_word(in, word);
      parse_date_words(in, word, &begin, NULL);
    }
    else if (word == "to" || word == "until") {
      read_lower_word(in, word);
      parse_date_words(in, word, NULL, &end);
    }
    else {
      parse_inclusion_specifier(word, &begin, &end);
    }
  }
}

bool parse_date_mask(const char * date_str, struct std::tm * result)
{
  for (const char ** f = formats; *f; f++) {
    memset(result, INT_MAX, sizeof(struct std::tm));
    if (strptime(date_str, *f, result))
      return true;
  }
  return false;
}

bool parse_date(const char * date_str, std::time_t * result, const int year)
{
  struct std::tm when;

  if (! parse_date_mask(date_str, &when))
    return false;

  when.tm_hour = 0;
  when.tm_min  = 0;
  when.tm_sec  = 0;

  if (when.tm_year == -1)
    when.tm_year = ((year == -1) ? now_year : (year - 1900));

  if (when.tm_mon == -1)
    when.tm_mon = 0;

  if (when.tm_mday == -1)
    when.tm_mday = 1;

  *result = std::mktime(&when);

  return true;
}

bool quick_parse_date(const char * date_str, std::time_t * result)
{
  int year = -1, month = -1, day, num = 0;

  for (const char * p = date_str; *p; p++) {
    if (*p == '/' || *p == '-' || *p == '.') {
      if (year == -1)
	year = num;
      else
	month = num;
      num = 0;
    }
    else if (*p < '0' || *p > '9') {
      return false;
    }
    else {
      num *= 10;
      num += *p - '0';
    }
  }

  day = num;

  if (month == -1) {
    month = year;
    year  = now_year + 1900;
  }

  if (base == -1 || year != base_year) {
    struct std::tm when;
    std::memset(&when, 0, sizeof(when));

    base_year    = year == -1 ? now_year + 1900 : year;
    when.tm_year = year == -1 ? now_year : year - 1900;
    when.tm_mday = 1;

    base = std::mktime(&when);
    year = base_year;
  }

  *result = base;

  --month;
  while (--month >= 0) {
    *result += month_days[month] * 24 * 60 * 60;
    if (month == 1 && year % 4 == 0 && year != 2000) // february in leap years
      *result += 24 * 60 * 60;
  }

  if (--day)
    *result += day * 24 * 60 * 60;

  return true;
}

} // namespace ledger

#ifdef USE_BOOST_PYTHON

#include <boost/python.hpp>

using namespace boost::python;
using namespace ledger;

unsigned int interval_len(interval_t& interval)
{
  int periods = 1;
  std::time_t when = interval.first();
  while (interval.end && when < interval.end) {
    when = interval.increment(when);
    if (when < interval.end)
      periods++;
  }
  return periods;
}

std::time_t interval_getitem(interval_t& interval, int i)
{
  static std::time_t last_index = 0;
  static std::time_t last_moment = 0;

  if (i == 0) {
    last_index = 0;
    last_moment = interval.first();
  }
  else {
    last_moment = interval.increment(last_moment);
    if (interval.end && last_moment >= interval.end) {
      PyErr_SetString(PyExc_IndexError, "Index out of range");
      throw_error_already_set();
    }
  }
  return last_moment;
}

std::time_t py_parse_date(const char * date_str)
{
  std::time_t temp;
  if (parse_date(date_str, &temp))
    return temp;
  return 0;
}

std::time_t py_parse_date_yr(const char * date_str, const int year)
{
  std::time_t temp;
  if (parse_date(date_str, &temp, year))
    return temp;
  return 0;
}

void export_datetime()
{
  class_< interval_t >
    ("Interval", init<optional<int, int, int, std::time_t, std::time_t> >())
    .def(init<std::string>())
    .def(! self)

    .def_readwrite("years", &interval_t::years)
    .def_readwrite("months", &interval_t::months)
    .def_readwrite("seconds", &interval_t::seconds)
    .def_readwrite("begin", &interval_t::begin)
    .def_readwrite("end", &interval_t::end)

    .def("__len__", interval_len)
    .def("__getitem__", interval_getitem)

    .def("increment", &interval_t::increment)
    ;

  def("parse_date", py_parse_date);
  def("parse_date", py_parse_date_yr);
}

#endif // USE_BOOST_PYTHON
<|endoftext|>


<commit_before>/*
 * TessuMod: Mod for integrating TeamSpeak into World of Tanks
 * Copyright (C) 2015  Janne Hakonen
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 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
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301
 * USA
 */

#include "settingsstorage.h"
#include "../entities/settings.h"
#include "../interfaces/drivers.h"

namespace Storage
{

SettingsStorage::SettingsStorage( Interfaces::SettingsDriver *driver, QObject *parent )
	: QObject( parent ), driver( driver )
{
}

Entity::Settings SettingsStorage::get() const
{
	Entity::Settings settings;
	settings.audioBackend        = (Entity::AudioBackend) driver->get( "General", "AudioBackend", (int)Entity::OpenALBackend ).toInt();
	settings.positioningEnabled  = driver->get( "General", "PositionalAudioEnabled", true ).toBool();
	settings.testRotateMode      = (Entity::RotateMode) driver->get( "General", "TestRotateMode", Entity::RotateYAxis ).toInt();
	settings.hrtfEnabled         = driver->get( "General", "HrtfEnabled", false ).toBool();
	settings.hrtfDataSet         = driver->get( "General", "HrtfDataSet", "MIT_KEMAR" ).toString();
	settings.audioLoggingEnabled = driver->get( "General", "AudioLoggingEnabled", false ).toBool();
	return settings;
}

void SettingsStorage::set( const Entity::Settings &settings )
{
	driver->set( "General", "AudioBackend",           (int)settings.audioBackend );
	driver->set( "General", "PositionalAudioEnabled", settings.positioningEnabled );
	driver->set( "General", "TestRotateMode",         (int)settings.testRotateMode );
	driver->set( "General", "HrtfEnabled",            settings.hrtfEnabled );
	driver->set( "General", "HrtfDataSet",            settings.hrtfDataSet );
	driver->set( "General", "AudioLoggingEnabled",    settings.audioLoggingEnabled );
}

}
<commit_msg>Issue #3: Fixed default HRTF not set correctly.<commit_after>/*
 * TessuMod: Mod for integrating TeamSpeak into World of Tanks
 * Copyright (C) 2015  Janne Hakonen
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 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
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301
 * USA
 */

#include "settingsstorage.h"
#include "../entities/settings.h"
#include "../interfaces/drivers.h"

namespace Storage
{

SettingsStorage::SettingsStorage( Interfaces::SettingsDriver *driver, QObject *parent )
	: QObject( parent ), driver( driver )
{
}

Entity::Settings SettingsStorage::get() const
{
	Entity::Settings settings;
	settings.audioBackend        = (Entity::AudioBackend) driver->get( "General", "AudioBackend", (int)Entity::OpenALBackend ).toInt();
	settings.positioningEnabled  = driver->get( "General", "PositionalAudioEnabled", true ).toBool();
	settings.testRotateMode      = (Entity::RotateMode) driver->get( "General", "TestRotateMode", Entity::RotateYAxis ).toInt();
	settings.hrtfEnabled         = driver->get( "General", "HrtfEnabled", false ).toBool();
	settings.hrtfDataSet         = driver->get( "General", "HrtfDataSet", ":/etc/hrtfs/mit_kemar-44100.mhr" ).toString();
	settings.audioLoggingEnabled = driver->get( "General", "AudioLoggingEnabled", false ).toBool();
	return settings;
}

void SettingsStorage::set( const Entity::Settings &settings )
{
	driver->set( "General", "AudioBackend",           (int)settings.audioBackend );
	driver->set( "General", "PositionalAudioEnabled", settings.positioningEnabled );
	driver->set( "General", "TestRotateMode",         (int)settings.testRotateMode );
	driver->set( "General", "HrtfEnabled",            settings.hrtfEnabled );
	driver->set( "General", "HrtfDataSet",            settings.hrtfDataSet );
	driver->set( "General", "AudioLoggingEnabled",    settings.audioLoggingEnabled );
}

}
<|endoftext|>


<commit_before>// This file is part of the dune-gdt project:
//   http://users.dune-project.org/projects/dune-gdt
// Copyright holders: Felix Schindler
// License: BSD 2-Clause License (http://opensource.org/licenses/BSD-2-Clause)

#ifndef DUNE_GDT_ASSEMBLER_TMP_STORAGE_HH
#define DUNE_GDT_ASSEMBLER_TMP_STORAGE_HH

#include <vector>

#include <dune/stuff/common/disable_warnings.hh>
# include <dune/common/dynmatrix.hh>
#include <dune/stuff/common/reenable_warnings.hh>
#include <dune/common/dynvector.hh>

namespace Dune {
namespace GDT {
namespace TmpStorageProvider {

template< class FieldType = double >
class Matrices
{
  static size_t safely_get(const std::vector< size_t >& vec, const size_t ii)
  {
    assert(ii < vec.size());
    return vec[ii];
  } // ... safely_get(...)

public:
  typedef DynamicMatrix< FieldType > LocalMatrixType;

  Matrices(const std::vector< size_t >& num_tmp_objects,
           const size_t max_rows,
           const size_t max_cols)
    : matrices_({ std::vector< LocalMatrixType >(safely_get(num_tmp_objects, 0),
                                                 LocalMatrixType(max_rows, max_cols, FieldType(0)))
                , std::vector< LocalMatrixType >(safely_get(num_tmp_objects, 1),
                                                 LocalMatrixType(max_rows, max_cols, FieldType(0))) })
    , indices_(4, Dune::DynamicVector< size_t >(std::max(max_rows, max_cols)))
  {}

  virtual ~Matrices() {}

  std::vector< std::vector< LocalMatrixType > >& matrices()
  {
    return matrices_;
  }

  std::vector< Dune::DynamicVector< size_t > >& indices()
  {
    return indices_;
  }

protected:
  std::vector< std::vector< LocalMatrixType > > matrices_;
  std::vector< DynamicVector< size_t > > indices_;
}; // class Matrices

template< class FieldType = double >
class Vectors
{
  static size_t safely_get(const std::vector< size_t >& vec, const size_t ii)
  {
    assert(ii < vec.size());
    return vec[ii];
  } // ... safely_get(...)

public:
  typedef DynamicVector< FieldType > LocalVectorType;

  Vectors(const std::vector< size_t >& num_tmp_objects,
          const size_t max_size)
    : vectors_({ std::vector< LocalVectorType >(safely_get(num_tmp_objects, 0),
                                                LocalVectorType(max_size, FieldType(0)))
               , std::vector< LocalVectorType >(safely_get(num_tmp_objects, 1),
                                                LocalVectorType(max_size, FieldType(0))) })
    , indices_(max_size)
  {}

  virtual ~Vectors() {}

  std::vector< std::vector< LocalVectorType > >& vectors()
  {
    return vectors_;
  }

  Dune::DynamicVector< size_t >& indices()
  {
    return indices_;
  }

protected:
  std::vector< std::vector< LocalVectorType > > vectors_;
  Dune::DynamicVector< size_t > indices_;
}; // class Vectors

} // namespace TmpStorageProvider
} // namespace GDT
} // namespace Dune

#endif // DUNE_GDT_ASSEMBLER_TMP_STORAGE_HH
<commit_msg>[assembler] thread safe tmp storage<commit_after>// This file is part of the dune-gdt project:
//   http://users.dune-project.org/projects/dune-gdt
// Copyright holders: Felix Schindler
// License: BSD 2-Clause License (http://opensource.org/licenses/BSD-2-Clause)

#ifndef DUNE_GDT_ASSEMBLER_TMP_STORAGE_HH
#define DUNE_GDT_ASSEMBLER_TMP_STORAGE_HH

#include <vector>

#include <dune/stuff/common/disable_warnings.hh>
# include <dune/common/dynmatrix.hh>
#include <dune/stuff/common/reenable_warnings.hh>
#include <dune/common/dynvector.hh>
#include <dune/stuff/common/parallel/threadmanager.hh>

namespace Dune {
namespace GDT {
namespace TmpStorageProvider {

template< class FieldType = double >
class Matrices
{
public:
  typedef DynamicMatrix< FieldType > LocalMatrixType;
protected:
  typedef std::vector< std::vector< LocalMatrixType > > LocalMatrixContainerType;

public:

  Matrices(const std::vector< size_t >& num_tmp_objects,
           const size_t max_rows,
           const size_t max_cols)
    : matrices_(LocalMatrixContainerType({std::vector< LocalMatrixType >(num_tmp_objects.at(0),
                                                 LocalMatrixType(max_rows, max_cols, FieldType(0)))
                , std::vector< LocalMatrixType >(num_tmp_objects.at(1),
                                                 LocalMatrixType(max_rows, max_cols, FieldType(0))) } ))
    , indices_(4, Dune::DynamicVector< size_t >(std::max(max_rows, max_cols)))
  {}

  virtual ~Matrices() {}

  std::vector< std::vector< LocalMatrixType > >& matrices()
  {
    return *matrices_;
  }

  std::vector< Dune::DynamicVector< size_t > >& indices()
  {
    return *indices_;
  }

protected:
  DS::PerThreadValue< LocalMatrixContainerType > matrices_;
  DS::PerThreadValue< std::vector< DynamicVector< size_t > > > indices_;
}; // class Matrices

template< class FieldType = double >
class Vectors
{
public:
  typedef DynamicVector< FieldType > LocalVectorType;
protected:
  typedef std::vector< std::vector< LocalVectorType > > LocalVectorContainerType;

  Vectors(const std::vector< size_t >& num_tmp_objects,
          const size_t max_size)
    : vectors_(LocalVectorContainerType({ std::vector< LocalVectorType >(num_tmp_objects.at(0),
                                                LocalVectorType(max_size, FieldType(0)))
               , std::vector< LocalVectorType >(num_tmp_objects.at(1),
                                                LocalVectorType(max_size, FieldType(0))) } ))
    , indices_(max_size)
  {}

  virtual ~Vectors() {}

  std::vector< std::vector< LocalVectorType > >& vectors()
  {
    return *vectors_;
  }

  Dune::DynamicVector< size_t >& indices()
  {
    return *indices_;
  }

protected:
  DS::PerThreadValue< std::vector< std::vector< LocalVectorType > > > vectors_;
  DS::PerThreadValue< Dune::DynamicVector< size_t > > indices_;
}; // class Vectors

} // namespace TmpStorageProvider
} // namespace GDT
} // namespace Dune

#endif // DUNE_GDT_ASSEMBLER_TMP_STORAGE_HH
<|endoftext|>


<commit_before>#ifndef DUNE_STUFF_FUNCTION_EXPRESSION_HH
#define DUNE_STUFF_FUNCTION_EXPRESSION_HH

#include <sstream>
#include <vector>

#include <dune/common/fvector.hh>
#include <dune/common/exceptions.hh>

#include <dune/stuff/common/parameter/tree.hh>
#include <dune/stuff/common/string.hh>
#include <dune/stuff/common/color.hh>

#include "expression/base.hh"
#include "interface.hh"

namespace Dune {
namespace Stuff {

template< class DomainFieldImp, int domainDim, class RangeFieldImp, int rangeDim >
class FunctionExpression
  : public FunctionExpressionBase< DomainFieldImp, domainDim, RangeFieldImp, rangeDim >
  , public FunctionInterface< DomainFieldImp, domainDim, RangeFieldImp, rangeDim, 1 >
{
  typedef FunctionExpressionBase<  DomainFieldImp, domainDim, RangeFieldImp, rangeDim > BaseType;
  typedef FunctionInterface<  DomainFieldImp, domainDim, RangeFieldImp, rangeDim, 1 >   InterfaceType;
public:
  typedef FunctionExpression<  DomainFieldImp, domainDim, RangeFieldImp, rangeDim >     ThisType;

  typedef typename InterfaceType::DomainFieldType DomainFieldType;
  static const int                                dimDomain = InterfaceType::dimDomain;
  typedef typename InterfaceType::DomainType      DomainType;
  typedef typename InterfaceType::RangeFieldType  RangeFieldType;
  static const int                                dimRange = InterfaceType::dimRange;
  typedef typename InterfaceType::RangeType       RangeType;

  static const std::string id()
  {
    return InterfaceType::id() + ".expression";
  }

  FunctionExpression(const std::string _variable,
                     const std::string _expression,
                     const int _order = -1,
                     const std::string _name = id())
    : BaseType(_variable, _expression)
    , order_(_order)
    , name_(_name)
  {}

  FunctionExpression(const std::string _variable,
                     const std::vector< std::string > _expressions,
                     const int _order = -1,
                     const std::string _name = id())
    : BaseType(_variable, _expressions)
    , order_(_order)
    , name_(_name)
  {}

  static Dune::ParameterTree createSampleDescription(const std::string subName = "")
  {
    Dune::ParameterTree description;
    description["variable"] = "x";
    description["expression"] = "[x[0]; sin(x[0])]";
    description["order"] = "1";
    description["name"] = "function.expression";
    if (subName.empty())
      return description;
    else {
      Dune::Stuff::Common::ExtendedParameterTree extendedDescription;
      extendedDescription.add(description, subName);
      return extendedDescription;
    }
  } // ... createSampleDescription(...)

  static ThisType* create(const DSC::ExtendedParameterTree description)
  {
    // get necessary
    const std::string _variable = description.get< std::string >("variable", "x");
    std::vector< std::string > _expressions;
    // lets see, if there is a key or vector
    if (description.hasVector("expression")) {
      const std::vector< std::string > expr = description.getVector< std::string >("expression", 1);
      for (size_t ii = 0; ii < expr.size(); ++ii)
        _expressions.push_back(expr[ii]);
    } else if (description.hasKey("expression")) {
      const std::string expr = description.get< std::string >("expression");
      _expressions.push_back(expr);
    } else
      DUNE_THROW(Dune::IOError,
                 "\n" << Dune::Stuff::Common::colorStringRed("ERROR:")
                 << " neither key nor vector 'expression' found in the following description:\n"
                 << description.reportString("  "));
    // get optional
    const int _order = description.get< int >("order", -1);
    const std::string _name = description.get< std::string >("name", "function.expression");
    // create and return
    return new ThisType(_variable, _expressions, _order, _name);
  } // ... create(...)

  virtual int order() const
  {
    return order_;
  }

  virtual std::string name() const
  {
    return name_;
  }

  virtual void evaluate(const DomainType& _x, RangeType& _ret) const
  {
    BaseType::evaluate(_x, _ret);
  }

private:
  int order_;
  std::string name_;
}; // class FunctionExpression

} // namespace Stuff
} // namespace Dune

#endif // DUNE_STUFF_FUNCTION_EXPRESSION_HH
<commit_msg>[function.expression] added localFunction<commit_after>#ifndef DUNE_STUFF_FUNCTION_EXPRESSION_HH
#define DUNE_STUFF_FUNCTION_EXPRESSION_HH

#include <sstream>
#include <vector>

#include <dune/common/fvector.hh>
#include <dune/common/exceptions.hh>

#include <dune/stuff/common/parameter/tree.hh>
#include <dune/stuff/common/string.hh>
#include <dune/stuff/common/color.hh>

#include "expression/base.hh"
#include "interface.hh"

namespace Dune {
namespace Stuff {

template< class DomainFieldImp, int domainDim, class RangeFieldImp, int rangeDim >
class FunctionExpression
  : public FunctionExpressionBase< DomainFieldImp, domainDim, RangeFieldImp, rangeDim >
  , public FunctionInterface< DomainFieldImp, domainDim, RangeFieldImp, rangeDim, 1 >
{
  typedef FunctionExpressionBase<  DomainFieldImp, domainDim, RangeFieldImp, rangeDim > BaseType;
  typedef FunctionInterface<  DomainFieldImp, domainDim, RangeFieldImp, rangeDim, 1 >   InterfaceType;
public:
  typedef FunctionExpression<  DomainFieldImp, domainDim, RangeFieldImp, rangeDim >     ThisType;

  typedef typename InterfaceType::DomainFieldType DomainFieldType;
  static const int                                dimDomain = InterfaceType::dimDomain;
  typedef typename InterfaceType::DomainType      DomainType;
  typedef typename InterfaceType::RangeFieldType  RangeFieldType;
  static const int                                dimRange = InterfaceType::dimRange;
  typedef typename InterfaceType::RangeType       RangeType;

  static const std::string id()
  {
    return InterfaceType::id() + ".expression";
  }

  FunctionExpression(const std::string _variable,
                     const std::string _expression,
                     const int _order = -1,
                     const std::string _name = id())
    : BaseType(_variable, _expression)
    , order_(_order)
    , name_(_name)
  {}

  FunctionExpression(const std::string _variable,
                     const std::vector< std::string > _expressions,
                     const int _order = -1,
                     const std::string _name = id())
    : BaseType(_variable, _expressions)
    , order_(_order)
    , name_(_name)
  {}

  static Dune::ParameterTree createSampleDescription(const std::string subName = "")
  {
    Dune::ParameterTree description;
    description["variable"] = "x";
    description["expression"] = "[x[0]; sin(x[0])]";
    description["order"] = "1";
    description["name"] = "function.expression";
    if (subName.empty())
      return description;
    else {
      Dune::Stuff::Common::ExtendedParameterTree extendedDescription;
      extendedDescription.add(description, subName);
      return extendedDescription;
    }
  } // ... createSampleDescription(...)

  static ThisType* create(const DSC::ExtendedParameterTree description)
  {
    // get necessary
    const std::string _variable = description.get< std::string >("variable", "x");
    std::vector< std::string > _expressions;
    // lets see, if there is a key or vector
    if (description.hasVector("expression")) {
      const std::vector< std::string > expr = description.getVector< std::string >("expression", 1);
      for (size_t ii = 0; ii < expr.size(); ++ii)
        _expressions.push_back(expr[ii]);
    } else if (description.hasKey("expression")) {
      const std::string expr = description.get< std::string >("expression");
      _expressions.push_back(expr);
    } else
      DUNE_THROW(Dune::IOError,
                 "\n" << Dune::Stuff::Common::colorStringRed("ERROR:")
                 << " neither key nor vector 'expression' found in the following description:\n"
                 << description.reportString("  "));
    // get optional
    const int _order = description.get< int >("order", -1);
    const std::string _name = description.get< std::string >("name", "function.expression");
    // create and return
    return new ThisType(_variable, _expressions, _order, _name);
  } // ... create(...)

  virtual int order() const
  {
    return order_;
  }

  virtual std::string name() const
  {
    return name_;
  }

  virtual void evaluate(const DomainType& _x, RangeType& _ret) const
  {
    BaseType::evaluate(_x, _ret);
  }

  using InterfaceType::localFunction;

private:
  int order_;
  std::string name_;
}; // class FunctionExpression

} // namespace Stuff
} // namespace Dune

#endif // DUNE_STUFF_FUNCTION_EXPRESSION_HH
<|endoftext|>


<commit_before>// This file is part of the dune-stuff project:
//   https://users.dune-project.org/projects/dune-stuff
// Copyright holders: Rene Milk, Felix Schindler
// License: BSD 2-Clause License (http://opensource.org/licenses/BSD-2-Clause)

#include "test_common.hh"

#include <unordered_map>
#include <dune/common/mpihelper.hh>
#include <dune/common/parametertreeparser.hh>

#include <dune/stuff/grid/provider/cube.hh>

#include <dune/stuff/functions/expression.hh>
#include <dune/stuff/common/profiler.hh>
#include <dune/stuff/common/ranges.hh>
#include <dune/stuff/functions/femadapter.hh>
#include <dune/stuff/functions/norm.hh>
#include <dune/stuff/functions/global.hh>
#include <dune/stuff/functions/pdelabadapter.hh>
#include <dune/stuff/fem/namespace.hh>
#include <dune/stuff/aliases.hh>

#if HAVE_DUNE_FEM
# include <dune/fem/gridpart/adaptiveleafgridpart.hh>
# include <dune/fem/function/adaptivefunction/adaptivefunction.hh>
# include <dune/fem/space/common/functionspace.hh>
# include <dune/fem/space/lagrange.hh>
# include <dune/fem/io/file/vtkio.hh>
# include <dune/fem/operator/lagrangeinterpolation.hh>
#endif // HAVE_DUNE_FEM

//#define HAVE_DUNE_PDELAB 1
#if HAVE_DUNE_PDELAB
# include <dune/pdelab/common/function.hh>
# include <dune/pdelab/gridfunctionspace/gridfunctionspace.hh>
# include <dune/pdelab/backend/istl/descriptors.hh>
# include <dune/pdelab/backend/istl/bcrsmatrixbackend.hh>
# include <dune/pdelab/finiteelementmap/qkfem.hh>
# include <dune/pdelab/backend/istlvectorbackend.hh>
# include <dune/pdelab/backend/backendselector.hh>
# include <dune/pdelab/constraints/conforming.hh>
# include <dune/pdelab/gridfunctionspace/interpolate.hh>
#endif
using namespace Dune;

static const int dim = 2;
typedef testing::Types< Dune::YaspGrid< dim >
#if HAVE_ALUGRID
  , Dune::ALUCubeGrid< dim, dim >
  , Dune::ALUConformGrid< dim, dim >
  , Dune::ALUSimplexGrid< dim, dim >
#endif
#if HAVE_ALBERTA
  , Dune::AlbertaGrid< dim, dim >
#endif
#if HAVE_UG
  , Dune::UGGrid< dim >
#endif
  , Dune::SGrid< dim, dim > > GridTypes;

typedef YaspGrid<dim> SourceGrid;
typedef std::unordered_map<std::string, double> ResultMap;

template <class Grid>
struct GTraits {
  typedef double FieldType;
  static constexpr int polynomial_order = 1;
  typedef DSG::Providers::Cube<Grid> GridProvider;
  typedef typename Grid::template Codim<0>::Entity Entity;
  typedef Stuff::GlobalConstantFunction<Entity, typename Grid::ctype,
      Grid::dimension, typename Grid::ctype, 1> ConstantFunction;
  typedef Stuff::Functions::Expression< Entity, typename Grid::ctype,
      Grid::dimension, typename Grid::ctype, 1 > ScalarFunction;
#if HAVE_DUNE_FEM
  typedef Dune::Fem::AdaptiveLeafGridPart<Grid> GridPart;
  typedef Dune::Fem::FunctionSpace<FieldType, FieldType, dim,1> ContFunctionSpace;
  typedef Dune::Fem::LagrangeDiscreteFunctionSpace<ContFunctionSpace, Dune::Fem::AdaptiveLeafGridPart<Grid>, polynomial_order> DiscreteSpace;
  typedef Fem::AdaptiveDiscreteFunction<DiscreteSpace> DiscreteFunction;
#endif
#if HAVE_DUNE_PDELAB
  typedef PDELab::QkLocalFiniteElementMap<typename Grid::LeafGridView, typename Grid::ctype,FieldType,polynomial_order>
  FEMap;
  typedef Dune::PDELab::ISTLVectorBackend<> VectorBackend;
  typedef Dune::PDELab::istl::BCRSMatrixBackend<> MatrixBackend;
  typedef PDELab::GridFunctionSpace<typename Grid::LeafGridView,FEMap,PDELab::ConformingDirichletConstraints,
            VectorBackend> GridFunctionSpace;
  typedef typename PDELab::BackendVectorSelector<GridFunctionSpace,FieldType>::Type PdelabVector;

#endif
};

template <class Grid>
std::shared_ptr<Grid> make_grid(const int macro_elements) {
  auto source_cube = typename GTraits<Grid>::GridProvider(0,1,macro_elements).grid();
  source_cube->globalRefine(2);
  return source_cube;
}

void output(const ResultMap& values) {
  for(auto pair : values) {
    DSC_LOG_INFO << (boost::format("%s\t%e\n") % pair.first % pair.second).str();
  }
}

template <class Grid>
void fem(const int macro_elements, ResultMap& values)
{
  typedef GTraits<Grid> Traits;

  auto grid = make_grid<Grid>(macro_elements);
  typename Traits::GridPart part(*grid);
  typename Traits::DiscreteSpace space(part);

  typename Traits::ScalarFunction linear_gradient("x", "x[0]");
  typename Traits::DiscreteFunction linear_gradient_df("", space);
  typename Traits::ConstantFunction constant_0(0);
  typename Traits::ConstantFunction constant_neg1(-1);
  typename Traits::DiscreteFunction constant_0_df("", space);
  typename Traits::DiscreteFunction constant_neg1_df("", space);

  Fem::LagrangeInterpolation<typename Traits::ScalarFunction,typename Traits::DiscreteFunction>
      ::apply(linear_gradient, linear_gradient_df);
  Fem::LagrangeInterpolation<typename Traits::ConstantFunction,typename Traits::DiscreteFunction>
      ::apply(constant_0, constant_0_df);
  Fem::LagrangeInterpolation<typename Traits::ConstantFunction,typename Traits::DiscreteFunction>
      ::apply(constant_neg1, constant_neg1_df);

  values["constant_0_l2"] = DS::l2norm(constant_0_df);
  values["constant_0_h1"] = DS::h1norm(constant_0_df);
  values["constant_neg1_l2"] = DS::l2norm(constant_neg1_df);
  values["constant_neg1_h1"] = DS::h1norm(constant_neg1_df);
}

template <class Grid>
void pdelab(const int macro_elements, ResultMap& values)
{
  typedef GTraits<Grid> Traits;

  auto grid = make_grid<Grid>(macro_elements);
  const auto& grid_view = grid->leafGridView();
  typename Traits::FEMap fe_map(grid_view);
  typename Traits::ScalarFunction linear_gradient_ltr("x", "x[0]", 1, "id", {{"1", "0"}});
  typename Traits::ScalarFunction linear_gradient_btt("x", "x[1]", 1, "id", {{"0", "1"}});
  typename Traits::GridFunctionSpace space(grid_view, fe_map);
  typename Traits::ConstantFunction constant_0(0);
  typename Traits::ConstantFunction constant_neg1(-1);
  typename Traits::PdelabVector constant_0_pde(space, 0.0);
  typename Traits::PdelabVector constant_neg1_pde(space, -1.0);
  typename Traits::PdelabVector linear_gradient_ltr_pde(space, 0.0);
  typename Traits::PdelabVector linear_gradient_btt_pde(space, 0.0);
  Dune::PDELab::interpolate(DS::pdelabAdapted(linear_gradient_ltr, grid_view), space, linear_gradient_ltr_pde);
  Dune::PDELab::interpolate(DS::pdelabAdapted(linear_gradient_btt, grid_view), space, linear_gradient_btt_pde);

  values["constant_0_l2_diff"] = DS::l2distance(constant_0, constant_0_pde);
  values["constant_0_h1_diff"] = DS::h1distance(constant_0, constant_0_pde);
  values["constant_neg1_l2_diff"] = DS::l2distance(constant_neg1, constant_neg1_pde);
  values["constant_neg1_h1_diff"] = DS::h1distance(constant_neg1, constant_neg1_pde);
  values["scalar_grad_ltr_l2_diff"] = DS::l2distance(linear_gradient_ltr, linear_gradient_ltr_pde);
  values["scalar_grad_ltr_h1_diff"] = DS::h1distance(linear_gradient_ltr, linear_gradient_ltr_pde);
  values["scalar_grad_ltr_to_0_l2_diff"] = DS::l2distance(constant_0, linear_gradient_ltr_pde);
  values["scalar_grad_ltr_to_0_h1_diff"] = DS::h1distance(constant_0, linear_gradient_ltr_pde);
  values["scalar_grad_btt_l2_diff"] = DS::l2distance(linear_gradient_btt, linear_gradient_btt_pde);
  values["scalar_grad_btt_h1_diff"] = DS::h1distance(linear_gradient_btt, linear_gradient_btt_pde);
  values["scalar_grad_btt_to_0_l2_diff"] = DS::l2distance(constant_0, linear_gradient_btt_pde);
  values["scalar_grad_btt_to_0_h1_diff"] = DS::h1distance(constant_0, linear_gradient_btt_pde);
}

TEST(Norm, All){
  const int runs = DSC_CONFIG_GET("runs", 1);
  DSC_PROFILER.reset(runs);
  for (auto i : DSC::valueRange(runs)) {
    const auto el = std::pow(8, i+1);
    ResultMap values;
#if HAVE_DUNE_FEM
    fem<SourceGrid>(el, values);
    DSC_LOG_INFO << "dune-fem results:\n";
    output(values);
#endif // HAVE_DUNE_FEM
#if HAVE_DUNE_PDELAB
    pdelab<SourceGrid>(el, values);
    DSC_LOG_INFO << "dune-pdelab results:\n";
    output(values);
#endif // HAVE_DUNE_PDELAB
    DSC_PROFILER.nextRun();
  }
  DSC_PROFILER.outputTimingsAll();
  DSC_LOG_INFO << std::endl;
}

int main(int argc, char** argv)
{
  test_init(argc, argv);
  return RUN_ALL_TESTS();
}

<commit_msg>[test.functions_norm] fixed some names and includes<commit_after>// This file is part of the dune-stuff project:
//   https://users.dune-project.org/projects/dune-stuff
// Copyright holders: Rene Milk, Felix Schindler
// License: BSD 2-Clause License (http://opensource.org/licenses/BSD-2-Clause)

#include "test_common.hh"

#include <unordered_map>
#include <dune/common/mpihelper.hh>
#include <dune/common/parametertreeparser.hh>

#include <dune/stuff/grid/provider/cube.hh>

#include <dune/stuff/functions/constant.hh>
#include <dune/stuff/functions/expression.hh>
#include <dune/stuff/common/profiler.hh>
#include <dune/stuff/common/ranges.hh>
#include <dune/stuff/playground/functions/femadapter.hh>
#include <dune/stuff/playground/functions/norm.hh>
#include <dune/stuff/playground/functions/pdelabadapter.hh>
#include <dune/stuff/aliases.hh>

#if HAVE_DUNE_FEM
# include <dune/fem/gridpart/adaptiveleafgridpart.hh>
# include <dune/fem/function/adaptivefunction/adaptivefunction.hh>
# include <dune/fem/space/common/functionspace.hh>
# include <dune/fem/space/lagrange.hh>
# include <dune/fem/io/file/vtkio.hh>
# include <dune/fem/operator/lagrangeinterpolation.hh>
#endif // HAVE_DUNE_FEM

#if HAVE_DUNE_PDELAB
# include <dune/pdelab/common/function.hh>
# include <dune/pdelab/gridfunctionspace/gridfunctionspace.hh>
# include <dune/pdelab/backend/istl/descriptors.hh>
# include <dune/pdelab/backend/istl/bcrsmatrixbackend.hh>
# include <dune/pdelab/finiteelementmap/qkfem.hh>
# include <dune/pdelab/backend/istlvectorbackend.hh>
# include <dune/pdelab/backend/backendselector.hh>
# include <dune/pdelab/constraints/conforming.hh>
# include <dune/pdelab/gridfunctionspace/interpolate.hh>
#endif
using namespace Dune;

static const int dim = 2;
typedef testing::Types< Dune::YaspGrid< dim >
#if HAVE_ALUGRID
  , Dune::ALUCubeGrid< dim, dim >
  , Dune::ALUConformGrid< dim, dim >
  , Dune::ALUSimplexGrid< dim, dim >
#endif
#if HAVE_ALBERTA
  , Dune::AlbertaGrid< dim, dim >
#endif
#if HAVE_UG
  , Dune::UGGrid< dim >
#endif
  , Dune::SGrid< dim, dim > > GridTypes;

typedef YaspGrid<dim> SourceGrid;
typedef std::unordered_map<std::string, double> ResultMap;

template <class Grid>
struct GTraits {
  typedef double FieldType;
  static constexpr int polynomial_order = 1;
  typedef DSG::Providers::Cube<Grid> GridProvider;
  typedef typename Grid::template Codim<0>::Entity Entity;
  typedef Stuff::Functions::Constant<Entity, typename Grid::ctype,
      Grid::dimension, typename Grid::ctype, 1> ConstantFunction;
  typedef Stuff::Functions::Expression< Entity, typename Grid::ctype,
      Grid::dimension, typename Grid::ctype, 1 > ScalarFunction;
#if HAVE_DUNE_FEM
  typedef Dune::Fem::AdaptiveLeafGridPart<Grid> GridPart;
  typedef Dune::Fem::FunctionSpace<FieldType, FieldType, dim,1> ContFunctionSpace;
  typedef Dune::Fem::LagrangeDiscreteFunctionSpace<ContFunctionSpace, Dune::Fem::AdaptiveLeafGridPart<Grid>, polynomial_order> DiscreteSpace;
  typedef Fem::AdaptiveDiscreteFunction<DiscreteSpace> DiscreteFunction;
#endif
#if HAVE_DUNE_PDELAB
  typedef PDELab::QkLocalFiniteElementMap<typename Grid::LeafGridView, typename Grid::ctype,FieldType,polynomial_order>
  FEMap;
  typedef Dune::PDELab::ISTLVectorBackend<> VectorBackend;
  typedef Dune::PDELab::istl::BCRSMatrixBackend<> MatrixBackend;
  typedef PDELab::GridFunctionSpace<typename Grid::LeafGridView,FEMap,PDELab::ConformingDirichletConstraints,
            VectorBackend> GridFunctionSpace;
  typedef typename PDELab::BackendVectorSelector<GridFunctionSpace,FieldType>::Type PdelabVector;

#endif
};

template <class Grid>
std::shared_ptr<Grid> make_grid(const int macro_elements) {
  auto source_cube = typename GTraits<Grid>::GridProvider(0,1,macro_elements).grid();
  source_cube->globalRefine(2);
  return source_cube;
}

void output(const ResultMap& values) {
  for(auto pair : values) {
    DSC_LOG_INFO << (boost::format("%s\t%e\n") % pair.first % pair.second).str();
  }
}

template <class Grid>
void fem(const int macro_elements, ResultMap& values)
{
  typedef GTraits<Grid> Traits;

  auto grid = make_grid<Grid>(macro_elements);
  typename Traits::GridPart part(*grid);
  typename Traits::DiscreteSpace space(part);

  typename Traits::ScalarFunction linear_gradient("x", "x[0]");
  typename Traits::DiscreteFunction linear_gradient_df("", space);
  typename Traits::ConstantFunction constant_0(0);
  typename Traits::ConstantFunction constant_neg1(-1);
  typename Traits::DiscreteFunction constant_0_df("", space);
  typename Traits::DiscreteFunction constant_neg1_df("", space);

  Fem::LagrangeInterpolation<typename Traits::ScalarFunction,typename Traits::DiscreteFunction>
      ::apply(linear_gradient, linear_gradient_df);
  Fem::LagrangeInterpolation<typename Traits::ConstantFunction,typename Traits::DiscreteFunction>
      ::apply(constant_0, constant_0_df);
  Fem::LagrangeInterpolation<typename Traits::ConstantFunction,typename Traits::DiscreteFunction>
      ::apply(constant_neg1, constant_neg1_df);

  values["constant_0_l2"] = DS::l2norm(constant_0_df);
  values["constant_0_h1"] = DS::h1norm(constant_0_df);
  values["constant_neg1_l2"] = DS::l2norm(constant_neg1_df);
  values["constant_neg1_h1"] = DS::h1norm(constant_neg1_df);
}

template <class Grid>
void pdelab(const int macro_elements, ResultMap& values)
{
  typedef GTraits<Grid> Traits;

  auto grid = make_grid<Grid>(macro_elements);
  const auto& grid_view = grid->leafGridView();
  typename Traits::FEMap fe_map(grid_view);
  typename Traits::ScalarFunction linear_gradient_ltr("x", "x[0]", 1, "id", {{"1", "0"}});
  typename Traits::ScalarFunction linear_gradient_btt("x", "x[1]", 1, "id", {{"0", "1"}});
  typename Traits::GridFunctionSpace space(grid_view, fe_map);
  typename Traits::ConstantFunction constant_0(0);
  typename Traits::ConstantFunction constant_neg1(-1);
  typename Traits::PdelabVector constant_0_pde(space, 0.0);
  typename Traits::PdelabVector constant_neg1_pde(space, -1.0);
  typename Traits::PdelabVector linear_gradient_ltr_pde(space, 0.0);
  typename Traits::PdelabVector linear_gradient_btt_pde(space, 0.0);
  Dune::PDELab::interpolate(DS::pdelabAdapted(linear_gradient_ltr, grid_view), space, linear_gradient_ltr_pde);
  Dune::PDELab::interpolate(DS::pdelabAdapted(linear_gradient_btt, grid_view), space, linear_gradient_btt_pde);

  values["constant_0_l2_diff"] = DS::l2distance(constant_0, constant_0_pde);
  values["constant_0_h1_diff"] = DS::h1distance(constant_0, constant_0_pde);
  values["constant_neg1_l2_diff"] = DS::l2distance(constant_neg1, constant_neg1_pde);
  values["constant_neg1_h1_diff"] = DS::h1distance(constant_neg1, constant_neg1_pde);
  values["scalar_grad_ltr_l2_diff"] = DS::l2distance(linear_gradient_ltr, linear_gradient_ltr_pde);
  values["scalar_grad_ltr_h1_diff"] = DS::h1distance(linear_gradient_ltr, linear_gradient_ltr_pde);
  values["scalar_grad_ltr_to_0_l2_diff"] = DS::l2distance(constant_0, linear_gradient_ltr_pde);
  values["scalar_grad_ltr_to_0_h1_diff"] = DS::h1distance(constant_0, linear_gradient_ltr_pde);
  values["scalar_grad_btt_l2_diff"] = DS::l2distance(linear_gradient_btt, linear_gradient_btt_pde);
  values["scalar_grad_btt_h1_diff"] = DS::h1distance(linear_gradient_btt, linear_gradient_btt_pde);
  values["scalar_grad_btt_to_0_l2_diff"] = DS::l2distance(constant_0, linear_gradient_btt_pde);
  values["scalar_grad_btt_to_0_h1_diff"] = DS::h1distance(constant_0, linear_gradient_btt_pde);
}

TEST(Norm, All){
  const int runs = DSC_CONFIG_GET("runs", 1);
  DSC_PROFILER.reset(runs);
  for (auto i : DSC::valueRange(runs)) {
    const auto el = std::pow(8, i+1);
    ResultMap values;
#if HAVE_DUNE_FEM
    fem<SourceGrid>(el, values);
    DSC_LOG_INFO << "dune-fem results:\n";
    output(values);
#endif // HAVE_DUNE_FEM
#if HAVE_DUNE_PDELAB
    pdelab<SourceGrid>(el, values);
    DSC_LOG_INFO << "dune-pdelab results:\n";
    output(values);
#endif // HAVE_DUNE_PDELAB
    DSC_PROFILER.nextRun();
  }
  DSC_PROFILER.outputTimingsAll();
  DSC_LOG_INFO << std::endl;
}

int main(int argc, char** argv)
{
  test_init(argc, argv);
  return RUN_ALL_TESTS();
}

<|endoftext|>