Skip to content

Commit 27a224b

Browse files
committed
Fixed encoding and decoding of negative and infinity real numbers
... in .NET library
1 parent 5232d42 commit 27a224b

File tree

10 files changed

+192
-112
lines changed

10 files changed

+192
-112
lines changed

BinaryNotes.NET/BinaryNotes/org/bn/coders/ber/BERDecoder.cs

Lines changed: 29 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -294,48 +294,45 @@ public override DecodedObject<object> decodeReal(DecodedObject<object> decodedTa
294294
int realPreamble = stream.ReadByte();
295295

296296
Double result = 0.0D;
297-
int szResult = len.Value;
298-
if ((realPreamble & 0x40) == 1)
297+
if (realPreamble == 0x40)
299298
{
300299
// 01000000 Value is PLUS-INFINITY
301300
result = Double.PositiveInfinity;
302301
}
303-
if ((realPreamble & 0x41) == 1)
302+
else if (realPreamble == 0x41)
304303
{
305304
// 01000001 Value is MINUS-INFINITY
306305
result = Double.NegativeInfinity;
307-
szResult += 1;
308306
}
309-
else
310-
if (len.Value > 0)
307+
else if (len.Value > 0)
308+
{
309+
int szOfExp = 1 + (realPreamble & 0x3);
310+
int sign = realPreamble & 0x40;
311+
int ff = (realPreamble & 0x0C) >> 2;
312+
DecodedObject<object> exponentEncFrm = decodeLongValue(stream, new DecodedObject<int>(szOfExp));
313+
long exponent = (long)exponentEncFrm.Value;
314+
DecodedObject<object> mantissaEncFrm = decodeLongValue(stream, new DecodedObject<int>(len.Value - szOfExp - 1));
315+
// Unpack mantissa & decrement exponent for base 2
316+
long mantissa = (long)mantissaEncFrm.Value << ff;
317+
while ((mantissa & 0x000ff00000000000L) == 0x0)
311318
{
312-
int szOfExp = 1 + (realPreamble & 0x3);
313-
int sign = realPreamble & 0x40;
314-
int ff = (realPreamble & 0x0C) >> 2;
315-
DecodedObject<object> exponentEncFrm = decodeLongValue(stream, new DecodedObject<int>(szOfExp));
316-
long exponent = (long)exponentEncFrm.Value;
317-
DecodedObject<object> mantissaEncFrm = decodeLongValue(stream, new DecodedObject<int>(szResult - szOfExp - 1));
318-
// Unpack mantissa & decrement exponent for base 2
319-
long mantissa = (long)mantissaEncFrm.Value << ff;
320-
while ((mantissa & 0x000ff00000000000L) == 0x0)
321-
{
322-
exponent -= 8;
323-
mantissa <<= 8;
324-
}
325-
while ((mantissa & 0x0010000000000000L) == 0x0)
326-
{
327-
exponent -= 1;
328-
mantissa <<= 1;
329-
}
330-
mantissa &= 0x0FFFFFFFFFFFFFL;
331-
long lValue = (exponent + 1023 + 52) << 52;
332-
lValue |= mantissa;
333-
if (sign == 1)
334-
{
335-
lValue = (long)((ulong)lValue | 0x8000000000000000L);
336-
}
337-
result = System.BitConverter.Int64BitsToDouble(lValue);
319+
exponent -= 8;
320+
mantissa <<= 8;
321+
}
322+
while ((mantissa & 0x0010000000000000L) == 0x0)
323+
{
324+
exponent -= 1;
325+
mantissa <<= 1;
338326
}
327+
mantissa &= 0x0FFFFFFFFFFFFFL;
328+
long lValue = (exponent + 1023 + 52) << 52;
329+
lValue |= mantissa;
330+
if (sign == 0x40)
331+
{
332+
lValue = (long)((ulong)lValue | 0x8000000000000000L);
333+
}
334+
result = System.BitConverter.Int64BitsToDouble(lValue);
335+
}
339336
return new DecodedObject<object>(result, len.Value + len.Size);
340337
}
341338

