杨锴
2024-08-14 909e20941e45f8712c012db602034b47da0bfdb0
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
//
//  Bitwise Ops.swift
//  CS.BigInt
//
//  Created by Károly Lőrentey on 2016-01-03.
//  Copyright © 2016-2017 Károly Lőrentey.
//
 
//MARK: Bitwise Operations
 
extension CS.BigUInt {
    /// Return the ones' complement of `a`.
    ///
    /// - Complexity: O(a.count)
    public static prefix func ~(a: CS.BigUInt) -> CS.BigUInt {
        return CS.BigUInt(words: a.words.map { ~$0 })
    }
 
    /// Calculate the bitwise OR of `a` and `b`, and store the result in `a`.
    ///
    /// - Complexity: O(max(a.count, b.count))
    public static func |= (a: inout CS.BigUInt, b: CS.BigUInt) {
        a.reserveCapacity(b.count)
        for i in 0 ..< b.count {
            a[i] |= b[i]
        }
    }
 
    /// Calculate the bitwise AND of `a` and `b` and return the result.
    ///
    /// - Complexity: O(max(a.count, b.count))
    public static func &= (a: inout CS.BigUInt, b: CS.BigUInt) {
        for i in 0 ..< Swift.max(a.count, b.count) {
            a[i] &= b[i]
        }
    }
 
    /// Calculate the bitwise XOR of `a` and `b` and return the result.
    ///
    /// - Complexity: O(max(a.count, b.count))
    public static func ^= (a: inout CS.BigUInt, b: CS.BigUInt) {
        a.reserveCapacity(b.count)
        for i in 0 ..< b.count {
            a[i] ^= b[i]
        }
    }
}
 
extension CS.BigInt {
    public static prefix func ~(x: CS.BigInt) -> CS.BigInt {
        switch x.sign {
        case .plus:
            return CS.BigInt(sign: .minus, magnitude: x.magnitude + 1)
        case .minus:
            return CS.BigInt(sign: .plus, magnitude: x.magnitude - 1)
        }
    }
    
    public static func &(lhs: inout CS.BigInt, rhs: CS.BigInt) -> CS.BigInt {
        let left = lhs.words
        let right = rhs.words
        // Note we aren't using left.count/right.count here; we account for the sign bit separately later.
        let count = Swift.max(lhs.magnitude.count, rhs.magnitude.count)
        var words: [UInt] = []
        words.reserveCapacity(count)
        for i in 0 ..< count {
            words.append(left[i] & right[i])
        }
        if lhs.sign == .minus && rhs.sign == .minus {
            words.twosComplement()
            return CS.BigInt(sign: .minus, magnitude: CS.BigUInt(words: words))
        }
        return CS.BigInt(sign: .plus, magnitude: CS.BigUInt(words: words))
    }
    
    public static func |(lhs: inout CS.BigInt, rhs: CS.BigInt) -> CS.BigInt {
        let left = lhs.words
        let right = rhs.words
        // Note we aren't using left.count/right.count here; we account for the sign bit separately later.
        let count = Swift.max(lhs.magnitude.count, rhs.magnitude.count)
        var words: [UInt] = []
        words.reserveCapacity(count)
        for i in 0 ..< count {
            words.append(left[i] | right[i])
        }
        if lhs.sign == .minus || rhs.sign == .minus {
            words.twosComplement()
            return CS.BigInt(sign: .minus, magnitude: CS.BigUInt(words: words))
        }
        return CS.BigInt(sign: .plus, magnitude: CS.BigUInt(words: words))
    }
    
    public static func ^(lhs: inout CS.BigInt, rhs: CS.BigInt) -> CS.BigInt {
        let left = lhs.words
        let right = rhs.words
        // Note we aren't using left.count/right.count here; we account for the sign bit separately later.
        let count = Swift.max(lhs.magnitude.count, rhs.magnitude.count)
        var words: [UInt] = []
        words.reserveCapacity(count)
        for i in 0 ..< count {
            words.append(left[i] ^ right[i])
        }
        if (lhs.sign == .minus) != (rhs.sign == .minus) {
            words.twosComplement()
            return CS.BigInt(sign: .minus, magnitude: CS.BigUInt(words: words))
        }
        return CS.BigInt(sign: .plus, magnitude: CS.BigUInt(words: words))
    }
    
    public static func &=(lhs: inout CS.BigInt, rhs: CS.BigInt) {
        lhs = lhs & rhs
    }
    
    public static func |=(lhs: inout CS.BigInt, rhs: CS.BigInt) {
        lhs = lhs | rhs
    }
    
    public static func ^=(lhs: inout CS.BigInt, rhs: CS.BigInt) {
        lhs = lhs ^ rhs
    }
}