This is an automated email from the ASF dual-hosted git repository.

ptupitsyn pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/ignite.git


The following commit(s) were added to refs/heads/master by this push:
     new 4e6a6c54ca9 IGNITE-25119 .NET: Fix decimal negative scale handling 
(#12102)
4e6a6c54ca9 is described below

commit 4e6a6c54ca98a94024cb934c8d30f42844704219
Author: Pavel Tupitsyn <[email protected]>
AuthorDate: Wed May 28 12:38:55 2025 +0300

    IGNITE-25119 .NET: Fix decimal negative scale handling (#12102)
    
    Add support for decimal values with negative scale, such as `1.12E+1`, 
which is `1.12 scale -1` in Java BigDecimal, and is equivalent to `11.2`.
---
 .../Compute/ComputeApiTest.JavaTask.cs             | 257 ++++++++++++---------
 .../Apache.Ignite.Core/Impl/Binary/BinaryUtils.cs  |  33 ++-
 2 files changed, 177 insertions(+), 113 deletions(-)

diff --git 
a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Compute/ComputeApiTest.JavaTask.cs
 
b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Compute/ComputeApiTest.JavaTask.cs
index 2ebfa0768d1..3fc200ab744 100644
--- 
a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Compute/ComputeApiTest.JavaTask.cs
+++ 
b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Compute/ComputeApiTest.JavaTask.cs
@@ -128,114 +128,114 @@ namespace Apache.Ignite.Core.Tests.Compute
         {
             decimal val;
 
-            Assert.AreEqual(val = decimal.Zero, 
_grid1.GetCompute().ExecuteJavaTask<object>(DecimalTask, new object[] { val, 
val.ToString() }));
-
-            Assert.AreEqual(val = new decimal(0, 0, 1, false, 0), 
_grid1.GetCompute().ExecuteJavaTask<object>(DecimalTask, new object[] { val, 
val.ToString() }));
-            Assert.AreEqual(val = new decimal(0, 0, 1, true, 0), 
_grid1.GetCompute().ExecuteJavaTask<object>(DecimalTask, new object[] { val, 
val.ToString() }));
-            Assert.AreEqual(val = new decimal(0, 0, 1, false, 0) - 1, 
_grid1.GetCompute().ExecuteJavaTask<object>(DecimalTask, new object[] { val, 
val.ToString() }));
-            Assert.AreEqual(val = new decimal(0, 0, 1, true, 0) - 1, 
_grid1.GetCompute().ExecuteJavaTask<object>(DecimalTask, new object[] { val, 
val.ToString() }));
-            Assert.AreEqual(val = new decimal(0, 0, 1, false, 0) + 1, 
_grid1.GetCompute().ExecuteJavaTask<object>(DecimalTask, new object[] { val, 
val.ToString() }));
-            Assert.AreEqual(val = new decimal(0, 0, 1, true, 0) + 1, 
_grid1.GetCompute().ExecuteJavaTask<object>(DecimalTask, new object[] { val, 
val.ToString() }));
-            Assert.AreEqual(val = new decimal(0, 0, int.MinValue, false, 0), 
_grid1.GetCompute().ExecuteJavaTask<object>(DecimalTask, new object[] { val, 
val.ToString() }));
-            Assert.AreEqual(val = new decimal(0, 0, int.MinValue, true, 0), 
_grid1.GetCompute().ExecuteJavaTask<object>(DecimalTask, new object[] { val, 
val.ToString() }));
-            Assert.AreEqual(val = new decimal(0, 0, int.MinValue, false, 0) - 
1, _grid1.GetCompute().ExecuteJavaTask<object>(DecimalTask, new object[] { val, 
val.ToString() }));
-            Assert.AreEqual(val = new decimal(0, 0, int.MinValue, true, 0) - 
1, _grid1.GetCompute().ExecuteJavaTask<object>(DecimalTask, new object[] { val, 
val.ToString() }));
-            Assert.AreEqual(val = new decimal(0, 0, int.MinValue, false, 0) + 
1, _grid1.GetCompute().ExecuteJavaTask<object>(DecimalTask, new object[] { val, 
val.ToString() }));
-            Assert.AreEqual(val = new decimal(0, 0, int.MinValue, true, 0) + 
1, _grid1.GetCompute().ExecuteJavaTask<object>(DecimalTask, new object[] { val, 
val.ToString() }));
-            Assert.AreEqual(val = new decimal(0, 0, int.MaxValue, false, 0), 
_grid1.GetCompute().ExecuteJavaTask<object>(DecimalTask, new object[] { val, 
val.ToString() }));
-            Assert.AreEqual(val = new decimal(0, 0, int.MaxValue, true, 0), 
_grid1.GetCompute().ExecuteJavaTask<object>(DecimalTask, new object[] { val, 
val.ToString() }));
-            Assert.AreEqual(val = new decimal(0, 0, int.MaxValue, false, 0) - 
1, _grid1.GetCompute().ExecuteJavaTask<object>(DecimalTask, new object[] { val, 
val.ToString() }));
-            Assert.AreEqual(val = new decimal(0, 0, int.MaxValue, true, 0) - 
1, _grid1.GetCompute().ExecuteJavaTask<object>(DecimalTask, new object[] { val, 
val.ToString() }));
-            Assert.AreEqual(val = new decimal(0, 0, int.MaxValue, false, 0) + 
1, _grid1.GetCompute().ExecuteJavaTask<object>(DecimalTask, new object[] { val, 
val.ToString() }));
-            Assert.AreEqual(val = new decimal(0, 0, int.MaxValue, true, 0) + 
1, _grid1.GetCompute().ExecuteJavaTask<object>(DecimalTask, new object[] { val, 
val.ToString() }));
-
-            Assert.AreEqual(val = new decimal(0, 1, 0, false, 0), 
_grid1.GetCompute().ExecuteJavaTask<object>(DecimalTask, new object[] { val, 
val.ToString() }));
-            Assert.AreEqual(val = new decimal(0, 1, 0, true, 0), 
_grid1.GetCompute().ExecuteJavaTask<object>(DecimalTask, new object[] { val, 
val.ToString() }));
-            Assert.AreEqual(val = new decimal(0, 1, 0, false, 0) - 1, 
_grid1.GetCompute().ExecuteJavaTask<object>(DecimalTask, new object[] { val, 
val.ToString() }));
-            Assert.AreEqual(val = new decimal(0, 1, 0, true, 0) - 1, 
_grid1.GetCompute().ExecuteJavaTask<object>(DecimalTask, new object[] { val, 
val.ToString() }));
-            Assert.AreEqual(val = new decimal(0, 1, 0, false, 0) + 1, 
_grid1.GetCompute().ExecuteJavaTask<object>(DecimalTask, new object[] { val, 
val.ToString() }));
-            Assert.AreEqual(val = new decimal(0, 1, 0, true, 0) + 1, 
_grid1.GetCompute().ExecuteJavaTask<object>(DecimalTask, new object[] { val, 
val.ToString() }));
-            Assert.AreEqual(val = new decimal(0, int.MinValue, 0, false, 0), 
_grid1.GetCompute().ExecuteJavaTask<object>(DecimalTask, new object[] { val, 
val.ToString() }));
-            Assert.AreEqual(val = new decimal(0, int.MinValue, 0, true, 0), 
_grid1.GetCompute().ExecuteJavaTask<object>(DecimalTask, new object[] { val, 
val.ToString() }));
-            Assert.AreEqual(val = new decimal(0, int.MinValue, 0, false, 0) - 
1, _grid1.GetCompute().ExecuteJavaTask<object>(DecimalTask, new object[] { val, 
val.ToString() }));
-            Assert.AreEqual(val = new decimal(0, int.MinValue, 0, true, 0) - 
1, _grid1.GetCompute().ExecuteJavaTask<object>(DecimalTask, new object[] { val, 
val.ToString() }));
-            Assert.AreEqual(val = new decimal(0, int.MinValue, 0, false, 0) + 
1, _grid1.GetCompute().ExecuteJavaTask<object>(DecimalTask, new object[] { val, 
val.ToString() }));
-            Assert.AreEqual(val = new decimal(0, int.MinValue, 0, true, 0) + 
1, _grid1.GetCompute().ExecuteJavaTask<object>(DecimalTask, new object[] { val, 
val.ToString() }));
-            Assert.AreEqual(val = new decimal(0, int.MaxValue, 0, false, 0), 
_grid1.GetCompute().ExecuteJavaTask<object>(DecimalTask, new object[] { val, 
val.ToString() }));
-            Assert.AreEqual(val = new decimal(0, int.MaxValue, 0, true, 0), 
_grid1.GetCompute().ExecuteJavaTask<object>(DecimalTask, new object[] { val, 
val.ToString() }));
-            Assert.AreEqual(val = new decimal(0, int.MaxValue, 0, false, 0) - 
1, _grid1.GetCompute().ExecuteJavaTask<object>(DecimalTask, new object[] { val, 
val.ToString() }));
-            Assert.AreEqual(val = new decimal(0, int.MaxValue, 0, true, 0) - 
1, _grid1.GetCompute().ExecuteJavaTask<object>(DecimalTask, new object[] { val, 
val.ToString() }));
-            Assert.AreEqual(val = new decimal(0, int.MaxValue, 0, false, 0) + 
1, _grid1.GetCompute().ExecuteJavaTask<object>(DecimalTask, new object[] { val, 
val.ToString() }));
-            Assert.AreEqual(val = new decimal(0, int.MaxValue, 0, true, 0) + 
1, _grid1.GetCompute().ExecuteJavaTask<object>(DecimalTask, new object[] { val, 
val.ToString() }));
-
-            Assert.AreEqual(val = new decimal(1, 0, 0, false, 0), 
_grid1.GetCompute().ExecuteJavaTask<object>(DecimalTask, new object[] { val, 
val.ToString() }));
-            Assert.AreEqual(val = new decimal(1, 0, 0, true, 0), 
_grid1.GetCompute().ExecuteJavaTask<object>(DecimalTask, new object[] { val, 
val.ToString() }));
-            Assert.AreEqual(val = new decimal(1, 0, 0, false, 0) - 1, 
_grid1.GetCompute().ExecuteJavaTask<object>(DecimalTask, new object[] { val, 
val.ToString() }));
-            Assert.AreEqual(val = new decimal(1, 0, 0, true, 0) - 1, 
_grid1.GetCompute().ExecuteJavaTask<object>(DecimalTask, new object[] { val, 
val.ToString() }));
-            Assert.AreEqual(val = new decimal(1, 0, 0, false, 0) + 1, 
_grid1.GetCompute().ExecuteJavaTask<object>(DecimalTask, new object[] { val, 
val.ToString() }));
-            Assert.AreEqual(val = new decimal(1, 0, 0, true, 0) + 1, 
_grid1.GetCompute().ExecuteJavaTask<object>(DecimalTask, new object[] { val, 
val.ToString() }));
-            Assert.AreEqual(val = new decimal(int.MinValue, 0, 0, false, 0), 
_grid1.GetCompute().ExecuteJavaTask<object>(DecimalTask, new object[] { val, 
val.ToString() }));
-            Assert.AreEqual(val = new decimal(int.MinValue, 0, 0, true, 0), 
_grid1.GetCompute().ExecuteJavaTask<object>(DecimalTask, new object[] { val, 
val.ToString() }));
-            Assert.AreEqual(val = new decimal(int.MinValue, 0, 0, false, 0) - 
1, _grid1.GetCompute().ExecuteJavaTask<object>(DecimalTask, new object[] { val, 
val.ToString() }));
-            Assert.AreEqual(val = new decimal(int.MinValue, 0, 0, true, 0) - 
1, _grid1.GetCompute().ExecuteJavaTask<object>(DecimalTask, new object[] { val, 
val.ToString() }));
-            Assert.AreEqual(val = new decimal(int.MinValue, 0, 0, false, 0) + 
1, _grid1.GetCompute().ExecuteJavaTask<object>(DecimalTask, new object[] { val, 
val.ToString() }));
-            Assert.AreEqual(val = new decimal(int.MinValue, 0, 0, true, 0) + 
1, _grid1.GetCompute().ExecuteJavaTask<object>(DecimalTask, new object[] { val, 
val.ToString() }));
-            Assert.AreEqual(val = new decimal(int.MaxValue, 0, 0, false, 0), 
_grid1.GetCompute().ExecuteJavaTask<object>(DecimalTask, new object[] { val, 
val.ToString() }));
-            Assert.AreEqual(val = new decimal(int.MaxValue, 0, 0, true, 0), 
_grid1.GetCompute().ExecuteJavaTask<object>(DecimalTask, new object[] { val, 
val.ToString() }));
-            Assert.AreEqual(val = new decimal(int.MaxValue, 0, 0, false, 0) - 
1, _grid1.GetCompute().ExecuteJavaTask<object>(DecimalTask, new object[] { val, 
val.ToString() }));
-            Assert.AreEqual(val = new decimal(int.MaxValue, 0, 0, true, 0) - 
1, _grid1.GetCompute().ExecuteJavaTask<object>(DecimalTask, new object[] { val, 
val.ToString() }));
-            Assert.AreEqual(val = new decimal(int.MaxValue, 0, 0, false, 0) + 
1, _grid1.GetCompute().ExecuteJavaTask<object>(DecimalTask, new object[] { val, 
val.ToString() }));
-            Assert.AreEqual(val = new decimal(int.MaxValue, 0, 0, true, 0) + 
1, _grid1.GetCompute().ExecuteJavaTask<object>(DecimalTask, new object[] { val, 
val.ToString() }));
-
-            Assert.AreEqual(val = new decimal(1, 1, 1, false, 0), 
_grid1.GetCompute().ExecuteJavaTask<object>(DecimalTask, new object[] { val, 
val.ToString() }));
-            Assert.AreEqual(val = new decimal(1, 1, 1, true, 0), 
_grid1.GetCompute().ExecuteJavaTask<object>(DecimalTask, new object[] { val, 
val.ToString() }));
-            Assert.AreEqual(val = new decimal(1, 1, 1, false, 0) - 1, 
_grid1.GetCompute().ExecuteJavaTask<object>(DecimalTask, new object[] { val, 
val.ToString() }));
-            Assert.AreEqual(val = new decimal(1, 1, 1, true, 0) - 1, 
_grid1.GetCompute().ExecuteJavaTask<object>(DecimalTask, new object[] { val, 
val.ToString() }));
-            Assert.AreEqual(val = new decimal(1, 1, 1, false, 0) + 1, 
_grid1.GetCompute().ExecuteJavaTask<object>(DecimalTask, new object[] { val, 
val.ToString() }));
-            Assert.AreEqual(val = new decimal(1, 1, 1, true, 0) + 1, 
_grid1.GetCompute().ExecuteJavaTask<object>(DecimalTask, new object[] { val, 
val.ToString() }));
-
-            Assert.AreEqual(val = decimal.Parse("65536"), 
_grid1.GetCompute().ExecuteJavaTask<object>(DecimalTask, new object[] { val, 
val.ToString() }));
-            Assert.AreEqual(val = decimal.Parse("-65536"), 
_grid1.GetCompute().ExecuteJavaTask<object>(DecimalTask, new object[] { val, 
val.ToString() }));
-            Assert.AreEqual(val = decimal.Parse("65536") - 1, 
_grid1.GetCompute().ExecuteJavaTask<object>(DecimalTask, new object[] { val, 
val.ToString() }));
-            Assert.AreEqual(val = decimal.Parse("-65536") - 1, 
_grid1.GetCompute().ExecuteJavaTask<object>(DecimalTask, new object[] { val, 
val.ToString() }));
-            Assert.AreEqual(val = decimal.Parse("65536") + 1, 
_grid1.GetCompute().ExecuteJavaTask<object>(DecimalTask, new object[] { val, 
val.ToString() }));
-            Assert.AreEqual(val = decimal.Parse("-65536") + 1, 
_grid1.GetCompute().ExecuteJavaTask<object>(DecimalTask, new object[] { val, 
val.ToString() }));
-
-            Assert.AreEqual(val = decimal.Parse("4294967296"), 
_grid1.GetCompute().ExecuteJavaTask<object>(DecimalTask, new object[] { val, 
val.ToString() }));
-            Assert.AreEqual(val = decimal.Parse("-4294967296"), 
_grid1.GetCompute().ExecuteJavaTask<object>(DecimalTask, new object[] { val, 
val.ToString() }));
-            Assert.AreEqual(val = decimal.Parse("4294967296") - 1, 
_grid1.GetCompute().ExecuteJavaTask<object>(DecimalTask, new object[] { val, 
val.ToString() }));
-            Assert.AreEqual(val = decimal.Parse("-4294967296") - 1, 
_grid1.GetCompute().ExecuteJavaTask<object>(DecimalTask, new object[] { val, 
val.ToString() }));
-            Assert.AreEqual(val = decimal.Parse("4294967296") + 1, 
_grid1.GetCompute().ExecuteJavaTask<object>(DecimalTask, new object[] { val, 
val.ToString() }));
-            Assert.AreEqual(val = decimal.Parse("-4294967296") + 1, 
_grid1.GetCompute().ExecuteJavaTask<object>(DecimalTask, new object[] { val, 
val.ToString() }));
-
-            Assert.AreEqual(val = decimal.Parse("281474976710656"), 
_grid1.GetCompute().ExecuteJavaTask<object>(DecimalTask, new object[] { val, 
val.ToString() }));
-            Assert.AreEqual(val = decimal.Parse("-281474976710656"), 
_grid1.GetCompute().ExecuteJavaTask<object>(DecimalTask, new object[] { val, 
val.ToString() }));
-            Assert.AreEqual(val = decimal.Parse("281474976710656") - 1, 
_grid1.GetCompute().ExecuteJavaTask<object>(DecimalTask, new object[] { val, 
val.ToString() }));
-            Assert.AreEqual(val = decimal.Parse("-281474976710656") - 1, 
_grid1.GetCompute().ExecuteJavaTask<object>(DecimalTask, new object[] { val, 
val.ToString() }));
-            Assert.AreEqual(val = decimal.Parse("281474976710656") + 1, 
_grid1.GetCompute().ExecuteJavaTask<object>(DecimalTask, new object[] { val, 
val.ToString() }));
-            Assert.AreEqual(val = decimal.Parse("-281474976710656") + 1, 
_grid1.GetCompute().ExecuteJavaTask<object>(DecimalTask, new object[] { val, 
val.ToString() }));
-
-            Assert.AreEqual(val = decimal.Parse("18446744073709551616"), 
_grid1.GetCompute().ExecuteJavaTask<object>(DecimalTask, new object[] { val, 
val.ToString() }));
-            Assert.AreEqual(val = decimal.Parse("-18446744073709551616"), 
_grid1.GetCompute().ExecuteJavaTask<object>(DecimalTask, new object[] { val, 
val.ToString() }));
-            Assert.AreEqual(val = decimal.Parse("18446744073709551616") - 1, 
_grid1.GetCompute().ExecuteJavaTask<object>(DecimalTask, new object[] { val, 
val.ToString() }));
-            Assert.AreEqual(val = decimal.Parse("-18446744073709551616") - 1, 
_grid1.GetCompute().ExecuteJavaTask<object>(DecimalTask, new object[] { val, 
val.ToString() }));
-            Assert.AreEqual(val = decimal.Parse("18446744073709551616") + 1, 
_grid1.GetCompute().ExecuteJavaTask<object>(DecimalTask, new object[] { val, 
val.ToString() }));
-            Assert.AreEqual(val = decimal.Parse("-18446744073709551616") + 1, 
_grid1.GetCompute().ExecuteJavaTask<object>(DecimalTask, new object[] { val, 
val.ToString() }));
-
-            Assert.AreEqual(val = decimal.Parse("1208925819614629174706176"), 
_grid1.GetCompute().ExecuteJavaTask<object>(DecimalTask, new object[] { val, 
val.ToString() }));
-            Assert.AreEqual(val = decimal.Parse("-1208925819614629174706176"), 
_grid1.GetCompute().ExecuteJavaTask<object>(DecimalTask, new object[] { val, 
val.ToString() }));
-            Assert.AreEqual(val = decimal.Parse("1208925819614629174706176") - 
1, _grid1.GetCompute().ExecuteJavaTask<object>(DecimalTask, new object[] { val, 
val.ToString() }));
-            Assert.AreEqual(val = decimal.Parse("-1208925819614629174706176") 
- 1, _grid1.GetCompute().ExecuteJavaTask<object>(DecimalTask, new object[] { 
val, val.ToString() }));
-            Assert.AreEqual(val = decimal.Parse("1208925819614629174706176") + 
1, _grid1.GetCompute().ExecuteJavaTask<object>(DecimalTask, new object[] { val, 
val.ToString() }));
-            Assert.AreEqual(val = decimal.Parse("-1208925819614629174706176") 
+ 1, _grid1.GetCompute().ExecuteJavaTask<object>(DecimalTask, new object[] { 
val, val.ToString() }));
-
-            Assert.AreEqual(val = decimal.MaxValue, 
_grid1.GetCompute().ExecuteJavaTask<object>(DecimalTask, new object[] { val, 
val.ToString() }));
-            Assert.AreEqual(val = decimal.MinValue, 
_grid1.GetCompute().ExecuteJavaTask<object>(DecimalTask, new object[] { val, 
val.ToString() }));
-            Assert.AreEqual(val = decimal.MaxValue - 1, 
_grid1.GetCompute().ExecuteJavaTask<object>(DecimalTask, new object[] { val, 
val.ToString() }));
-            Assert.AreEqual(val = decimal.MinValue + 1, 
_grid1.GetCompute().ExecuteJavaTask<object>(DecimalTask, new object[] { val, 
val.ToString() }));
-
-            Assert.AreEqual(val = decimal.Parse("11,12"), 
_grid1.GetCompute().ExecuteJavaTask<object>(DecimalTask, new object[] { val, 
val.ToString() }));
-            Assert.AreEqual(val = decimal.Parse("-11,12"), 
_grid1.GetCompute().ExecuteJavaTask<object>(DecimalTask, new object[] { val, 
val.ToString() }));
+            Assert.AreEqual(val = decimal.Zero, ExecuteDecimalTask(val));
+
+            Assert.AreEqual(val = new decimal(0, 0, 1, false, 0), 
ExecuteDecimalTask(val));
+            Assert.AreEqual(val = new decimal(0, 0, 1, true, 0), 
ExecuteDecimalTask(val));
+            Assert.AreEqual(val = new decimal(0, 0, 1, false, 0) - 1, 
ExecuteDecimalTask(val));
+            Assert.AreEqual(val = new decimal(0, 0, 1, true, 0) - 1, 
ExecuteDecimalTask(val));
+            Assert.AreEqual(val = new decimal(0, 0, 1, false, 0) + 1, 
ExecuteDecimalTask(val));
+            Assert.AreEqual(val = new decimal(0, 0, 1, true, 0) + 1, 
ExecuteDecimalTask(val));
+            Assert.AreEqual(val = new decimal(0, 0, int.MinValue, false, 0), 
ExecuteDecimalTask(val));
+            Assert.AreEqual(val = new decimal(0, 0, int.MinValue, true, 0), 
ExecuteDecimalTask(val));
+            Assert.AreEqual(val = new decimal(0, 0, int.MinValue, false, 0) - 
1, ExecuteDecimalTask(val));
+            Assert.AreEqual(val = new decimal(0, 0, int.MinValue, true, 0) - 
1, ExecuteDecimalTask(val));
+            Assert.AreEqual(val = new decimal(0, 0, int.MinValue, false, 0) + 
1, ExecuteDecimalTask(val));
+            Assert.AreEqual(val = new decimal(0, 0, int.MinValue, true, 0) + 
1, ExecuteDecimalTask(val));
+            Assert.AreEqual(val = new decimal(0, 0, int.MaxValue, false, 0), 
ExecuteDecimalTask(val));
+            Assert.AreEqual(val = new decimal(0, 0, int.MaxValue, true, 0), 
ExecuteDecimalTask(val));
+            Assert.AreEqual(val = new decimal(0, 0, int.MaxValue, false, 0) - 
1, ExecuteDecimalTask(val));
+            Assert.AreEqual(val = new decimal(0, 0, int.MaxValue, true, 0) - 
1, ExecuteDecimalTask(val));
+            Assert.AreEqual(val = new decimal(0, 0, int.MaxValue, false, 0) + 
1, ExecuteDecimalTask(val));
+            Assert.AreEqual(val = new decimal(0, 0, int.MaxValue, true, 0) + 
1, ExecuteDecimalTask(val));
+
+            Assert.AreEqual(val = new decimal(0, 1, 0, false, 0), 
ExecuteDecimalTask(val));
+            Assert.AreEqual(val = new decimal(0, 1, 0, true, 0), 
ExecuteDecimalTask(val));
+            Assert.AreEqual(val = new decimal(0, 1, 0, false, 0) - 1, 
ExecuteDecimalTask(val));
+            Assert.AreEqual(val = new decimal(0, 1, 0, true, 0) - 1, 
ExecuteDecimalTask(val));
+            Assert.AreEqual(val = new decimal(0, 1, 0, false, 0) + 1, 
ExecuteDecimalTask(val));
+            Assert.AreEqual(val = new decimal(0, 1, 0, true, 0) + 1, 
ExecuteDecimalTask(val));
+            Assert.AreEqual(val = new decimal(0, int.MinValue, 0, false, 0), 
ExecuteDecimalTask(val));
+            Assert.AreEqual(val = new decimal(0, int.MinValue, 0, true, 0), 
ExecuteDecimalTask(val));
+            Assert.AreEqual(val = new decimal(0, int.MinValue, 0, false, 0) - 
1, ExecuteDecimalTask(val));
+            Assert.AreEqual(val = new decimal(0, int.MinValue, 0, true, 0) - 
1, ExecuteDecimalTask(val));
+            Assert.AreEqual(val = new decimal(0, int.MinValue, 0, false, 0) + 
1, ExecuteDecimalTask(val));
+            Assert.AreEqual(val = new decimal(0, int.MinValue, 0, true, 0) + 
1, ExecuteDecimalTask(val));
+            Assert.AreEqual(val = new decimal(0, int.MaxValue, 0, false, 0), 
ExecuteDecimalTask(val));
+            Assert.AreEqual(val = new decimal(0, int.MaxValue, 0, true, 0), 
ExecuteDecimalTask(val));
+            Assert.AreEqual(val = new decimal(0, int.MaxValue, 0, false, 0) - 
1, ExecuteDecimalTask(val));
+            Assert.AreEqual(val = new decimal(0, int.MaxValue, 0, true, 0) - 
1, ExecuteDecimalTask(val));
+            Assert.AreEqual(val = new decimal(0, int.MaxValue, 0, false, 0) + 
1, ExecuteDecimalTask(val));
+            Assert.AreEqual(val = new decimal(0, int.MaxValue, 0, true, 0) + 
1, ExecuteDecimalTask(val));
+
+            Assert.AreEqual(val = new decimal(1, 0, 0, false, 0), 
ExecuteDecimalTask(val));
+            Assert.AreEqual(val = new decimal(1, 0, 0, true, 0), 
ExecuteDecimalTask(val));
+            Assert.AreEqual(val = new decimal(1, 0, 0, false, 0) - 1, 
ExecuteDecimalTask(val));
+            Assert.AreEqual(val = new decimal(1, 0, 0, true, 0) - 1, 
ExecuteDecimalTask(val));
+            Assert.AreEqual(val = new decimal(1, 0, 0, false, 0) + 1, 
ExecuteDecimalTask(val));
+            Assert.AreEqual(val = new decimal(1, 0, 0, true, 0) + 1, 
ExecuteDecimalTask(val));
+            Assert.AreEqual(val = new decimal(int.MinValue, 0, 0, false, 0), 
ExecuteDecimalTask(val));
+            Assert.AreEqual(val = new decimal(int.MinValue, 0, 0, true, 0), 
ExecuteDecimalTask(val));
+            Assert.AreEqual(val = new decimal(int.MinValue, 0, 0, false, 0) - 
1, ExecuteDecimalTask(val));
+            Assert.AreEqual(val = new decimal(int.MinValue, 0, 0, true, 0) - 
1, ExecuteDecimalTask(val));
+            Assert.AreEqual(val = new decimal(int.MinValue, 0, 0, false, 0) + 
1, ExecuteDecimalTask(val));
+            Assert.AreEqual(val = new decimal(int.MinValue, 0, 0, true, 0) + 
1, ExecuteDecimalTask(val));
+            Assert.AreEqual(val = new decimal(int.MaxValue, 0, 0, false, 0), 
ExecuteDecimalTask(val));
+            Assert.AreEqual(val = new decimal(int.MaxValue, 0, 0, true, 0), 
ExecuteDecimalTask(val));
+            Assert.AreEqual(val = new decimal(int.MaxValue, 0, 0, false, 0) - 
1, ExecuteDecimalTask(val));
+            Assert.AreEqual(val = new decimal(int.MaxValue, 0, 0, true, 0) - 
1, ExecuteDecimalTask(val));
+            Assert.AreEqual(val = new decimal(int.MaxValue, 0, 0, false, 0) + 
1, ExecuteDecimalTask(val));
+            Assert.AreEqual(val = new decimal(int.MaxValue, 0, 0, true, 0) + 
1, ExecuteDecimalTask(val));
+
+            Assert.AreEqual(val = new decimal(1, 1, 1, false, 0), 
ExecuteDecimalTask(val));
+            Assert.AreEqual(val = new decimal(1, 1, 1, true, 0), 
ExecuteDecimalTask(val));
+            Assert.AreEqual(val = new decimal(1, 1, 1, false, 0) - 1, 
ExecuteDecimalTask(val));
+            Assert.AreEqual(val = new decimal(1, 1, 1, true, 0) - 1, 
ExecuteDecimalTask(val));
+            Assert.AreEqual(val = new decimal(1, 1, 1, false, 0) + 1, 
ExecuteDecimalTask(val));
+            Assert.AreEqual(val = new decimal(1, 1, 1, true, 0) + 1, 
ExecuteDecimalTask(val));
+
+            Assert.AreEqual(val = decimal.Parse("65536"), 
ExecuteDecimalTask(val));
+            Assert.AreEqual(val = decimal.Parse("-65536"), 
ExecuteDecimalTask(val));
+            Assert.AreEqual(val = decimal.Parse("65536") - 1, 
ExecuteDecimalTask(val));
+            Assert.AreEqual(val = decimal.Parse("-65536") - 1, 
ExecuteDecimalTask(val));
+            Assert.AreEqual(val = decimal.Parse("65536") + 1, 
ExecuteDecimalTask(val));
+            Assert.AreEqual(val = decimal.Parse("-65536") + 1, 
ExecuteDecimalTask(val));
+
+            Assert.AreEqual(val = decimal.Parse("4294967296"), 
ExecuteDecimalTask(val));
+            Assert.AreEqual(val = decimal.Parse("-4294967296"), 
ExecuteDecimalTask(val));
+            Assert.AreEqual(val = decimal.Parse("4294967296") - 1, 
ExecuteDecimalTask(val));
+            Assert.AreEqual(val = decimal.Parse("-4294967296") - 1, 
ExecuteDecimalTask(val));
+            Assert.AreEqual(val = decimal.Parse("4294967296") + 1, 
ExecuteDecimalTask(val));
+            Assert.AreEqual(val = decimal.Parse("-4294967296") + 1, 
ExecuteDecimalTask(val));
+
+            Assert.AreEqual(val = decimal.Parse("281474976710656"), 
ExecuteDecimalTask(val));
+            Assert.AreEqual(val = decimal.Parse("-281474976710656"), 
ExecuteDecimalTask(val));
+            Assert.AreEqual(val = decimal.Parse("281474976710656") - 1, 
ExecuteDecimalTask(val));
+            Assert.AreEqual(val = decimal.Parse("-281474976710656") - 1, 
ExecuteDecimalTask(val));
+            Assert.AreEqual(val = decimal.Parse("281474976710656") + 1, 
ExecuteDecimalTask(val));
+            Assert.AreEqual(val = decimal.Parse("-281474976710656") + 1, 
ExecuteDecimalTask(val));
+
+            Assert.AreEqual(val = decimal.Parse("18446744073709551616"), 
ExecuteDecimalTask(val));
+            Assert.AreEqual(val = decimal.Parse("-18446744073709551616"), 
ExecuteDecimalTask(val));
+            Assert.AreEqual(val = decimal.Parse("18446744073709551616") - 1, 
ExecuteDecimalTask(val));
+            Assert.AreEqual(val = decimal.Parse("-18446744073709551616") - 1, 
ExecuteDecimalTask(val));
+            Assert.AreEqual(val = decimal.Parse("18446744073709551616") + 1, 
ExecuteDecimalTask(val));
+            Assert.AreEqual(val = decimal.Parse("-18446744073709551616") + 1, 
ExecuteDecimalTask(val));
+
+            Assert.AreEqual(val = decimal.Parse("1208925819614629174706176"), 
ExecuteDecimalTask(val));
+            Assert.AreEqual(val = decimal.Parse("-1208925819614629174706176"), 
ExecuteDecimalTask(val));
+            Assert.AreEqual(val = decimal.Parse("1208925819614629174706176") - 
1, ExecuteDecimalTask(val));
+            Assert.AreEqual(val = decimal.Parse("-1208925819614629174706176") 
- 1, ExecuteDecimalTask(val));
+            Assert.AreEqual(val = decimal.Parse("1208925819614629174706176") + 
1, ExecuteDecimalTask(val));
+            Assert.AreEqual(val = decimal.Parse("-1208925819614629174706176") 
+ 1, ExecuteDecimalTask(val));
+
+            Assert.AreEqual(val = decimal.MaxValue, ExecuteDecimalTask(val));
+            Assert.AreEqual(val = decimal.MinValue, ExecuteDecimalTask(val));
+            Assert.AreEqual(val = decimal.MaxValue - 1, 
ExecuteDecimalTask(val));
+            Assert.AreEqual(val = decimal.MinValue + 1, 
ExecuteDecimalTask(val));
+
+            Assert.AreEqual(val = decimal.Parse("11,12"), 
ExecuteDecimalTask(val));
+            Assert.AreEqual(val = decimal.Parse("-11,12"), 
ExecuteDecimalTask(val));
 
             // Test echo with overflow.
             var ex = Assert.Throws<BinaryObjectException>(() => 
_grid1.GetCompute()
@@ -243,11 +243,36 @@ namespace Apache.Ignite.Core.Tests.Compute
 
             Assert.AreEqual("Decimal magnitude overflow (must be less than 96 
bits): 104", ex.Message);
 
-            // Negative scale. 1E+1 parses to "1 scale -1" on Java side.
             ex = Assert.Throws<BinaryObjectException>(() => _grid1.GetCompute()
-                .ExecuteJavaTask<object>(DecimalTask, new object[] { null, 
"1E+1" }));
+                .ExecuteJavaTask<object>(DecimalTask, new object[] { null, 
"1E+29" }));
 
-            Assert.AreEqual("Decimal value scale overflow (must be between 0 
and 28): -1", ex.Message);
+            Assert.AreEqual("Decimal value scale overflow (must be between -28 
and 28, inclusive): -29", ex.Message);
+        }
+
+        /// <summary>
+        /// Test echo with decimals with a negative scale.
+        /// 1E+1 parses to "1 scale -1" on Java side.
+        /// </summary>
+        [Test]
+        public void TestEchoDecimalNegativeScale()
+        {
+            Assert.AreEqual(10m, ExecuteDecimalTask(null, "1E+1"));
+            Assert.AreEqual(12300m, ExecuteDecimalTask(null, "1.23E+4"));
+            Assert.AreEqual(123456000000000000000000000m, 
ExecuteDecimalTask(null, "123456E+21"));
+            Assert.AreEqual(10000000000000000000000000000m, 
ExecuteDecimalTask(null, "1E+28"));
+        }
+
+        /// <summary>
+        /// Test decimal values where the scale is within the allowed range,
+        /// but the resulting value can't be represented by .NET decimal type.
+        /// </summary>
+        [Test]
+        public void TestEchoDecimalNegativeScaleOverflow()
+        {
+            var ex = Assert.Throws<BinaryObjectException>(() => 
ExecuteDecimalTask(null, "12345E+25"));
+
+            Assert.AreEqual("Decimal value overflow [unscaled=12345, 
scale=-25]", ex.Message);
+            Assert.IsInstanceOf<OverflowException>(ex.InnerException);
         }
 
         /// <summary>
@@ -580,5 +605,15 @@ namespace Apache.Ignite.Core.Tests.Compute
             Assert.AreEqual(1, 
_grid1.GetCluster().ForNodeIds(res.ElementAt(0)).GetNodes().Count);
             Assert.AreEqual(1, 
_grid1.GetCluster().ForNodeIds(res.ElementAt(1)).GetNodes().Count);
         }
+
+        private object ExecuteDecimalTask(decimal val)
+        {
+            return ExecuteDecimalTask(val, val.ToString());
+        }
+
+        private object ExecuteDecimalTask(decimal? val, string str)
+        {
+            return _grid1.GetCompute().ExecuteJavaTask<object>(DecimalTask, 
new object[] { val, str });
+        }
     }
 }
