Auto merge of #4897 - krishna-veerareddy:issue-2040-accurate-float-functions, r=flip1995

Add lint to improve floating-point expressions

Looks for floating-point expressions that can be expressed using built-in methods to improve accuracy, performance and/or succinctness.

changelog: Add lint `floating_point_improvements`.

Fixes #4726
Partly addresses [#2040](https://github.com/rust-lang/rust-clippy/issues/2040)

Currently linted expressions:

| Expression | Suggestion |
|---------------------------------|------------|
| x.log(2.0) | x.log2() |
| x.log(10.0) | x.log10() |
| x.log(std::f32::consts::E) | x.ln() |
| (1 + x).ln() | x.ln_1p() |
| (2.0).powf(x) | x.exp2() |
| (std::f32::consts::E).powf(x) | x.exp() |
| x.powf(1/2) | x.sqrt() |
| x.powf(1/3) | x.cbrt() |
| x.powf(y), where y is whole | x.powi(y) |
| x.exp() - 1 | x.exp_m1() |
|x * y + z|x.mul_add(y, z)|
This commit is contained in:
bors 2020-02-24 08:33:03 +00:00
commit 2734e4e1f7
23 changed files with 1092 additions and 263 deletions

View file

@ -1169,6 +1169,7 @@ Released 2018-09-13
[`ifs_same_cond`]: https://rust-lang.github.io/rust-clippy/master/index.html#ifs_same_cond
[`implicit_hasher`]: https://rust-lang.github.io/rust-clippy/master/index.html#implicit_hasher
[`implicit_return`]: https://rust-lang.github.io/rust-clippy/master/index.html#implicit_return
[`imprecise_flops`]: https://rust-lang.github.io/rust-clippy/master/index.html#imprecise_flops
[`inconsistent_digit_grouping`]: https://rust-lang.github.io/rust-clippy/master/index.html#inconsistent_digit_grouping
[`indexing_slicing`]: https://rust-lang.github.io/rust-clippy/master/index.html#indexing_slicing
[`ineffective_bit_mask`]: https://rust-lang.github.io/rust-clippy/master/index.html#ineffective_bit_mask
@ -1210,7 +1211,6 @@ Released 2018-09-13
[`lossy_float_literal`]: https://rust-lang.github.io/rust-clippy/master/index.html#lossy_float_literal
[`main_recursion`]: https://rust-lang.github.io/rust-clippy/master/index.html#main_recursion
[`manual_memcpy`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_memcpy
[`manual_mul_add`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_mul_add
[`manual_saturating_arithmetic`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_saturating_arithmetic
[`manual_swap`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_swap
[`many_single_char_names`]: https://rust-lang.github.io/rust-clippy/master/index.html#many_single_char_names
@ -1349,6 +1349,7 @@ Released 2018-09-13
[`string_lit_as_bytes`]: https://rust-lang.github.io/rust-clippy/master/index.html#string_lit_as_bytes
[`string_to_string`]: https://rust-lang.github.io/rust-clippy/master/index.html#string_to_string
[`struct_excessive_bools`]: https://rust-lang.github.io/rust-clippy/master/index.html#struct_excessive_bools
[`suboptimal_flops`]: https://rust-lang.github.io/rust-clippy/master/index.html#suboptimal_flops
[`suspicious_arithmetic_impl`]: https://rust-lang.github.io/rust-clippy/master/index.html#suspicious_arithmetic_impl
[`suspicious_assignment_formatting`]: https://rust-lang.github.io/rust-clippy/master/index.html#suspicious_assignment_formatting
[`suspicious_else_formatting`]: https://rust-lang.github.io/rust-clippy/master/index.html#suspicious_else_formatting

View file

@ -5,7 +5,7 @@
A collection of lints to catch common mistakes and improve your [Rust](https://github.com/rust-lang/rust) code.
[There are 357 lints included in this crate!](https://rust-lang.github.io/rust-clippy/master/index.html)
[There are 358 lints included in this crate!](https://rust-lang.github.io/rust-clippy/master/index.html)
We have a bunch of lint categories to allow you to choose how much Clippy is supposed to ~~annoy~~ help you:

View file

@ -0,0 +1,380 @@
use crate::consts::{
constant, Constant,
Constant::{F32, F64},
};
use crate::utils::{span_lint_and_sugg, sugg};
use if_chain::if_chain;
use rustc::ty;
use rustc_errors::Applicability;
use rustc_hir::{BinOpKind, Expr, ExprKind, UnOp};
use rustc_lint::{LateContext, LateLintPass};
use rustc_session::{declare_lint_pass, declare_tool_lint};
use rustc_span::source_map::Spanned;
use std::f32::consts as f32_consts;
use std::f64::consts as f64_consts;
use sugg::{format_numeric_literal, Sugg};
use syntax::ast;
declare_clippy_lint! {
/// **What it does:** Looks for floating-point expressions that
/// can be expressed using built-in methods to improve accuracy
/// at the cost of performance.
///
/// **Why is this bad?** Negatively impacts accuracy.
///
/// **Known problems:** None
///
/// **Example:**
///
/// ```rust
///
/// let a = 3f32;
/// let _ = a.powf(1.0 / 3.0);
/// let _ = (1.0 + a).ln();
/// let _ = a.exp() - 1.0;
/// ```
///
/// is better expressed as
///
/// ```rust
///
/// let a = 3f32;
/// let _ = a.cbrt();
/// let _ = a.ln_1p();
/// let _ = a.exp_m1();
/// ```
pub IMPRECISE_FLOPS,
nursery,
"usage of imprecise floating point operations"
}
declare_clippy_lint! {
/// **What it does:** Looks for floating-point expressions that
/// can be expressed using built-in methods to improve both
/// accuracy and performance.
///
/// **Why is this bad?** Negatively impacts accuracy and performance.
///
/// **Known problems:** None
///
/// **Example:**
///
/// ```rust
/// use std::f32::consts::E;
///
/// let a = 3f32;
/// let _ = (2f32).powf(a);
/// let _ = E.powf(a);
/// let _ = a.powf(1.0 / 2.0);
/// let _ = a.log(2.0);
/// let _ = a.log(10.0);
/// let _ = a.log(E);
/// let _ = a.powf(2.0);
/// let _ = a * 2.0 + 4.0;
/// ```
///
/// is better expressed as
///
/// ```rust
/// use std::f32::consts::E;
///
/// let a = 3f32;
/// let _ = a.exp2();
/// let _ = a.exp();
/// let _ = a.sqrt();
/// let _ = a.log2();
/// let _ = a.log10();
/// let _ = a.ln();
/// let _ = a.powi(2);
/// let _ = a.mul_add(2.0, 4.0);
/// ```
pub SUBOPTIMAL_FLOPS,
nursery,
"usage of sub-optimal floating point operations"
}
declare_lint_pass!(FloatingPointArithmetic => [
IMPRECISE_FLOPS,
SUBOPTIMAL_FLOPS
]);
// Returns the specialized log method for a given base if base is constant
// and is one of 2, 10 and e
fn get_specialized_log_method(cx: &LateContext<'_, '_>, base: &Expr<'_>) -> Option<&'static str> {
if let Some((value, _)) = constant(cx, cx.tables, base) {
if F32(2.0) == value || F64(2.0) == value {
return Some("log2");
} else if F32(10.0) == value || F64(10.0) == value {
return Some("log10");
} else if F32(f32_consts::E) == value || F64(f64_consts::E) == value {
return Some("ln");
}
}
None
}
// Adds type suffixes and parenthesis to method receivers if necessary
fn prepare_receiver_sugg<'a>(cx: &LateContext<'_, '_>, mut expr: &'a Expr<'a>) -> Sugg<'a> {
let mut suggestion = Sugg::hir(cx, expr, "..");
if let ExprKind::Unary(UnOp::UnNeg, inner_expr) = &expr.kind {
expr = &inner_expr;
}
if_chain! {
// if the expression is a float literal and it is unsuffixed then
// add a suffix so the suggestion is valid and unambiguous
if let ty::Float(float_ty) = cx.tables.expr_ty(expr).kind;
if let ExprKind::Lit(lit) = &expr.kind;
if let ast::LitKind::Float(sym, ast::LitFloatType::Unsuffixed) = lit.node;
then {
let op = format!(
"{}{}{}",
suggestion,
// Check for float literals without numbers following the decimal
// separator such as `2.` and adds a trailing zero
if sym.as_str().ends_with('.') {
"0"
} else {
""
},
float_ty.name_str()
).into();
suggestion = match suggestion {
Sugg::MaybeParen(_) => Sugg::MaybeParen(op),
_ => Sugg::NonParen(op)
};
}
}
suggestion.maybe_par()
}
fn check_log_base(cx: &LateContext<'_, '_>, expr: &Expr<'_>, args: &[Expr<'_>]) {
if let Some(method) = get_specialized_log_method(cx, &args[1]) {
span_lint_and_sugg(
cx,
SUBOPTIMAL_FLOPS,
expr.span,
"logarithm for bases 2, 10 and e can be computed more accurately",
"consider using",
format!("{}.{}()", Sugg::hir(cx, &args[0], ".."), method),
Applicability::MachineApplicable,
);
}
}
// TODO: Lint expressions of the form `(x + y).ln()` where y > 1 and
// suggest usage of `(x + (y - 1)).ln_1p()` instead
fn check_ln1p(cx: &LateContext<'_, '_>, expr: &Expr<'_>, args: &[Expr<'_>]) {
if let ExprKind::Binary(
Spanned {
node: BinOpKind::Add, ..
},
lhs,
rhs,
) = &args[0].kind
{
let recv = match (constant(cx, cx.tables, lhs), constant(cx, cx.tables, rhs)) {
(Some((value, _)), _) if F32(1.0) == value || F64(1.0) == value => rhs,
(_, Some((value, _))) if F32(1.0) == value || F64(1.0) == value => lhs,
_ => return,
};
span_lint_and_sugg(
cx,
IMPRECISE_FLOPS,
expr.span,
"ln(1 + x) can be computed more accurately",
"consider using",
format!("{}.ln_1p()", prepare_receiver_sugg(cx, recv)),
Applicability::MachineApplicable,
);
}
}
// Returns an integer if the float constant is a whole number and it can be
// converted to an integer without loss of precision. For now we only check
// ranges [-16777215, 16777216) for type f32 as whole number floats outside
// this range are lossy and ambiguous.
#[allow(clippy::cast_possible_truncation)]
fn get_integer_from_float_constant(value: &Constant) -> Option<i32> {
match value {
F32(num) if num.fract() == 0.0 => {
if (-16_777_215.0..16_777_216.0).contains(num) {
Some(num.round() as i32)
} else {
None
}
},
F64(num) if num.fract() == 0.0 => {
if (-2_147_483_648.0..2_147_483_648.0).contains(num) {
Some(num.round() as i32)
} else {
None
}
},
_ => None,
}
}
fn check_powf(cx: &LateContext<'_, '_>, expr: &Expr<'_>, args: &[Expr<'_>]) {
// Check receiver
if let Some((value, _)) = constant(cx, cx.tables, &args[0]) {
let method = if F32(f32_consts::E) == value || F64(f64_consts::E) == value {
"exp"
} else if F32(2.0) == value || F64(2.0) == value {
"exp2"
} else {
return;
};
span_lint_and_sugg(
cx,
SUBOPTIMAL_FLOPS,
expr.span,
"exponent for bases 2 and e can be computed more accurately",
"consider using",
format!("{}.{}()", prepare_receiver_sugg(cx, &args[1]), method),
Applicability::MachineApplicable,
);
}
// Check argument
if let Some((value, _)) = constant(cx, cx.tables, &args[1]) {
let (lint, help, suggestion) = if F32(1.0 / 2.0) == value || F64(1.0 / 2.0) == value {
(
SUBOPTIMAL_FLOPS,
"square-root of a number can be computed more efficiently and accurately",
format!("{}.sqrt()", Sugg::hir(cx, &args[0], "..")),
)
} else if F32(1.0 / 3.0) == value || F64(1.0 / 3.0) == value {
(
IMPRECISE_FLOPS,
"cube-root of a number can be computed more accurately",
format!("{}.cbrt()", Sugg::hir(cx, &args[0], "..")),
)
} else if let Some(exponent) = get_integer_from_float_constant(&value) {
(
SUBOPTIMAL_FLOPS,
"exponentiation with integer powers can be computed more efficiently",
format!(
"{}.powi({})",
Sugg::hir(cx, &args[0], ".."),
format_numeric_literal(&exponent.to_string(), None, false)
),
)
} else {
return;
};
span_lint_and_sugg(
cx,
lint,
expr.span,
help,
"consider using",
suggestion,
Applicability::MachineApplicable,
);
}
}
// TODO: Lint expressions of the form `x.exp() - y` where y > 1
// and suggest usage of `x.exp_m1() - (y - 1)` instead
fn check_expm1(cx: &LateContext<'_, '_>, expr: &Expr<'_>) {
if_chain! {
if let ExprKind::Binary(Spanned { node: BinOpKind::Sub, .. }, ref lhs, ref rhs) = expr.kind;
if cx.tables.expr_ty(lhs).is_floating_point();
if let Some((value, _)) = constant(cx, cx.tables, rhs);
if F32(1.0) == value || F64(1.0) == value;
if let ExprKind::MethodCall(ref path, _, ref method_args) = lhs.kind;
if cx.tables.expr_ty(&method_args[0]).is_floating_point();
if path.ident.name.as_str() == "exp";
then {
span_lint_and_sugg(
cx,
IMPRECISE_FLOPS,
expr.span,
"(e.pow(x) - 1) can be computed more accurately",
"consider using",
format!(
"{}.exp_m1()",
Sugg::hir(cx, &method_args[0], "..")
),
Applicability::MachineApplicable,
);
}
}
}
fn is_float_mul_expr<'a>(cx: &LateContext<'_, '_>, expr: &'a Expr<'a>) -> Option<(&'a Expr<'a>, &'a Expr<'a>)> {
if_chain! {
if let ExprKind::Binary(Spanned { node: BinOpKind::Mul, .. }, ref lhs, ref rhs) = &expr.kind;
if cx.tables.expr_ty(lhs).is_floating_point();
if cx.tables.expr_ty(rhs).is_floating_point();
then {
return Some((lhs, rhs));
}
}
None
}
// TODO: Fix rust-lang/rust-clippy#4735
fn check_mul_add(cx: &LateContext<'_, '_>, expr: &Expr<'_>) {
if let ExprKind::Binary(
Spanned {
node: BinOpKind::Add, ..
},
lhs,
rhs,
) = &expr.kind
{
let (recv, arg1, arg2) = if let Some((inner_lhs, inner_rhs)) = is_float_mul_expr(cx, lhs) {
(inner_lhs, inner_rhs, rhs)
} else if let Some((inner_lhs, inner_rhs)) = is_float_mul_expr(cx, rhs) {
(inner_lhs, inner_rhs, lhs)
} else {
return;
};
span_lint_and_sugg(
cx,
SUBOPTIMAL_FLOPS,
expr.span,
"multiply and add expressions can be calculated more efficiently and accurately",
"consider using",
format!(
"{}.mul_add({}, {})",
prepare_receiver_sugg(cx, recv),
Sugg::hir(cx, arg1, ".."),
Sugg::hir(cx, arg2, ".."),
),
Applicability::MachineApplicable,
);
}
}
impl<'a, 'tcx> LateLintPass<'a, 'tcx> for FloatingPointArithmetic {
fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr<'_>) {
if let ExprKind::MethodCall(ref path, _, args) = &expr.kind {
let recv_ty = cx.tables.expr_ty(&args[0]);
if recv_ty.is_floating_point() {
match &*path.ident.name.as_str() {
"ln" => check_ln1p(cx, expr, args),
"log" => check_log_base(cx, expr, args),
"powf" => check_powf(cx, expr, args),
_ => {},
}
}
} else {
check_expm1(cx, expr);
check_mul_add(cx, expr);
}
}
}

View file

@ -208,6 +208,7 @@ pub mod exit;
pub mod explicit_write;
pub mod fallible_impl_from;
pub mod float_literal;
pub mod floating_point_arithmetic;
pub mod format;
pub mod formatting;
pub mod functions;
@ -248,7 +249,6 @@ pub mod missing_const_for_fn;
pub mod missing_doc;
pub mod missing_inline;
pub mod modulo_arithmetic;
pub mod mul_add;
pub mod multiple_crate_versions;
pub mod mut_key;
pub mod mut_mut;
@ -538,6 +538,8 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
&fallible_impl_from::FALLIBLE_IMPL_FROM,
&float_literal::EXCESSIVE_PRECISION,
&float_literal::LOSSY_FLOAT_LITERAL,
&floating_point_arithmetic::IMPRECISE_FLOPS,
&floating_point_arithmetic::SUBOPTIMAL_FLOPS,
&format::USELESS_FORMAT,
&formatting::POSSIBLE_MISSING_COMMA,
&formatting::SUSPICIOUS_ASSIGNMENT_FORMATTING,
@ -690,7 +692,6 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
&missing_doc::MISSING_DOCS_IN_PRIVATE_ITEMS,
&missing_inline::MISSING_INLINE_IN_PUBLIC_ITEMS,
&modulo_arithmetic::MODULO_ARITHMETIC,
&mul_add::MANUAL_MUL_ADD,
&multiple_crate_versions::MULTIPLE_CRATE_VERSIONS,
&mut_key::MUTABLE_KEY_TYPE,
&mut_mut::MUT_MUT,
@ -966,7 +967,6 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
store.register_late_pass(|| box inherent_to_string::InherentToString);
store.register_late_pass(|| box trait_bounds::TraitBounds);
store.register_late_pass(|| box comparison_chain::ComparisonChain);
store.register_late_pass(|| box mul_add::MulAddCheck);
store.register_late_pass(|| box mut_key::MutableKeyType);
store.register_late_pass(|| box modulo_arithmetic::ModuloArithmetic);
store.register_early_pass(|| box reference::DerefAddrOf);
@ -1000,6 +1000,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
store.register_late_pass(|| box to_digit_is_some::ToDigitIsSome);
let array_size_threshold = conf.array_size_threshold;
store.register_late_pass(move || box large_stack_arrays::LargeStackArrays::new(array_size_threshold));
store.register_late_pass(move || box floating_point_arithmetic::FloatingPointArithmetic);
store.register_early_pass(|| box as_conversions::AsConversions);
store.register_early_pass(|| box utils::internal_lints::ProduceIce);
store.register_late_pass(|| box let_underscore::LetUnderscore);
@ -1648,8 +1649,9 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
store.register_group(true, "clippy::nursery", Some("clippy_nursery"), vec![
LintId::of(&attrs::EMPTY_LINE_AFTER_OUTER_ATTR),
LintId::of(&fallible_impl_from::FALLIBLE_IMPL_FROM),
LintId::of(&floating_point_arithmetic::IMPRECISE_FLOPS),
LintId::of(&floating_point_arithmetic::SUBOPTIMAL_FLOPS),
LintId::of(&missing_const_for_fn::MISSING_CONST_FOR_FN),
LintId::of(&mul_add::MANUAL_MUL_ADD),
LintId::of(&mutable_debug_assertion::DEBUG_ASSERT_WITH_MUT_CALL),
LintId::of(&mutex_atomic::MUTEX_INTEGER),
LintId::of(&needless_borrow::NEEDLESS_BORROW),

View file

@ -1,111 +0,0 @@
use rustc_errors::Applicability;
use rustc_hir::{BinOpKind, Expr, ExprKind};
use rustc_lint::{LateContext, LateLintPass};
use rustc_session::{declare_lint_pass, declare_tool_lint};
use crate::utils::{snippet, span_lint_and_sugg};
declare_clippy_lint! {
/// **What it does:** Checks for expressions of the form `a * b + c`
/// or `c + a * b` where `a`, `b`, `c` are floats and suggests using
/// `a.mul_add(b, c)` instead.
///
/// **Why is this bad?** Calculating `a * b + c` may lead to slight
/// numerical inaccuracies as `a * b` is rounded before being added to
/// `c`. Depending on the target architecture, `mul_add()` may be more
/// performant.
///
/// **Known problems:** This lint can emit semantic incorrect suggestions.
/// For example, for `a * b * c + d` the suggestion `a * b.mul_add(c, d)`
/// is emitted, which is equivalent to `a * (b * c + d)`. (#4735)
///
/// **Example:**
///
/// ```rust
/// # let a = 0_f32;
/// # let b = 0_f32;
/// # let c = 0_f32;
/// let foo = (a * b) + c;
/// ```
///
/// can be written as
///
/// ```rust
/// # let a = 0_f32;
/// # let b = 0_f32;
/// # let c = 0_f32;
/// let foo = a.mul_add(b, c);
/// ```
pub MANUAL_MUL_ADD,
nursery,
"Using `a.mul_add(b, c)` for floating points has higher numerical precision than `a * b + c`"
}
declare_lint_pass!(MulAddCheck => [MANUAL_MUL_ADD]);
fn is_float<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, expr: &Expr<'_>) -> bool {
cx.tables.expr_ty(expr).is_floating_point()
}
// Checks whether expression is multiplication of two floats
fn is_float_mult_expr<'a, 'tcx, 'b>(
cx: &LateContext<'a, 'tcx>,
expr: &'b Expr<'b>,
) -> Option<(&'b Expr<'b>, &'b Expr<'b>)> {
if let ExprKind::Binary(op, lhs, rhs) = &expr.kind {
if let BinOpKind::Mul = op.node {
if is_float(cx, &lhs) && is_float(cx, &rhs) {
return Some((&lhs, &rhs));
}
}
}
None
}
impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MulAddCheck {
fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr<'_>) {
if let ExprKind::Binary(op, lhs, rhs) = &expr.kind {
if let BinOpKind::Add = op.node {
//Converts mult_lhs * mult_rhs + rhs to mult_lhs.mult_add(mult_rhs, rhs)
if let Some((mult_lhs, mult_rhs)) = is_float_mult_expr(cx, lhs) {
if is_float(cx, rhs) {
span_lint_and_sugg(
cx,
MANUAL_MUL_ADD,
expr.span,
"consider using `mul_add()` for better numerical precision",
"try",
format!(
"{}.mul_add({}, {})",
snippet(cx, mult_lhs.span, "_"),
snippet(cx, mult_rhs.span, "_"),
snippet(cx, rhs.span, "_"),
),
Applicability::MaybeIncorrect,
);
}
}
//Converts lhs + mult_lhs * mult_rhs to mult_lhs.mult_add(mult_rhs, lhs)
if let Some((mult_lhs, mult_rhs)) = is_float_mult_expr(cx, rhs) {
if is_float(cx, lhs) {
span_lint_and_sugg(
cx,
MANUAL_MUL_ADD,
expr.span,
"consider using `mul_add()` for better numerical precision",
"try",
format!(
"{}.mul_add({}, {})",
snippet(cx, mult_lhs.span, "_"),
snippet(cx, mult_rhs.span, "_"),
snippet(cx, lhs.span, "_"),
),
Applicability::MaybeIncorrect,
);
}
}
}
}
}
}

View file

@ -6,7 +6,7 @@ pub use lint::Lint;
pub use lint::LINT_LEVELS;
// begin lint list, do not remove this comment, its used in `update_lints`
pub const ALL_LINTS: [Lint; 357] = [
pub const ALL_LINTS: [Lint; 358] = [
Lint {
name: "absurd_extreme_comparisons",
group: "correctness",
@ -749,6 +749,13 @@ pub const ALL_LINTS: [Lint; 357] = [
deprecation: None,
module: "implicit_return",
},
Lint {
name: "imprecise_flops",
group: "nursery",
desc: "usage of imprecise floating point operations",
deprecation: None,
module: "floating_point_arithmetic",
},
Lint {
name: "inconsistent_digit_grouping",
group: "style",
@ -1022,13 +1029,6 @@ pub const ALL_LINTS: [Lint; 357] = [
deprecation: None,
module: "loops",
},
Lint {
name: "manual_mul_add",
group: "nursery",
desc: "Using `a.mul_add(b, c)` for floating points has higher numerical precision than `a * b + c`",
deprecation: None,
module: "mul_add",
},
Lint {
name: "manual_saturating_arithmetic",
group: "style",
@ -1960,6 +1960,13 @@ pub const ALL_LINTS: [Lint; 357] = [
deprecation: None,
module: "excessive_bools",
},
Lint {
name: "suboptimal_flops",
group: "nursery",
desc: "usage of sub-optimal floating point operations",
deprecation: None,
module: "floating_point_arithmetic",
},
Lint {
name: "suspicious_arithmetic_impl",
group: "correctness",

View file

@ -0,0 +1,18 @@
// run-rustfix
#![warn(clippy::imprecise_flops)]
fn main() {
let x = 2f32;
let _ = x.exp_m1();
let _ = x.exp_m1() + 2.0;
// Cases where the lint shouldn't be applied
let _ = x.exp() - 2.0;
let _ = x.exp() - 1.0 * 2.0;
let x = 2f64;
let _ = x.exp_m1();
let _ = x.exp_m1() + 2.0;
// Cases where the lint shouldn't be applied
let _ = x.exp() - 2.0;
let _ = x.exp() - 1.0 * 2.0;
}

View file

@ -0,0 +1,18 @@
// run-rustfix
#![warn(clippy::imprecise_flops)]
fn main() {
let x = 2f32;
let _ = x.exp() - 1.0;
let _ = x.exp() - 1.0 + 2.0;
// Cases where the lint shouldn't be applied
let _ = x.exp() - 2.0;
let _ = x.exp() - 1.0 * 2.0;
let x = 2f64;
let _ = x.exp() - 1.0;
let _ = x.exp() - 1.0 + 2.0;
// Cases where the lint shouldn't be applied
let _ = x.exp() - 2.0;
let _ = x.exp() - 1.0 * 2.0;
}

View file

@ -0,0 +1,28 @@
error: (e.pow(x) - 1) can be computed more accurately
--> $DIR/floating_point_exp.rs:6:13
|
LL | let _ = x.exp() - 1.0;
| ^^^^^^^^^^^^^ help: consider using: `x.exp_m1()`
|
= note: `-D clippy::imprecise-flops` implied by `-D warnings`
error: (e.pow(x) - 1) can be computed more accurately
--> $DIR/floating_point_exp.rs:7:13
|
LL | let _ = x.exp() - 1.0 + 2.0;
| ^^^^^^^^^^^^^ help: consider using: `x.exp_m1()`
error: (e.pow(x) - 1) can be computed more accurately
--> $DIR/floating_point_exp.rs:13:13
|
LL | let _ = x.exp() - 1.0;
| ^^^^^^^^^^^^^ help: consider using: `x.exp_m1()`
error: (e.pow(x) - 1) can be computed more accurately
--> $DIR/floating_point_exp.rs:14:13
|
LL | let _ = x.exp() - 1.0 + 2.0;
| ^^^^^^^^^^^^^ help: consider using: `x.exp_m1()`
error: aborting due to 4 previous errors

View file

@ -0,0 +1,58 @@
// run-rustfix
#![allow(dead_code, clippy::double_parens)]
#![warn(clippy::suboptimal_flops, clippy::imprecise_flops)]
const TWO: f32 = 2.0;
const E: f32 = std::f32::consts::E;
fn check_log_base() {
let x = 1f32;
let _ = x.log2();
let _ = x.log10();
let _ = x.ln();
let _ = x.log2();
let _ = x.ln();
let x = 1f64;
let _ = x.log2();
let _ = x.log10();
let _ = x.ln();
}
fn check_ln1p() {
let x = 1f32;
let _ = 2.0f32.ln_1p();
let _ = 2.0f32.ln_1p();
let _ = x.ln_1p();
let _ = (x / 2.0).ln_1p();
let _ = x.powi(2).ln_1p();
let _ = (x.powi(2) / 2.0).ln_1p();
let _ = ((std::f32::consts::E - 1.0)).ln_1p();
let _ = x.ln_1p();
let _ = x.powi(2).ln_1p();
let _ = (x + 2.0).ln_1p();
let _ = (x / 2.0).ln_1p();
// Cases where the lint shouldn't be applied
let _ = (1.0 + x + 2.0).ln();
let _ = (x + 1.0 + 2.0).ln();
let _ = (x + 1.0 / 2.0).ln();
let _ = (1.0 + x - 2.0).ln();
let x = 1f64;
let _ = 2.0f64.ln_1p();
let _ = 2.0f64.ln_1p();
let _ = x.ln_1p();
let _ = (x / 2.0).ln_1p();
let _ = x.powi(2).ln_1p();
let _ = x.ln_1p();
let _ = x.powi(2).ln_1p();
let _ = (x + 2.0).ln_1p();
let _ = (x / 2.0).ln_1p();
// Cases where the lint shouldn't be applied
let _ = (1.0 + x + 2.0).ln();
let _ = (x + 1.0 + 2.0).ln();
let _ = (x + 1.0 / 2.0).ln();
let _ = (1.0 + x - 2.0).ln();
}
fn main() {}

View file

@ -0,0 +1,58 @@
// run-rustfix
#![allow(dead_code, clippy::double_parens)]
#![warn(clippy::suboptimal_flops, clippy::imprecise_flops)]
const TWO: f32 = 2.0;
const E: f32 = std::f32::consts::E;
fn check_log_base() {
let x = 1f32;
let _ = x.log(2f32);
let _ = x.log(10f32);
let _ = x.log(std::f32::consts::E);
let _ = x.log(TWO);
let _ = x.log(E);
let x = 1f64;
let _ = x.log(2f64);
let _ = x.log(10f64);
let _ = x.log(std::f64::consts::E);
}
fn check_ln1p() {
let x = 1f32;
let _ = (1f32 + 2.).ln();
let _ = (1f32 + 2.0).ln();
let _ = (1.0 + x).ln();
let _ = (1.0 + x / 2.0).ln();
let _ = (1.0 + x.powi(2)).ln();
let _ = (1.0 + x.powi(2) / 2.0).ln();
let _ = (1.0 + (std::f32::consts::E - 1.0)).ln();
let _ = (x + 1.0).ln();
let _ = (x.powi(2) + 1.0).ln();
let _ = (x + 2.0 + 1.0).ln();
let _ = (x / 2.0 + 1.0).ln();
// Cases where the lint shouldn't be applied
let _ = (1.0 + x + 2.0).ln();
let _ = (x + 1.0 + 2.0).ln();
let _ = (x + 1.0 / 2.0).ln();
let _ = (1.0 + x - 2.0).ln();
let x = 1f64;
let _ = (1f64 + 2.).ln();
let _ = (1f64 + 2.0).ln();
let _ = (1.0 + x).ln();
let _ = (1.0 + x / 2.0).ln();
let _ = (1.0 + x.powi(2)).ln();
let _ = (x + 1.0).ln();
let _ = (x.powi(2) + 1.0).ln();
let _ = (x + 2.0 + 1.0).ln();
let _ = (x / 2.0 + 1.0).ln();
// Cases where the lint shouldn't be applied
let _ = (1.0 + x + 2.0).ln();
let _ = (x + 1.0 + 2.0).ln();
let _ = (x + 1.0 / 2.0).ln();
let _ = (1.0 + x - 2.0).ln();
}
fn main() {}

View file

@ -0,0 +1,174 @@
error: logarithm for bases 2, 10 and e can be computed more accurately
--> $DIR/floating_point_log.rs:10:13
|
LL | let _ = x.log(2f32);
| ^^^^^^^^^^^ help: consider using: `x.log2()`
|
= note: `-D clippy::suboptimal-flops` implied by `-D warnings`
error: logarithm for bases 2, 10 and e can be computed more accurately
--> $DIR/floating_point_log.rs:11:13
|
LL | let _ = x.log(10f32);
| ^^^^^^^^^^^^ help: consider using: `x.log10()`
error: logarithm for bases 2, 10 and e can be computed more accurately
--> $DIR/floating_point_log.rs:12:13
|
LL | let _ = x.log(std::f32::consts::E);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `x.ln()`
error: logarithm for bases 2, 10 and e can be computed more accurately
--> $DIR/floating_point_log.rs:13:13
|
LL | let _ = x.log(TWO);
| ^^^^^^^^^^ help: consider using: `x.log2()`
error: logarithm for bases 2, 10 and e can be computed more accurately
--> $DIR/floating_point_log.rs:14:13
|
LL | let _ = x.log(E);
| ^^^^^^^^ help: consider using: `x.ln()`
error: logarithm for bases 2, 10 and e can be computed more accurately
--> $DIR/floating_point_log.rs:17:13
|
LL | let _ = x.log(2f64);
| ^^^^^^^^^^^ help: consider using: `x.log2()`
error: logarithm for bases 2, 10 and e can be computed more accurately
--> $DIR/floating_point_log.rs:18:13
|
LL | let _ = x.log(10f64);
| ^^^^^^^^^^^^ help: consider using: `x.log10()`
error: logarithm for bases 2, 10 and e can be computed more accurately
--> $DIR/floating_point_log.rs:19:13
|
LL | let _ = x.log(std::f64::consts::E);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `x.ln()`
error: ln(1 + x) can be computed more accurately
--> $DIR/floating_point_log.rs:24:13
|
LL | let _ = (1f32 + 2.).ln();
| ^^^^^^^^^^^^^^^^ help: consider using: `2.0f32.ln_1p()`
|
= note: `-D clippy::imprecise-flops` implied by `-D warnings`
error: ln(1 + x) can be computed more accurately
--> $DIR/floating_point_log.rs:25:13
|
LL | let _ = (1f32 + 2.0).ln();
| ^^^^^^^^^^^^^^^^^ help: consider using: `2.0f32.ln_1p()`
error: ln(1 + x) can be computed more accurately
--> $DIR/floating_point_log.rs:26:13
|
LL | let _ = (1.0 + x).ln();
| ^^^^^^^^^^^^^^ help: consider using: `x.ln_1p()`
error: ln(1 + x) can be computed more accurately
--> $DIR/floating_point_log.rs:27:13
|
LL | let _ = (1.0 + x / 2.0).ln();
| ^^^^^^^^^^^^^^^^^^^^ help: consider using: `(x / 2.0).ln_1p()`
error: ln(1 + x) can be computed more accurately
--> $DIR/floating_point_log.rs:28:13
|
LL | let _ = (1.0 + x.powi(2)).ln();
| ^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `x.powi(2).ln_1p()`
error: ln(1 + x) can be computed more accurately
--> $DIR/floating_point_log.rs:29:13
|
LL | let _ = (1.0 + x.powi(2) / 2.0).ln();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `(x.powi(2) / 2.0).ln_1p()`
error: ln(1 + x) can be computed more accurately
--> $DIR/floating_point_log.rs:30:13
|
LL | let _ = (1.0 + (std::f32::consts::E - 1.0)).ln();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `((std::f32::consts::E - 1.0)).ln_1p()`
error: ln(1 + x) can be computed more accurately
--> $DIR/floating_point_log.rs:31:13
|
LL | let _ = (x + 1.0).ln();
| ^^^^^^^^^^^^^^ help: consider using: `x.ln_1p()`
error: ln(1 + x) can be computed more accurately
--> $DIR/floating_point_log.rs:32:13
|
LL | let _ = (x.powi(2) + 1.0).ln();
| ^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `x.powi(2).ln_1p()`
error: ln(1 + x) can be computed more accurately
--> $DIR/floating_point_log.rs:33:13
|
LL | let _ = (x + 2.0 + 1.0).ln();
| ^^^^^^^^^^^^^^^^^^^^ help: consider using: `(x + 2.0).ln_1p()`
error: ln(1 + x) can be computed more accurately
--> $DIR/floating_point_log.rs:34:13
|
LL | let _ = (x / 2.0 + 1.0).ln();
| ^^^^^^^^^^^^^^^^^^^^ help: consider using: `(x / 2.0).ln_1p()`
error: ln(1 + x) can be computed more accurately
--> $DIR/floating_point_log.rs:42:13
|
LL | let _ = (1f64 + 2.).ln();
| ^^^^^^^^^^^^^^^^ help: consider using: `2.0f64.ln_1p()`
error: ln(1 + x) can be computed more accurately
--> $DIR/floating_point_log.rs:43:13
|
LL | let _ = (1f64 + 2.0).ln();
| ^^^^^^^^^^^^^^^^^ help: consider using: `2.0f64.ln_1p()`
error: ln(1 + x) can be computed more accurately
--> $DIR/floating_point_log.rs:44:13
|
LL | let _ = (1.0 + x).ln();
| ^^^^^^^^^^^^^^ help: consider using: `x.ln_1p()`
error: ln(1 + x) can be computed more accurately
--> $DIR/floating_point_log.rs:45:13
|
LL | let _ = (1.0 + x / 2.0).ln();
| ^^^^^^^^^^^^^^^^^^^^ help: consider using: `(x / 2.0).ln_1p()`
error: ln(1 + x) can be computed more accurately
--> $DIR/floating_point_log.rs:46:13
|
LL | let _ = (1.0 + x.powi(2)).ln();
| ^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `x.powi(2).ln_1p()`
error: ln(1 + x) can be computed more accurately
--> $DIR/floating_point_log.rs:47:13
|
LL | let _ = (x + 1.0).ln();
| ^^^^^^^^^^^^^^ help: consider using: `x.ln_1p()`
error: ln(1 + x) can be computed more accurately
--> $DIR/floating_point_log.rs:48:13
|
LL | let _ = (x.powi(2) + 1.0).ln();
| ^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `x.powi(2).ln_1p()`
error: ln(1 + x) can be computed more accurately
--> $DIR/floating_point_log.rs:49:13
|
LL | let _ = (x + 2.0 + 1.0).ln();
| ^^^^^^^^^^^^^^^^^^^^ help: consider using: `(x + 2.0).ln_1p()`
error: ln(1 + x) can be computed more accurately
--> $DIR/floating_point_log.rs:50:13
|
LL | let _ = (x / 2.0 + 1.0).ln();
| ^^^^^^^^^^^^^^^^^^^^ help: consider using: `(x / 2.0).ln_1p()`
error: aborting due to 28 previous errors

View file

@ -0,0 +1,21 @@
// run-rustfix
#![warn(clippy::suboptimal_flops)]
fn main() {
let a: f64 = 1234.567;
let b: f64 = 45.67834;
let c: f64 = 0.0004;
let d: f64 = 0.0001;
let _ = a.mul_add(b, c);
let _ = a.mul_add(b, c);
let _ = 2.0f64.mul_add(4.0, a);
let _ = 2.0f64.mul_add(4., a);
let _ = a.mul_add(b, c);
let _ = a.mul_add(b, c);
let _ = (a * b).mul_add(c, d);
let _ = a.mul_add(b, c).mul_add(a.mul_add(b, c), a.mul_add(b, c)) + c;
let _ = 1234.567_f64.mul_add(45.67834_f64, 0.0004_f64);
}

View file

@ -0,0 +1,21 @@
// run-rustfix
#![warn(clippy::suboptimal_flops)]
fn main() {
let a: f64 = 1234.567;
let b: f64 = 45.67834;
let c: f64 = 0.0004;
let d: f64 = 0.0001;
let _ = a * b + c;
let _ = c + a * b;
let _ = a + 2.0 * 4.0;
let _ = a + 2. * 4.;
let _ = (a * b) + c;
let _ = c + (a * b);
let _ = a * b * c + d;
let _ = a.mul_add(b, c) * a.mul_add(b, c) + a.mul_add(b, c) + c;
let _ = 1234.567_f64 * 45.67834_f64 + 0.0004_f64;
}

View file

@ -0,0 +1,58 @@
error: multiply and add expressions can be calculated more efficiently and accurately
--> $DIR/floating_point_mul_add.rs:10:13
|
LL | let _ = a * b + c;
| ^^^^^^^^^ help: consider using: `a.mul_add(b, c)`
|
= note: `-D clippy::suboptimal-flops` implied by `-D warnings`
error: multiply and add expressions can be calculated more efficiently and accurately
--> $DIR/floating_point_mul_add.rs:11:13
|
LL | let _ = c + a * b;
| ^^^^^^^^^ help: consider using: `a.mul_add(b, c)`
error: multiply and add expressions can be calculated more efficiently and accurately
--> $DIR/floating_point_mul_add.rs:12:13
|
LL | let _ = a + 2.0 * 4.0;
| ^^^^^^^^^^^^^ help: consider using: `2.0f64.mul_add(4.0, a)`
error: multiply and add expressions can be calculated more efficiently and accurately
--> $DIR/floating_point_mul_add.rs:13:13
|
LL | let _ = a + 2. * 4.;
| ^^^^^^^^^^^ help: consider using: `2.0f64.mul_add(4., a)`
error: multiply and add expressions can be calculated more efficiently and accurately
--> $DIR/floating_point_mul_add.rs:15:13
|
LL | let _ = (a * b) + c;
| ^^^^^^^^^^^ help: consider using: `a.mul_add(b, c)`
error: multiply and add expressions can be calculated more efficiently and accurately
--> $DIR/floating_point_mul_add.rs:16:13
|
LL | let _ = c + (a * b);
| ^^^^^^^^^^^ help: consider using: `a.mul_add(b, c)`
error: multiply and add expressions can be calculated more efficiently and accurately
--> $DIR/floating_point_mul_add.rs:17:13
|
LL | let _ = a * b * c + d;
| ^^^^^^^^^^^^^ help: consider using: `(a * b).mul_add(c, d)`
error: multiply and add expressions can be calculated more efficiently and accurately
--> $DIR/floating_point_mul_add.rs:19:13
|
LL | let _ = a.mul_add(b, c) * a.mul_add(b, c) + a.mul_add(b, c) + c;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `a.mul_add(b, c).mul_add(a.mul_add(b, c), a.mul_add(b, c))`
error: multiply and add expressions can be calculated more efficiently and accurately
--> $DIR/floating_point_mul_add.rs:20:13
|
LL | let _ = 1234.567_f64 * 45.67834_f64 + 0.0004_f64;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `1234.567_f64.mul_add(45.67834_f64, 0.0004_f64)`
error: aborting due to 9 previous errors

View file

@ -0,0 +1,42 @@
// run-rustfix
#![warn(clippy::suboptimal_flops, clippy::imprecise_flops)]
fn main() {
let x = 3f32;
let _ = x.exp2();
let _ = 3.1f32.exp2();
let _ = (-3.1f32).exp2();
let _ = x.exp();
let _ = 3.1f32.exp();
let _ = (-3.1f32).exp();
let _ = x.sqrt();
let _ = x.cbrt();
let _ = x.powi(2);
let _ = x.powi(-2);
let _ = x.powi(16_777_215);
let _ = x.powi(-16_777_215);
// Cases where the lint shouldn't be applied
let _ = x.powf(2.1);
let _ = x.powf(-2.1);
let _ = x.powf(16_777_216.0);
let _ = x.powf(-16_777_216.0);
let x = 3f64;
let _ = x.exp2();
let _ = 3.1f64.exp2();
let _ = (-3.1f64).exp2();
let _ = x.exp();
let _ = 3.1f64.exp();
let _ = (-3.1f64).exp();
let _ = x.sqrt();
let _ = x.cbrt();
let _ = x.powi(2);
let _ = x.powi(-2);
let _ = x.powi(-2_147_483_648);
let _ = x.powi(2_147_483_647);
// Cases where the lint shouldn't be applied
let _ = x.powf(2.1);
let _ = x.powf(-2.1);
let _ = x.powf(-2_147_483_649.0);
let _ = x.powf(2_147_483_648.0);
}

View file

@ -0,0 +1,42 @@
// run-rustfix
#![warn(clippy::suboptimal_flops, clippy::imprecise_flops)]
fn main() {
let x = 3f32;
let _ = 2f32.powf(x);
let _ = 2f32.powf(3.1);
let _ = 2f32.powf(-3.1);
let _ = std::f32::consts::E.powf(x);
let _ = std::f32::consts::E.powf(3.1);
let _ = std::f32::consts::E.powf(-3.1);
let _ = x.powf(1.0 / 2.0);
let _ = x.powf(1.0 / 3.0);
let _ = x.powf(2.0);
let _ = x.powf(-2.0);
let _ = x.powf(16_777_215.0);
let _ = x.powf(-16_777_215.0);
// Cases where the lint shouldn't be applied
let _ = x.powf(2.1);
let _ = x.powf(-2.1);
let _ = x.powf(16_777_216.0);
let _ = x.powf(-16_777_216.0);
let x = 3f64;
let _ = 2f64.powf(x);
let _ = 2f64.powf(3.1);
let _ = 2f64.powf(-3.1);
let _ = std::f64::consts::E.powf(x);
let _ = std::f64::consts::E.powf(3.1);
let _ = std::f64::consts::E.powf(-3.1);
let _ = x.powf(1.0 / 2.0);
let _ = x.powf(1.0 / 3.0);
let _ = x.powf(2.0);
let _ = x.powf(-2.0);
let _ = x.powf(-2_147_483_648.0);
let _ = x.powf(2_147_483_647.0);
// Cases where the lint shouldn't be applied
let _ = x.powf(2.1);
let _ = x.powf(-2.1);
let _ = x.powf(-2_147_483_649.0);
let _ = x.powf(2_147_483_648.0);
}

View file

@ -0,0 +1,150 @@
error: exponent for bases 2 and e can be computed more accurately
--> $DIR/floating_point_powf.rs:6:13
|
LL | let _ = 2f32.powf(x);
| ^^^^^^^^^^^^ help: consider using: `x.exp2()`
|
= note: `-D clippy::suboptimal-flops` implied by `-D warnings`
error: exponent for bases 2 and e can be computed more accurately
--> $DIR/floating_point_powf.rs:7:13
|
LL | let _ = 2f32.powf(3.1);
| ^^^^^^^^^^^^^^ help: consider using: `3.1f32.exp2()`
error: exponent for bases 2 and e can be computed more accurately
--> $DIR/floating_point_powf.rs:8:13
|
LL | let _ = 2f32.powf(-3.1);
| ^^^^^^^^^^^^^^^ help: consider using: `(-3.1f32).exp2()`
error: exponent for bases 2 and e can be computed more accurately
--> $DIR/floating_point_powf.rs:9:13
|
LL | let _ = std::f32::consts::E.powf(x);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `x.exp()`
error: exponent for bases 2 and e can be computed more accurately
--> $DIR/floating_point_powf.rs:10:13
|
LL | let _ = std::f32::consts::E.powf(3.1);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `3.1f32.exp()`
error: exponent for bases 2 and e can be computed more accurately
--> $DIR/floating_point_powf.rs:11:13
|
LL | let _ = std::f32::consts::E.powf(-3.1);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `(-3.1f32).exp()`
error: square-root of a number can be computed more efficiently and accurately
--> $DIR/floating_point_powf.rs:12:13
|
LL | let _ = x.powf(1.0 / 2.0);
| ^^^^^^^^^^^^^^^^^ help: consider using: `x.sqrt()`
error: cube-root of a number can be computed more accurately
--> $DIR/floating_point_powf.rs:13:13
|
LL | let _ = x.powf(1.0 / 3.0);
| ^^^^^^^^^^^^^^^^^ help: consider using: `x.cbrt()`
|
= note: `-D clippy::imprecise-flops` implied by `-D warnings`
error: exponentiation with integer powers can be computed more efficiently
--> $DIR/floating_point_powf.rs:14:13
|
LL | let _ = x.powf(2.0);
| ^^^^^^^^^^^ help: consider using: `x.powi(2)`
error: exponentiation with integer powers can be computed more efficiently
--> $DIR/floating_point_powf.rs:15:13
|
LL | let _ = x.powf(-2.0);
| ^^^^^^^^^^^^ help: consider using: `x.powi(-2)`
error: exponentiation with integer powers can be computed more efficiently
--> $DIR/floating_point_powf.rs:16:13
|
LL | let _ = x.powf(16_777_215.0);
| ^^^^^^^^^^^^^^^^^^^^ help: consider using: `x.powi(16_777_215)`
error: exponentiation with integer powers can be computed more efficiently
--> $DIR/floating_point_powf.rs:17:13
|
LL | let _ = x.powf(-16_777_215.0);
| ^^^^^^^^^^^^^^^^^^^^^ help: consider using: `x.powi(-16_777_215)`
error: exponent for bases 2 and e can be computed more accurately
--> $DIR/floating_point_powf.rs:25:13
|
LL | let _ = 2f64.powf(x);
| ^^^^^^^^^^^^ help: consider using: `x.exp2()`
error: exponent for bases 2 and e can be computed more accurately
--> $DIR/floating_point_powf.rs:26:13
|
LL | let _ = 2f64.powf(3.1);
| ^^^^^^^^^^^^^^ help: consider using: `3.1f64.exp2()`
error: exponent for bases 2 and e can be computed more accurately
--> $DIR/floating_point_powf.rs:27:13
|
LL | let _ = 2f64.powf(-3.1);
| ^^^^^^^^^^^^^^^ help: consider using: `(-3.1f64).exp2()`
error: exponent for bases 2 and e can be computed more accurately
--> $DIR/floating_point_powf.rs:28:13
|
LL | let _ = std::f64::consts::E.powf(x);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `x.exp()`
error: exponent for bases 2 and e can be computed more accurately
--> $DIR/floating_point_powf.rs:29:13
|
LL | let _ = std::f64::consts::E.powf(3.1);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `3.1f64.exp()`
error: exponent for bases 2 and e can be computed more accurately
--> $DIR/floating_point_powf.rs:30:13
|
LL | let _ = std::f64::consts::E.powf(-3.1);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `(-3.1f64).exp()`
error: square-root of a number can be computed more efficiently and accurately
--> $DIR/floating_point_powf.rs:31:13
|
LL | let _ = x.powf(1.0 / 2.0);
| ^^^^^^^^^^^^^^^^^ help: consider using: `x.sqrt()`
error: cube-root of a number can be computed more accurately
--> $DIR/floating_point_powf.rs:32:13
|
LL | let _ = x.powf(1.0 / 3.0);
| ^^^^^^^^^^^^^^^^^ help: consider using: `x.cbrt()`
error: exponentiation with integer powers can be computed more efficiently
--> $DIR/floating_point_powf.rs:33:13
|
LL | let _ = x.powf(2.0);
| ^^^^^^^^^^^ help: consider using: `x.powi(2)`
error: exponentiation with integer powers can be computed more efficiently
--> $DIR/floating_point_powf.rs:34:13
|
LL | let _ = x.powf(-2.0);
| ^^^^^^^^^^^^ help: consider using: `x.powi(-2)`
error: exponentiation with integer powers can be computed more efficiently
--> $DIR/floating_point_powf.rs:35:13
|
LL | let _ = x.powf(-2_147_483_648.0);
| ^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `x.powi(-2_147_483_648)`
error: exponentiation with integer powers can be computed more efficiently
--> $DIR/floating_point_powf.rs:36:13
|
LL | let _ = x.powf(2_147_483_647.0);
| ^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `x.powi(2_147_483_647)`
error: aborting due to 24 previous errors

View file

@ -1,16 +0,0 @@
#![warn(clippy::manual_mul_add)]
#![allow(unused_variables)]
fn mul_add_test() {
let a: f64 = 1234.567;
let b: f64 = 45.67834;
let c: f64 = 0.0004;
// Examples of not auto-fixable expressions
let test1 = (a * b + c) * (c + a * b) + (c + (a * b) + c);
let test2 = 1234.567 * 45.67834 + 0.0004;
}
fn main() {
mul_add_test();
}

View file

@ -1,34 +0,0 @@
error: consider using `mul_add()` for better numerical precision
--> $DIR/mul_add.rs:10:17
|
LL | let test1 = (a * b + c) * (c + a * b) + (c + (a * b) + c);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `(a * b + c).mul_add((c + a * b), (c + (a * b) + c))`
|
= note: `-D clippy::manual-mul-add` implied by `-D warnings`
error: consider using `mul_add()` for better numerical precision
--> $DIR/mul_add.rs:10:17
|
LL | let test1 = (a * b + c) * (c + a * b) + (c + (a * b) + c);
| ^^^^^^^^^^^ help: try: `a.mul_add(b, c)`
error: consider using `mul_add()` for better numerical precision
--> $DIR/mul_add.rs:10:31
|
LL | let test1 = (a * b + c) * (c + a * b) + (c + (a * b) + c);
| ^^^^^^^^^^^ help: try: `a.mul_add(b, c)`
error: consider using `mul_add()` for better numerical precision
--> $DIR/mul_add.rs:10:46
|
LL | let test1 = (a * b + c) * (c + a * b) + (c + (a * b) + c);
| ^^^^^^^^^^^ help: try: `a.mul_add(b, c)`
error: consider using `mul_add()` for better numerical precision
--> $DIR/mul_add.rs:11:17
|
LL | let test2 = 1234.567 * 45.67834 + 0.0004;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `1234.567.mul_add(45.67834, 0.0004)`
error: aborting due to 5 previous errors

View file

@ -1,24 +0,0 @@
// run-rustfix
#![warn(clippy::manual_mul_add)]
#![allow(unused_variables)]
fn mul_add_test() {
let a: f64 = 1234.567;
let b: f64 = 45.67834;
let c: f64 = 0.0004;
// Auto-fixable examples
let test1 = a.mul_add(b, c);
let test2 = a.mul_add(b, c);
let test3 = a.mul_add(b, c);
let test4 = a.mul_add(b, c);
let test5 = a.mul_add(b, c).mul_add(a.mul_add(b, c), a.mul_add(b, c)) + c;
let test6 = 1234.567_f64.mul_add(45.67834_f64, 0.0004_f64);
}
fn main() {
mul_add_test();
}

View file

@ -1,24 +0,0 @@
// run-rustfix
#![warn(clippy::manual_mul_add)]
#![allow(unused_variables)]
fn mul_add_test() {
let a: f64 = 1234.567;
let b: f64 = 45.67834;
let c: f64 = 0.0004;
// Auto-fixable examples
let test1 = a * b + c;
let test2 = c + a * b;
let test3 = (a * b) + c;
let test4 = c + (a * b);
let test5 = a.mul_add(b, c) * a.mul_add(b, c) + a.mul_add(b, c) + c;
let test6 = 1234.567_f64 * 45.67834_f64 + 0.0004_f64;
}
fn main() {
mul_add_test();
}

View file

@ -1,40 +0,0 @@
error: consider using `mul_add()` for better numerical precision
--> $DIR/mul_add_fixable.rs:12:17
|
LL | let test1 = a * b + c;
| ^^^^^^^^^ help: try: `a.mul_add(b, c)`
|
= note: `-D clippy::manual-mul-add` implied by `-D warnings`
error: consider using `mul_add()` for better numerical precision
--> $DIR/mul_add_fixable.rs:13:17
|
LL | let test2 = c + a * b;
| ^^^^^^^^^ help: try: `a.mul_add(b, c)`
error: consider using `mul_add()` for better numerical precision
--> $DIR/mul_add_fixable.rs:15:17
|
LL | let test3 = (a * b) + c;
| ^^^^^^^^^^^ help: try: `a.mul_add(b, c)`
error: consider using `mul_add()` for better numerical precision
--> $DIR/mul_add_fixable.rs:16:17
|
LL | let test4 = c + (a * b);
| ^^^^^^^^^^^ help: try: `a.mul_add(b, c)`
error: consider using `mul_add()` for better numerical precision
--> $DIR/mul_add_fixable.rs:18:17
|
LL | let test5 = a.mul_add(b, c) * a.mul_add(b, c) + a.mul_add(b, c) + c;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `a.mul_add(b, c).mul_add(a.mul_add(b, c), a.mul_add(b, c))`
error: consider using `mul_add()` for better numerical precision
--> $DIR/mul_add_fixable.rs:19:17
|
LL | let test6 = 1234.567_f64 * 45.67834_f64 + 0.0004_f64;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `1234.567_f64.mul_add(45.67834_f64, 0.0004_f64)`
error: aborting due to 6 previous errors