1<?php
2
3/**
4 * This file is part of the Nette Framework (https://nette.org)
5 * Copyright (c) 2004 David Grudl (https://davidgrudl.com)
6 */
7
8declare(strict_types=1);
9
10namespace Nette\Utils;
11
12use Nette;
13
14
15/**
16 * Floating-point numbers comparison.
17 */
18class Floats
19{
20	use Nette\StaticClass;
21
22	private const Epsilon = 1e-10;
23
24
25	public static function isZero(float $value): bool
26	{
27		return abs($value) < self::Epsilon;
28	}
29
30
31	public static function isInteger(float $value): bool
32	{
33		return abs(round($value) - $value) < self::Epsilon;
34	}
35
36
37	/**
38	 * Compare two floats. If $a < $b it returns -1, if they are equal it returns 0 and if $a > $b it returns 1
39	 * @throws \LogicException if one of parameters is NAN
40	 */
41	public static function compare(float $a, float $b): int
42	{
43		if (is_nan($a) || is_nan($b)) {
44			throw new \LogicException('Trying to compare NAN');
45
46		} elseif (!is_finite($a) && !is_finite($b) && $a === $b) {
47			return 0;
48		}
49
50		$diff = abs($a - $b);
51		if (($diff < self::Epsilon || ($diff / max(abs($a), abs($b)) < self::Epsilon))) {
52			return 0;
53		}
54
55		return $a < $b ? -1 : 1;
56	}
57
58
59	/**
60	 * Returns true if $a = $b
61	 * @throws \LogicException if one of parameters is NAN
62	 */
63	public static function areEqual(float $a, float $b): bool
64	{
65		return self::compare($a, $b) === 0;
66	}
67
68
69	/**
70	 * Returns true if $a < $b
71	 * @throws \LogicException if one of parameters is NAN
72	 */
73	public static function isLessThan(float $a, float $b): bool
74	{
75		return self::compare($a, $b) < 0;
76	}
77
78
79	/**
80	 * Returns true if $a <= $b
81	 * @throws \LogicException if one of parameters is NAN
82	 */
83	public static function isLessThanOrEqualTo(float $a, float $b): bool
84	{
85		return self::compare($a, $b) <= 0;
86	}
87
88
89	/**
90	 * Returns true if $a > $b
91	 * @throws \LogicException if one of parameters is NAN
92	 */
93	public static function isGreaterThan(float $a, float $b): bool
94	{
95		return self::compare($a, $b) > 0;
96	}
97
98
99	/**
100	 * Returns true if $a >= $b
101	 * @throws \LogicException if one of parameters is NAN
102	 */
103	public static function isGreaterThanOrEqualTo(float $a, float $b): bool
104	{
105		return self::compare($a, $b) >= 0;
106	}
107}
108