diff --git 
a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinaryUtils.cs 
b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinaryUtils.cs
index 60746a63ac1..40d2b0952ea 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinaryUtils.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinaryUtils.cs
@@ -808,8 +808,8 @@ namespace Apache.Ignite.Core.Impl.Binary
                 neg = true;
             }
 
-            if (scale < 0 || scale > 28)
-                throw new BinaryObjectException("Decimal value scale overflow 
(must be between 0 and 28): " + scale);
+            if (-28 > scale || scale > 28)
+                throw new BinaryObjectException("Decimal value scale overflow 
(must be between -28 and 28, inclusive): " + scale);
 
             if (mag.Length > 13)
                 throw new BinaryObjectException("Decimal magnitude overflow 
(must be less than 96 bits): " +
@@ -843,9 +843,38 @@ namespace Apache.Ignite.Core.Impl.Binary
                     lo = (lo << 8) + mag[i];
             }
 
+            if (scale < 0)
+            {
+                var unscaled = new decimal(lo, mid, hi, neg, 0);
+                return SetNegativeScale(unscaled, scale);
+            }
+
             return new decimal(lo, mid, hi, neg, (byte)scale);
         }
 
+        private static decimal SetNegativeScale(decimal unscaled, int scale)
+        {
+            // Java BigDecimal:
+            // "if negative, the unscaled value is multiplied by ten to the 
power of the negation of the scale"
+            // 
(https://docs.oracle.com/javase/8/docs/api/java/math/BigDecimal.html).
+            var res = unscaled;
+
+            // There is no Pow for decimals, and using double Math.Pow(10, 
-scale) might be inaccurate.
+            try
+            {
+                for (int i = 0; i < -scale; i++)
+                {
+                    res *= 10;
+                }
+            }
+            catch (OverflowException e)
+            {
+                throw new BinaryObjectException($"Decimal value overflow 
[unscaled={unscaled}, scale={scale}]", e);
+            }
+
+            return res;
+        }
+
         /**
          * <summary>Write decimal array.</summary>
          * <param name="vals">Decimal array.</param>

Reply via email to