mirror of
https://github.com/sass/sass.git
synced 2024-09-21 10:37:22 +00:00
[Floating Point] Integrate the proposal into the spec (#3408)
This commit is contained in:
parent
1d442b9505
commit
78d28d300b
@ -14,6 +14,11 @@ though some have special handling of units.
|
||||
* [Variables](#variables)
|
||||
* [`$e`](#e)
|
||||
* [`$pi`](#pi)
|
||||
* [`$epsilon`](#epsilon)
|
||||
* [`$max-safe-integer`](#max-safe-integer)
|
||||
* [`$min-safe-integer`](#min-safe-integer)
|
||||
* [`$max-number`](#max-number)
|
||||
* [`$min-number`](#min-number)
|
||||
* [Functions](#functions)
|
||||
* [Bounding Functions](#bounding-functions)
|
||||
* [`ceil()`](#ceil)
|
||||
@ -34,7 +39,6 @@ though some have special handling of units.
|
||||
* [`asin()`](#asin)
|
||||
* [`atan()`](#atan)
|
||||
* [`atan2()`](#atan2)
|
||||
* [Edge cases](#edge-cases)
|
||||
* [`cos()`](#cos)
|
||||
* [`sin()`](#sin)
|
||||
* [`tan()`](#tan)
|
||||
@ -51,13 +55,57 @@ though some have special handling of units.
|
||||
|
||||
### `$e`
|
||||
|
||||
Equal to the value of the mathematical constant `e` with a precision of 10
|
||||
digits after the decimal point: `2.7182818285`.
|
||||
A unitless number whose value is the closest possible [double] approximation of
|
||||
the [mathematical constant e].
|
||||
|
||||
[double]: ../types/number.md#double
|
||||
[mathematical constant e]: https://en.wikipedia.org/wiki/E_(mathematical_constant)
|
||||
|
||||
> This is `2.718281828459045`.
|
||||
|
||||
### `$pi`
|
||||
|
||||
Equal to the value of the mathematical constant `pi` with a precision of 10
|
||||
digits after the decimal point: `3.1415926536`.
|
||||
A unitless number whose value is the closest possible [double] approximation of
|
||||
the [mathematical constant π].
|
||||
|
||||
[mathematical constant π]: https://en.wikipedia.org/wiki/Pi
|
||||
|
||||
> This is `3.141592653589793`.
|
||||
|
||||
### `$epsilon`
|
||||
|
||||
A unitless number whose value is the difference between 1 and the smallest
|
||||
[double] greater than 1.
|
||||
|
||||
> This is `2.220446049250313e-16`.
|
||||
|
||||
### `$max-safe-integer`
|
||||
|
||||
A unitless number whose value represents the maximum mathematical integer `n`
|
||||
such that `n` and `n + 1` both have an exact [double] representation.
|
||||
|
||||
> This is `9007199254740991`.
|
||||
|
||||
### `$min-safe-integer`
|
||||
|
||||
A unitless number whose value represents the minimum mathematical integer `n`
|
||||
such that `n` and `n - 1` both have an exact [double] representation.
|
||||
|
||||
> This is `-9007199254740991`.
|
||||
|
||||
### `$max-number`
|
||||
|
||||
A unitless number whose value represents the greatest finite number that can be
|
||||
represented by a [double].
|
||||
|
||||
> This is `1.7976931348623157e+308`.
|
||||
|
||||
### `$min-number`
|
||||
|
||||
A unitless number whose value represents the least positive number that can be
|
||||
represented by a [double].
|
||||
|
||||
> This is `5e-324`.
|
||||
|
||||
## Functions
|
||||
|
||||
@ -71,6 +119,12 @@ ceil($number)
|
||||
|
||||
This function is also available as a global function named `ceil()`.
|
||||
|
||||
* Return a number whose value is the result of
|
||||
`convertToIntegerTowardPositive($number.value)` as defined by [IEEE 754 2019],
|
||||
§5.8; and whose units are the same as `$number`'s.
|
||||
|
||||
[IEEE 754 2019]: https://ieeexplore.ieee.org/document/8766229
|
||||
|
||||
#### `clamp()`
|
||||
|
||||
```
|
||||
@ -95,6 +149,10 @@ floor($number)
|
||||
|
||||
This function is also available as a global function named `floor()`.
|
||||
|
||||
* Return a number whose value is the result of
|
||||
`convertToIntegerTowardNegative($number.value)` as defined by [IEEE 754 2019],
|
||||
§5.8; and whose units are the same as `$number`'s.
|
||||
|
||||
#### `max()`
|
||||
|
||||
```
|
||||
@ -119,6 +177,10 @@ round($number)
|
||||
|
||||
This function is also available as a global function named `round()`.
|
||||
|
||||
* Return a number whose value is the result of
|
||||
`convertToIntegerTiesToAway($number.value)` as defined by [IEEE 754 2019],
|
||||
§5.8; and whose units are the same as `$number`'s.
|
||||
|
||||
### Distance Functions
|
||||
|
||||
#### `abs()`
|
||||
@ -129,6 +191,9 @@ abs($number)
|
||||
|
||||
This function is also available as a global function named `abs()`.
|
||||
|
||||
* Return a number whose value is the result of `abs($number.value)` as defined
|
||||
by [IEEE 754 2019], §5.5.1; and whose units are the same as `$number`'s.
|
||||
|
||||
#### `hypot()`
|
||||
|
||||
```
|
||||
@ -156,16 +221,15 @@ hypot($numbers...)
|
||||
log($number, $base: null)
|
||||
```
|
||||
|
||||
* If `$number` has units, throw an error.
|
||||
* If `$base` is null:
|
||||
* If `$number < 0`, return `NaN` as a unitless number.
|
||||
* If `$number == 0`, return `-Infinity` as a unitless number.
|
||||
* If `$number == Infinity`, return `Infinity` as a unitless number.
|
||||
* Return the [natural log] of `$number`, as a unitless number.
|
||||
* Otherwise, return the natural log of `$number` divided by the natural log of
|
||||
`$base`, as a unitless number.
|
||||
|
||||
[natural log]: https://en.wikipedia.org/wiki/Natural_logarithm
|
||||
* If `$number` has units, throw an error.
|
||||
|
||||
* Return a unitless number whose value is the result of `log($number.value)` as
|
||||
defined by [IEEE 754 2019], §9.2.
|
||||
|
||||
> This is the [natural logarithm].
|
||||
>
|
||||
> [natural logarithm]: https://en.wikipedia.org/wiki/Natural_logarithm
|
||||
|
||||
#### `pow()`
|
||||
|
||||
@ -175,36 +239,8 @@ pow($base, $exponent)
|
||||
|
||||
* If `$base` or `$exponent` has units, throw an error.
|
||||
|
||||
* If `$exponent == 0`, return `1` as a unitless number.
|
||||
|
||||
* Otherwise, if `$exponent == Infinity` or `$exponent == -Infinity`:
|
||||
* If `$base == 1` or `$base == -1`, return `NaN` as a unitless number.
|
||||
* If `$base < -1` or `$base > 1` and if `$exponent > 0`, *or* if `$base > -1`
|
||||
and `$base < 1` and `$exponent < 0`, return `Infinity` as a
|
||||
unitless number.
|
||||
* Return `0` as a unitless number.
|
||||
|
||||
* Otherwise:
|
||||
* If `$base < 0` and `$exponent` is not an integer, return `NaN` as a unitless
|
||||
number.
|
||||
|
||||
* If `$base == 0` and `$exponent < 0`, or if `$base == Infinity` and
|
||||
`$exponent > 0`, return `Infinity` as a unitless number.
|
||||
|
||||
* If `$base == -0` and `$exponent < 0`, or if `$base == -Infinity` and
|
||||
`$exponent > 0`:
|
||||
* If `$exponent` is an odd integer, return `-Infinity` as a unitless number.
|
||||
* Return `Infinity` as a unitless number.
|
||||
|
||||
* If `$base == 0` and `$exponent > 0`, or if `$base == Infinity` and
|
||||
`$exponent < 0`, return `0` as a unitless number.
|
||||
|
||||
* If `$base == -0` and `$exponent > 0`, or if `$base == -Infinity` and
|
||||
`$exponent < 0`:
|
||||
* If `$exponent` is an odd integer, return `-0` as a unitless number.
|
||||
* Return `0` as a unitless number.
|
||||
|
||||
* Return `$base` raised to the power of `$exponent`, as a unitless number.
|
||||
* Return a unitless number whose value is the result of `pow($number.value,
|
||||
$exponent.value)` as defined by [IEEE 754 2019], §9.2.
|
||||
|
||||
#### `sqrt()`
|
||||
|
||||
@ -213,11 +249,9 @@ sqrt($number)
|
||||
```
|
||||
|
||||
* If `$number` has units, throw an error.
|
||||
* If `$number < 0`, return `NaN` as a unitless number.
|
||||
* If `$number == -0`, return `-0` as a unitless number.
|
||||
* If `$number == 0`, return `0` as a unitless number.
|
||||
* If `$number == Infinity`, return `Infinity` as a unitless number.
|
||||
* Return the square root of `$number`, as a unitless number.
|
||||
|
||||
* Return a unitless number whose value is the result of `rootn($number.value,
|
||||
2)` as defined by [IEEE 754 2019], §9.2.
|
||||
|
||||
### Trigonometric Functions
|
||||
|
||||
@ -237,11 +271,13 @@ acos($number)
|
||||
```
|
||||
|
||||
* If `$number` has units, throw an error.
|
||||
* If `$number < -1` or `$number > 1`, return `NaN` as a number in `deg`.
|
||||
* If `$number == 1`, return `0deg`.
|
||||
* Return the [arccosine] of `$number`, as a number in `deg`.
|
||||
|
||||
[arccosine]: https://en.wikipedia.org/wiki/Inverse_trigonometric_functions#Basic_properties
|
||||
* Let `result` be a number in `rad` whose value is the result of
|
||||
`acos($number.value)` as defined by [IEEE 754 2019], §9.2.
|
||||
|
||||
* Return the result of [converting `result` to `deg`].
|
||||
|
||||
[converting `result` to `deg`]: ../spec/types/number.md#converting-a-number-to-a-unit
|
||||
|
||||
#### `asin()`
|
||||
|
||||
@ -250,12 +286,11 @@ asin($number)
|
||||
```
|
||||
|
||||
* If `$number` has units, throw an error.
|
||||
* If `$number < -1` or `$number > 1`, return `NaN` as a number in `deg`.
|
||||
* If `$number == -0`, return `-0deg`.
|
||||
* If `$number == 0`, return `0deg`.
|
||||
* Return the [arcsine] of `$number`, as a number in `deg`.
|
||||
|
||||
[arcsine]: https://en.wikipedia.org/wiki/Inverse_trigonometric_functions#Basic_properties
|
||||
* Let `result` be a number in `rad` whose value is the result of
|
||||
`asin($number.value)` as defined by [IEEE 754 2019], §9.2.
|
||||
|
||||
* Return the result of [converting `result` to `deg`].
|
||||
|
||||
#### `atan()`
|
||||
|
||||
@ -264,13 +299,11 @@ atan($number)
|
||||
```
|
||||
|
||||
* If `$number` has units, throw an error.
|
||||
* If `$number == -0`, return `-0deg`.
|
||||
* If `$number == 0`, return `0deg`.
|
||||
* If `$number == -Infinity`, return `-90deg`.
|
||||
* If `$number == Infinity`, return `90deg`.
|
||||
* Return the [arctangent] of `$number`, as a number in `deg`.
|
||||
|
||||
[arctangent]: https://en.wikipedia.org/wiki/Inverse_trigonometric_functions#Basic_properties
|
||||
* Let `result` be a number in `rad` whose value is the result of
|
||||
`atan($number.value)` as defined by [IEEE 754 2019], §9.2.
|
||||
|
||||
* Return the result of [converting `result` to `deg`].
|
||||
|
||||
#### `atan2()`
|
||||
|
||||
@ -284,89 +317,13 @@ atan2($y, $x)
|
||||
```
|
||||
|
||||
* If the units of `$y` and `$x` are not [compatible], throw an error.
|
||||
|
||||
* If `$y` has units and `$x` does not, or vice-versa, throw an error.
|
||||
* If the inputs match one of the following edge cases, return the provided
|
||||
number. Otherwise, return the [2-argument arctangent] of `$y` and `$x`, as a
|
||||
number in `deg`.
|
||||
|
||||
[2-argument arctangent]: https://en.wikipedia.org/wiki/Atan2
|
||||
* Let `result` be a number in `rad` whose value is the result of
|
||||
`atan2($y.value, $x.value)` as defined by [IEEE 754 2019], §9.2.
|
||||
|
||||
##### Edge cases
|
||||
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<td colspan="2"></td>
|
||||
<th colspan="6" style="text-align: center">X</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan="2"></td>
|
||||
<th>−Infinity</th>
|
||||
<th>-finite</th>
|
||||
<th>-0</th>
|
||||
<th>0</th>
|
||||
<th>finite</th>
|
||||
<th>Infinity</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<th rowspan="6">Y</th>
|
||||
<th>−Infinity</th>
|
||||
<td>-135deg</td>
|
||||
<td>-90deg</td>
|
||||
<td>-90deg</td>
|
||||
<td>-90deg</td>
|
||||
<td>-90deg</td>
|
||||
<td>-45deg</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>-finite</th>
|
||||
<td>-180deg</td>
|
||||
<td></td>
|
||||
<td>-90deg</td>
|
||||
<td>-90deg</td>
|
||||
<td></td>
|
||||
<td>-0deg</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>-0</th>
|
||||
<td>-180deg</td>
|
||||
<td>-180deg</td>
|
||||
<td>-180deg</td>
|
||||
<td>-0deg</td>
|
||||
<td>-0deg</td>
|
||||
<td>-0deg</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>0</th>
|
||||
<td>180deg</td>
|
||||
<td>180deg</td>
|
||||
<td>180deg</td>
|
||||
<td>0deg</td>
|
||||
<td>0deg</td>
|
||||
<td>0deg</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>finite</th>
|
||||
<td>180deg</td>
|
||||
<td></td>
|
||||
<td>90deg</td>
|
||||
<td>90deg</td>
|
||||
<td></td>
|
||||
<td>0deg</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Infinity</th>
|
||||
<td>135deg</td>
|
||||
<td>90deg</td>
|
||||
<td>90deg</td>
|
||||
<td>90deg</td>
|
||||
<td>90deg</td>
|
||||
<td>45deg</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
* Return the result of [converting `result` to `deg`].
|
||||
|
||||
#### `cos()`
|
||||
|
||||
@ -374,13 +331,13 @@ atan2($y, $x)
|
||||
cos($number)
|
||||
```
|
||||
|
||||
* If `$number` has units but is not an angle, throw an error.
|
||||
* If `$number` is unitless, treat it as though its unit were `rad`.
|
||||
* If `$number == Infinity` or `$number == -Infinity`, return `NaN` as a unitless
|
||||
number.
|
||||
* Return the [cosine] of `$number`, as a unitless number.
|
||||
* Let `double` be the value of [converting `$number` to `rad`] allowing
|
||||
unitless.
|
||||
|
||||
[cosine]: https://en.wikipedia.org/wiki/Trigonometric_functions#Right-angled_triangle_definitions
|
||||
[converting `$number` to `rad`]: #converting-a-number-to-units
|
||||
|
||||
* Return a unitless number whose value is the result of `cos(double)` as defined
|
||||
by [IEEE 754 2019], §9.2.
|
||||
|
||||
#### `sin()`
|
||||
|
||||
@ -388,15 +345,13 @@ cos($number)
|
||||
sin($number)
|
||||
```
|
||||
|
||||
* If `$number` has units but is not an angle, throw an error.
|
||||
* If `$number` is unitless, treat it as though its unit were `rad`.
|
||||
* If `$number == Infinity` or `$number == -Infinity`, return `NaN` as a unitless
|
||||
number.
|
||||
* If `$number == -0`, return `-0` as a unitless number.
|
||||
* If `$number == 0`, return `0` as a unitless number.
|
||||
* Return the [sine] of `$number`, as a unitless number.
|
||||
* Let `double` be the value of [converting `$number` to `rad`] allowing
|
||||
unitless.
|
||||
|
||||
[sine]: https://en.wikipedia.org/wiki/Trigonometric_functions#Right-angled_triangle_definitions
|
||||
[converting `$number` to `rad`]: #converting-a-number-to-units
|
||||
|
||||
* Return a unitless number whose value is the result of `sin(double)` as defined
|
||||
by [IEEE 754 2019], §9.2.
|
||||
|
||||
#### `tan()`
|
||||
|
||||
@ -404,19 +359,13 @@ sin($number)
|
||||
tan($number)
|
||||
```
|
||||
|
||||
* If `$number` has units but is not an angle, throw an error.
|
||||
* If `$number` is unitless, treat it as though its unit were `rad`.
|
||||
* If `$number == Infinity` or `$number == -Infinity`, return `NaN` as a unitless
|
||||
number.
|
||||
* If `$number == -0`, return `-0` as a unitless number.
|
||||
* If `$number == 0`, return `0` as a unitless number.
|
||||
* If `$number` is equivalent to `90deg +/- 360deg * n`, where `n` is any
|
||||
integer, return `Infinity` as a unitless number.
|
||||
* If `$number` is equivalent to `-90deg +/- 360deg * n`, where `n` is any
|
||||
integer, return `-Infinity` as a unitless number.
|
||||
* Return the [tangent] of `$number`, as a unitless number.
|
||||
* Let `double` be the value of [converting `$number` to `rad`] allowing
|
||||
unitless.
|
||||
|
||||
[tangent]: https://en.wikipedia.org/wiki/Trigonometric_functions#Right-angled_triangle_definitions
|
||||
[converting `$number` to `rad`]: #converting-a-number-to-units
|
||||
|
||||
* Return a unitless number whose value is the result of `tan(double)` as defined
|
||||
by [IEEE 754 2019], §9.2.
|
||||
|
||||
### Unit Functions
|
||||
|
||||
@ -464,8 +413,8 @@ div($number1, $number2)
|
||||
unquoted string whose contents is the result of serializing `$number1`
|
||||
followed by `"/"` followed by the result of serializing `$number2`.
|
||||
* Let `quotient` be a number such that:
|
||||
* Its value is the result of dividing `$number1`'s value by `$number2`'s
|
||||
value.
|
||||
* Its value is the result of `divide($number1.value, $number2.value)` as defined
|
||||
by [IEEE 754 2019], §5.4.1.
|
||||
* Its numerator units are equal to `$number1`'s numerator units followed by
|
||||
`$number2`'s denominator units.
|
||||
* Its denominator units are equal to `$number1`'s denominator units followed
|
||||
@ -493,10 +442,10 @@ This function is also available as a global function named `random()`.
|
||||
|
||||
> Example: `math.random() => 0.1337001337`
|
||||
|
||||
* If `$limit` is an **integer** [number] greater than zero:
|
||||
* If `$limit` is an [integer] greater than zero:
|
||||
|
||||
* Return a pseudo-random integer in the range `[1, $limit]` with the same
|
||||
[units] as `$limit`.
|
||||
units as `$limit`.
|
||||
|
||||
> Examples:
|
||||
> - `math.random(123) => 87`
|
||||
@ -505,5 +454,4 @@ This function is also available as a global function named `random()`.
|
||||
|
||||
* Otherwise throw an error.
|
||||
|
||||
[number]: https://sass-lang.com/documentation/values/numbers
|
||||
[units]: https://sass-lang.com/documentation/values/numbers#units
|
||||
[integer]: ../types/number.md#integer
|
||||
|
@ -3,16 +3,49 @@
|
||||
## Table of Contents
|
||||
|
||||
* [Definitions](#definitions)
|
||||
* [Double](#double)
|
||||
* [Conversion Factors](#conversion-factors)
|
||||
* [Set of Units](#set-of-units)
|
||||
* [Compatible Units](#compatible-units)
|
||||
* [Possibly-Compatible Units](#possibly-compatible-units)
|
||||
* [Possibly-Compatible Numbers](#possibly-compatible-numbers)
|
||||
* [Fuzzy Equality](#fuzzy-equality)
|
||||
* [Integer](#integer)
|
||||
* [Potentially Slash-Separated Number](#potentially-slash-separated-number)
|
||||
* [Types](#types)
|
||||
* [Operations](#operations)
|
||||
* [Equality](#equality)
|
||||
* [Greater Than or Equal To](#greater-than-or-equal-to)
|
||||
* [Less Than or Equal To](#less-than-or-equal-to)
|
||||
* [Greater Than](#greater-than)
|
||||
* [Less Than](#less-than)
|
||||
* [Addition](#addition)
|
||||
* [Subtraction](#subtraction)
|
||||
* [Multiplication](#multiplication)
|
||||
* [Modulo](#modulo)
|
||||
* [Negation](#negation)
|
||||
* [Procedures](#procedures)
|
||||
* [Converting a Number to a Unit](#converting-a-number-to-a-unit)
|
||||
* [Matching Two Numbers' Units](#matching-two-numbers-units)
|
||||
* [Simplifying a Number](#simplifying-a-number)
|
||||
|
||||
## Definitions
|
||||
|
||||
### Double
|
||||
|
||||
A *double* is a floating-point datum representable in a format with
|
||||
|
||||
* `b = 2`
|
||||
* `p = 53`
|
||||
* `emax = 1023`
|
||||
|
||||
as defined by [IEEE 754 2019], §3.2-3.3.
|
||||
|
||||
[IEEE 754 2019]: https://ieeexplore.ieee.org/document/8766229
|
||||
|
||||
> This is the standard 64-bit floating point representation, defined as
|
||||
> `binary64` in [IEEE 754 2019], §3.6.
|
||||
|
||||
### Conversion Factors
|
||||
|
||||
Certain units have conversion factors that define how they can be converted to
|
||||
@ -48,22 +81,36 @@ The following conversion factors are defined:
|
||||
* `dpi`: 1/96 `dppx`
|
||||
* `dpcm`: 2.54/96 `dppx`
|
||||
|
||||
### Set of Units
|
||||
|
||||
A *set of units* is structure with:
|
||||
|
||||
* A list of strings called "numerator units".
|
||||
* A list of strings called "denominator units".
|
||||
|
||||
When not otherwise specified, a single unit refers to numerator units containing
|
||||
only that unit and empty denominator units.
|
||||
|
||||
### Compatible Units
|
||||
|
||||
Two numbers' units are said to be *compatible* if:
|
||||
Two numbers' units are said to be *compatible* if both:
|
||||
|
||||
* there's a one-to-one mapping between those numbers' numerator units such
|
||||
that each pair of units is either identical, or both units have a [conversion
|
||||
factor] and those two conversion factors have the same unit; and
|
||||
* There's a one-to-one mapping between those numbers' numerator units such that
|
||||
each pair of units is either identical, or both units have a [conversion
|
||||
factor] and those two conversion factors have the same unit. This mapping is
|
||||
known as the numbers' *numerator compatibility map*.
|
||||
|
||||
* there's the same type of mapping between those numbers' denominator units.
|
||||
* There's the same type of mapping between those numbers' denominator units.
|
||||
This mapping is known as the numbers' *denominator compatibility map*.
|
||||
|
||||
[conversion factors]: #conversion-factors
|
||||
[conversion factor]: ../spec/types/number.md#conversion-factors
|
||||
|
||||
Similarly, a number is *compatible with* a set of units if it's compatible with
|
||||
a number that has those units; and two sets of units are *compatible* if a
|
||||
Similarly, a number is *compatible with* a [set of units] if it's compatible
|
||||
with a number that has those units; and two sets of units are *compatible* if a
|
||||
number with one set is compatible with a number with the other.
|
||||
|
||||
[set of units]: #set-of-units
|
||||
|
||||
### Possibly-Compatible Units
|
||||
|
||||
Two units are *possibly-compatible* with one another if and only if either both
|
||||
@ -105,6 +152,34 @@ Two numbers are *definitely-incompatible* if they are not possibly-compatible.
|
||||
> complex units, but in practice these numbers are already flagged as errors
|
||||
> prior to any possible-compatibility checks.
|
||||
|
||||
### Fuzzy Equality
|
||||
|
||||
Two [doubles] are said to be *fuzzy equal* to one another if either:
|
||||
|
||||
[doubles]: #double
|
||||
|
||||
* They are equal according to the `compareQuietEqual` predicate as defined
|
||||
by [IEEE 754 2019], §5.11.
|
||||
|
||||
* They are both finite numbers and the mathematical numbers they represent
|
||||
produce the same value when rounded to the nearest 1e⁻¹¹ (with ties away from
|
||||
zero).
|
||||
|
||||
### Integer
|
||||
|
||||
A SassScript number `n` is said to be an *integer* if there exists a
|
||||
mathematical integer `m` with an exact [double] representation and `n`'s value
|
||||
[fuzzy equals] that double.
|
||||
|
||||
If `m` exists, we say that `n`'s *integer value* is the double that represents
|
||||
`m`.
|
||||
|
||||
[double]: #double
|
||||
[fuzzy equals]: #fuzzy-equality
|
||||
|
||||
> To avoid ambiguity, specification text will generally use the term
|
||||
> "mathematical integer" when referring to the abstract mathematical objects.
|
||||
|
||||
### Potentially Slash-Separated Number
|
||||
|
||||
A Sass number may be *potentially slash-separated*. If it is, it is associated
|
||||
@ -155,32 +230,208 @@ value, it is written as the original numerator followed by `/` followed by the
|
||||
original denominator. If either the original numerator or denominator are
|
||||
themselves slash-separated, they're also written this way.
|
||||
|
||||
## Types
|
||||
|
||||
The value type known as a *number* has three components:
|
||||
|
||||
* A [double] called its "value".
|
||||
* A list of strings called *numerator units*.
|
||||
* A list of strings called *denominator units*.
|
||||
|
||||
[double]: #doubles
|
||||
|
||||
Several shorthands exist when referring to numbers:
|
||||
|
||||
* A number's *units* refers to the [set of units] containing its numerator units
|
||||
and denominator units.
|
||||
|
||||
* A number is *unitless* if its numerator and denominator units are both empty.
|
||||
|
||||
* A number is *in a given unit* (such as "in `px`") if it has that unit as its
|
||||
single numerator unit and has no denominator units.
|
||||
|
||||
### Operations
|
||||
|
||||
#### Equality
|
||||
|
||||
Let `n1` and `n2` be two numbers. To determine `n1 == n2`:
|
||||
|
||||
* Let `c1` and `c2` be the result of [matching units] for `n1` and `n2`. If this
|
||||
throws an error, return false.
|
||||
|
||||
[matching units]: #matching-two-numbers-units
|
||||
|
||||
* Return true if `c1`'s value [fuzzy equals] `c2`'s and false otherwise.
|
||||
|
||||
#### Greater Than or Equal To
|
||||
|
||||
Let `n1` and `n2` be two numbers. To determine `n1 >= n2`:
|
||||
|
||||
* Let `c1` and `c2` be the result of [matching units] for `n1` and `n2` allowing
|
||||
unitless.
|
||||
|
||||
* Return true if `c1`'s value [fuzzy equals] `c2`'s, or if
|
||||
`compareQuietGreaterEqual(c1.value, c2.value)` returns `true` as defined by
|
||||
[IEEE 754 2019], §5.11. Return false otherwise.
|
||||
|
||||
#### Less Than or Equal To
|
||||
|
||||
Let `n1` and `n2` be two numbers. To determine `n1 <= n2`:
|
||||
|
||||
* Let `c1` and `c2` be the result of [matching units] for `n1` and `n2` allowing
|
||||
unitless.
|
||||
|
||||
* Return true if `c1`'s value [fuzzy equals] `c2`'s, or if
|
||||
`compareQuietLessEqual(c1.value, c2.value)` returns `true` as defined by [IEEE
|
||||
754 2019], §5.11. Return false otherwise.
|
||||
|
||||
#### Greater Than
|
||||
|
||||
Let `n1` and `n2` be two numbers. To determine `n1 > n2`, return `n1 >= n2 and
|
||||
n1 != n2`.
|
||||
|
||||
#### Less Than
|
||||
|
||||
Let `n1` and `n2` be two numbers. To determine `n1 < n2`, return `n1 <= n2 and
|
||||
n1 != n2`.
|
||||
|
||||
#### Addition
|
||||
|
||||
Let `n1` and `n2` be two numbers. To determine `n1 + n2`:
|
||||
|
||||
* Let `c1` and `c2` be the result of [matching units] for `n1` and `n2` allowing
|
||||
unitless.
|
||||
|
||||
* Return a number whose value is the result of `addition(c1.value, c2.value)` as defined by
|
||||
[IEEE 754 2019], §5.4.1; and whose units are the same as `c1`'s.
|
||||
|
||||
#### Subtraction
|
||||
|
||||
Let `n1` and `n2` be two numbers. To determine `n1 - n2`:
|
||||
|
||||
* Let `c1` and `c2` be the result of [matching units] for `n1` and `n2` allowing
|
||||
unitless.
|
||||
|
||||
* Return a number whose value is the result of `subtraction(c1.value, c2.value)`
|
||||
as defined by [IEEE 754 2019], §5.4.1; and whose units are the same as `c1`'s.
|
||||
|
||||
#### Multiplication
|
||||
|
||||
Let `n1` and `n2` be two numbers. To determine `n1 * n2`:
|
||||
|
||||
* Let `product` be a number whose value is the result of
|
||||
`multiplication(n1.value, n2.value)` as defined by [IEEE 754 2019], §5.4.1;
|
||||
whose numerator units are the concatenation of `n1`'s and `n2`'s numerator
|
||||
units; and whose denominator units are the concatenation of `n1`'s and `n2`'s
|
||||
denominator units.
|
||||
|
||||
* Return the result of [simplifying] `product`.
|
||||
|
||||
[simplifying]: #simplifying-a-number
|
||||
|
||||
#### Modulo
|
||||
|
||||
Let `n1` and `n2` be two numbers. To determine `n1 % n2`:
|
||||
|
||||
* Let `c1` and `c2` be the result of [matching units] for `n1` and `n2` allowing
|
||||
unitless.
|
||||
|
||||
* Let `remainder` be a number whose value is the result of `remainder(c1.value,
|
||||
c2.value)` as defined by [IEEE 754 2019], §5.3.1; and whose units are the same
|
||||
as `c1`'s.
|
||||
|
||||
* If `c2`'s value is less than 0 and `remainder`'s value isn't `0` or `-0`,
|
||||
return `result - c2`.
|
||||
|
||||
> This is known as [floored division]. It differs from the standard IEEE 754
|
||||
> specification because it was originally inherited from Ruby when that was
|
||||
> used for Sass's original implementation.
|
||||
>
|
||||
> [floored division]: https://en.wikipedia.org/wiki/Modulo_operation#Variants_of_the_definition
|
||||
>
|
||||
> Note: These comparisons are not the same as `c2 < 0` or `remainder == 0`,
|
||||
> because they don't do fuzzy equality.
|
||||
|
||||
* Otherwise, return `result`.
|
||||
|
||||
#### Negation
|
||||
|
||||
Let `number` be a number. To determine `-number`, return a number whose value is
|
||||
the result of `negate(number)` as defined by [IEEE 754 2019], §5.5.1; and whose
|
||||
units are the same as `number`'s.
|
||||
|
||||
## Procedures
|
||||
|
||||
### Converting a Number to a Unit
|
||||
|
||||
This algorithm takes a SassScript number `number` and a unit `unit`. It's
|
||||
written "convert `number` to `unit`" or "convert `number` to `unit` allowing
|
||||
unitless". It returns a number with the given unit. The `unit` argument must
|
||||
have a conversion factor.
|
||||
This algorithm takes a SassScript number `number` and a [set of units] `units`.
|
||||
It returns a number with the given units. It's written "convert `number` to
|
||||
`units`" or "convert `number` to `units` allowing unitless".
|
||||
|
||||
* If `number` has no units:
|
||||
* If `number` is unitless and this procedure allows unitless, return
|
||||
`number` with `units`.
|
||||
|
||||
* If this procedure allows unitless, return `number` with unit `unit`.
|
||||
|
||||
* Otherwise, throw an error.
|
||||
|
||||
* If `number`'s unit is `unit`, return `number` as-is.
|
||||
|
||||
* Let `number-factor` be `number`'s unit's conversion factor. If `number`
|
||||
doesn't have a unit or that unit doesn't have a conversion factor, throw an
|
||||
* Otherwise, if `number`'s units aren't [compatible with] `units`, throw an
|
||||
error.
|
||||
|
||||
* Let `unit-factor` be `unit`'s conversion factor.
|
||||
[compatible with]: #compatible-units
|
||||
|
||||
* If `number-factor` and `unit-factor` don't have the same unit, throw an error.
|
||||
* Let `value` be `number`'s value.
|
||||
|
||||
* Let `result` be the result of multiplying `number`'s numeric component by
|
||||
`number-factor`'s, then dividing by `unit-factor`'s numeric component.
|
||||
* For each pair of units `u1`, `u2` in the [numerator compatibility
|
||||
map] between `number` and `units` such that `u1 != u2`:
|
||||
|
||||
* Return `result` with unit `unit`.
|
||||
[numerator compatibility map]: #compatible-units
|
||||
|
||||
* Let `v1` and `v2` be the values of `u1` and `u2`'s [conversion factors].
|
||||
|
||||
[conversion factors]: ../spec/types/number.md#conversion-factors
|
||||
|
||||
* Set `value` to `division(multiplication(value, v1), v2)` as defined by
|
||||
[IEEE 754 2019], §5.4.1.
|
||||
|
||||
* For each pair of units `u1`, `u2` in the [denominator compatibility map]
|
||||
between `number` and `units` such that `u1 != u2`:
|
||||
|
||||
* Let `v1` and `v2` be the values of `u1` and `u2`'s [conversion factors].
|
||||
|
||||
* Set `value` to `division(multiplication(value, v2), v1)` as defined by
|
||||
[IEEE 754 2019], §5.4.1.
|
||||
|
||||
* Return a number with value `value` and units `units`.
|
||||
|
||||
### Matching Two Numbers' Units
|
||||
|
||||
This algorithm takes two SassScript numbers `n1` and `n2` and returns two
|
||||
numbers. It's written "match units for `n1` and `n2`" or "match units for `n1`
|
||||
and `n2` allowing unitless".
|
||||
|
||||
* If `n1` is unitless and this procedure allows unitless, return `n1`
|
||||
with the same units as `n2` and `n2`.
|
||||
|
||||
* Otherwise, if `n2` is unitless and this procedure allows unitless, return `n1`
|
||||
and `n2` with the same units as `n1`.
|
||||
|
||||
* Return `n1` and the result of [converting `n2` to `n1`'s units].
|
||||
|
||||
[converting `n1` to `n2`'s units]: #converting-a-number-to-units
|
||||
|
||||
### Simplifying a Number
|
||||
|
||||
This algorithm takes a SassScript number `number` and returns an equivalent
|
||||
number with simplified units.
|
||||
|
||||
* Let `mapping` be a one-to-one mapping between `number`'s numerator units and
|
||||
its denominator units such that each pair of units is either identical, or
|
||||
both units have a [conversion factor] and those two conversion factors have
|
||||
the same unit.
|
||||
|
||||
* Let `newUnits` be a copy of `number`'s units without any of the units in
|
||||
`mapping`.
|
||||
|
||||
> `newUnits` for `1px*px/px` is `px`, because only one of the numerator `px`
|
||||
> is included in the mapping.
|
||||
|
||||
* Return the result of [converting `number` to `newUnits`].
|
||||
|
||||
[converting `number` to `newUnits`]: #converting-a-number-to-units
|
||||
|
Loading…
Reference in New Issue
Block a user