Created
February 25, 2016 18:21
-
-
Save xi/5bbe8480c48e2fc10ab5 to your computer and use it in GitHub Desktop.
Generated by SassMeister.com.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// ---- | |
// libsass (v3.2.5) | |
// ---- | |
// This provides some common mathemetical functions implemented in pure sass: | |
// | |
// - $PI | |
// - ln($x, $steps: 32) | |
// - pow($x, $exponent, $steps: 32) | |
// - sqrt($x, $exponent: 2, $steps: 32) | |
// - sin($x, $steps: 32) | |
// - cos($x, $steps: 32) | |
// - tan($x, $steps: 32) | |
// | |
// The implementations are based on taylor expansions. The `$steps` argument | |
// defines how many steps of the series will be calculated. So a higher number | |
// will result in higher precision. | |
// | |
// Taylor expansions converge quickly around their centers, so a decent | |
// approximation can be calculated in constant time. | |
// | |
// If the input $x is too far off of the center, it is converted to a closer | |
// value $y in a way that allows to calculate f($x) from f($y). This conversion | |
// uses exact arithmetics and can be done in constant or logarithmic time. | |
// | |
// This approach is havily inspired by | |
// <http://www.sassmeister.com/gist/ad6e6771df050ff3727f>. However, the | |
// implementations in this gist are much more efficient. | |
$PI: 3.141592653589793; | |
@function -math-exp-taylor-0($x, $steps) { | |
$item: 1; | |
$result: 1; | |
@for $i from 1 to $steps { | |
$item: $item * $x / $i; | |
$result: $result + $item; | |
} | |
@return $result; | |
} | |
@function -math-ln-taylor-1($x, $steps) { | |
$z: ($x - 1) / ($x + 1); | |
$power: $z; | |
$result: $z; | |
@for $i from 1 to $steps { | |
$power: $power * $z *$z; | |
$result: $result + $power / (2 * $i + 1); | |
} | |
@return 2 * $result; | |
} | |
@function -math-sin-taylor-0($x, $steps) { | |
$item: $x; | |
$result: $x; | |
@for $i from 1 to $steps { | |
$item: -$item * $x * $x / (2 * $i) / (2 * $i + 1); | |
$result: $result + $item; | |
} | |
@return $result; | |
} | |
@function -math-pow-int($base, $exponent) { | |
@if $exponent < 0 { | |
@return 1 / -math-pow-int($base, -$exponent); | |
} @else if $exponent == 0 { | |
@return 1; | |
} @else if $exponent == 1 { | |
@return $base; | |
} @else { | |
$exp: floor($exponent / 2); | |
$pow: -math-pow-int($base, $exp); | |
@if $exp * 2 == $exponent { | |
@return $pow * $pow; | |
} @else { | |
@return $pow * $pow * $base; | |
} | |
} | |
} | |
@function -math-log-approx($x) { | |
@if $x <= 0 { | |
@error "cannot calculate log of #{$x}"; | |
} @else if $x >= 1 { | |
// choose the smaller option (-1) because it yield better | |
// results in ln(). | |
@return str-length(inspect(round($x))) - 1; | |
} @else { | |
@return -1 * str-length(inspect(round(1 / $x))); | |
} | |
} | |
@function ln($x, $steps: 32) { | |
$ln10: 2.302585092994046; | |
$approx: -math-log-approx($x); | |
// $y is in range [1, 10] | |
$y: $x / -math-pow-int(10, $approx); | |
@return $approx * $ln10 + -math-ln-taylor-1($y, $steps); | |
} | |
@function pow($x, $exponent, $steps: 32) { | |
$exp1: round($exponent); | |
$exp2: $exponent - $exp1; | |
$pow1: -math-pow-int($x, $exp1); | |
@if $exp2 == 0 { | |
@return $pow1; | |
} @else { | |
$y: ln($x, $steps) * $exp2; | |
$pow2: -math-exp-taylor-0($y, $steps); | |
@return $pow1 * $pow2; | |
} | |
} | |
@function sqrt($x, $exponent: 2, $steps: 32) { | |
@return pow($x, 1 / $exponent, $steps); | |
} | |
@function sin($x, $steps: 32) { | |
$y: $x % (2 * $PI); | |
@if $y > $PI { | |
@return -1 * sin($y - $PI); | |
} @else if $y < 0 { | |
@return -1 * sin(-$y); | |
} @else { | |
@return -math-sin-taylor-0($y % (2 * $PI), $steps); | |
} | |
} | |
@function cos($x, $steps: 32) { | |
@return sin($x - $PI / 2, $steps); | |
} | |
@function tan($x, $steps: 32) { | |
@return sin($x, $steps) / $cos($x, $steps); | |
} | |
.test-ln { | |
input: 'ln(1)'; | |
expected: 0; | |
actual: ln(1); | |
input: 'ln(0.1)'; | |
expected: -2.3025850929940455; | |
actual: ln(0.1); | |
input: 'ln(123456789)'; | |
expected: 18.63140176616802; | |
actual: ln(123456789); | |
} | |
.test-pow { | |
input: 'pow(3, 2)'; | |
expected: 9; | |
actual: pow(3, 2); | |
input: 'pow(4, 3/2)'; | |
expected: 8; | |
actual: pow(4, 3/2); | |
input: 'pow(144, 1/2)'; | |
expected: 12; | |
actual: pow(144, 1/2); | |
input: 'pow(-3, 2)'; | |
expected: 9; | |
actual: pow(-3, 2); | |
input: 'pow(3, -2)'; | |
expected: 0.1111; | |
actual: pow(3, -2); | |
input: 'pow(64, -1/2)'; | |
expected: 0.125; | |
actual: pow(64, -1/2); | |
input: 'pow(12, 3.4)'; | |
expected: 4668.91789313; | |
actual: pow(12, 3.4); | |
} | |
.test-sin { | |
input: 'sin(0)'; | |
expected: 0; | |
actual: sin(0); | |
input: 'sin($PI)'; | |
expected: 0; | |
actual: sin($PI); | |
input: 'sin(2 * $PI)'; | |
expected: 0; | |
actual: sin(2 * $PI); | |
input: 'sin(123456789 * $PI)'; | |
expected: 0; | |
actual: sin(123456789 * $PI); | |
input: 'sin(-$PI)'; | |
expected: 0; | |
actual: sin(-$PI); | |
input: 'sin(1/2 * $PI)'; | |
expected: 1; | |
actual: sin(1/2 * $PI); | |
input: 'sin(3/2 * PI)'; | |
expected: -1; | |
actual: sin(3/2 * $PI); | |
input: 'sin(1)'; | |
expected: 0.8414709848078965; | |
actual: sin(1); | |
input: 'sin(2)'; | |
expected: 0.9092974268256817; | |
actual: sin(2); | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
.test-ln { | |
input: 'ln(1)'; | |
expected: 0; | |
actual: 0; | |
input: 'ln(0.1)'; | |
expected: -2.3025850929940455; | |
actual: -2.30259; | |
input: 'ln(123456789)'; | |
expected: 18.63140176616802; | |
actual: 18.6314; | |
} | |
.test-pow { | |
input: 'pow(3, 2)'; | |
expected: 9; | |
actual: 9; | |
input: 'pow(4, 3/2)'; | |
expected: 8; | |
actual: 8; | |
input: 'pow(144, 1/2)'; | |
expected: 12; | |
actual: 12; | |
input: 'pow(-3, 2)'; | |
expected: 9; | |
actual: 9; | |
input: 'pow(3, -2)'; | |
expected: 0.1111; | |
actual: 0.11111; | |
input: 'pow(64, -1/2)'; | |
expected: 0.125; | |
actual: 0.125; | |
input: 'pow(12, 3.4)'; | |
expected: 4668.91789313; | |
actual: 4668.91789; | |
} | |
.test-sin { | |
input: 'sin(0)'; | |
expected: 0; | |
actual: 0; | |
input: 'sin($PI)'; | |
expected: 0; | |
actual: 0; | |
input: 'sin(2 * $PI)'; | |
expected: 0; | |
actual: 0; | |
input: 'sin(123456789 * $PI)'; | |
expected: 0; | |
actual: 0.0; | |
input: 'sin(-$PI)'; | |
expected: 0; | |
actual: 0; | |
input: 'sin(1/2 * $PI)'; | |
expected: 1; | |
actual: 1; | |
input: 'sin(3/2 * PI)'; | |
expected: -1; | |
actual: -1; | |
input: 'sin(1)'; | |
expected: 0.8414709848078965; | |
actual: 0.84147; | |
input: 'sin(2)'; | |
expected: 0.9092974268256817; | |
actual: 0.9093; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
This is now packaged in https://github.com/xi/sass-planifolia