pitrou commented on code in PR #43957:
URL: https://github.com/apache/arrow/pull/43957#discussion_r1766813001


##########
cpp/src/arrow/util/decimal_test.cc:
##########
@@ -1230,65 +1275,72 @@ TYPED_TEST(TestDecimalToRealDouble, LargeValues) {
 }
 
 TYPED_TEST(TestDecimalToRealDouble, Precision) {
-  // 2**63 + 2**11 (exactly representable in a double's 53 bits of precision)
-  CheckDecimalToReal<TypeParam, double>("9223372036854777856", 0, 
9.223372036854778e+18);
-  CheckDecimalToReal<TypeParam, double>("-9223372036854777856", 0,
-                                        -9.223372036854778e+18);
-  // 2**64 - 2**11 (exactly representable in a double)
-  CheckDecimalToReal<TypeParam, double>("18446744073709549568", 0, 
1.844674407370955e+19);
-  CheckDecimalToReal<TypeParam, double>("-18446744073709549568", 0,
-                                        -1.844674407370955e+19);
-  // 2**64 + 2**11 (exactly representable in a double)
-  CheckDecimalToReal<TypeParam, double>("18446744073709555712", 0,
-                                        1.8446744073709556e+19);
-  CheckDecimalToReal<TypeParam, double>("-18446744073709555712", 0,
-                                        -1.8446744073709556e+19);
-  // Almost 10**38 (minus 2**73)
-  CheckDecimalToReal<TypeParam, 
double>("99999999999999978859343891977453174784", 0,
-                                        9.999999999999998e+37);
-  CheckDecimalToReal<TypeParam, 
double>("-99999999999999978859343891977453174784", 0,
-                                        -9.999999999999998e+37);
-  CheckDecimalToReal<TypeParam, 
double>("99999999999999978859343891977453174784", 10,
-                                        9.999999999999998e+27);
-  CheckDecimalToReal<TypeParam, 
double>("-99999999999999978859343891977453174784", 10,
-                                        -9.999999999999998e+27);
-  CheckDecimalToReal<TypeParam, 
double>("99999999999999978859343891977453174784", -10,
-                                        9.999999999999998e+47);
-  CheckDecimalToReal<TypeParam, 
double>("-99999999999999978859343891977453174784", -10,
-                                        -9.999999999999998e+47);
+  if constexpr (TypeParam::kMaxPrecision >= 19) {
+    // 2**63 + 2**11 (exactly representable in a double's 53 bits of precision)
+    CheckDecimalToReal<TypeParam, double>("9223372036854777856", 0,
+                                          9.223372036854778e+18);
+    CheckDecimalToReal<TypeParam, double>("-9223372036854777856", 0,
+                                          -9.223372036854778e+18);
+    // 2**64 - 2**11 (exactly representable in a double)
+    CheckDecimalToReal<TypeParam, double>("18446744073709549568", 0,
+                                          1.844674407370955e+19);
+    CheckDecimalToReal<TypeParam, double>("-18446744073709549568", 0,
+                                          -1.844674407370955e+19);
+    // 2**64 + 2**11 (exactly representable in a double)
+    CheckDecimalToReal<TypeParam, double>("18446744073709555712", 0,
+                                          1.8446744073709556e+19);
+    CheckDecimalToReal<TypeParam, double>("-18446744073709555712", 0,
+                                          -1.8446744073709556e+19);
+
+    // Almost 10**38 (minus 2**73)
+    CheckDecimalToReal<TypeParam, 
double>("99999999999999978859343891977453174784", 0,
+                                          9.999999999999998e+37);
+    CheckDecimalToReal<TypeParam, 
double>("-99999999999999978859343891977453174784", 0,
+                                          -9.999999999999998e+37);
+    CheckDecimalToReal<TypeParam, 
double>("99999999999999978859343891977453174784", 10,
+                                          9.999999999999998e+27);
+    CheckDecimalToReal<TypeParam, 
double>("-99999999999999978859343891977453174784", 10,
+                                          -9.999999999999998e+27);
+    CheckDecimalToReal<TypeParam, 
double>("99999999999999978859343891977453174784", -10,
+                                          9.999999999999998e+47);
+    CheckDecimalToReal<TypeParam, 
double>("-99999999999999978859343891977453174784", -10,
+                                          -9.999999999999998e+47);
+  }
   // Integers are always exact
   auto scale = TypeParam::kMaxScale - 1;
   std::string seven = "7.";
   seven.append(scale, '0');
   CheckDecimalToReal<TypeParam, double>(seven, scale, 7.0);
   CheckDecimalToReal<TypeParam, double>("-" + seven, scale, -7.0);
-
-  CheckDecimalToReal<TypeParam, 
double>("99999999999999999999.0000000000000000", 16,
-                                        99999999999999999999.0);
-  CheckDecimalToReal<TypeParam, 
double>("-99999999999999999999.0000000000000000", 16,
-                                        -99999999999999999999.0);
+  if constexpr (TypeParam::kMaxPrecision >= 20) {
+    CheckDecimalToReal<TypeParam, 
double>("99999999999999999999.0000000000000000", 16,
+                                          99999999999999999999.0);
+    CheckDecimalToReal<TypeParam, 
double>("-99999999999999999999.0000000000000000", 16,
+                                          -99999999999999999999.0);
+  }
 
   // Small fractions are within one ULP
   CheckDecimalToRealWithinOneULP<TypeParam, double>("9999999.9", 1, 9999999.9);
   CheckDecimalToRealWithinOneULP<TypeParam, double>("-9999999.9", 1, 
-9999999.9);
-  CheckDecimalToRealWithinOneULP<TypeParam, double>("9999999.999999999999999", 
15,
-                                                    9999999.999999999999999);
-  CheckDecimalToRealWithinOneULP<TypeParam, 
double>("-9999999.999999999999999", 15,
-                                                    -9999999.999999999999999);
-
-  // Large fractions are within 2^-52
-  constexpr double epsilon = 2.220446049250313080847263336181640625e-16;  // 
2^-52
-  CheckDecimalToRealWithinEpsilon<TypeParam, double>(
-      "112334829348925.99070703983306884765625", 23, epsilon,
-      112334829348925.99070703983306884765625);
-  CheckDecimalToRealWithinEpsilon<TypeParam, double>(
-      "1.987748987892758765582589910934859345", 36, epsilon,
-      1.987748987892758765582589910934859345);
+  if constexpr (TypeParam::kMaxPrecision >= 23) {
+    CheckDecimalToRealWithinOneULP<TypeParam, 
double>("9999999.999999999999999", 15,
+                                                      9999999.999999999999999);
+    CheckDecimalToRealWithinOneULP<TypeParam, 
double>("-9999999.999999999999999", 15,
+                                                      
-9999999.999999999999999);
+    // Large fractions are within 2^-52
+    constexpr double epsilon = 2.220446049250313080847263336181640625e-16;  // 
2^-52
+    CheckDecimalToRealWithinEpsilon<TypeParam, double>(
+        "112334829348925.99070703983306884765625", 23, epsilon,
+        112334829348925.99070703983306884765625);
+    CheckDecimalToRealWithinEpsilon<TypeParam, double>(
+        "1.987748987892758765582589910934859345", 36, epsilon,
+        1.987748987892758765582589910934859345);
+  }
 }
 
 #endif  // __MINGW32__
 
