2015-08-20 16:10:54 -04:00
|
|
|
// This file:
|
|
|
|
// Copyright (c) 2013 Takeru Suzuki
|
|
|
|
// Licensed under the MIT license.
|
|
|
|
// https://github.com/terkel/mathsass
|
|
|
|
|
|
|
|
// Constants
|
2023-02-07 10:24:57 -05:00
|
|
|
@use "sass:math";
|
|
|
|
|
2018-06-08 05:49:31 -04:00
|
|
|
$E: 2.718281828459045;
|
|
|
|
$PI: 3.141592653589793;
|
|
|
|
$LN2: 0.6931471805599453;
|
2015-08-20 16:10:54 -04:00
|
|
|
$SQRT2: 1.4142135623730951;
|
|
|
|
|
|
|
|
@function error($message) {
|
|
|
|
@warn "#{_error("The direction used does not exist")}";
|
|
|
|
@return null;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Returns the factorial of a non-negative integer.
|
|
|
|
// @param {Number} $x A non-negative integer.
|
|
|
|
// @return {Number}
|
|
|
|
// @example
|
|
|
|
// fact(0) // 1
|
|
|
|
// fact(8) // 40320
|
2018-06-08 05:49:31 -04:00
|
|
|
@function fact($x) {
|
|
|
|
@if $x < 0 or $x != floor($x) {
|
2015-08-20 16:10:54 -04:00
|
|
|
@warn "Argument for `fact()` must be a positive integer.";
|
|
|
|
@return null;
|
|
|
|
}
|
|
|
|
$ret: 1;
|
|
|
|
@while $x > 0 {
|
|
|
|
$ret: $ret * $x;
|
|
|
|
$x: $x - 1;
|
|
|
|
}
|
|
|
|
@return $ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Returns a two-element list containing the normalized fraction and exponent of number.
|
|
|
|
// @param {Number} $x
|
|
|
|
// @return {List} fraction, exponent
|
2018-06-08 05:49:31 -04:00
|
|
|
@function frexp($x) {
|
2015-08-20 16:10:54 -04:00
|
|
|
$exp: 0;
|
|
|
|
@if $x < 0 {
|
|
|
|
$x: $x * -1;
|
|
|
|
}
|
|
|
|
@if $x < 0.5 {
|
|
|
|
@while $x < 0.5 {
|
|
|
|
$x: $x * 2;
|
|
|
|
$exp: $exp - 1;
|
|
|
|
}
|
|
|
|
} @else if $x >= 1 {
|
|
|
|
@while $x >= 1 {
|
2023-02-07 10:24:57 -05:00
|
|
|
$x: $x * 0.5;
|
2015-08-20 16:10:54 -04:00
|
|
|
$exp: $exp + 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
@return $x, $exp;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Returns $x * 2^$exp
|
|
|
|
// @param {Number} $x
|
|
|
|
// @param {Number} $exp
|
2018-06-08 05:49:31 -04:00
|
|
|
@function ldexp($x, $exp) {
|
2023-02-07 10:24:57 -05:00
|
|
|
$b: if($exp >= 0, 2, 1 * 0.5);
|
2015-08-20 16:10:54 -04:00
|
|
|
@if $exp < 0 {
|
|
|
|
$exp: $exp * -1;
|
|
|
|
}
|
|
|
|
@while $exp > 0 {
|
|
|
|
@if $exp % 2 == 1 {
|
|
|
|
$x: $x * $b;
|
|
|
|
}
|
|
|
|
$b: $b * $b;
|
|
|
|
$exp: floor($exp * 0.5);
|
|
|
|
}
|
|
|
|
@return $x;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Returns the natural logarithm of a number.
|
|
|
|
// @param {Number} $x
|
|
|
|
// @example
|
|
|
|
// log(2) // 0.69315
|
|
|
|
// log(10) // 2.30259
|
2018-06-08 05:49:31 -04:00
|
|
|
@function log($x) {
|
2015-08-20 16:10:54 -04:00
|
|
|
@if $x <= 0 {
|
2023-02-07 10:24:57 -05:00
|
|
|
@return math.div(0, 0);
|
2015-08-20 16:10:54 -04:00
|
|
|
}
|
2023-02-07 10:24:57 -05:00
|
|
|
$k: nth(frexp(math.div($x, $SQRT2)), 2);
|
|
|
|
$x: math.div($x, ldexp(1, $k));
|
|
|
|
$x: math.div($x - 1, $x + 1);
|
2015-08-20 16:10:54 -04:00
|
|
|
$x2: $x * $x;
|
|
|
|
$i: 1;
|
|
|
|
$s: $x;
|
|
|
|
$sp: null;
|
|
|
|
@while $sp != $s {
|
|
|
|
$x: $x * $x2;
|
|
|
|
$i: $i + 2;
|
|
|
|
$sp: $s;
|
2023-02-07 10:24:57 -05:00
|
|
|
$s: $s + math.div($x, $i);
|
2015-08-20 16:10:54 -04:00
|
|
|
}
|
|
|
|
@return $LN2 * $k + 2 * $s;
|
|
|
|
}
|
|
|
|
|
|
|
|
@function ipow($base, $exp) {
|
|
|
|
@if $exp != floor($exp) {
|
|
|
|
@return error("Exponent for `ipow()` must be an integer.");
|
|
|
|
}
|
|
|
|
$r: 1;
|
|
|
|
$s: 0;
|
|
|
|
@if $exp < 0 {
|
|
|
|
$exp: $exp * -1;
|
|
|
|
$s: 1;
|
|
|
|
}
|
|
|
|
@while $exp > 0 {
|
|
|
|
@if $exp % 2 == 1 {
|
|
|
|
$r: $r * $base;
|
|
|
|
}
|
|
|
|
$exp: floor($exp * 0.5);
|
|
|
|
$base: $base * $base;
|
|
|
|
}
|
2023-02-07 10:24:57 -05:00
|
|
|
@return if($s != 0, math.div(1, $r), $r);
|
2015-08-20 16:10:54 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
// Returns E^x, where x is the argument, and E is Euler's constant, the base of the natural logarithms.
|
|
|
|
// @param {Number} $x
|
|
|
|
// @example
|
|
|
|
// exp(1) // 2.71828
|
|
|
|
// exp(-1) // 0.36788
|
2018-06-08 05:49:31 -04:00
|
|
|
@function exp($x) {
|
2015-08-20 16:10:54 -04:00
|
|
|
$ret: 0;
|
|
|
|
@for $n from 0 to 24 {
|
2023-02-07 10:24:57 -05:00
|
|
|
$ret: $ret + math.div(ipow($x, $n), fact($n));
|
2015-08-20 16:10:54 -04:00
|
|
|
}
|
|
|
|
@return $ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Returns base to the exponent power.
|
|
|
|
// @param {Number} $base The base number
|
|
|
|
// @param {Number} $exp The exponent to which to raise base
|
|
|
|
// @return {Number}
|
|
|
|
// @example
|
|
|
|
// pow(4, 2) // 16
|
|
|
|
// pow(4, -2) // 0.0625
|
|
|
|
// pow(4, 0.2) // 1.31951
|
2018-06-08 05:49:31 -04:00
|
|
|
@function pow($base, $exp) {
|
2015-08-20 16:10:54 -04:00
|
|
|
@if $exp == floor($exp) {
|
|
|
|
@return ipow($base, $exp);
|
|
|
|
} @else {
|
|
|
|
@return exp(log($base) * $exp);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Returns the square root of a number.
|
|
|
|
// @param {Number} $x
|
|
|
|
// @example
|
|
|
|
// sqrt(2) // 1.41421
|
|
|
|
// sqrt(5) // 2.23607
|
2018-06-08 05:49:31 -04:00
|
|
|
@function sqrt($x) {
|
2015-08-20 16:10:54 -04:00
|
|
|
@if $x < 0 {
|
|
|
|
@return error("Argument for `sqrt()` must be a positive number.");
|
|
|
|
}
|
|
|
|
$ret: 1;
|
|
|
|
@for $i from 1 through 24 {
|
2023-02-07 10:24:57 -05:00
|
|
|
$ret: $ret - math.div(pow($ret, 2) - $x, 2 * $ret);
|
2015-08-20 16:10:54 -04:00
|
|
|
}
|
|
|
|
@return $ret;
|
|
|
|
}
|