LoginSignup
8
2

More than 3 years have passed since last update.

[Rust] IntegerとFloatの両方でmaxが必要なとき

Last updated at Posted at 2019-12-05

TL;DR

i32にもf32にもmaxを使うような関数max(a:T, b:T)を作るときは,ジェネリック境界にPartialOrdを使いましょう.

max2dをジェネリックにしたい

2次元の行列からmaxを計算する関数があったとしましょう.

use ndarray::*;
use std::f32;

pub fn max2d_f32(input: &Array2<f32>) -> Array1<f32> 
{
    input.fold_axis(Axis(1), f32::MIN, |m, i| (*m).max(*i))
}

これをi32でも動くようにしたい.

pub fn max2d_i32(input: &Array2<i32>) -> Array1<i32> 
{
    input.fold_axis(Axis(1), i32::MIN, |m, i| (*m).max(*i))
}

これだと,使うとき分岐しなきゃいけないし,f64にも対応したいってときに関数が増えていく.

そこで,ジェネリックにするために

use ndarray::*;
use num_traits::bounds::Bounded;

fn max<T:PartialOrd>(a:T, b:T)-> T { if a > b {a} else{b}}
pub fn max2d<T>(input: &Array2<T>) -> Array1<T>
where T: Clone + Copy + Bounded + PartialOrd
{
    input.fold_axis(Axis(1), T::min_value(), |m, i| max(*m, *i))
}

と書けばOK.

maxはTがOrdという前提なんだけど,f32はNanがあるためにPartialOrd,という点に注意して書けば,
大丈夫!

動作確認用
use ndarray::*;
use ndarray_rand::RandomExt;
use ndarray_rand::rand_distr::Uniform;
use std::f32;
use std::i32;
use num_traits::bounds::Bounded;

pub fn max2d_f32(input: &Array2<f32>) -> Array1<f32> 
{
    input.fold_axis(Axis(1), f32::MIN, |m, i| (*m).max(*i))
}

pub fn max2d_i32(input: &Array2<i32>) -> Array1<i32> 
{
    input.fold_axis(Axis(1), i32::MIN, |m, i| (*m).max(*i))
}

fn max<T:PartialOrd>(a:T, b:T)-> T { if a > b {a} else{b}}
pub fn max2d<T>(input: &Array2<T>) -> Array1<T>
where T: Clone + Copy + Bounded + PartialOrd
{
    input.fold_axis(Axis(1), T::min_value(), |m, i| max(*m, *i))
}

fn main() {
    let a = Array::random((10000, 1000), Uniform::new(0., 10.));
    let b = Array::random((10000, 1000), Uniform::new(0, 100));

    println!("{:8.4}", max2d_f32(&a));
    println!("{:8.4}", max2d(&a));
    println!("{:8.4}", max2d_i32(&b));
    println!("{:8.4}", max2d(&b));

}

必要なジェネリック境界が減ると,もっとスッキリするんだけど.

8
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
8
2