Interval.php 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103
  1. <?php
  2. /*
  3. * This file is part of the Symfony package.
  4. *
  5. * (c) Fabien Potencier <fabien.potencier@symfony-project.com>
  6. *
  7. * For the full copyright and license information, please view the LICENSE
  8. * file that was distributed with this source code.
  9. */
  10. namespace Symfony\Component\Translation;
  11. /**
  12. * Tests if a given number belongs to a given math interval.
  13. *
  14. * An interval can represent a finite set of numbers:
  15. *
  16. * {1,2,3,4}
  17. *
  18. * An interval can represent numbers between two numbers:
  19. *
  20. * [1, +Inf]
  21. * ]-1,2[
  22. *
  23. * The left delimiter can be [ (inclusive) or ] (exclusive).
  24. * The right delimiter can be [ (exclusive) or ] (inclusive).
  25. * Beside numbers, you can use -Inf and +Inf for the infinite.
  26. *
  27. * @see http://en.wikipedia.org/wiki/Interval_%28mathematics%29#The_ISO_notation
  28. *
  29. * @author Fabien Potencier <fabien.potencier@symfony-project.com>
  30. */
  31. class Interval
  32. {
  33. /**
  34. * Tests if the given number is in the math interval.
  35. *
  36. * @param integer $number A number
  37. * @param string $interval An interval
  38. */
  39. static public function test($number, $interval)
  40. {
  41. $interval = trim($interval);
  42. if (!preg_match('/^'.self::getIntervalRegexp().'$/x', $interval, $matches)) {
  43. throw new \InvalidArgumentException(sprintf('"%s" is not a valid interval.', $interval));
  44. }
  45. if ($matches[1]) {
  46. foreach (explode(',', $matches[2]) as $n) {
  47. if ($number == $n) {
  48. return true;
  49. }
  50. }
  51. } else {
  52. $leftNumber = self::convertNumber($matches['left']);
  53. $rightNumber = self::convertNumber($matches['right']);
  54. return
  55. ('[' === $matches['left_delimiter'] ? $number >= $leftNumber : $number > $leftNumber)
  56. && (']' === $matches['right_delimiter'] ? $number <= $rightNumber : $number < $rightNumber)
  57. ;
  58. }
  59. return false;
  60. }
  61. /**
  62. * Returns a Regexp that matches valid intervals.
  63. *
  64. * @return string A Regexp (without the delimiters)
  65. */
  66. static public function getIntervalRegexp()
  67. {
  68. return <<<EOF
  69. ({\s*
  70. (\-?\d+[\s*,\s*\-?\d+]*)
  71. \s*})
  72. |
  73. (?<left_delimiter>[\[\]])
  74. \s*
  75. (?<left>-Inf|\-?\d+)
  76. \s*,\s*
  77. (?<right>\+?Inf|\-?\d+)
  78. \s*
  79. (?<right_delimiter>[\[\]])
  80. EOF;
  81. }
  82. static protected function convertNumber($number)
  83. {
  84. if ('-Inf' === $number) {
  85. return log(0);
  86. } elseif ('+Inf' === $number || 'Inf' === $number) {
  87. return -log(0);
  88. }
  89. return (int) $number;
  90. }
  91. }