Adding BaseNumbers trait, start to implement addition

This commit is contained in:
Chris Stewart 2016-06-15 21:28:47 -05:00
parent c7dc6dca77
commit 50a59aef2c
2 changed files with 42 additions and 26 deletions

View File

@ -1,11 +1,12 @@
package org.bitcoins.core.number package org.bitcoins.core.number
import org.bitcoins.core.util.{BitcoinSLogger, Factory, NumberUtil} import org.bitcoins.core.protocol.NetworkElement
import org.bitcoins.core.util.{BitcoinSLogger, BitcoinSUtil, Factory, NumberUtil}
/** /**
* Created by chris on 6/4/16. * Created by chris on 6/4/16.
*/ */
sealed trait Number extends BitcoinSLogger { sealed trait Number extends NetworkElement with BitcoinSLogger {
type A type A
def underlying : A def underlying : A
def + (num : Number): Number def + (num : Number): Number
@ -21,7 +22,10 @@ sealed trait UInt32 extends UnsignedNumber {
override type A = Long override type A = Long
def + (num : Number): Number = num match { def + (num : Number): Number = num match {
case uInt32 : UInt32 => UInt64(underlying + uInt32.underlying) case uInt32 : UInt32 =>
val n : BigInt = underlying + uInt32.underlying
if (n == n.toLong) UInt32(n.toLong)
else UInt64(n)
case uInt64 : UInt64 => UInt64(uInt64.underlying + underlying) case uInt64 : UInt64 => UInt64(uInt64.underlying + underlying)
case int32 : Int32 => ??? case int32 : Int32 => ???
case int64 : Int64 => ??? case int64 : Int64 => ???
@ -60,16 +64,19 @@ object UnsignedNumber extends Factory[UnsignedNumber] {
} }
} }
/**
trait BaseNumbers { * Represents various numbers that should be implemented
def zero : Number * inside of any companion object for a [[Number]]
def one : Number */
def min : Number trait BaseNumbers[T <: Number] {
def max : Number def zero : T
def one : T
def min : T
def max : T
} }
object UInt32 extends Factory[UInt32] with BitcoinSLogger with BaseNumbers { object UInt32 extends Factory[UInt32] with BitcoinSLogger with BaseNumbers[UInt32] {
private case class UInt32Impl(underlying : Long) extends UInt32 private case class UInt32Impl(underlying : Long, hex : String) extends UInt32
lazy val zero = fromBytes(Seq(0.toByte)) lazy val zero = fromBytes(Seq(0.toByte))
lazy val one = fromBytes(Seq(1.toByte)) lazy val one = fromBytes(Seq(1.toByte))
@ -82,18 +89,20 @@ object UInt32 extends Factory[UInt32] with BitcoinSLogger with BaseNumbers {
val individualByteValues = for { val individualByteValues = for {
(byte,index) <- bytes.reverse.zipWithIndex (byte,index) <- bytes.reverse.zipWithIndex
} yield NumberUtil.calculateNumberFromByte(index, byte) } yield NumberUtil.calculateNumberFromByte(index, byte)
UInt32Impl(individualByteValues.sum.toLong) UInt32Impl(individualByteValues.sum.toLong, BitcoinSUtil.encodeHex(bytes))
} }
def apply(long : Long) : UInt32 = UInt32Impl(long, BitcoinSUtil.encodeHex(BigInt(long).toByteArray))
} }
object UInt64 extends Factory[UInt64] with BitcoinSLogger with BaseNumbers { object UInt64 extends Factory[UInt64] with BitcoinSLogger with BaseNumbers[UInt64] {
private case class UInt64Impl(underlying : BigInt) extends UInt64 private case class UInt64Impl(underlying : BigInt, hex : String) extends UInt64
lazy val zero = UInt32.zero lazy val zero = fromBytes(Seq(0.toByte))
lazy val one = UInt32.one lazy val one = fromBytes(Seq(1.toByte))
lazy val min = zero lazy val min = zero
lazy val max = fromBytes(Seq(0xff.toByte, 0xff.toByte, 0xff.toByte, 0xff.toByte, lazy val max = fromBytes(Seq(0xff.toByte, 0xff.toByte, 0xff.toByte, 0xff.toByte,
@ -105,15 +114,15 @@ object UInt64 extends Factory[UInt64] with BitcoinSLogger with BaseNumbers {
(byte,index) <- bytes.reverse.zipWithIndex (byte,index) <- bytes.reverse.zipWithIndex
} yield NumberUtil.calculateNumberFromByte(index, byte) } yield NumberUtil.calculateNumberFromByte(index, byte)
logger.debug("Individual bytes values: " + individualByteValues) logger.debug("Individual bytes values: " + individualByteValues)
UInt64Impl(individualByteValues.sum) UInt64Impl(individualByteValues.sum, BitcoinSUtil.encodeHex(bytes))
} }
def apply(num : BigInt): UInt64 = UInt64Impl(num) def apply(num : BigInt): UInt64 = UInt64Impl(num, BitcoinSUtil.encodeHex(num.toByteArray))
} }
object Int32 extends Factory[Int32] with BaseNumbers { object Int32 extends Factory[Int32] with BaseNumbers[Int32] {
private case class Int32Impl(underlying : Int) extends Int32 private case class Int32Impl(underlying : Int, hex : String) extends Int32
lazy val zero = fromBytes(Seq(0.toByte)) lazy val zero = fromBytes(Seq(0.toByte))
lazy val one = fromBytes(Seq(1.toByte)) lazy val one = fromBytes(Seq(1.toByte))
@ -123,22 +132,22 @@ object Int32 extends Factory[Int32] with BaseNumbers {
override def fromBytes(bytes : Seq[Byte]): Int32 = { override def fromBytes(bytes : Seq[Byte]): Int32 = {
require(bytes.size <= 4, "We cannot have an Int32 be larger than 4 bytes") require(bytes.size <= 4, "We cannot have an Int32 be larger than 4 bytes")
Int32Impl(BigInt(bytes.toArray).toInt) Int32Impl(BigInt(bytes.toArray).toInt, BitcoinSUtil.encodeHex(bytes))
} }
} }
object Int64 extends Factory[Int64] with BaseNumbers { object Int64 extends Factory[Int64] with BaseNumbers[Int64] {
private case class Int64Impl(underlying : Long) extends Int64 private case class Int64Impl(underlying : Long, hex : String) extends Int64
lazy val zero = Int32.zero lazy val zero = fromBytes(Seq(0.toByte))
lazy val one = Int32.one lazy val one = fromBytes(Seq(1.toByte))
lazy val min = fromBytes(Seq(0x80.toByte,0.toByte, 0.toByte, 0.toByte,0.toByte, 0.toByte, 0.toByte, 0.toByte)) lazy val min = fromBytes(Seq(0x80.toByte,0.toByte, 0.toByte, 0.toByte,0.toByte, 0.toByte, 0.toByte, 0.toByte))
lazy val max = fromBytes(Seq(0x7f.toByte, 0xff.toByte, 0xff.toByte, 0xff.toByte, lazy val max = fromBytes(Seq(0x7f.toByte, 0xff.toByte, 0xff.toByte, 0xff.toByte,
0xff.toByte, 0xff.toByte, 0xff.toByte, 0xff.toByte)) 0xff.toByte, 0xff.toByte, 0xff.toByte, 0xff.toByte))
override def fromBytes(bytes : Seq[Byte]): Int64 = { override def fromBytes(bytes : Seq[Byte]): Int64 = {
require(bytes.size <= 8, "We cannot have an Int64 be larger than 8 bytes") require(bytes.size <= 8, "We cannot have an Int64 be larger than 8 bytes")
Int64Impl(BigInt(bytes.toArray).toLong) Int64Impl(BigInt(bytes.toArray).toLong, BitcoinSUtil.encodeHex(bytes))
} }
} }

View File

@ -70,4 +70,11 @@ class UInt32Test extends FlatSpec with MustMatchers {
it must "have the correct maximum number representation for UInt32" in { it must "have the correct maximum number representation for UInt32" in {
UInt32.max.underlying must be (4294967295L) UInt32.max.underlying must be (4294967295L)
} }
//addition tests
it must "say 0 + 0 = 0" in {
(UInt32.zero + UInt32.zero) must be (UInt32.zero)
}
} }