From 5f6fa1288614dcb4af8f2c6f3ab08f1ee8982bea Mon Sep 17 00:00:00 2001
From: theazgra <theazgra@gmail.com>
Date: Mon, 25 Mar 2019 14:07:03 +0100
Subject: [PATCH] Implemented second mapped method.

---
 .../app/src/compression/benchmark.cpp         |   4 +-
 .../include/azgra/utilities/type_mapper.h     | 130 +++++++++++++++++-
 2 files changed, 125 insertions(+), 9 deletions(-)

diff --git a/czi/source_code/app/src/compression/benchmark.cpp b/czi/source_code/app/src/compression/benchmark.cpp
index c591a1c..2d74179 100644
--- a/czi/source_code/app/src/compression/benchmark.cpp
+++ b/czi/source_code/app/src/compression/benchmark.cpp
@@ -279,7 +279,7 @@ void _diff_from_frame_gray16(const ByteArray &pfData, const ByteArray &cfData,
     ByteArray ushortMappedDeltaBytes;
 
     {
-        TypeMapper<int, ushort> typeMapper;
+        TypeMapper<int, ushort, MappingType_NegativeAfterPositive> typeMapper;
         std::vector<ushort> ushortMappedDelta = typeMapper.map(delta);
         ushortMappedDeltaBytes = ushort_array_to_bytes(ushortMappedDelta);
     }
@@ -314,7 +314,7 @@ void _diff_from_frame_gray16_va_bit_count(const ByteArray &pfData, const ByteArr
     ByteArray diffBytes;
     size_t requiredSize;
     {
-        TypeMapper<int, ushort> typeMapper;
+        TypeMapper<int, ushort, MappingType_NegativeAfterPositive> typeMapper;
         std::vector<ushort> ushortMappedDelta = typeMapper.map(delta);
 
         ushort ushortMappedDeltaMax = vecUtil::find_max(ushortMappedDelta);
diff --git a/czi/source_code/azgra_lib/include/azgra/utilities/type_mapper.h b/czi/source_code/azgra_lib/include/azgra/utilities/type_mapper.h
index be2afa6..454c77f 100644
--- a/czi/source_code/azgra_lib/include/azgra/utilities/type_mapper.h
+++ b/czi/source_code/azgra_lib/include/azgra/utilities/type_mapper.h
@@ -5,15 +5,37 @@
 namespace azgra
 {
 
-// Provide mapping utilites from signed types to big enaugh unsigned types.
-template <typename SourceType, typename TargetType>
+enum MappingType
+{
+    // Negative values are stored after positive values.
+    MappingType_NegativeAfterPositive,
+    // Negative values are stored at even places, while positive at odd.
+    MappingType_NegativeToEven
+};
+
+/**
+ * @brief Provide mapping utilites from signed types to unsigned types.
+ * 
+ * @tparam SourceType Signed type to map.
+ * @tparam TargetType Unsigned result type.
+ */
+template <typename SourceType, typename TargetType, MappingType MappingMethod>
 class TypeMapper
 {
   private:
-  public:
-    // Map `SourceType` vector to `TargetType` vector. Saving mapping point as first element.
-    std::vector<TargetType> map(std::vector<SourceType> &data)
+    MappingType _mappingType = MappingMethod;
+
+    /**
+     * @brief Map `SourceType` vector to `TargetType` vector. Saving mapping point as first element. 
+     * Negative values are stored after the maximum positive value.
+     * 
+     * @param data Data to map.
+     * @return std::vector<TargetType> Mapped data.
+     */
+    std::vector<TargetType> map_negative_after_positive(const std::vector<SourceType> &data)
     {
+        always_assert(_mappingType == MappingType_NegativeAfterPositive);
+
         auto limits = vecUtil::find_min_max(data);
         SourceType min = limits.min;
         SourceType max = limits.max;
@@ -45,9 +67,16 @@ class TypeMapper
         return result;
     }
 
-    // Map back `TargetType` vector to `SourceType` vector.
-    std::vector<SourceType> map_back(std::vector<TargetType> &data)
+    /**
+     * @brief Map back `TargetType` vector to `SourceType` vector.
+     * 
+     * @param data Data to map back.
+     * @return std::vector<SourceType> Original unrolled data.
+     */
+    std::vector<SourceType> map_back_negative_after_positive(const std::vector<TargetType> &data)
     {
+        always_assert(_mappingType == MappingType_NegativeAfterPositive);
+
         std::vector<SourceType> result;
         result.resize(data.size() - 1);
 
@@ -69,5 +98,92 @@ class TypeMapper
         }
         return result;
     }
+
+    std::vector<TargetType> map_negative_to_even(const std::vector<SourceType> &data)
+    {
+        auto limits = vecUtil::find_min_max(data);
+        TargetType ttMax = std::numeric_limits<TargetType>::max();
+
+        always_assert((((limits.max * 2) - 1) <= ttMax) &&
+                      ((2 * std::abs(limits.min)) <= ttMax));
+
+        std::vector<TargetType> result;
+        result.resize(data.size());
+        /*
+        -7  -6  -5  -4  -3  -2  -1  0   1   2   3   4   5   6   7
+        14  12  10   8   6   4   2  0   1   3   5   7   9   11  13
+        */
+        for (size_t i = 0; i < data.size(); i++)
+        {
+            if (data[i] == 0)
+            {
+                result[i] = 0;
+            }
+            else if (data[i] < 0)
+            {
+                result[i] = 2 * std::abs(data[i]);
+            }
+            else // data[i] > 0
+            {
+                result[i] = (2 * data[i]) - 1;
+            }
+        }
+        return result;
+    }
+
+    std::vector<SourceType> map_back_negative_to_even(const std::vector<TargetType> &data)
+    {
+        std::vector<SourceType> result;
+        result.resize(data.size());
+
+        /*
+        14  12  10   8   6   4   2  0   1   3   5   7   9   11  13
+        -7  -6  -5  -4  -3  -2  -1  0   1   2   3   4   5   6   7
+        */
+        for (size_t i = 0; i < data.size(); i++)
+        {
+            if (data[i] == 0)
+            {
+                result[i] = 0;
+            }
+            else if (data[i] % 2 == 0)
+            {
+                result[i] = -(data[i] / 2);
+            }
+            else // data[i] % 2 != 0
+            {
+                result[i] = (data[i] / 2) + 1;
+            }
+        }
+        return result;
+    }
+
+  public:
+    std::vector<TargetType> map(const std::vector<SourceType> &data)
+    {
+        switch (_mappingType)
+        {
+        case MappingType_NegativeAfterPositive:
+            return map_negative_after_positive(data);
+        case MappingType_NegativeToEven:
+            return map_negative_to_even(data);
+        default:
+            INVALID_CASE;
+            return std::vector<TargetType>();
+        }
+    }
+    std::vector<SourceType> map_back(const std::vector<TargetType> &data)
+    {
+        switch (_mappingType)
+        {
+        case MappingType_NegativeAfterPositive:
+            return map_back_negative_after_positive(data);
+        case MappingType_NegativeToEven:
+            return map_back_negative_to_even(data);
+        default:
+            INVALID_CASE;
+            return std::vector<SourceType>();
+        }
+    }
 };
 } // namespace azgra
\ No newline at end of file
-- 
GitLab