Skip to content

Commit

Permalink
Fixed negation to properly carry to higher bits.
Browse files Browse the repository at this point in the history
  • Loading branch information
CurtHagenlocher committed Oct 27, 2023
1 parent a7f46a7 commit a756f45
Show file tree
Hide file tree
Showing 2 changed files with 11 additions and 7 deletions.
16 changes: 10 additions & 6 deletions csharp/src/Apache.Arrow/DecimalUtility.cs
Original file line number Diff line number Diff line change
Expand Up @@ -81,18 +81,23 @@ internal static SqlDecimal GetSqlDecimal128(in ArrowBuffer valueBuffer, int inde
{
const int byteWidth = 16;
const int intWidth = byteWidth / 4;
const int longWidth = byteWidth / 8;

byte mostSignificantByte = valueBuffer.Span[(index + 1) * byteWidth - 1];
bool isPositive = (mostSignificantByte & 0x80) == 0;

ReadOnlySpan<int> value = valueBuffer.Span.CastTo<int>().Slice(index * intWidth, intWidth);
if (isPositive)
{
ReadOnlySpan<int> value = valueBuffer.Span.CastTo<int>().Slice(index * intWidth, intWidth);
return new SqlDecimal((byte)precision, (byte)scale, true, value[0], value[1], value[2], value[3]);
}
else
{
return new SqlDecimal((byte)precision, (byte)scale, false, -value[0], ~value[1], ~value[2], ~value[3]);
ReadOnlySpan<long> value = valueBuffer.Span.CastTo<long>().Slice(index * longWidth, longWidth);
long data1 = -value[0];
long data2 = (data1 == 0) ? -value[1] : ~value[1];

return new SqlDecimal((byte)precision, (byte)scale, false, (int)(data1 & 0xffffffff), (int)(data1 >> 32), (int)(data2 & 0xffffffff), (int)(data2 >> 32));
}
}
#endif
Expand Down Expand Up @@ -207,10 +212,9 @@ internal static void GetBytes(SqlDecimal value, int precision, int scale, Span<b
value.Data.AsSpan().CopyTo(span);
if (!value.IsPositive)
{
span[0] = -span[0];
span[1] = ~span[1];
span[2] = ~span[2];
span[3] = ~span[3];
Span<long> longSpan = bytes.CastTo<long>();
longSpan[0] = -longSpan[0];
longSpan[1] = (longSpan[0] == 0) ? -longSpan[1] : ~longSpan[1];
}
}
#endif
Expand Down
2 changes: 1 addition & 1 deletion csharp/test/Apache.Arrow.Tests/DecimalUtilityTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ public void NegativeSqlDecimal()
const int scale = 0;
const int bitWidth = 16;

var negative = new SqlDecimal(precision, scale, false, -1, -1, 1, 0);
var negative = new SqlDecimal(precision, scale, false, 0, 0, 1, 0);
var bytes = new byte[16];
DecimalUtility.GetBytes(negative.Value, precision, scale, bitWidth, bytes);
var sqlNegative = DecimalUtility.GetSqlDecimal128(new ArrowBuffer(bytes), 0, precision, scale);
Expand Down

0 comments on commit a756f45

Please sign in to comment.