summaryrefslogtreecommitdiff
path: root/src/utils/ByteUtils.scala
diff options
context:
space:
mode:
Diffstat (limited to 'src/utils/ByteUtils.scala')
-rw-r--r--src/utils/ByteUtils.scala32
1 files changed, 27 insertions, 5 deletions
diff --git a/src/utils/ByteUtils.scala b/src/utils/ByteUtils.scala
index 2c51917..18942c0 100644
--- a/src/utils/ByteUtils.scala
+++ b/src/utils/ByteUtils.scala
@@ -1,6 +1,7 @@
package ixee.cryptopals.utils
import FunctionUtils.tup
+import ConversionUtils._
object ByteUtils {
trait SizedNumeric[T] {
@@ -9,8 +10,8 @@ object ByteUtils {
def bitSize: Int
def fromLong(l: Long): T
def toLong(l: T): Long
- def buildFrom[U : SizedNumeric](from: U): T = fromLong(from.toLong)
- def truncate[U : SizedNumeric](from: U): T = buildFrom(from)
+ def buildFrom[U : SizedNumeric : BitOps](from: U): T = fromLong(from.toLong)
+ def truncate[U : SizedNumeric : BitOps](from: U): T = buildFrom(from)
override def toString = s"SizedNumeric[${manifest}]"
}
@@ -21,6 +22,7 @@ object ByteUtils {
def @&(a: T, b: T): T
def @^(a: T, b: T): T
def @+(a: T, b: T): T
+ def @-(a: T, b: T): T
}
implicit val byteOps: BitOps[Byte] = new BitOps[Byte] {
@@ -30,6 +32,7 @@ object ByteUtils {
def @&(a: Byte, b: Byte): Byte = (a & b).toByte
def @^(a: Byte, b: Byte): Byte = (a ^ b).toByte
def @+(a: Byte, b: Byte): Byte = (a + b).toByte
+ def @-(a: Byte, b: Byte): Byte = (a - b).toByte
}
implicit val intOps: BitOps[Int] = new BitOps[Int] {
@@ -39,6 +42,7 @@ object ByteUtils {
def @&(a: Int, b: Int): Int = a & b
def @^(a: Int, b: Int): Int = a ^ b
def @+(a: Int, b: Int): Int = a + b
+ def @-(a: Int, b: Int): Int = a - b
}
implicit class WithBitOpts[T : BitOps](x: T) {
@@ -48,9 +52,10 @@ object ByteUtils {
def @&(b: T): T = implicitly[BitOps[T]].@&(x, b)
def @^(b: T): T = implicitly[BitOps[T]].@^(x, b)
def @+(b: T): T = implicitly[BitOps[T]].@+(x, b)
+ def @-(b: T): T = implicitly[BitOps[T]].@-(x, b)
}
- implicit class SizedWithByteInfo[T : SizedNumeric](x: T) {
+ implicit class SizedWithByteInfo[T : SizedNumeric : BitOps](x: T) {
def byteSize = implicitly[SizedNumeric[T]].byteSize
def octetSize = byteSize * 2
def bitSize = implicitly[SizedNumeric[T]].bitSize
@@ -65,6 +70,17 @@ object ByteUtils {
uSize.buildFrom(x)
}
def hex: String = s"%0${octetSize}x" format x
+ def bitsSet: Int = {
+ var bits = 0
+ var num = x
+
+ while (num.toLong > 0) {
+ bits = bits + 1
+ num = num @& (num @- 1.truncatedTo[T])
+ }
+
+ bits
+ }
def truncatedTo[U : SizedNumeric]: U = {
implicitly[SizedNumeric[U]].truncate(x)
}
@@ -82,8 +98,14 @@ object ByteUtils {
implicit val shortized = sizedNumeric(2) { x: Long => x.toShort } { _.toLong }
implicit val byteSized = sizedNumeric(1) { x: Long => x.toByte } { _.toLong }
- implicit class SeqByteOps(seq: Seq[Byte]) {
- def xor(other: Seq[Byte]): Seq[Byte] =
+ implicit class SeqByteOps[T : SizedNumeric : BitOps](seq: Seq[T]) {
+ def xor(other: Seq[T]): Seq[T] =
seq.zip(other).map(tup(_ @^ _))
}
+
+ def hammingDistance(a: String, b: String): Int =
+ hammingDistance(a.asBytes, b.asBytes)
+
+ def hammingDistance[T : BitOps : SizedNumeric](a: Seq[T], b: Seq[T]): Int =
+ (a xor b).map(_.bitsSet).reduce(_ @+ _)
}