Last active
December 26, 2015 12:09
-
-
Save jamiebuilds/7148858 to your computer and use it in GitHub Desktop.
Testing different methods of calculating square-root in Sass.
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
/* TESTING DIFFERENT METHODS OF CALCULATING SQUARE-ROOT IN SASS */ | |
.actual { | |
test-1: 1; | |
test-2: 1.414213562373095; | |
test-3: 1.732050807568877; | |
test-10: 3.16227766016838; | |
test-20: 4.47213595499958; | |
test-30: 5.477225575051661; | |
test-60: 7.745966692414834; | |
test-100: 10; | |
test-0-2: 0.447213595499958; | |
test--2: 'imaginary number'; | |
test--30: 'imaginary number'; | |
} | |
/* sassy-math */ | |
.method-1-test { | |
test-1: 1; | |
test-2: 1.41421; | |
test-3: 1.73205; | |
test-10: 3.16228; | |
test-20: 4.47214; | |
test-30: 5.47723; | |
test-60: 7.74597; | |
test-100: 10; | |
test-0-2: 0.44721; | |
test--2: -1.07057; | |
test--30: -22.77485; | |
} | |
/* css-recipes */ | |
.method-2-test { | |
test-1: 1; | |
test-2: 1.41421; | |
test-3: 1.73205; | |
test-10: 3.16228; | |
test-20: 4.47214; | |
test-30: 5.47723; | |
test-60: 7.74597; | |
test-100: 10; | |
test-0-2: 0.44721; | |
test--2: 1.41421; | |
test--30: 5.47723; | |
} | |
/* Sass-Math */ | |
/* This method is very slow and isn't very | |
* accurate so I've opted to disabled it. | |
*/ | |
/* | |
.method-3-test { | |
test-1: method-3-sqrt( 1); | |
test-2: method-3-sqrt( 2); | |
test-3: method-3-sqrt( 3); | |
test-10: method-3-sqrt( 10); | |
test-20: method-3-sqrt( 20); | |
test-30: method-3-sqrt( 30); | |
test-60: method-3-sqrt( 60); | |
test-100: method-3-sqrt(100); | |
test-0-2: method-3-sqrt(0.2); | |
test--2: method-3-sqrt( -2); | |
test--30: method-3-sqrt(-30); | |
} | |
*/ | |
/* mathsass */ | |
.method-4-test { | |
test-1: 1; | |
test-2: 1.41421; | |
test-3: 1.73205; | |
test-10: 3.16228; | |
test-20: 4.47214; | |
test-30: 5.47723; | |
test-60: 7.74597; | |
test-100: 10; | |
test-0-2: 0.44721; | |
} | |
/* ishango */ | |
.method-5-test { | |
test-1: 1; | |
test-2: 1.41422; | |
test-3: 1.73205; | |
test-10: 3.16228; | |
test-20: 4.47214; | |
test-30: 5.47723; | |
test-60: 7.74597; | |
test-100: 10.0; | |
test-0-2: 0.44721; | |
} |
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
// ---- | |
// Sass (v3.3.0.rc.1) | |
// Compass (v0.13.alpha.7) | |
// ---- | |
/* TESTING DIFFERENT METHODS OF CALCULATING SQUARE-ROOT IN SASS */ | |
.actual { | |
test-1: 1; | |
test-2: 1.414213562373095; | |
test-3: 1.732050807568877; | |
test-10: 3.16227766016838; | |
test-20: 4.47213595499958; | |
test-30: 5.477225575051661; | |
test-60: 7.745966692414834; | |
test-100: 10; | |
test-0-2: 0.447213595499958; | |
test--2: 'imaginary number'; | |
test--30: 'imaginary number'; | |
} | |
// ------------------------ | |
// Sassy-Math | |
// https://github.com/Team-Sass/Sassy-math/blob/master/sass/math.scss#L259 | |
$method-1-iter: 50; | |
@function method-1-rand() { | |
@return 4; | |
} | |
@function method-1-exponent($base, $exponent) { | |
// reset value | |
$value: $base; | |
// positive intergers get multiplied | |
@if $exponent > 1 { | |
@for $i from 2 through $exponent { | |
$value: $value * $base; | |
} | |
} | |
// negitive intergers get divided. A number divided by itself is 1 | |
@if $exponent < 1 { | |
@for $i from 0 through -$exponent { | |
$value: $value / $base; | |
} | |
} | |
// return the last value written | |
@return $value; | |
} | |
@function method-1-sqrt($number) { | |
$guess: method-1-rand(); | |
$root: $guess; | |
@for $i from 1 through $method-1-iter { | |
$root: $root - (method-1-exponent($root, 2) - $number) / (2 * $root); | |
} | |
@return $root; | |
} | |
/* sassy-math */ | |
.method-1-test { | |
test-1: method-1-sqrt( 1); | |
test-2: method-1-sqrt( 2); | |
test-3: method-1-sqrt( 3); | |
test-10: method-1-sqrt( 10); | |
test-20: method-1-sqrt( 20); | |
test-30: method-1-sqrt( 30); | |
test-60: method-1-sqrt( 60); | |
test-100: method-1-sqrt(100); | |
test-0-2: method-1-sqrt(0.2); | |
test--2: method-1-sqrt( -2); | |
test--30: method-1-sqrt(-30); | |
} | |
// ------------------------ | |
// css-recipes | |
// https://github.com/css-recipes/math/blob/master/_index.scss#L67 | |
$method-2-approximationLimit: 10; | |
$method-2-approximationDecimalRound: 5; | |
@function method-2-power($x, $exponent) { | |
// reset value | |
$value: 1; | |
// positive intergers get multiplied | |
@if $exponent >= 0 { | |
@for $i from 1 through $exponent { | |
$value: $value * $x; | |
} | |
} | |
// negitive intergers get divided. A number divided by itself is 1 | |
@else { | |
@for $i from $exponent to 0 { | |
$value: $value / $x; | |
} | |
} | |
// return the last value written | |
@return $value; | |
} | |
@function method-2-decimalRound($x, $decimal: $method-2-approximationDecimalRound) { | |
$r: method-2-power(10, $decimal); | |
@return round($x * $r) / $r; | |
} | |
@function method-2-sqrt($x) { | |
$x: abs($x); | |
$guess: 4; | |
$root: $guess; | |
@for $i from 1 through $method-2-approximationLimit { | |
$root: $root - (method-2-power($root, 2) - $x) / (2 * $root); | |
} | |
@return method-2-decimalRound($root); | |
} | |
/* css-recipes */ | |
.method-2-test { | |
test-1: method-2-sqrt( 1); | |
test-2: method-2-sqrt( 2); | |
test-3: method-2-sqrt( 3); | |
test-10: method-2-sqrt( 10); | |
test-20: method-2-sqrt( 20); | |
test-30: method-2-sqrt( 30); | |
test-60: method-2-sqrt( 60); | |
test-100: method-2-sqrt(100); | |
test-0-2: method-2-sqrt(0.2); | |
test--2: method-2-sqrt( -2); | |
test--30: method-2-sqrt(-30); | |
} | |
// ------------------------ | |
// Sass-Math | |
// https://github.com/adambom/Sass-Math/blob/master/math.scss#L77 | |
@function method-3-power($x, $n) { | |
$ret: 1; | |
@if $n >= 0 { | |
@for $i from 1 through $n { | |
$ret: $ret * $x; | |
} | |
} @else { | |
@for $i from $n to 0 { | |
$ret: $ret / $x; | |
} | |
} | |
@return $ret; | |
} | |
@function method-3-factorial($x) { | |
$ret: 1; | |
@if $x > 0 { | |
@while $x > 0 { | |
$ret: $ret * $x; | |
$x: $x - 1; | |
} | |
} @else { | |
$ret: 1; | |
} | |
@return $ret; | |
} | |
@function method-3-exp($x) { | |
$ret: 0; | |
@for $n from 0 to 25 { | |
$ret: $ret + method-3-power($x, $n) / method-3-factorial($n); | |
} | |
@return $ret; | |
} | |
@function method-3-ln($x) { | |
$ret: 0; | |
$n: 1; | |
$dx: .001; | |
@while $n <= $x { | |
$ret: $ret + $dx / $n; | |
$n: $n + $dx; | |
} | |
@return $ret; | |
} | |
@function method-3-sqrt($x) { | |
@return method-3-exp(0.5 * method-3-ln($x)); | |
} | |
/* Sass-Math */ | |
/* This method is very slow and isn't very | |
* accurate so I've opted to disabled it. | |
*/ | |
/* | |
.method-3-test { | |
test-1: method-3-sqrt( 1); | |
test-2: method-3-sqrt( 2); | |
test-3: method-3-sqrt( 3); | |
test-10: method-3-sqrt( 10); | |
test-20: method-3-sqrt( 20); | |
test-30: method-3-sqrt( 30); | |
test-60: method-3-sqrt( 60); | |
test-100: method-3-sqrt(100); | |
test-0-2: method-3-sqrt(0.2); | |
test--2: method-3-sqrt( -2); | |
test--30: method-3-sqrt(-30); | |
} | |
*/ | |
// ------------------------ | |
// mathsass | |
// https://github.com/terkel/mathsass/blob/master/_math.scss#L66 | |
@function method-4-fact($x) { | |
@if $x < 0 or $x != floor($x) { | |
@warn "Argument for `fact()` must be a positive integer."; | |
@return null; | |
} | |
$ret: 1; | |
@while $x > 0 { | |
$ret: $ret * $x; | |
$x: $x - 1; | |
} | |
@return $ret; | |
} | |
@function method-4-exp($x) { | |
$ret: 0; | |
@for $n from 0 to 24 { | |
$ret: $ret + method-4-pow($x, $n) / method-4-fact($n); | |
} | |
@return $ret; | |
} | |
@function method-4-pow($base, $exp) { | |
@if $exp == floor($exp) { | |
$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; | |
} | |
@return if($s != 0, 1 / $r, $r); | |
} @else { | |
@return method-4-exp(method-4-log($base) * $exp); | |
} | |
} | |
@function method-4-sqrt($x) { | |
@if $x < 0 { | |
@warn "Argument for `sqrt()` must be a positive number."; | |
@return null; | |
} | |
$ret: 1; | |
@for $i from 1 through 24 { | |
$ret: $ret - (method-4-pow($ret, 2) - $x) / (2 * $ret); | |
} | |
@return $ret; | |
} | |
/* mathsass */ | |
.method-4-test { | |
test-1: method-4-sqrt( 1); | |
test-2: method-4-sqrt( 2); | |
test-3: method-4-sqrt( 3); | |
test-10: method-4-sqrt( 10); | |
test-20: method-4-sqrt( 20); | |
test-30: method-4-sqrt( 30); | |
test-60: method-4-sqrt( 60); | |
test-100: method-4-sqrt(100); | |
test-0-2: method-4-sqrt(0.2); | |
test--2: method-4-sqrt( -2); | |
test--30: method-4-sqrt(-30); | |
} | |
// ------------------------ | |
// ishango | |
// https://github.com/nathancrank/ishango/blob/master/_ishango.scss#L460 | |
@function method-5-exponent($value,$expN,$expD: 1) { | |
@if type-of($value) != number { | |
@debug "exponent only accepts number values for the base. Returning null."; | |
@return null; | |
} | |
@if ( method-5-is-int($expN) and unitless($expN) ) == false { | |
@debug "exponent only accepts unitless integer values for numerators. Returning null."; | |
@return null; | |
} | |
@if ( method-5-is-int($expD) and unitless($expD) ) == false { | |
@debug "exponent only accepts unitless integer values for denominators. Returning null."; | |
@return null; | |
} | |
$units: 1; | |
@if unitless($value) == false { | |
@if $value == 0 { | |
$units: $value / ( method-5-remove-unit($value) + 1); | |
} @else { | |
$units: $value / method-5-remove-unit($value); | |
} | |
$value: method-5-remove-unit($value); | |
} | |
@if $expD == 0 { | |
@debug "exponent(#{$value},#{$expN}, #{$expD}) results in a complex number. You can't divide by zero. Returning Null."; | |
@return null; | |
} | |
@if $expN == 0 { @return 1 * $units; } | |
@if $value == 0 { @return 0; } | |
@if $value < 0 and method-5-is-int($expN / $expD) == false { | |
@debug "exponent(#{$value},#{$expN}, #{$expD}) results in a complex number. Returning Null."; | |
@return null; | |
} | |
@if $expN == $expD { @return $value * $units; } | |
@if opp($expN) == $expD { @return ( 1 / $value ) * $units; } | |
$result: $value; | |
$neg: ($expN < 0); | |
$expN: abs($expN); | |
@for $i from 1 to $expN { | |
$result: $result * $value; | |
} | |
@if $expD != 1 { | |
@if $expD < 0 { | |
$expD: $expD * -1; | |
@if $neg { $neg: false; } | |
@else { $neg: true; } | |
} | |
$result: method-5-nth-root($result,$expD, true); | |
} | |
@if $neg { @return ( 1 / $result ) * $units; } | |
@else { @return $result * $units; } | |
} | |
@function method-5-remove-unit($value) { | |
@if type-of($value) != number { | |
@debug "You can only remove units from variables that are numbers. Returning value unchanged."; | |
@return $value; | |
} | |
@if unitless($value) == true { @return $value }; | |
$units: unit($value); | |
@if $units == "%" { @return $value / 1%; } | |
@else if $units == "em" { @return $value / 1em; } | |
@else if $units == "rem" { @return $value / 1rem; } | |
@else if $units == "px" { @return $value / 1px; } | |
@else if $units == "in" { @return $value / 1in; } | |
@else if $units == "cm" { @return $value / 1cm; } | |
@else if $units == "mm" { @return $value / 1mm; } | |
@else if $units == "ex" { @return $value / 1ex; } | |
@else if $units == "pt" { @return $value / 1pt; } | |
@else if $units == "pc" { @return $value / 1pc; } | |
} | |
@function method-5-aprox-equal($value1, $value2, $prec: .00002) { | |
@if type-of($value1) != number { | |
@debug "aprox-equal only accepts number values for the comparison. Returning false."; | |
@return false; | |
} | |
@if type-of($value2) != number { | |
@debug "aprox-equal only accepts number values for the comparison. Returning false."; | |
@return false; | |
} | |
@if ( type-of($prec) == number and unitless($prec) ) == false { | |
@debug " aprox-equal $prec must be set with a unitless number values. Returning false."; | |
@return false; | |
} | |
@if abs($value1 - $value2) <= $prec { @return true; } | |
@else { @return false; } | |
} | |
@function method-5-not-aprox-equal($value1, $value2, $prec: .00002) { | |
@if method-5-aprox-equal($value1, $value2, $prec) { @return false; } | |
@else { @return true; } | |
} | |
@function method-5-nth-root($value, $n, $recursing: false) { | |
@if type-of($value) != number { | |
@debug "nth-root only accepts number values for the base. Returning null."; | |
@return null; | |
} | |
@if ( is-int($n) and unitless($n) ) == false { | |
@debug "nth-root only accepts unitless integer values for n. Returning null."; | |
@return null; | |
} | |
@if type-of($recursing) != bool { | |
@debug "Don't pass a third argument to nth-root. Returning null."; | |
@return null; | |
} | |
$units: 1; | |
@if unitless($value) == false { | |
@if $value == 0 { | |
$units: $value / ( method-5-remove-unit($value) + 1); | |
} @else { | |
$units: $value / method-5-remove-unit($value); | |
} | |
$value: method-5-remove-unit($value); | |
} | |
@if $value == 0 { @return 0; } | |
@if $value < 0 and $recursing == false { | |
@debug "method-5-nth-root(#{$value},#{$n}) results in a complex number. Returning null."; | |
@return null; | |
} | |
@if $n < -1 and $recursing == false { @return method-5-exponent($value, 1, $n) * $units; } | |
@if $n == -1 { @return ( 1 / $value ) * $units; } | |
@if $n == 0 { @return 1 * $units; } | |
$value: abs($value); | |
$result: $value; | |
$test: method-5-exponent($result, $n); | |
@while method-5-not-aprox-equal($value,$test) { | |
$result: (1 / $n) * ( ( ($n - 1) * $result) + ($value / method-5-exponent($result, $n - 1)) ); | |
$test: method-5-exponent($result, $n); | |
} | |
@if ($n < 0) { $result: 1 / $result } | |
@return $result * $units; | |
} | |
@function method-5-sqrt($value) { | |
@return method-5-nth-root($value, 2); | |
} | |
/* ishango */ | |
.method-5-test { | |
test-1: method-5-sqrt( 1); | |
test-2: method-5-sqrt( 2); | |
test-3: method-5-sqrt( 3); | |
test-10: method-5-sqrt( 10); | |
test-20: method-5-sqrt( 20); | |
test-30: method-5-sqrt( 30); | |
test-60: method-5-sqrt( 60); | |
test-100: method-5-sqrt(100); | |
test-0-2: method-5-sqrt(0.2); | |
test--2: method-5-sqrt( -2); | |
test--30: method-5-sqrt(-30); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment