Dave Jarvis' Repositories

git clone https://repo.autonoma.ca/repo/delibero.git

Improved colour distribution for pie chart colours.

Author Dave Jarvis <email>
Date 2014-08-24 23:41:58 GMT-0700
Commit bdbae1dbb9923877f4dc3e8444c9495c4bc99cdf
Parent 5150f7b
Delta 459 lines added, 147 lines removed, 312-line increase
xml/chart.xsl
<xsl:include href="math.xsl"/>
-
-<!-- Pie wedge colours based on this hue. -->
-<xsl:variable name="base_colour" select="'46A5E5'"/>
-
-<!-- Pie wedge stroke colour. -->
-<xsl:variable name="stroke_colour" select="'white'"/>
+<xsl:include href="colour.xsl"/>
<!-- Pie chart width and height. -->
transform="translate({$radius},{$radius})"
d="M 0 0 L {$x1r} {$y1r} A {$r} {$r} 0 {$sweep} 0 {$x2r} {$y2r} Z"/>
-</xsl:template>
-
-<!--
- | Creates a colour for a particular pie wedge.
- |
- | http://en.wikipedia.org/wiki/HSL_and_HSV
- +-->
-<xsl:template name="fill">
- <!-- Current wedge number for generating a colour. -->
- <xsl:param name="wedge"/>
- <!-- Total number of wedges in the pie. -->
- <xsl:param name="wedges"/>
- <!-- RGB colour in hexadecimal. -->
- <xsl:param name="colour"/>
-
- <!-- Derive the colour decimal values from $colour's HEX code. -->
- <xsl:variable name="r">
- <xsl:call-template name="hex2dec">
- <xsl:with-param name="hex"
- select="substring( $colour, 1, 2 )"/>
- </xsl:call-template>
- </xsl:variable>
- <xsl:variable name="g">
- <xsl:call-template name="hex2dec">
- <xsl:with-param name="hex"
- select="substring( $colour, 3, 2 )"/>
- </xsl:call-template>
- </xsl:variable>
- <xsl:variable name="b">
- <xsl:call-template name="hex2dec">
- <xsl:with-param name="hex"
- select="substring( $colour, 5, 2 )"/>
- </xsl:call-template>
- </xsl:variable>
-
- <xsl:variable name="alpha"
- select="(2 * $r - $g - $b) * 0.5"/>
- <xsl:variable name="beta"
- select="0.86602540378 * ($g - $b)"/>
-
- <xsl:variable name="base_hue">
- <xsl:call-template name="atan2">
- <xsl:with-param name="x" select="$alpha"/>
- <xsl:with-param name="y" select="$beta"/>
- </xsl:call-template>
- </xsl:variable>
-
- <xsl:variable name="chroma">
- <xsl:call-template name="sqrt">
- <xsl:with-param name="n"
- select="($alpha * $alpha) + ($beta * $beta)"/>
- </xsl:call-template>
- </xsl:variable>
-
- <xsl:variable name="value">
- <xsl:variable name="max_rg">
- <xsl:call-template name="max">
- <xsl:with-param name="a" select="$r"/>
- <xsl:with-param name="b" select="$g"/>
- </xsl:call-template>
- </xsl:variable>
- <xsl:variable name="max_gb">
- <xsl:call-template name="max">
- <xsl:with-param name="a" select="$g"/>
- <xsl:with-param name="b" select="$b"/>
- </xsl:call-template>
- </xsl:variable>
- <xsl:call-template name="max">
- <xsl:with-param name="a" select="$max_rg"/>
- <xsl:with-param name="b" select="$max_gb"/>
- </xsl:call-template>
- </xsl:variable>
-
- <!-- Calculate the wedge hue from the base colour. -->
- <xsl:variable name="h_rotate"
- select="($base_hue + ((240 div $wedges) * $wedge) mod 240)"/>
- <xsl:variable name="h_prime"
- select="$h_rotate div 60.0"/>
- <xsl:variable name="h_mod"
- select="$h_prime mod 2 - 1"/>
- <xsl:variable name="h_abs"
- select="($h_mod &gt;= 0) * $h_mod - not($h_mod &gt;= 0) * $h_mod"/>
-
- <xsl:variable name="c" select="$chroma"/>
- <xsl:variable name="x" select="$c * (1 - $h_abs)"/>
- <xsl:variable name="m" select="$value - $c"/>
-
- <xsl:variable name="cm" select="round( $c + $m )"/>
- <xsl:variable name="xm" select="round( $x + $m )"/>
- <xsl:variable name="zm" select="round( 0 + $m )"/>
-
- <xsl:text>rgb(</xsl:text>
- <xsl:choose>
- <xsl:when test="0 &lt;= $h_prime and $h_prime &lt; 1">
- <xsl:value-of select="concat( $cm, ',', $xm, ',', $zm )"/>
- </xsl:when>
- <xsl:when test="1 &lt;= $h_prime and $h_prime &lt; 2">
- <xsl:value-of select="concat( $xm, ',', $cm, ',', $zm )"/>
- </xsl:when>
- <xsl:when test="2 &lt;= $h_prime and $h_prime &lt; 3">
- <xsl:value-of select="concat( $zm, ',', $cm, ',', $xm )"/>
- </xsl:when>
- <xsl:when test="3 &lt;= $h_prime and $h_prime &lt; 4">
- <xsl:value-of select="concat( $zm, ',', $xm, ',', $cm )"/>
- </xsl:when>
- <xsl:when test="4 &lt;= $h_prime and $h_prime &lt; 5">
- <xsl:value-of select="concat( $xm, ',', $zm, ',', $cm )"/>
- </xsl:when>
- <xsl:when test="5 &lt;= $h_prime and $h_prime &lt; 6">
- <xsl:value-of select="concat( $cm, ',', $zm, ',', $xm )"/>
- </xsl:when>
- <xsl:otherwise>
- <xsl:value-of select="concat( $r, ',', $g, ',', $b )"/>
- </xsl:otherwise>
- </xsl:choose>
- <xsl:text>)</xsl:text>
</xsl:template>
xml/colour.xsl
+<?xml version="1.0"?>
+<!--
+ | The MIT License
+ |
+ | Copyright 2014 White Magic Software, Inc.
+ |
+ | Permission is hereby granted, free of charge, to any person
+ | obtaining a copy of this software and associated documentation
+ | files (the "Software"), to deal in the Software without
+ | restriction, including without limitation the rights to use,
+ | copy, modify, merge, publish, distribute, sublicense, and/or
+ | sell copies of the Software, and to permit persons to whom the
+ | Software is furnished to do so, subject to the following
+ | conditions:
+ |
+ | The above copyright notice and this permission notice shall be
+ | included in all copies or substantial portions of the Software.
+ |
+ | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ | OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ | HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ | WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ | FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ | OTHER DEALINGS IN THE SOFTWARE.
+ +-->
+<xsl:stylesheet version="1.0"
+ xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
+
+<!-- Reference white (X, Y, and Z components) -->
+<xsl:variable name="X_r" select="0.950456"/>
+<xsl:variable name="Y_r" select="1.000000"/>
+<xsl:variable name="Z_r" select="1.088754"/>
+<xsl:variable name="LAB_EPSILON" select="216.0 div 24389.0"/>
+<xsl:variable name="LAB_K" select="24389.0 div 27.0"/>
+
+<!-- Pie wedge colours based on this hue. -->
+<xsl:variable name="base_colour" select="'46A5E5'"/>
+
+<!-- Pie wedge stroke colour. -->
+<xsl:variable name="stroke_colour" select="'white'"/>
+
+<!--
+ | Creates a colour for a particular pie wedge.
+ |
+ | http://en.wikipedia.org/wiki/HSL_and_HSV
+ +-->
+<xsl:template name="fill">
+ <!-- Current wedge number for generating a colour. -->
+ <xsl:param name="wedge"/>
+ <!-- Total number of wedges in the pie. -->
+ <xsl:param name="wedges"/>
+ <!-- RGB colour in hexadecimal. -->
+ <xsl:param name="colour"/>
+
+ <!-- Derive the colour decimal values from $colour's HEX code. -->
+ <xsl:variable name="r">
+ <xsl:call-template name="hex2dec">
+ <xsl:with-param name="hex"
+ select="substring( $colour, 1, 2 )"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:variable name="g">
+ <xsl:call-template name="hex2dec">
+ <xsl:with-param name="hex"
+ select="substring( $colour, 3, 2 )"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:variable name="b">
+ <xsl:call-template name="hex2dec">
+ <xsl:with-param name="hex"
+ select="substring( $colour, 5, 2 )"/>
+ </xsl:call-template>
+ </xsl:variable>
+
+ <!--
+ | Convert RGB to XYZ, using nominal range for RGB.
+ | http://www.brucelindbloom.com/index.html?Eqn_RGB_to_XYZ.html
+ +-->
+ <xsl:variable name="r_n" select="$r div 255" />
+ <xsl:variable name="g_n" select="$g div 255" />
+ <xsl:variable name="b_n" select="$b div 255" />
+
+ <!--
+ | Assume colours are in sRGB.
+ | http://www.brucelindbloom.com/index.html?Eqn_RGB_XYZ_Matrix.html
+ -->
+ <xsl:variable name="x"
+ select=".4124564 * $r_n + .3575761 * $g_n + .1804375 * $b_n"/>
+ <xsl:variable name="y"
+ select=".2126729 * $r_n + .7151522 * $g_n + .0721750 * $b_n"/>
+ <xsl:variable name="z"
+ select=".0193339 * $r_n + .1191920 * $g_n + .9503041 * $b_n"/>
+
+ <!--
+ | Convert XYZ to L*a*b.
+ | http://www.brucelindbloom.com/index.html?Eqn_XYZ_to_Lab.html
+ +-->
+ <xsl:variable name="if_x">
+ <xsl:call-template name="lab_f">
+ <xsl:with-param name="xyz_n" select="$x div $X_r"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:variable name="if_y">
+ <xsl:call-template name="lab_f">
+ <xsl:with-param name="xyz_n" select="$y div $Y_r"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:variable name="if_z">
+ <xsl:call-template name="lab_f">
+ <xsl:with-param name="xyz_n" select="$z div $Z_r"/>
+ </xsl:call-template>
+ </xsl:variable>
+
+ <xsl:variable name="lab_l" select="(116.0 * $if_y) - 16.0"/>
+ <xsl:variable name="lab_a" select="500.0 * ($if_x - $if_y)"/>
+ <xsl:variable name="lab_b" select="200.0 * ($if_y - $if_z)"/>
+
+ <!--
+ | Convert L*a*b to LCH.
+ +-->
+ <xsl:variable name="lch_l" select="$lab_l"/>
+
+ <xsl:variable name="lch_c">
+ <xsl:call-template name="sqrt">
+ <xsl:with-param name="n" select="($lab_a * $lab_a) + ($lab_b * $lab_b)"/>
+ </xsl:call-template>
+ </xsl:variable>
+
+ <xsl:variable name="lch_h">
+ <xsl:call-template name="atan2">
+ <xsl:with-param name="x" select="$lab_b"/>
+ <xsl:with-param name="y" select="$lab_a"/>
+ </xsl:call-template>
+ </xsl:variable>
+
+ <!-- lch_l, lch_c, and lch_h are now set; rotate the hue. -->
+ <xsl:variable name="lch_wedge_h" select="(360.0 div $wedges) * $wedge"/>
+
+ <!--
+ | Convert wedge's hue-adjusted LCH to L*a*b.
+ | http://www.brucelindbloom.com/index.html?Eqn_LCH_to_Lab.html
+ +-->
+ <xsl:variable name="lab_sin_h">
+ <xsl:call-template name="sine">
+ <xsl:with-param name="degrees" select="$lch_wedge_h"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:variable name="lab_cos_h">
+ <xsl:call-template name="cosine">
+ <xsl:with-param name="degrees" select="$lch_wedge_h"/>
+ </xsl:call-template>
+ </xsl:variable>
+
+ <xsl:variable name="final_lab_l" select="$lch_l"/>
+ <xsl:variable name="final_lab_a" select="$lch_c * $lab_cos_h"/>
+ <xsl:variable name="final_lab_b" select="$lch_c * $lab_sin_h"/>
+
+ <!--
+ | Convert L*a*b to XYZ.
+ | http://www.brucelindbloom.com/index.html?Eqn_Lab_to_XYZ.html
+ +-->
+ <xsl:variable name="of_y" select="($final_lab_l + 16.0) div 116.0"/>
+ <xsl:variable name="of_x" select="($final_lab_a div 500.0) + $of_y"/>
+ <xsl:variable name="of_z" select="$of_y - ($final_lab_b div 200.0)"/>
+
+ <xsl:variable name="of_x_pow">
+ <xsl:call-template name="power">
+ <xsl:with-param name="base" select="$of_x"/>
+ <xsl:with-param name="exponent" select="3"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:variable name="of_z_pow">
+ <xsl:call-template name="power">
+ <xsl:with-param name="base" select="$of_z"/>
+ <xsl:with-param name="exponent" select="3"/>
+ </xsl:call-template>
+ </xsl:variable>
+
+ <xsl:variable name="ox_r">
+ <xsl:choose>
+ <xsl:when test="$of_x_pow &gt; $LAB_EPSILON">
+ <xsl:value-of select="$of_x_pow"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="((116.0 * $of_x) - 16.0) div $LAB_K"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:variable name="oy_r">
+ <xsl:choose>
+ <xsl:when test="$final_lab_l &gt; ($LAB_K * $LAB_EPSILON)">
+ <xsl:call-template name="power">
+ <xsl:with-param name="base"
+ select="($final_lab_l + 16.0) div 116.0"/>
+ <xsl:with-param name="exponent"
+ select="3"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="$final_lab_l div $LAB_K"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:variable name="oz_r">
+ <xsl:choose>
+ <xsl:when test="$of_z_pow &gt; $LAB_EPSILON">
+ <xsl:value-of select="$of_z_pow"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="((116.0 * $of_z) - 16.0) div $LAB_K"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+
+ <xsl:variable name="X" select="$ox_r * $X_r"/>
+ <xsl:variable name="Y" select="$oy_r * $Y_r"/>
+ <xsl:variable name="Z" select="$oz_r * $Z_r"/>
+
+ <!--
+ | Convert XYZ to sRGB.
+ |
+ | http://www.brucelindbloom.com/index.html?Eqn_RGB_XYZ_Matrix.html
+ +-->
+ <xsl:variable name="R"
+ select="3.2404542 * $X + -1.5371385 * $Y + -0.4985314 * $Z"/>
+ <xsl:variable name="G"
+ select="-0.9692660 * $X + 1.8760108 * $Y + 0.0415560 * $Z"/>
+ <xsl:variable name="B"
+ select="0.0556434 * $X + -0.2040259 * $Y + 1.0572252 * $Z"/>
+
+ <!-- Round the result. -->
+ <xsl:variable name="R_r" select="round( $R * 255 )"/>
+ <xsl:variable name="G_r" select="round( $G * 255 )"/>
+ <xsl:variable name="B_r" select="round( $B * 255 )"/>
+
+ <xsl:text>rgb(</xsl:text>
+ <xsl:value-of select="concat( $R_r, ',', $G_r, ',', $B_r )"/>
+ <xsl:text>)</xsl:text>
+</xsl:template>
+
+<xsl:template name="lab_f">
+ <xsl:param name="xyz_n"/>
+
+ <xsl:choose>
+ <xsl:when test="$xyz_n &gt; $LAB_EPSILON">
+ <xsl:call-template name="nthroot">
+ <xsl:with-param name="index" select="3"/>
+ <xsl:with-param name="radicand" select="$xyz_n"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="($LAB_K * $xyz_n + 16.0) div 116.0" />
+ </xsl:otherwise>
+ </xsl:choose>
+</xsl:template>
+
+<!-- Returns $x, ensuring $x is between -100 and 100. -->
+<xsl:template name="constrain">
+ <xsl:param name="x"/>
+ <xsl:param name="max" select="100"/>
+ <xsl:choose>
+ <xsl:when test="$x &gt; $max">
+ <xsl:value-of select="$max"/>
+ </xsl:when>
+ <xsl:when test="$x &lt; -$max">
+ <xsl:value-of select="-$max"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="$x"/>
+ </xsl:otherwise>
+ </xsl:choose>
+</xsl:template>
+
+<!-- Converts a two-digit hexadecimal number to decimal. -->
+<xsl:template name="hex2dec">
+ <xsl:param name="hex"/>
+
+ <xsl:variable name="digits" select="'0123456789ABCDEF'"/>
+ <xsl:variable name="X" select="substring( $hex, 1, 1 )"/>
+ <xsl:variable name="Y" select="substring( $hex, 2, 1 )"/>
+ <xsl:variable name="Xval"
+ select="string-length(substring-before($digits,$X))"/>
+ <xsl:variable name="Yval"
+ select="string-length(substring-before($digits,$Y))"/>
+ <xsl:value-of select="16 * $Xval + $Yval"/>
+</xsl:template>
+
+</xsl:stylesheet>
xml/math.xsl
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
-<xsl:variable name="PI">3.14159265358979323846</xsl:variable>
+<xsl:variable name="PI">3.14159265358979323846264338327950</xsl:variable>
+<xsl:variable name="PHI">1.61803398874989484820458683436564</xsl:variable>
+<xsl:variable name="PIDIV2" select="$PI div 2.0"/>
+<xsl:variable name="ROOT_PRECISION" select="0.00001"/>
-<!-- Find the square root of a number (n). -->
+<!-- Calculates square root of n. -->
<xsl:template name="sqrt">
<!-- Number to root. -->
<xsl:param name="n" select="0"/>
<!-- Used internally. -->
<xsl:param name="try" select="1"/>
<!-- Maximum number of iterations (decreases recursively). -->
- <xsl:param name="iter" select="20"/>
+ <xsl:param name="iter" select="17"/>
<!-- Nate Austin's implementation using Newton's method -->
<!--
- | Calculates sin(x) using:
+ | Calculates sin(x) as:
| x(1 - (x^2/2*3)(1 - (x^2/4*5)(1 - (x^2/6*7))))
+ | https://www.wolframalpha.com/input/?i=expand+sin(x)
+-->
<xsl:template name="sine">
<!-- Degrees (should be between 0 and 360). -->
<xsl:param name="degrees"/>
- <!-- Used internally to convert degrees to radians. -->
+ <!-- Convert degrees to radians when degrees are used. -->
<xsl:param name="rad" select="$degrees * $PI div 180"/>
<!-- Maximum number of iterations (decreases recursively). -->
</xsl:template>
-<!-- Calculates the normalized arc tangent form. -->
+<!--
+ | Calculates cos(x) as:
+ | sine($PIDIV2 - $rad)
+ +-->
+<xsl:template name="cosine">
+ <!-- Degrees (should be between 0 and 360). -->
+ <xsl:param name="degrees"/>
+ <!-- Convert degrees to radians when degrees are used. -->
+ <xsl:param name="rad" select="$degrees * $PI div 180"/>
+ <xsl:call-template name="sine">
+ <xsl:with-param name="rad" select="$PIDIV2 - $rad" />
+ </xsl:call-template>
+</xsl:template>
+
+<!-- Calculates: normalized arc tangent form -->
<xsl:template name="atan2">
<xsl:param name="y"/>
<xsl:param name="x"/>
<!--
| http://lists.apple.com/archives/PerfOptimization-dev/2005/Jan/msg00051.html
! http://permalink.gmane.org/gmane.text.xml.xslt.extensions/840
+-->
- <xsl:variable name="PIBY2" select="$PI div 2.0"/>
<xsl:choose>
<xsl:when test="$x = 0.0">
<xsl:choose>
<xsl:when test="($y &gt; 0.0)">
- <xsl:value-of select="$PIBY2"/>
+ <xsl:value-of select="$PIDIV2"/>
</xsl:when>
<xsl:when test="($y &lt; 0.0)">
- <xsl:value-of select="-$PIBY2"/>
+ <xsl:value-of select="-$PIDIV2"/>
</xsl:when>
<xsl:otherwise>
<xsl:choose>
<xsl:when test="($absZ &lt; 1.0)">
- <xsl:variable name="f1Z" select="$z div (1.0 + 0.28*$z*$z)"/>
+ <xsl:variable name="f1Z"
+ select="$z div (1.0 + 0.28*$z*$z)"/>
<xsl:choose>
<xsl:when test="($x &lt; 0.0) and ($y &lt; 0.0)">
<xsl:otherwise>
<xsl:variable name="f2Z"
- select="$PIBY2 - ($z div ($z*$z + 0.28))"/>
+ select="$PIDIV2 - ($z div ($z*$z + 0.28))"/>
<xsl:choose>
<xsl:when test="($y &lt; 0.0)">
<xsl:param name="a"/>
<xsl:param name="b"/>
-
- <xsl:if test="$a &gt;= $b"><xsl:value-of select="$a"/></xsl:if>
- <xsl:if test="$a &lt; $b"><xsl:value-of select="$b"/></xsl:if>
+
+ <xsl:choose>
+ <xsl:when test="$a &gt; $b"><xsl:value-of select="$a"/></xsl:when>
+ <xsl:otherwise><xsl:value-of select="$b"/></xsl:otherwise>
+ </xsl:choose>
</xsl:template>
-<!-- Converts a two-digit hexadecimal number to decimal. -->
-<xsl:template name="hex2dec">
- <xsl:param name="hex"/>
+<!-- Calculates: radicand^(1/index) -->
+<!-- http://www.shodor.org/unchem/math/newton/ -->
+<xsl:template name="nthroot">
+ <xsl:param name="index"/>
+ <xsl:param name="radicand"/>
+ <!-- Initial guess -->
+ <xsl:param name="guess" select="1 + (($radicand - 1) div $index)"/>
- <xsl:variable name="digits" select="'0123456789ABCDEF'"/>
- <xsl:variable name="X" select="substring( $hex, 1, 1 )"/>
- <xsl:variable name="Y" select="substring( $hex, 2, 1 )"/>
- <xsl:variable name="Xval"
- select="string-length(substring-before($digits,$X))"/>
- <xsl:variable name="Yval"
- select="string-length(substring-before($digits,$Y))"/>
- <xsl:value-of select="16 * $Xval + $Yval"/>
+ <xsl:variable name="approx">
+ <xsl:call-template name="nthroot_approx">
+ <xsl:with-param name="guess" select="$guess"/>
+ <xsl:with-param name="index" select="$index"/>
+ <xsl:with-param name="radicand" select="$radicand"/>
+ </xsl:call-template>
+ </xsl:variable>
+
+ <xsl:variable name="derivative">
+ <xsl:call-template name="nthroot_derivative">
+ <xsl:with-param name="guess" select="$guess"/>
+ <xsl:with-param name="index" select="$index"/>
+ </xsl:call-template>
+ </xsl:variable>
+
+ <xsl:variable name="newGuess" select="$guess - $approx div $derivative"/>
+ <xsl:variable name="difference" select="$newGuess - $guess"/>
+ <xsl:variable name="precision" select="$guess * $ROOT_PRECISION"/>
+
+ <xsl:variable name="abs_difference">
+ <xsl:call-template name="abs">
+ <xsl:with-param name="x" select="$difference"/>
+ </xsl:call-template>
+ </xsl:variable>
+
+ <xsl:variable name="abs_precision">
+ <xsl:call-template name="abs">
+ <xsl:with-param name="x" select="$precision"/>
+ </xsl:call-template>
+ </xsl:variable>
+
+ <xsl:choose>
+ <xsl:when test="$abs_difference &lt; $abs_precision">
+ <xsl:value-of select="$newGuess"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:call-template name="nthroot">
+ <xsl:with-param name="index" select="$index"/>
+ <xsl:with-param name="radicand" select="$radicand"/>
+ <xsl:with-param name="guess" select="$newGuess"/>
+ </xsl:call-template>
+ </xsl:otherwise>
+ </xsl:choose>
+</xsl:template>
+
+<!-- Calculates: (guess ^ index) - radicand -->
+<xsl:template name="nthroot_approx">
+ <xsl:param name="guess"/>
+ <xsl:param name="index"/>
+ <xsl:param name="radicand"/>
+
+ <xsl:variable name="power">
+ <xsl:call-template name="power">
+ <xsl:with-param name="base" select="$guess"/>
+ <xsl:with-param name="exponent" select="$index"/>
+ </xsl:call-template>
+ </xsl:variable>
+
+ <xsl:value-of select="$power - $radicand"/>
+</xsl:template>
+
+<!-- Calculates: index * (guess ^ (index - 1)) -->
+<xsl:template name="nthroot_derivative">
+ <xsl:param name="guess"/>
+ <xsl:param name="index"/>
+
+ <xsl:variable name="power">
+ <xsl:call-template name="power">
+ <xsl:with-param name="base" select="$guess"/>
+ <xsl:with-param name="exponent" select="($index - 1)"/>
+ </xsl:call-template>
+ </xsl:variable>
+
+ <xsl:value-of select="$index * $power"/>
+</xsl:template>
+
+<!-- Calculates: base ^ exponent (whole number exponents) -->
+<xsl:template name="power">
+ <xsl:param name="base"/>
+ <xsl:param name="exponent"/>
+ <xsl:choose>
+ <xsl:when test="$exponent = 0">
+ <xsl:value-of select="1"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:variable name="t">
+ <xsl:call-template name="power">
+ <xsl:with-param name="base" select="$base"/>
+ <xsl:with-param name="exponent" select="$exponent - 1"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:value-of select="$base * $t"/>
+ </xsl:otherwise>
+ </xsl:choose>
+</xsl:template>
+
+<!-- Calculates: |x| -->
+<!-- http://en.wikipedia.org/wiki/Absolute_value -->
+<xsl:template name="abs">
+ <xsl:param name="x"/>
+ <xsl:value-of select="($x &gt;= 0) * $x - not($x &gt;= 0) * $x"/>
</xsl:template>
xml/resources.xml
<value>$ CAD</value>
</header>
+ <!--
+ <data>
+ <name>Pig</name>
+ <value>211124</value>
+ </data>
+ <data>
+ <name>Cow</name>
+ <value>121554</value>
+ </data>
+ <data>
+ <name>Cat</name>
+ <value>221554</value>
+ </data>
+ <data>
+ <name>Dog</name>
+ <value>92455</value>
+ </data>
+ <data>
+ <name>Horse</name>
+ <value>71554</value>
+ </data>
+ <data>
+ <name>Sheep</name>
+ <value>102455</value>
+ </data>
+ -->
<data>
<name>Salaries and Employee Benefits</name>