feat!: add bounded slices for eval_5hand and eval_7hand
authorMA Beaudet <ma@beaudet.xyz>
Sun, 7 Nov 2021 19:49:07 +0000 (20:49 +0100)
committerMA Beaudet <ma@beaudet.xyz>
Sun, 7 Nov 2021 19:49:07 +0000 (20:49 +0100)
eval_5hand now transmutes (unsafe rust) the `&[Card; 5]`. It "should" not
be unsafe as Card has the same repr as u32.
Looking for suggestions on how to convert slice newtype to inner.

src/lib.rs

index 6a72610..d102a5a 100644 (file)
@@ -7,6 +7,7 @@ pub mod constants;
 use std::{
     collections::HashMap,
     convert::{TryFrom, TryInto},
+    mem::transmute,
     rc::Rc,
     str::FromStr,
     sync::{Arc, Mutex},
@@ -116,7 +117,9 @@ impl Evaluator {
                 .hands
                 .iter()
                 .map(|player| match self.algorithm {
-                    Algorithm::CactusKev => self.eval_5hand(player.as_ref().clone()),
+                    Algorithm::CactusKev => {
+                        self.eval_5hand(&player.as_ref().0[..5].try_into().unwrap())
+                    }
                 })
                 .enumerate()
                 .collect(),
@@ -132,7 +135,7 @@ impl Evaluator {
                         .collect()
                 })
                 .map(|player: Vec<Card>| match self.algorithm {
-                    Algorithm::CactusKev => self.eval_7hand(Cards(player)),
+                    Algorithm::CactusKev => self.eval_7hand(&player.try_into().unwrap()),
                 })
                 .enumerate()
                 .collect(),
@@ -140,33 +143,29 @@ impl Evaluator {
         result
     }
 
-    pub fn eval_5hand(&self, cards: Cards) -> u16 {
-        let cards: Vec<u32> = cards.0.into_iter().map(|c| u32::from(c)).collect();
-        if let [c1, c2, c3, c4, c5] = cards[..5] {
-            let mut q = (c1 | c2 | c3 | c4 | c5) >> 16;
-            if c1 & c2 & c3 & c4 & c5 & 0xF000 != 0 {
-                FLUSHES[q as usize]
-            } else if UNIQUE5[q as usize] != 0 {
-                UNIQUE5[q as usize]
-            } else {
-                q = (c1 & 0xff) * (c2 & 0xff) * (c3 & 0xff) * (c4 & 0xff) * (c5 & 0xff);
-                HASH_VALUES[find_fast((q as usize).try_into().unwrap()) as usize]
-            }
+    pub fn eval_5hand(&self, cards: &[Card; 5]) -> u16 {
+        let [c1, c2, c3, c4, c5]: &[u32; 5] = unsafe { transmute(cards) };
+        let q = (c1 | c2 | c3 | c4 | c5) >> 16;
+        if c1 & c2 & c3 & c4 & c5 & 0xF000 != 0 {
+            FLUSHES[q as usize]
+        } else if UNIQUE5[q as usize] != 0 {
+            UNIQUE5[q as usize]
         } else {
-            9999
+            let q = (c1 & 0xff) * (c2 & 0xff) * (c3 & 0xff) * (c4 & 0xff) * (c5 & 0xff);
+            HASH_VALUES[find_fast(q) as usize]
         }
     }
 
     /// Non-optimized method of determining the best five-card hand possible of seven cards.
-    pub fn eval_7hand(&self, cards: Cards) -> u16 {
+    pub fn eval_7hand(&self, cards: &[Card; 7]) -> u16 {
         let mut subhand: [Card; 5] = [Card(0); 5];
         let mut best = 9999;
 
         for i in 0..21 {
             for j in 0..5 {
-                subhand[j] = cards.0[..][PERM7[i][j] as usize];
+                subhand[j] = cards[..][PERM7[i][j] as usize];
             }
-            let q = self.eval_5hand(Cards(subhand.into()));
+            let q = self.eval_5hand(&subhand);
             if q < best {
                 best = q;
             }