open_pql/base/
rank16.rs

1use super::*;
2
3#[cfg(any(test, feature = "benchmark"))]
4#[macro_export]
5macro_rules! r16 {
6    ($s:expr) => {
7        $crate::Rank16::from(
8            $s.chars()
9                .filter(|c| !c.is_whitespace())
10                .map(|c| $crate::Rank::try_from(c).unwrap())
11                .collect::<Vec<_>>()
12                .as_ref() as &[Rank],
13        )
14    };
15}
16
17/// Rank Set
18/// # Memory Layout:
19/// ```text
20/// [15, 0]:   xxxAKQJT 98765432  // x: unused
21/// ```
22#[derive(
23    Copy,
24    Clone,
25    PartialEq,
26    Eq,
27    BitAnd,
28    BitOr,
29    PartialOrd,
30    Ord,
31    Hash,
32    Default,
33    BitOrAssign,
34    BitAndAssign,
35)]
36pub struct Rank16(u16);
37
38impl Rank16 {
39    /// Constructs [Rank16] from [u16]
40    ///
41    /// # Examples
42    ///
43    /// ```
44    /// use open_pql::{Rank, Rank16};
45    ///
46    /// let i: u16 = 0b0011;
47    /// let ranks: Rank16 = Rank16::from_u16(i);
48    ///
49    /// assert_eq!(ranks, Rank16::from([Rank::R2, Rank::R3].as_ref()));
50    /// ```
51    #[must_use]
52    #[inline]
53    pub const fn from_u16(v: u16) -> Self {
54        Self(v)
55    }
56
57    /// Returns the inner [u16]
58    ///
59    /// # Examples
60    ///
61    /// ```
62    /// use open_pql::Rank16;
63    ///
64    /// let i: u16 = 0b0011;
65    /// let ranks: Rank16 = Rank16::from_u16(i);
66    ///
67    /// assert_eq!(i, ranks.to_u16());
68    /// ```
69    #[must_use]
70    #[inline]
71    pub const fn to_u16(self) -> u16 {
72        self.0
73    }
74
75    #[inline]
76    const fn from_rank(r: Rank) -> Self {
77        Self(1 << r as u8)
78    }
79
80    /// Constructs an empty [Rank16]
81    ///
82    /// # Examples
83    ///
84    /// ```
85    /// use open_pql::{Card, Rank16};
86    ///
87    /// let ranks: Rank16 = Rank16::empty();
88    /// let cards: [Card; 0] = [];
89    ///
90    /// assert_eq!(ranks, Rank16::from(cards.as_ref()));
91    /// ```
92    #[must_use]
93    #[inline]
94    pub const fn empty() -> Self {
95        Self(0)
96    }
97
98    /// Checks whether all rank masks are unset
99    ///
100    /// # Examples
101    ///
102    /// ```
103    /// use open_pql::{Rank, Rank16};
104    ///
105    /// let ranks: Rank16 = Rank16::from(Rank::RA);
106    ///
107    /// assert!(!ranks.is_empty());
108    /// ```
109    #[must_use]
110    #[inline]
111    pub const fn is_empty(self) -> bool {
112        self.0 == 0
113    }
114
115    /// Mark a [Rank]
116    ///
117    /// # Examples
118    ///
119    /// ```
120    /// use open_pql::{Rank, Rank16};
121    ///
122    /// let mut ranks: Rank16 = Rank16::empty();
123    /// ranks.set(Rank::RA);
124    ///
125    /// assert_eq!(ranks, Rank16::from(Rank::RA));
126    /// ```
127    #[inline]
128    pub const fn set(&mut self, r: Rank) {
129        self.0 |= 1 << r as i8;
130    }
131
132    /// Unmark a [Rank]
133    ///
134    /// # Examples
135    ///
136    /// ```
137    /// use open_pql::{Rank, Rank16};
138    ///
139    /// let mut ranks: Rank16 = Rank16::from(Rank::RA);
140    /// ranks.unset(Rank::RA);
141    ///
142    /// assert_eq!(ranks, Rank16::empty());
143    /// ```
144    #[inline]
145    pub const fn unset(&mut self, r: Rank) {
146        self.0 &= !(1 << r as i8);
147    }
148
149    /// Checks whether a [Rank] is marked
150    ///
151    /// # Examples
152    ///
153    /// ```
154    /// use open_pql::{Rank, Rank16};
155    ///
156    /// let ranks: Rank16 = Rank16::from(Rank::RA);
157    ///
158    /// assert!(ranks.contains_rank(Rank::RA));
159    /// assert!(!ranks.contains_rank(Rank::RK));
160    /// ```
161    #[must_use]
162    #[inline]
163    pub const fn contains_rank(self, r: Rank) -> bool {
164        let v = 1u16 << (r as usize);
165        v == v & self.0
166    }
167
168    /// Returns the number of marked ranks
169    ///
170    /// # Examples
171    ///
172    /// ```
173    /// use open_pql::{Rank, Rank16};
174    ///
175    /// let ranks: Rank16 = Rank16::from(Rank::RA);
176    ///
177    /// assert_eq!(ranks.count(), 1);
178    /// ```
179    #[must_use]
180    #[inline]
181    pub const fn count(self) -> PQLCardCount {
182        self.0.count_ones().to_le_bytes()[0]
183    }
184
185    /// Returns smallest Rank in the set
186    #[must_use]
187    #[inline]
188    pub const fn min_rank(self) -> Option<Rank> {
189        match self.0.trailing_zeros() {
190            0 => Some(Rank::R2),
191            1 => Some(Rank::R3),
192            2 => Some(Rank::R4),
193            3 => Some(Rank::R5),
194            4 => Some(Rank::R6),
195            5 => Some(Rank::R7),
196            6 => Some(Rank::R8),
197            7 => Some(Rank::R9),
198            8 => Some(Rank::RT),
199            9 => Some(Rank::RJ),
200            10 => Some(Rank::RQ),
201            11 => Some(Rank::RK),
202            12 => Some(Rank::RA),
203            _ => None,
204        }
205    }
206
207    /// Returns largest Rank in the set
208    #[must_use]
209    #[inline]
210    pub const fn max_rank(self) -> Option<Rank> {
211        match (MASK16_RANKS & self.0).leading_zeros() {
212            15 => Some(Rank::R2),
213            14 => Some(Rank::R3),
214            13 => Some(Rank::R4),
215            12 => Some(Rank::R5),
216            11 => Some(Rank::R6),
217            10 => Some(Rank::R7),
218            9 => Some(Rank::R8),
219            8 => Some(Rank::R9),
220            7 => Some(Rank::RT),
221            6 => Some(Rank::RJ),
222            5 => Some(Rank::RQ),
223            4 => Some(Rank::RK),
224            3 => Some(Rank::RA),
225            _ => None,
226        }
227    }
228
229    /// Returns n-th Rank in the set
230    #[must_use]
231    #[inline]
232    pub fn nth_rank(self, mut n: u8) -> Option<Rank> {
233        for rank in Rank::ARR_ALL.iter().rev() {
234            if self.contains_rank(*rank) {
235                if n == 1 {
236                    return Some(*rank);
237                } else if n == 0 {
238                    return None;
239                }
240
241                n -= 1;
242            }
243        }
244
245        None
246    }
247
248    /// Returns all higher ranks than the max rank in the set
249    #[must_use]
250    #[inline]
251    pub const fn higher_of(r: Self) -> Self {
252        if r.is_empty() {
253            Self(MASK16_RANKS)
254        } else {
255            let i = r.to_u16().leading_zeros();
256
257            Self(!((U16_LEADING_ONE >> i) * 2 - 1) & MASK16_RANKS)
258        }
259    }
260}
261
262impl Not for Rank16 {
263    type Output = Self;
264
265    fn not(self) -> Self::Output {
266        Self(!self.0 & MASK16_RANKS)
267    }
268}
269
270impl From<Rank> for Rank16 {
271    fn from(r: Rank) -> Self {
272        Self::from_rank(r)
273    }
274}
275
276impl From<&[Rank]> for Rank16 {
277    fn from(rs: &[Rank]) -> Self {
278        let mut res = Self::empty();
279
280        for r in rs {
281            res.set(*r);
282        }
283
284        res
285    }
286}
287
288impl From<&[Card]> for Rank16 {
289    fn from(cs: &[Card]) -> Self {
290        let mut res = Self::empty();
291
292        for c in cs {
293            res.set(c.rank);
294        }
295
296        res
297    }
298}
299
300impl From<Card64> for Rank16 {
301    fn from(c: Card64) -> Self {
302        c.ranks_by_suit(Suit::S)
303            | c.ranks_by_suit(Suit::H)
304            | c.ranks_by_suit(Suit::D)
305            | c.ranks_by_suit(Suit::C)
306    }
307}
308
309pub fn u16_to_rank_str(v: u16) -> String {
310    let to_c = |i: u8| {
311        if v & 1 << i == 0 {
312            '\0'
313        } else {
314            RANK_NAMES[i as usize]
315        }
316    };
317
318    (0..N_RANKS)
319        .map(to_c)
320        .filter(|c| c.is_alphanumeric())
321        .collect::<String>()
322}
323
324impl fmt::Debug for Rank16 {
325    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
326        f.write_str(&format!("Rank16<{}>", u16_to_rank_str(self.0)))
327    }
328}
329
330#[cfg(test)]
331mod tests {
332    use constants::MASK16_RANKS;
333    use quickcheck::{Arbitrary, TestResult};
334
335    use super::*;
336
337    impl Arbitrary for Rank16 {
338        fn arbitrary(g: &mut quickcheck::Gen) -> Self {
339            let inner = u16::arbitrary(g);
340
341            Self(MASK16_RANKS & inner)
342        }
343    }
344
345    #[test]
346    fn test_empty() {
347        assert_eq!(Rank16::empty(), Rank16(0));
348        assert!(Rank16::empty().is_empty());
349        assert!(!Rank16(1).is_empty());
350    }
351
352    #[quickcheck]
353    fn test_set_and_contains(r: Rank) {
354        let mut ranks = Rank16::empty();
355
356        ranks.set(r);
357
358        assert!(!ranks.is_empty());
359        assert!(ranks.contains_rank(r));
360
361        ranks.unset(r);
362
363        assert!(ranks.is_empty());
364        assert!(!ranks.contains_rank(r));
365    }
366
367    #[quickcheck]
368    fn test_u16(i: u16) -> TestResult {
369        if i > 0b1_1111_1111_1111 {
370            return TestResult::discard();
371        }
372
373        assert_eq!(Rank16(i), Rank16::from_u16(i));
374        assert_eq!(i, Rank16(i).to_u16());
375
376        TestResult::passed()
377    }
378
379    #[quickcheck]
380    fn test_from_rank(r1: Rank, r2: Rank) {
381        let ranks = Rank16::from(r1);
382
383        assert!(ranks.contains_rank(r1));
384
385        let ranks = Rank16::from([r1, r2].as_ref());
386
387        assert!(ranks.contains_rank(r1));
388        assert!(ranks.contains_rank(r2));
389    }
390
391    #[test]
392    fn test_bit_not() {
393        assert_eq!((!Rank16::default()).to_u16(), MASK16_RANKS);
394    }
395
396    #[quickcheck]
397    fn test_bit_and(r1: Rank, r2: Rank) {
398        let a = Rank16::from(r1);
399        let b = Rank16::from(r2);
400
401        assert_eq!((a & b).is_empty(), r1 != r2);
402    }
403
404    #[quickcheck]
405    fn test_bit_or(r1: Rank, r2: Rank) {
406        let a = Rank16::from(r1);
407        let b = Rank16::from(r2);
408
409        assert!((a | b).contains_rank(r1));
410        assert!((a | b).contains_rank(r2));
411    }
412
413    #[quickcheck]
414    fn test_count(r1: Rank, r2: Rank) {
415        let ranks = Rank16::from([r1, r2].as_ref());
416
417        let count = if r1 == r2 { 1 } else { 2 };
418
419        assert_eq!(count, ranks.count());
420    }
421
422    #[quickcheck]
423    fn test_min_max_rank(cards: CardN<3>) {
424        let ranks = Rank16::from(cards.as_ref());
425
426        let min_r = ranks.min_rank().unwrap();
427        let max_r = ranks.max_rank().unwrap();
428
429        let min_i = cards
430            .as_ref()
431            .iter()
432            .map(|c| c.rank as usize)
433            .min()
434            .unwrap();
435        let max_i = cards
436            .as_ref()
437            .iter()
438            .map(|c| c.rank as usize)
439            .max()
440            .unwrap();
441
442        for c in cards {
443            let r = Rank16::from(&[c] as &[Card]);
444            assert_eq!(c.rank, r.min_rank().unwrap());
445            assert_eq!(c.rank, r.max_rank().unwrap());
446        }
447
448        assert_eq!(min_i, min_r as usize);
449        assert_eq!(max_i, max_r as usize);
450        assert_eq!(None, Rank16::empty().min_rank());
451        assert_eq!(None, Rank16::empty().max_rank());
452    }
453
454    #[test]
455    fn test_nth_rank() {
456        let ranks = r16!("256KA");
457
458        assert_eq!(ranks.nth_rank(0), None);
459        assert_eq!(ranks.nth_rank(1), Some(Rank::RA));
460        assert_eq!(ranks.nth_rank(2), Some(Rank::RK));
461        assert_eq!(ranks.nth_rank(3), Some(Rank::R6));
462        assert_eq!(ranks.nth_rank(4), Some(Rank::R5));
463        assert_eq!(ranks.nth_rank(5), Some(Rank::R2));
464        assert_eq!(ranks.nth_rank(6), None);
465    }
466
467    #[test]
468    fn test_higher_of() {
469        assert_eq!(r16!("KA"), Rank16::higher_of(r16!("2Q")));
470        assert_eq!(!Rank16::default(), Rank16::higher_of(r16!("")));
471        assert_eq!(Rank16::default(), Rank16::higher_of(r16!("A")));
472    }
473
474    #[quickcheck]
475    fn test_from_card64(cards: Vec<Card>) -> TestResult {
476        let mut ranks = Rank16::empty();
477
478        for i in 0..cards.len() {
479            ranks.set(cards[i].rank);
480
481            let c64: Card64 = cards[0..=i].into();
482
483            assert_eq!(Rank16::from(c64), ranks);
484        }
485
486        TestResult::passed()
487    }
488
489    #[test]
490    fn test_u16_to_rank_str() {
491        assert_eq!(u16_to_rank_str(0), "");
492        assert_eq!(u16_to_rank_str(1), "2");
493        assert_eq!(u16_to_rank_str(0b1), "2");
494        assert_eq!(u16_to_rank_str(0b10), "3");
495        assert_eq!(u16_to_rank_str(0b11), "23");
496        assert_eq!(u16_to_rank_str(0b1_0000_0000_0000), "A");
497        assert_eq!(u16_to_rank_str(0b1_0000_0000_0001), "2A");
498        assert_eq!(u16_to_rank_str(0b1_1111_1111_1111), "23456789TJQKA");
499    }
500
501    #[test]
502    fn test_debug() {
503        let s = format!("{:?}", r16!("J") | r16!("9"));
504        assert_eq!(s, "Rank16<9J>");
505    }
506}