UInt128.swift 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990
  1. //
  2. // UInt128.swift
  3. //
  4. // Copyright (C) 2014-2017 Marcin Krzyżanowski <marcin@krzyzanowskim.com>
  5. // This software is provided 'as-is', without any express or implied warranty.
  6. //
  7. // In no event will the authors be held liable for any damages arising from the use of this software.
  8. //
  9. // Permission is granted to anyone to use this software for any purpose,including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions:
  10. //
  11. // - The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation is required.
  12. // - Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
  13. // - This notice may not be removed or altered from any source or binary distribution.
  14. //
  15. import Foundation
  16. struct UInt128: Equatable, ExpressibleByIntegerLiteral {
  17. let i: (a: UInt64, b: UInt64)
  18. typealias IntegerLiteralType = UInt64
  19. init(integerLiteral value: IntegerLiteralType) {
  20. self = UInt128(value)
  21. }
  22. init(_ raw: Array<UInt8>) {
  23. self = raw.prefix(MemoryLayout<UInt128>.stride).withUnsafeBytes({ (rawBufferPointer) -> UInt128 in
  24. let arr = rawBufferPointer.bindMemory(to: UInt64.self)
  25. return UInt128((arr[0].bigEndian, arr[1].bigEndian))
  26. })
  27. }
  28. init(_ raw: ArraySlice<UInt8>) {
  29. self.init(Array(raw))
  30. }
  31. init(_ i: (a: UInt64, b: UInt64)) {
  32. self.i = i
  33. }
  34. init(a: UInt64, b: UInt64) {
  35. self.init((a, b))
  36. }
  37. init(_ b: UInt64) {
  38. self.init((0, b))
  39. }
  40. // Bytes
  41. var bytes: Array<UInt8> {
  42. var at = self.i.a.bigEndian
  43. var bt = self.i.b.bigEndian
  44. let ar = Data(bytes: &at, count: MemoryLayout.size(ofValue: at))
  45. let br = Data(bytes: &bt, count: MemoryLayout.size(ofValue: bt))
  46. var result = Data()
  47. result.append(ar)
  48. result.append(br)
  49. return result.bytes
  50. }
  51. static func ^ (n1: UInt128, n2: UInt128) -> UInt128 {
  52. UInt128((n1.i.a ^ n2.i.a, n1.i.b ^ n2.i.b))
  53. }
  54. static func & (n1: UInt128, n2: UInt128) -> UInt128 {
  55. UInt128((n1.i.a & n2.i.a, n1.i.b & n2.i.b))
  56. }
  57. static func >> (value: UInt128, by: Int) -> UInt128 {
  58. var result = value
  59. for _ in 0..<by {
  60. let a = result.i.a >> 1
  61. let b = result.i.b >> 1 + ((result.i.a & 1) << 63)
  62. result = UInt128((a, b))
  63. }
  64. return result
  65. }
  66. // Equatable.
  67. static func == (lhs: UInt128, rhs: UInt128) -> Bool {
  68. lhs.i == rhs.i
  69. }
  70. static func != (lhs: UInt128, rhs: UInt128) -> Bool {
  71. !(lhs == rhs)
  72. }
  73. }