public override void Write(decimal value, NpgsqlWriteBuffer buf, NpgsqlParameter parameter) { var raw = Unsafe.As <decimal, DecimalRaw>(ref value); var scaleDifference = MoneyScale - raw.Scale; if (scaleDifference > 0) { DecimalRaw.Multiply(ref raw, DecimalRaw.Powers10[scaleDifference]); } else { while (scaleDifference < 0) { var scaleChunk = Math.Min(DecimalRaw.MaxUInt32Scale, -scaleDifference); DecimalRaw.Divide(ref raw, DecimalRaw.Powers10[scaleChunk]); scaleDifference -= scaleChunk; } } var result = (long)raw.Mid << 32 | (long)raw.Low; if (raw.Negative) { result = -result; } buf.WriteInt64(result); }
public override void Write(decimal value, NpgsqlWriteBuffer buf, NpgsqlParameter parameter) { var raw = Unsafe.As <decimal, DecimalRaw>(ref value); var scaleDifference = MoneyScale - raw.Scale; if (scaleDifference > 0) { DecimalRaw.Multiply(ref raw, DecimalRaw.Powers10[scaleDifference]); } else { value = Math.Round(value, MoneyScale, MidpointRounding.AwayFromZero); raw = Unsafe.As <decimal, DecimalRaw>(ref value); } var result = (long)raw.Mid << 32 | (long)raw.Low; if (raw.Negative) { result = -result; } buf.WriteInt64(result); }
/// <inheritdoc /> public override decimal Read(NpgsqlReadBuffer buf, int len, FieldDescription?fieldDescription = null) { var result = new DecimalRaw(); var groups = buf.ReadInt16(); var weight = buf.ReadInt16() - groups + 1; var sign = buf.ReadUInt16(); if (sign == SignNan) { throw new InvalidCastException("Numeric NaN not supported by System.Decimal"); } if (sign == SignNegative) { DecimalRaw.Negate(ref result); } var scale = buf.ReadInt16(); if (scale > MaxDecimalScale) { throw new OverflowException("Numeric value does not fit in a System.Decimal"); } result.Scale = scale; var scaleDifference = scale + weight * MaxGroupScale; if (groups == MaxGroupCount) { while (groups-- > 1) { DecimalRaw.Multiply(ref result, MaxGroupSize); DecimalRaw.Add(ref result, buf.ReadUInt16()); } var group = buf.ReadUInt16(); var groupSize = DecimalRaw.Powers10[-scaleDifference]; if (group % groupSize != 0) { throw new OverflowException("Numeric value does not fit in a System.Decimal"); } DecimalRaw.Multiply(ref result, MaxGroupSize / groupSize); DecimalRaw.Add(ref result, group / groupSize); } else { while (groups-- > 0) { DecimalRaw.Multiply(ref result, MaxGroupSize); DecimalRaw.Add(ref result, buf.ReadUInt16()); } if (scaleDifference < 0) { DecimalRaw.Divide(ref result, DecimalRaw.Powers10[-scaleDifference]); } else { while (scaleDifference > 0) { var scaleChunk = Math.Min(DecimalRaw.MaxUInt32Scale, scaleDifference); DecimalRaw.Multiply(ref result, DecimalRaw.Powers10[scaleChunk]); scaleDifference -= scaleChunk; } } } return(result.Value); }