BinaryNotes.NET/BinaryNotes/org/bn/coders/ber/BEREncoder.cs

Lines changed: 27 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -157,43 +157,47 @@ public override int encodeReal(object obj, System.IO.Stream stream, ElementInfo
157157
Double value = (Double) obj;
158158
//CoderUtils.checkConstraints(value,elementInfo);
159159
int szOfInt = 0;
160-
long asLong = System.BitConverter.DoubleToInt64Bits(value);
160+
long asLong = BitConverter.DoubleToInt64Bits(value);
161161
if (value == Double.PositiveInfinity)
162162
{ // positive infinity
163163
stream.WriteByte(0x40); // 01000000 Value is PLUS-INFINITY
164+
szOfInt = 1;
164165
}
165-
else
166-
if(value == Double.NegativeInfinity)
166+
else if (value == Double.NegativeInfinity)
167167
{ // negative infinity
168168
stream.WriteByte(0x41); // 01000001 Value is MINUS-INFINITY
169-
}
170-
else
171-
if(asLong!=0x0) {
169+
szOfInt = 1;
170+
}
171+
else if (asLong != 0)
172+
{
172173
long exponent = ((0x7ff0000000000000L & asLong) >> 52) - 1023 - 52;
173174
long mantissa = 0x000fffffffffffffL & asLong;
174175
mantissa |= 0x10000000000000L; // set virtual delimeter
175-
176+
176177
// pack mantissa for base 2
177-
while((mantissa & 0xFFL) == 0x0) {
178+
while ((mantissa & 0xFFL) == 0)
179+
{
178180
mantissa >>= 8;
179181
exponent += 8; //increment exponent to 8 (base 2)
180-
}
181-
while((mantissa & 0x01L) == 0x0) {
182+
}
183+
while ((mantissa & 0x01L) == 0)
184+
{
182185
mantissa >>= 1;
183-
exponent+=1; //increment exponent to 1
186+
exponent += 1; //increment exponent to 1
187+
}
188+
189+
szOfInt += encodeIntegerValue(mantissa, stream);
190+
int szOfExp = CoderUtils.getIntegerLength(exponent);
191+
szOfInt += encodeIntegerValue(exponent, stream);
192+
193+
byte realPreamble = 0x80;
194+
realPreamble |= (byte)(szOfExp - 1);
195+
if (((ulong)asLong & 0x8000000000000000L) == 0x8000000000000000L)
196+
{
197+
realPreamble |= 0x40; // Sign
184198
}
185-
186-
szOfInt+= encodeIntegerValue(mantissa,stream);
187-
int szOfExp = CoderUtils.getIntegerLength(exponent);
188-
szOfInt+= encodeIntegerValue(exponent,stream);
189-
190-
byte realPreamble = 0x80;
191-
realPreamble |= (byte)(szOfExp - 1);
192-
if( ((ulong)asLong & 0x8000000000000000L) == 1) {
193-
realPreamble|= 0x40; // Sign
194-
}
195-
stream.WriteByte(realPreamble );
196-
szOfInt+=1;
199+
stream.WriteByte(realPreamble);
200+
szOfInt += 1;
197201
}
198202
resultSize += szOfInt;
199203
resultSize += encodeLength(szOfInt, stream);

BinaryNotes.NET/BinaryNotes/org/bn/coders/per/PERAlignedDecoder.cs

Lines changed: 29 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -499,51 +499,47 @@ public override DecodedObject<object> decodeReal(DecodedObject<object> decodedTa
499499
skipAlignedBits(stream);
500500

501501
Double result = 0.0D;
502-
int szResult = len;
503-
if ((realPreamble & 0x40) == 1)
502+
if (realPreamble == 0x40)
504503
{
505504
// 01000000 Value is PLUS-INFINITY
506505
result = Double.PositiveInfinity;
507506
}
508-
if ((realPreamble & 0x41) == 1)
507+
else if (realPreamble == 0x41)
509508
{
510509
// 01000001 Value is MINUS-INFINITY
511510
result = Double.NegativeInfinity;
512-
szResult += 1;
513511
}
514-
else
515-
if (len > 0)
512+
else if (len > 0)
513+
{
514+
int szOfExp = 1 + (realPreamble & 0x3);
515+
int sign = realPreamble & 0x40;
516+
int ff = (realPreamble & 0x0C) >> 2;
517+
long exponent = decodeIntegerValueAsBytes(szOfExp, stream);
518+
long mantissaEncFrm = decodeIntegerValueAsBytes(len - szOfExp - 1, stream);
519+
// Unpack mantissa & decrement exponent for base 2
520+
long mantissa = mantissaEncFrm << ff;
521+
while ((mantissa & 0x000ff00000000000L) == 0)
516522
{
517-
int szOfExp = 1 + (realPreamble & 0x3);
518-
int sign = realPreamble & 0x40;
519-
int ff = (realPreamble & 0x0C) >> 2;
520-
long exponent = decodeIntegerValueAsBytes(szOfExp, stream);
521-
long mantissaEncFrm = decodeIntegerValueAsBytes(szResult - szOfExp - 1, stream);
522-
// Unpack mantissa & decrement exponent for base 2
523-
long mantissa = mantissaEncFrm << ff;
524-
while ((mantissa & 0x000ff00000000000L) == 0x0)
525-
{
526-
exponent -= 8;
527-
mantissa <<= 8;
528-
}
529-
while ((mantissa & 0x0010000000000000L) == 0x0)
530-
{
531-
exponent -= 1;
532-
mantissa <<= 1;
533-
}
534-
mantissa &= 0x0FFFFFFFFFFFFFL;
535-
long lValue = (exponent + 1023 + 52) << 52;
536-
lValue |= mantissa;
537-
if (sign == 1)
538-
{
539-
lValue = (long)((ulong)lValue | 0x8000000000000000L);
540-
}
541-
result = System.BitConverter.Int64BitsToDouble(lValue);
523+
exponent -= 8;
524+
mantissa <<= 8;
525+
}
526+
while ((mantissa & 0x0010000000000000L) == 0)
527+
{
528+
exponent -= 1;
529+
mantissa <<= 1;
542530
}
543-
return new DecodedObject<object>(result, szResult);
531+
mantissa &= 0x0FFFFFFFFFFFFFL;
532+
long lValue = (exponent + 1023 + 52) << 52;
533+
lValue |= mantissa;
534+
if (sign == 0x40)
535+
{
536+
lValue = (long)((ulong)lValue | 0x8000000000000000L);
537+
}
538+
result = System.BitConverter.Int64BitsToDouble(lValue);
539+
}
540+
return new DecodedObject<object>(result, len);
544541
}
545542

546-
547543
public override DecodedObject<object> decodeOctetString(DecodedObject<object> decodedTag, System.Type objectClass, ElementInfo elementInfo, System.IO.Stream stream)
548544
{
549545
DecodedObject<object> result = new DecodedObject<object>();

BinaryNotes.NET/BinaryNotes/org/bn/coders/per/PERAlignedEncoder.cs

Lines changed: 26 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -307,50 +307,53 @@ public override int encodeReal(object obj, System.IO.Stream stream, ElementInfo
307307
//CoderUtils.checkConstraints(value,elementInfo);
308308

309309
long asLong = System.BitConverter.DoubleToInt64Bits(value);
310-
if(value == Double.PositiveInfinity ) { // positive infinity
311-
result+=encodeLengthDeterminant(1,bitStream);
310+
if (value == Double.PositiveInfinity)
311+
{ // positive infinity
312+
result += encodeLengthDeterminant(1,bitStream);
312313
doAlign(stream);
313314
stream.WriteByte(0x40); // 01000000 Value is PLUS-INFINITY
314-
result+=1;
315+
result += 1;
315316
}
316-
else
317-
if(value == Double.NegativeInfinity) { // negative infinity
318-
result+=encodeLengthDeterminant(1,bitStream);
317+
else if (value == Double.NegativeInfinity)
318+
{ // negative infinity
319+
result += encodeLengthDeterminant(1,bitStream);
319320
doAlign(stream);
320321
stream.WriteByte(0x41); // 01000001 Value is MINUS-INFINITY
321-
result+=1;
322-
}
323-
else
324-
if(asLong!=0x0) {
322+
result += 1;
323+
}
324+
else if (asLong != 0)
325+
{
325326
long exponent = ((0x7ff0000000000000L & asLong) >> 52) - 1023 - 52;
326327
long mantissa = 0x000fffffffffffffL & asLong;
327328
mantissa |= 0x10000000000000L; // set virtual delimeter
328-
329+
329330
// pack mantissa for base 2
330-
while((mantissa & 0xFFL) == 0x0) {
331+
while ((mantissa & 0xFFL) == 0)
332+
{
331333
mantissa >>= 8;
332334
exponent += 8; //increment exponent to 8 (base 2)
333-
}
334-
while((mantissa & 0x01L) == 0x0) {
335+
}
336+
while ((mantissa & 0x01L) == 0)
337+
{
335338
mantissa >>= 1;
336-
exponent+=1; //increment exponent to 1
339+
exponent += 1; //increment exponent to 1
337340
}
338341

339342
int szOfExp = CoderUtils.getIntegerLength(exponent);
340-
encodeLengthDeterminant(CoderUtils.getIntegerLength(mantissa)+szOfExp+1,bitStream);
343+
encodeLengthDeterminant(CoderUtils.getIntegerLength(mantissa) + szOfExp + 1, bitStream);
341344
doAlign(stream);
342-
byte realPreamble = 0x80;
343345

346+
byte realPreamble = 0x80;
344347
realPreamble |= (byte)(szOfExp - 1);
345-
if( (((ulong)asLong) & 0x8000000000000000L) == 1) {
346-
realPreamble|= 0x40; // Sign
348+
if ((((ulong)asLong) & 0x8000000000000000L) == 0x8000000000000000L)
349+
{
350+
realPreamble |= 0x40; // Sign
347351
}
348352
stream.WriteByte(realPreamble);
349-
result+=1;
353+
result += 1;
350354

351-
352-
result+= encodeIntegerValueAsBytes(exponent,stream);
353-
result+= encodeIntegerValueAsBytes(mantissa,stream);
355+
result += encodeIntegerValueAsBytes(exponent, stream);
356+
result += encodeIntegerValueAsBytes(mantissa, stream);
354357
}
355358
return result;
356359
}

BinaryNotes.NET/BinaryNotesTests/org/bn/coders/CoderTestUtilities.cs

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -426,6 +426,24 @@ public TestReal createTestRealBig()
426426
}
427427
public abstract byte[] createTestRealBigBytes();
428428

429+
public TestReal createTestRealPosInf()
430+
{
431+
return new TestReal(Double.PositiveInfinity);
432+
}
433+
public abstract byte[] createTestRealPosInfBytes();
434+
435+
public TestReal createTestRealNegInf()
436+
{
437+
return new TestReal(Double.NegativeInfinity);
438+
}
439+
public abstract byte[] createTestRealNegInfBytes();
440+
441+
public TestReal createTestRealNeg1_5()
442+
{
443+
return new TestReal(-1.5);
444+
}
445+
public abstract byte[] createTestRealNeg1_5Bytes();
446+
429447
public TaggedSequence createTaggedSequence()
430448
{
431449
TaggedSequence result = new TaggedSequence();

BinaryNotes.NET/BinaryNotesTests/org/bn/coders/DecoderTest.cs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -399,6 +399,18 @@ public void testDecodeReal()
399399
stream = new System.IO.MemoryStream(coderTestUtils.createTestRealBigBytes());
400400
val = decoder.decode<TestReal>(stream);
401401
Assert.AreEqual(val.Value, coderTestUtils.createTestRealBig().Value);
402+
403+
stream = new System.IO.MemoryStream(coderTestUtils.createTestRealPosInfBytes());
404+
val = decoder.decode<TestReal>(stream);
405+
Assert.AreEqual(val.Value, coderTestUtils.createTestRealPosInf().Value);
406+
407+
stream = new System.IO.MemoryStream(coderTestUtils.createTestRealNegInfBytes());
408+
val = decoder.decode<TestReal>(stream);
409+
Assert.AreEqual(val.Value, coderTestUtils.createTestRealNegInf().Value);
410+
411+
stream = new System.IO.MemoryStream(coderTestUtils.createTestRealNeg1_5Bytes());
412+
val = decoder.decode<TestReal>(stream);
413+
Assert.AreEqual(val.Value, coderTestUtils.createTestRealNeg1_5().Value);
402414
}
403415

404416
[TestMethod]

BinaryNotes.NET/BinaryNotesTests/org/bn/coders/EncoderTest.cs

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -331,7 +331,13 @@ public void testEncodeReals() {
331331
printEncoded("EncodeTestReal2: ",encoder, coderTestUtils.createTestReal2());
332332
checkEncoded(encoder, coderTestUtils.createTestReal2(), coderTestUtils.createTestReal2Bytes());
333333
printEncoded("EncodeTestRealBig: ",encoder, coderTestUtils.createTestRealBig());
334-
checkEncoded(encoder, coderTestUtils.createTestRealBig(), coderTestUtils.createTestRealBigBytes());
334+
checkEncoded(encoder, coderTestUtils.createTestRealBig(), coderTestUtils.createTestRealBigBytes());
335+
printEncoded("EncodeTestRealPosInf: ", encoder, coderTestUtils.createTestRealPosInf());
336+
checkEncoded(encoder, coderTestUtils.createTestRealPosInf(), coderTestUtils.createTestRealPosInfBytes());
337+
printEncoded("EncodeTestRealNegInf: ", encoder, coderTestUtils.createTestRealNegInf());
338+
checkEncoded(encoder, coderTestUtils.createTestRealNegInf(), coderTestUtils.createTestRealNegInfBytes());
339+
printEncoded("EncodeTestReal-1.5: ", encoder, coderTestUtils.createTestRealNeg1_5());
340+
checkEncoded(encoder, coderTestUtils.createTestRealNeg1_5(), coderTestUtils.createTestRealNeg1_5Bytes());
335341
}
336342

337343
[TestMethod]

BinaryNotes.NET/BinaryNotesTests/org/bn/coders/ber/BERCoderTestUtils.cs

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -255,6 +255,21 @@ public override byte[] createTestRealBigBytes()
255255
return new byte[] { 0x09, 0x05, (byte)0x80, (byte)0xFD, 0x18, 0x6D, 0x21 };
256256
}
257257

258+
public override byte[] createTestRealPosInfBytes()
259+
{
260+
return new byte[] { 0x09, 0x01, 0x40 };
261+
}
262+
263+
public override byte[] createTestRealNegInfBytes()
264+
{
265+
return new byte[] { 0x09, 0x01, 0x41 };
266+
}
267+
268+
public override byte[] createTestRealNeg1_5Bytes()
269+
{
270+
return new byte[] { 0x09, 0x03, (byte)0xC0, (byte)0xFF, 0x03 };
271+
}
272+
258273
public override byte[] createTaggedSequenceBytes()
259274
{
260275
return new byte[] { 0x68, 0x05, 0x87, 0x03, 0x41, 0x41, 0x41 };

0 commit comments

Comments
 (0)