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
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.
*/
sealed trait Number extends BitcoinSLogger {
sealed trait Number extends NetworkElement with BitcoinSLogger {
type A
def underlying : A
def + (num : Number): Number
@ -21,7 +22,10 @@ sealed trait UInt32 extends UnsignedNumber {
override type A = Long
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 int32 : Int32 => ???
case int64 : Int64 => ???
@ -60,16 +64,19 @@ object UnsignedNumber extends Factory[UnsignedNumber] {
}
}
trait BaseNumbers {
def zero : Number
def one : Number
def min : Number
def max : Number
/**
* Represents various numbers that should be implemented
* inside of any companion object for a [[Number]]
*/
trait BaseNumbers[T <: Number] {
def zero : T
def one : T
def min : T
def max : T
}
object UInt32 extends Factory[UInt32] with BitcoinSLogger with BaseNumbers {
private case class UInt32Impl(underlying : Long) extends UInt32
object UInt32 extends Factory[UInt32] with BitcoinSLogger with BaseNumbers[UInt32] {
private case class UInt32Impl(underlying : Long, hex : String) extends UInt32
lazy val zero = fromBytes(Seq(0.toByte))
lazy val one = fromBytes(Seq(1.toByte))
@ -82,18 +89,20 @@ object UInt32 extends Factory[UInt32] with BitcoinSLogger with BaseNumbers {
val individualByteValues = for {
(byte,index) <- bytes.reverse.zipWithIndex
} 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 {
private case class UInt64Impl(underlying : BigInt) extends UInt64
object UInt64 extends Factory[UInt64] with BitcoinSLogger with BaseNumbers[UInt64] {
private case class UInt64Impl(underlying : BigInt, hex : String) extends UInt64
lazy val zero = UInt32.zero
lazy val one = UInt32.one
lazy val zero = fromBytes(Seq(0.toByte))
lazy val one = fromBytes(Seq(1.toByte))
lazy val min = zero
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
} yield NumberUtil.calculateNumberFromByte(index, byte)
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 {
private case class Int32Impl(underlying : Int) extends Int32
object Int32 extends Factory[Int32] with BaseNumbers[Int32] {
private case class Int32Impl(underlying : Int, hex : String) extends Int32
lazy val zero = fromBytes(Seq(0.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 = {
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 {
private case class Int64Impl(underlying : Long) extends Int64
object Int64 extends Factory[Int64] with BaseNumbers[Int64] {
private case class Int64Impl(underlying : Long, hex : String) extends Int64
lazy val zero = Int32.zero
lazy val one = Int32.one
lazy val zero = fromBytes(Seq(0.toByte))
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 max = fromBytes(Seq(0x7f.toByte, 0xff.toByte, 0xff.toByte, 0xff.toByte,
0xff.toByte, 0xff.toByte, 0xff.toByte, 0xff.toByte))
override def fromBytes(bytes : Seq[Byte]): Int64 = {
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 {
UInt32.max.underlying must be (4294967295L)
}
//addition tests
it must "say 0 + 0 = 0" in {
(UInt32.zero + UInt32.zero) must be (UInt32.zero)
}
}