-TEST(Decimal128Test, TestFromBigEndian) {
+TEST(Decimal32Test, TestFromBigEndian) {

Review Comment:
   It seems a number of tests are mostly or exactly identical between the 
Decimal tests, perhaps you can write a generic version and call it for each 
concrete test type?



##########
cpp/src/arrow/util/decimal_test.cc:
##########
@@ -125,7 +137,7 @@ class DecimalFromStringTest : public ::testing::Test {
           "00a", "1e1a", "0.00123D/3", "1.23eA8", "1.23E+3A", "-1.23E--5",
           "1.2345E+++07"}) {
       ARROW_SCOPED_TRACE("invalid_value = '", invalid_value, "'");
-      ASSERT_RAISES(Invalid, Decimal128::FromString(invalid_value));
+      ASSERT_RAISES(Invalid, DecimalType::FromString(invalid_value));

Review Comment:
   :+1: 



##########
cpp/src/arrow/util/decimal_test.cc:
##########
@@ -1389,6 +1435,838 @@ std::vector<CType> GetRandomNumbers(int32_t size) {
   return ret;
 }
 
+TEST(Decimal32Test, Multiply) {
+  ASSERT_EQ(Decimal32(60501), Decimal32(301) * Decimal32(201));
+
+  ASSERT_EQ(Decimal32(-60501), Decimal32(-301) * Decimal32(201));
+
+  ASSERT_EQ(Decimal32(-60501), Decimal32(301) * Decimal32(-201));
+
+  ASSERT_EQ(Decimal32(60501), Decimal32(-301) * Decimal32(-201));
+
+  // Test some random numbers.
+  for (auto x : GetRandomNumbers<Int32Type>(16)) {
+    for (auto y : GetRandomNumbers<Int32Type>(16)) {
+      Decimal32 result = Decimal32(x) * Decimal32(y);
+      ASSERT_EQ(Decimal32(static_cast<int64_t>(x) * y), result)
+          << " x: " << x << " y: " << y;
+    }
+  }
+}
+
+TEST(Decimal32Test, Divide) {
+  ASSERT_EQ(Decimal32(66), Decimal32(20100) / Decimal32(301));
+
+  ASSERT_EQ(Decimal32(-66), Decimal32(-20100) / Decimal32(301));
+
+  ASSERT_EQ(Decimal32(-66), Decimal32(20100) / Decimal32(-301));
+
+  ASSERT_EQ(Decimal32(66), Decimal32(-20100) / Decimal32(-301));
+
+  // Test some random numbers.
+  for (auto x : GetRandomNumbers<Int32Type>(16)) {
+    for (auto y : GetRandomNumbers<Int32Type>(16)) {
+      if (y == 0) {
+        continue;
+      }
+
+      Decimal32 result = Decimal32(x) / Decimal32(y);
+      ASSERT_EQ(Decimal32(static_cast<int64_t>(x) / y), result)
+          << " x: " << x << " y: " << y;
+    }
+  }
+}
+
+TEST(Decimal32Test, Rescale) {
+  ASSERT_OK_AND_EQ(Decimal32(11100), Decimal32(111).Rescale(0, 2));
+  ASSERT_OK_AND_EQ(Decimal32(111), Decimal32(11100).Rescale(2, 0));
+  ASSERT_OK_AND_EQ(Decimal32(5), Decimal32(500000).Rescale(6, 1));
+  ASSERT_OK_AND_EQ(Decimal32(500000), Decimal32(5).Rescale(1, 6));
+  ASSERT_RAISES(Invalid, Decimal32(555555).Rescale(6, 1));
+
+  // Test some random numbers.
+  for (auto original_scale : GetRandomNumbers<Int8Type>(16)) {
+    for (auto value : GetRandomNumbers<Int16Type>(16)) {
+      Decimal32 unscaled_value = Decimal32(value);
+      Decimal32 scaled_value = unscaled_value;
+      for (int32_t new_scale = original_scale; new_scale < original_scale + 4;
+           new_scale++, scaled_value *= Decimal32(10)) {
+        ASSERT_OK_AND_EQ(scaled_value, unscaled_value.Rescale(original_scale, 
new_scale));
+        ASSERT_OK_AND_EQ(unscaled_value, scaled_value.Rescale(new_scale, 
original_scale));
+      }
+    }
+  }
+
+  for (auto original_scale : GetRandomNumbers<Int16Type>(16)) {
+    Decimal32 value(1);
+    for (int32_t new_scale = original_scale; new_scale < original_scale + 8;
+         new_scale++, value *= Decimal32(10)) {
+      Decimal32 negative_value = value * -1;
+      ASSERT_OK_AND_EQ(value, Decimal32(1).Rescale(original_scale, new_scale));
+      ASSERT_OK_AND_EQ(negative_value, Decimal32(-1).Rescale(original_scale, 
new_scale));
+      ASSERT_OK_AND_EQ(Decimal32(1), value.Rescale(new_scale, original_scale));
+      ASSERT_OK_AND_EQ(Decimal32(-1), negative_value.Rescale(new_scale, 
original_scale));
+    }
+  }
+}
+
+TEST(Decimal32Test, Mod) {
+  ASSERT_EQ(Decimal32(234), Decimal32(20100) % Decimal32(301));
+
+  ASSERT_EQ(Decimal32(-234), Decimal32(-20100) % Decimal32(301));
+
+  ASSERT_EQ(Decimal32(234), Decimal32(20100) % Decimal32(-301));
+
+  ASSERT_EQ(Decimal32(-234), Decimal32(-20100) % Decimal32(-301));
+
+  // Test some random numbers.
+  for (auto x : GetRandomNumbers<Int32Type>(16)) {
+    for (auto y : GetRandomNumbers<Int32Type>(16)) {
+      if (y == 0) {
+        continue;
+      }
+
+      Decimal32 result = Decimal32(x) % Decimal32(y);
+      ASSERT_EQ(Decimal32(static_cast<int64_t>(x) % y), result)
+          << " x: " << x << " y: " << y;
+    }
+  }
+}
+
+TEST(Decimal32Test, Sign) {
+  ASSERT_EQ(1, Decimal32(999999).Sign());
+  ASSERT_EQ(-1, Decimal32(-999999).Sign());
+  ASSERT_EQ(1, Decimal32(0).Sign());
+}
+
+TEST(Decimal32Test, GetWholeAndFraction) {
+  Decimal32 value("123456");
+  Decimal32 whole;
+  Decimal32 fraction;
+  int32_t out;
+
+  value.GetWholeAndFraction(0, &whole, &fraction);
+  ASSERT_OK(whole.ToInteger(&out));
+  ASSERT_EQ(123456, out);
+  ASSERT_OK(fraction.ToInteger(&out));
+  ASSERT_EQ(0, out);
+
+  value.GetWholeAndFraction(1, &whole, &fraction);
+  ASSERT_OK(whole.ToInteger(&out));
+  ASSERT_EQ(12345, out);
+  ASSERT_OK(fraction.ToInteger(&out));
+  ASSERT_EQ(6, out);
+
+  value.GetWholeAndFraction(5, &whole, &fraction);
+  ASSERT_OK(whole.ToInteger(&out));
+  ASSERT_EQ(1, out);
+  ASSERT_OK(fraction.ToInteger(&out));
+  ASSERT_EQ(23456, out);
+
+  value.GetWholeAndFraction(7, &whole, &fraction);
+  ASSERT_OK(whole.ToInteger(&out));
+  ASSERT_EQ(0, out);
+  ASSERT_OK(fraction.ToInteger(&out));
+  ASSERT_EQ(123456, out);
+}
+
+TEST(Decimal32Test, GetWholeAndFractionNegative) {
+  Decimal32 value("-123456");
+  Decimal32 whole;
+  Decimal32 fraction;
+  int32_t out;
+
+  value.GetWholeAndFraction(0, &whole, &fraction);
+  ASSERT_OK(whole.ToInteger(&out));
+  ASSERT_EQ(-123456, out);
+  ASSERT_OK(fraction.ToInteger(&out));
+  ASSERT_EQ(0, out);
+
+  value.GetWholeAndFraction(1, &whole, &fraction);
+  ASSERT_OK(whole.ToInteger(&out));
+  ASSERT_EQ(-12345, out);
+  ASSERT_OK(fraction.ToInteger(&out));
+  ASSERT_EQ(-6, out);
+
+  value.GetWholeAndFraction(5, &whole, &fraction);
+  ASSERT_OK(whole.ToInteger(&out));
+  ASSERT_EQ(-1, out);
+  ASSERT_OK(fraction.ToInteger(&out));
+  ASSERT_EQ(-23456, out);
+
+  value.GetWholeAndFraction(7, &whole, &fraction);
+  ASSERT_OK(whole.ToInteger(&out));
+  ASSERT_EQ(0, out);
+  ASSERT_OK(fraction.ToInteger(&out));
+  ASSERT_EQ(-123456, out);
+}
+
+TEST(Decimal32Test, IncreaseScale) {
+  Decimal32 result;
+  int32_t out;
+
+  result = Decimal32("1234").IncreaseScaleBy(0);

Review Comment:
   Same here and below: create helper functions to make these tests more 
concise and readable.



##########
cpp/src/arrow/util/decimal.cc:
##########
@@ -109,6 +110,11 @@ struct DecimalRealConversion : public 
BaseDecimalRealConversion {
       return OverflowError(real, precision, scale);
     }
 
+    if constexpr (std::is_base_of_v<BasicDecimal32, DecimalType> &&
+                  std::is_same_v<Real, double>) {
+      return DecimalType::FromReal(static_cast<float>(real), precision, scale);

Review Comment:
   I think what happens is that the algorithm below assumes the destination 
Decimal has more mantissa bits than the source Real. This is false for the 
double->Decimal64 conversion. I think what we should do in that case is simply 
fall back to `FromPositiveRealApprox`.
   
   Something like (untested :-)):
   ```c++
       if constexpr (kMaxPrecision <= kMantissaDigits) {
         return Derived::FromPositiveRealApprox(real, precision, scale);
       }
   ```



##########
cpp/src/arrow/util/decimal_test.cc:
##########
@@ -1170,40 +1206,49 @@ TYPED_TEST(TestDecimalToRealFloat, LargeValues) {
 }
 
 TYPED_TEST(TestDecimalToRealFloat, Precision) {

Review Comment:
   Should also expand the parametrization of `TestDecimalToReal` above?



##########
cpp/src/arrow/util/decimal.cc:
##########
@@ -109,6 +110,11 @@ struct DecimalRealConversion : public 
BaseDecimalRealConversion {
       return OverflowError(real, precision, scale);
     }
 
+    if constexpr (std::is_base_of_v<BasicDecimal32, DecimalType> &&
+                  std::is_same_v<Real, double>) {
+      return DecimalType::FromReal(static_cast<float>(real), precision, scale);

Review Comment:
   This is lowering the mantissa's precision to 24 bits even though Decimal32 
has 32 bits of precision, is it right?



##########
cpp/src/arrow/util/decimal_test.cc:
##########
@@ -896,22 +917,30 @@ TYPED_TEST_SUITE(TestDecimalFromRealFloat, DecimalTypes);
 
 TYPED_TEST(TestDecimalFromRealFloat, SuccessConversion) {

Review Comment:
   I think we'd like to expand the parametrization for `TestDecimalFromReal` 
above as well.



##########
cpp/src/arrow/util/decimal.cc:
##########
@@ -156,7 +162,9 @@ struct DecimalRealConversion : public 
BaseDecimalRealConversion {
         // NOTE: if `precision` is the full precision then the algorithm will
         // lose the last digit. If `precision` is almost the full precision,
         // there can be an off-by-one error due to rounding.
-        const int mul_step = std::max(1, kMaxPrecision - precision);
+        constexpr int is_dec32_or_dec64 =
+            DecimalType::kByteWidth <= BasicDecimal64::kByteWidth;
+        const int mul_step = std::max(1, kMaxPrecision - precision - 
is_dec32_or_dec64);

Review Comment:
   Hmm, why?



##########
cpp/src/arrow/util/decimal_test.cc:
##########
@@ -1389,6 +1435,838 @@ std::vector<CType> GetRandomNumbers(int32_t size) {
   return ret;
 }
 
+TEST(Decimal32Test, Multiply) {
+  ASSERT_EQ(Decimal32(60501), Decimal32(301) * Decimal32(201));
+
+  ASSERT_EQ(Decimal32(-60501), Decimal32(-301) * Decimal32(201));
+
+  ASSERT_EQ(Decimal32(-60501), Decimal32(301) * Decimal32(-201));
+
+  ASSERT_EQ(Decimal32(60501), Decimal32(-301) * Decimal32(-201));
+
+  // Test some random numbers.
+  for (auto x : GetRandomNumbers<Int32Type>(16)) {
+    for (auto y : GetRandomNumbers<Int32Type>(16)) {
+      Decimal32 result = Decimal32(x) * Decimal32(y);
+      ASSERT_EQ(Decimal32(static_cast<int64_t>(x) * y), result)
+          << " x: " << x << " y: " << y;
+    }
+  }
+}
+
+TEST(Decimal32Test, Divide) {
+  ASSERT_EQ(Decimal32(66), Decimal32(20100) / Decimal32(301));
+
+  ASSERT_EQ(Decimal32(-66), Decimal32(-20100) / Decimal32(301));
+
+  ASSERT_EQ(Decimal32(-66), Decimal32(20100) / Decimal32(-301));
+
+  ASSERT_EQ(Decimal32(66), Decimal32(-20100) / Decimal32(-301));
+
+  // Test some random numbers.
+  for (auto x : GetRandomNumbers<Int32Type>(16)) {
+    for (auto y : GetRandomNumbers<Int32Type>(16)) {
+      if (y == 0) {
+        continue;
+      }
+
+      Decimal32 result = Decimal32(x) / Decimal32(y);
+      ASSERT_EQ(Decimal32(static_cast<int64_t>(x) / y), result)
+          << " x: " << x << " y: " << y;
+    }
+  }
+}
+
+TEST(Decimal32Test, Rescale) {
+  ASSERT_OK_AND_EQ(Decimal32(11100), Decimal32(111).Rescale(0, 2));
+  ASSERT_OK_AND_EQ(Decimal32(111), Decimal32(11100).Rescale(2, 0));
+  ASSERT_OK_AND_EQ(Decimal32(5), Decimal32(500000).Rescale(6, 1));
+  ASSERT_OK_AND_EQ(Decimal32(500000), Decimal32(5).Rescale(1, 6));
+  ASSERT_RAISES(Invalid, Decimal32(555555).Rescale(6, 1));
+
+  // Test some random numbers.
+  for (auto original_scale : GetRandomNumbers<Int8Type>(16)) {
+    for (auto value : GetRandomNumbers<Int16Type>(16)) {
+      Decimal32 unscaled_value = Decimal32(value);
+      Decimal32 scaled_value = unscaled_value;
+      for (int32_t new_scale = original_scale; new_scale < original_scale + 4;
+           new_scale++, scaled_value *= Decimal32(10)) {
+        ASSERT_OK_AND_EQ(scaled_value, unscaled_value.Rescale(original_scale, 
new_scale));
+        ASSERT_OK_AND_EQ(unscaled_value, scaled_value.Rescale(new_scale, 
original_scale));
+      }
+    }
+  }
+
+  for (auto original_scale : GetRandomNumbers<Int16Type>(16)) {
+    Decimal32 value(1);
+    for (int32_t new_scale = original_scale; new_scale < original_scale + 8;
+         new_scale++, value *= Decimal32(10)) {
+      Decimal32 negative_value = value * -1;
+      ASSERT_OK_AND_EQ(value, Decimal32(1).Rescale(original_scale, new_scale));
+      ASSERT_OK_AND_EQ(negative_value, Decimal32(-1).Rescale(original_scale, 
new_scale));
+      ASSERT_OK_AND_EQ(Decimal32(1), value.Rescale(new_scale, original_scale));
+      ASSERT_OK_AND_EQ(Decimal32(-1), negative_value.Rescale(new_scale, 
original_scale));
+    }
+  }
+}
+
+TEST(Decimal32Test, Mod) {
+  ASSERT_EQ(Decimal32(234), Decimal32(20100) % Decimal32(301));
+
+  ASSERT_EQ(Decimal32(-234), Decimal32(-20100) % Decimal32(301));
+
+  ASSERT_EQ(Decimal32(234), Decimal32(20100) % Decimal32(-301));
+
+  ASSERT_EQ(Decimal32(-234), Decimal32(-20100) % Decimal32(-301));
+
+  // Test some random numbers.
+  for (auto x : GetRandomNumbers<Int32Type>(16)) {
+    for (auto y : GetRandomNumbers<Int32Type>(16)) {
+      if (y == 0) {
+        continue;
+      }
+
+      Decimal32 result = Decimal32(x) % Decimal32(y);
+      ASSERT_EQ(Decimal32(static_cast<int64_t>(x) % y), result)
+          << " x: " << x << " y: " << y;
+    }
+  }
+}
+
+TEST(Decimal32Test, Sign) {
+  ASSERT_EQ(1, Decimal32(999999).Sign());
+  ASSERT_EQ(-1, Decimal32(-999999).Sign());
+  ASSERT_EQ(1, Decimal32(0).Sign());
+}
+
+TEST(Decimal32Test, GetWholeAndFraction) {
+  Decimal32 value("123456");
+  Decimal32 whole;
+  Decimal32 fraction;
+  int32_t out;
+
+  value.GetWholeAndFraction(0, &whole, &fraction);
+  ASSERT_OK(whole.ToInteger(&out));
+  ASSERT_EQ(123456, out);
+  ASSERT_OK(fraction.ToInteger(&out));
+  ASSERT_EQ(0, out);

Review Comment:
   Looks like we want a helper function to avoid repeating these snippets:
   ```c++
   template <typename DecimalType>
   void AssertGetWholeAndFraction(
       DecimalType value, int32_t scale, std::pair<int32_t> 
expected_whole_and_fraction);
   
   AssertGetWholeAndFraction(value, 0, {123456, 0});
   AssertGetWholeAndFraction(value, 1, {12345, 6});
   ...
   ```



##########
cpp/src/arrow/util/decimal_internal.h:
##########
@@ -442,8 +516,9 @@ struct RealTraits<float> {
   static constexpr float two_to_192(float x) { return x == 0 ? 0 : kFloatInf; }
 
   static constexpr int kMantissaBits = 24;
-  // ceil(log10(2 ^ kMantissaBits))
-  static constexpr int kMantissaDigits = 8;
+  // log10(2 ^ kMantissaBits) ~= 7.2, let's be conservative to ensure more 
accuracy
+  // with our conversions for Decimal values

Review Comment:
   Did it come up in some of the tests otherwise?



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to