Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Generated by SassMeister.com.
// ----
// Sass (v3.4.11)
// Compass (v1.0.3)
// ----
@function math-pow($number, $exp) {
@if (round($exp) != $exp) {
@return math-exp($exp * math-ln($number));
}
// Traditional method for integers
$value: 1;
@if $exp > 0 {
@for $i from 1 through $exp {
$value: $value * $number;
}
}
@else if $exp < 0 {
@for $i from 1 through -$exp {
$value: $value / $number;
}
}
@return $value;
}
@function math-factorial($value) {
@if $value == 0 {
@return 1;
}
$result: 1;
@for $index from 1 through $value {
$result: $result * $index;
}
@return $result;
}
@function math-summation($iteratee, $input, $initial: 0, $limit: 100) {
$sum: 0;
@for $index from $initial to $limit {
$sum: $sum + call($iteratee, $input, $index);
}
@return $sum;
}
@function math-exp-maclaurin($x, $n) {
$result: math-pow($x, $n) / math-factorial($n);
@return $result;
}
@function math-exp($value) {
$result: math-summation(math-exp-maclaurin, $value, 0, 100);
@return $result;
}
@function math-ln-maclaurin($x, $n) {
$result: (math-pow(-1, $n + 1) / $n) * (math-pow($x - 1, $n));
@return $result;
}
@function math-ln($value) {
$ten-exp: 1;
$ln-ten: 2.30258509;
@while ($value > math-pow(10, $ten-exp)) {
$ten-exp: $ten-exp + 1;
}
$value: $value / math-pow(10, $ten-exp);
$result: math-summation(math-ln-maclaurin, $value, 1, 100);
@return $result + $ten-exp * $ln-ten;
}
.test {
input: 'math-pow(3, 2)';
expected: 9;
actual: math-pow(3, 2);
input: 'math-pow(4, 3/2)';
expected: 8;
actual: math-pow(4, 3/2);
input: 'math-pow(144, 1/2)';
expected: 12;
actual: math-pow(144, 1/2);
input: 'math-pow(-3, 2)';
expected: 9;
actual: math-pow(-3, 2);
input: 'math-pow(3, -2)';
expected: 0.1111;
actual: math-pow(3, -2);
input: 'math-pow(64, -1/2)';
expected: 0.125;
actual: math-pow(64, -1/2);
input: 'math-pow(12, 3.4)';
expected: 4668.91789313;
actual: math-pow(12, 3.4);
}
.test {
input: 'math-pow(3, 2)';
expected: 9;
actual: 9;
input: 'math-pow(4, 3/2)';
expected: 8;
actual: 8.0;
input: 'math-pow(144, 1/2)';
expected: 12;
actual: 12.0;
input: 'math-pow(-3, 2)';
expected: 9;
actual: 9;
input: 'math-pow(3, -2)';
expected: 0.1111;
actual: 0.11111;
input: 'math-pow(64, -1/2)';
expected: 0.125;
actual: 0.125;
input: 'math-pow(12, 3.4)';
expected: 4668.91789313;
actual: 4668.92127;
}
@xi
Copy link

xi commented Feb 25, 2016

The idea of using taylor/maclaurin expansions is great, but the implementation is very inefficient. For example the implementation of math-pow uses linear time, while it could be implemented in logarithmic time. Also for the series themselves you could save the factorial and power of each step instead of calculating it all again for the next one.

I tried to do a more efficient implementation at http://www.sassmeister.com/gist/5bbe8480c48e2fc10ab5. It compiles about 100 times faster while producing more output (I added sin). What do you think of it?

@jakob-e
Copy link

jakob-e commented Jan 31, 2017

Thank you both :-)
@xi hope you don't mind me linking to your sass-planifolia repo :-)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment