2017-10-20 92 views
1

我想實現一個依賴於模冪運算的算法。我找不到像u64(僅適用於bigint)等原生類型的任何模冪運算構造,所以我想我會編碼一個標準modular exponentiation by repeated squaring method如何才能要求對泛型類型的引用可以與泛型類型進行比較?

這就是我想出了:

fn powm(base: &u64, exponent: &u64, modulus: &u64) -> u64 { 
    if *modulus == 1u64 { 
     0 
    } else { 
     let mut result = 1; 
     let mut base = self % modulus; 
     let mut exp = *exponent; 
     while exp > 0 { 
      if exp % 2 == 1 { 
       result = (result * base) % modulus; 
      } 
      exp >>= 1; 
      base = (base * base) % modulus; 
     } 
     result 
    } 
} 

這工作得很好。現在,我想使這個函數是通用的,這樣它也可以用於除u64以外的數字類型。這是我開始有點失落的地方。

我發現了num箱子,它具有指定基本數值操作的Num特徵。分離出一個新的特點PowM,創造了一堆特質界後,我結束了:

extern crate num; 

use num::Num; 
use std::ops::{ShrAssign,Rem}; 

pub trait PowM { 
    fn powm(&self, exponent: &Self, modulus: &Self) -> Self; 
} 

pub trait Two { 
    fn two() -> Self; 
} 

impl Two for u64 { 
    fn two() -> u64 { return 2u64 } 
} 

impl Two for usize { 
    fn two() -> usize { return 2usize } 
} 

impl<T> PowM for T 
    where T: Num + Two + ShrAssign<T> + Rem<T> + PartialOrd<T> { 
    fn powm(&self, exponent: &T, modulus: &T) -> T { 
     if modulus == T::one() { 
      T::zero() 
     } else { 
      let mut result = T::one(); 
      let mut base = *self % *modulus; 
      let mut exp = *exponent; 
      while exp > T::zero() { 
       if exp % T::two() == T::one() { 
        result = (result * base) % *modulus; 
       } 
       exp >>= T::one(); 
       base = (base * base) % *modulus; 
      } 
      result 
     } 
    } 
} 

唯一的抱怨編譯器爲在以下

error[E0277]: the trait bound `&T: std::cmp::PartialEq<T>` is not satisfied 
    | 
30 |   if modulus == T::one() { 
    |     ^^ can't compare `&T` with `T` 
    | 
    = help: the trait `std::cmp::PartialEq<T>` is not implemented for `&T` 
    = help: consider adding a `where &T: std::cmp::PartialEq<T>` bound 

我想添加特質界限,但最終追了很多關於我的壽命並不完全瞭解編譯器錯誤的,並最終堅持了以下內容:

impl<'a, T> PowM for T 
    where T: 'a + Num + Two + ShrAssign<T> + Rem<T> + PartialOrd<T>, 
      &'a T: PartialEq<T> { 
    fn powm(&self, exponent: &T, modulus: &T) -> T { 
     if modulus == T::one() { 
[...] 

仍然給人錯誤。我該如何解決?

回答

2

您可以忽視的問題,並參考或非參考參考比較非參考:

if modulus == &T::one() { 
// Or 
if *modulus == T::one() { 

或者你可以使用更高的排名特質界定

impl<T> PowM for T 
where 
    T: Num + Two + ShrAssign<T> + Rem<T> + PartialOrd<T>, 
    for <'a> &'a T: PartialEq<T>, 
{ 
    // ... 
} 

在任何一種情況下,您都需要要求T執行Copy或實施Clone,然後將適當的呼叫添加到.clone()

參見: