<!--
===================================================================
Stylesheet: trignm.xsl.xsl
Version: 1.0 (2002-03-13)
Author: Dimitre Novatchev
Notice: Copyright (c)2002 D.Novatchev ALL RIGHTS RESERVED.
No limitation on use - except this code may not be
published, in whole or in part, without prior written
consent of the copyright owner.
Acknowledgements:
The documentation to this file, the general
documenting style and some efficiency optimisation
are work of Martin Rowlinson
===================================================================
-->
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:trigSin="f:trigSin" xmlns:trigCos="f:trigCos"
xmlns:trigTan="f:trigTan" xmlns:trigCot="f:trigCot"
xmlns:trigSec="f:trigSec" xmlns:trigCsc="f:trigCsc"
xmlns:x="f:trig_lib.xsl"
exclude-result-prefixes="xsl trigSin trigCos trigTan trigCot
trigSec trigCsc">
<!--
================================================================
Module Interface:
================================================================
-->
<!--
Template: sin
Purpose: Return the sine of X
Parameters:-
$pX - the angle (specified in radians or degrees-see $pUnit)
$pUnit - [optional] the unit of the given angle £pX
specify 'deg' for degrees or
'rad' for radians (default)
$pEps - [optional] accuracy required
increase the number of decimal places for greater
accuracy but at the expense of performance.
=================================================================
-->
<xsl:template name="sin">
<xsl:param name="pX"/>
<xsl:param name="pUnit" select="'rad'"/>
<xsl:param name="pEps" select=".00000001"/>
<xsl:call-template name="_trigWrapper">
<xsl:with-param name="pFun"
select="$x:vstTop/trigSin:*[1]"/>
<xsl:with-param name="pX" select="$pX"/>
<xsl:with-param name="pUnit" select="$pUnit"/>
<xsl:with-param name="pEps" select="$pEps"/>
</xsl:call-template>
</xsl:template>
<!--
=================================================================
Template: cos
Purpose: Return the cosine of X
Parameters:-
$pX - the angle (specified in radians or degrees-see $pUnit)
$pUnit - [optional] the unit of the given angle £pX
specify 'deg' for degrees or
'rad' for radians (default)
$pEps - [optional] accuracy required
increase the number of decimal places for greater
accuracy but at the expense of performance.
=================================================================
-->
<xsl:template name="cos">
<xsl:param name="pX"/>
<xsl:param name="pUnit" select="'rad'"/>
<xsl:param name="pEps" select=".00000001"/>
<xsl:call-template name="_trigWrapper">
<xsl:with-param name="pFun" select="$x:vstTop/trigCos:*[1]"/>
<xsl:with-param name="pX" select="$pX"/>
<xsl:with-param name="pUnit" select="$pUnit"/>
<xsl:with-param name="pEps" select="$pEps"/>
</xsl:call-template>
</xsl:template>
<!--
=================================================================
Template: tan
Purpose: Return the tangent of X
Parameters:-
$pX - the angle (specified in radians or degrees-see $pUnit)
$pUnit - [optional] the unit of the given angle £pX
specify 'deg' for degrees or
'rad' for radians (default)
$pEps - [optional] accuracy required
increase the number of decimal places for greater
accuracy but at the expense of performance.
=================================================================
-->
<xsl:template name="tan">
<xsl:param name="pX"/>
<xsl:param name="pUnit" select="'rad'"/>
<xsl:param name="pEps" select=".00000001"/>
<xsl:call-template name="_trigWrapper">
<xsl:with-param name="pFun" select="$x:vstTop/trigTan:*[1]"/>
<xsl:with-param name="pX" select="$pX"/>
<xsl:with-param name="pUnit" select="$pUnit"/>
<xsl:with-param name="pEps" select="$pEps"/>
</xsl:call-template>
</xsl:template>
<!--
=================================================================
Template: cot
Purpose: Return the cotangent of X
Parameters:-
$pX - the angle (specified in radians or degrees-see $pUnit)
$pUnit - [optional] the unit of the given angle £pX
specify 'deg' for degrees or
'rad' for radians (default)
$pEps - [optional] accuracy required
increase the number of decimal places for greater
accuracy but at the expense of performance.
=================================================================
-->
<xsl:template name="cot">
<xsl:param name="pX"/>
<xsl:param name="pUnit" select="'rad'"/>
<xsl:param name="pEps" select=".00000001"/>
<xsl:call-template name="_trigWrapper">
<xsl:with-param name="pFun" select="$x:vstTop/trigCot:*[1]"/>
<xsl:with-param name="pX" select="$pX"/>
<xsl:with-param name="pUnit" select="$pUnit"/>
<xsl:with-param name="pEps" select="$pEps"/>
</xsl:call-template>
</xsl:template>
<!--
=================================================================
Template: sec
Purpose: Return the secant of X
Parameters:-
$pX - the angle (specified in radians or degrees-see $pUnit)
$pUnit - [optional] the unit of the given angle £pX
specify 'deg' for degrees or
'rad' for radians (default)
$pEps - [optional] accuracy required
increase the number of decimal places for greater
accuracy but at the expense of performance.
=================================================================
-->
<xsl:template name="sec">
<xsl:param name="pX"/>
<xsl:param name="pUnit" select="'rad'"/>
<xsl:param name="pEps" select=".00000001"/>
<xsl:call-template name="_trigWrapper">
<xsl:with-param name="pFun" select="$x:vstTop/trigSec:*[1]"/>
<xsl:with-param name="pX" select="$pX"/>
<xsl:with-param name="pUnit" select="$pUnit"/>
<xsl:with-param name="pEps" select="$pEps"/>
</xsl:call-template>
</xsl:template>
<!--
=================================================================
Template: csc
Purpose: Return the cosecant of X
Parameters:-
$pX - the angle (specified in radians or degrees-see $pUnit)
$pUnit - [optional] the unit of the given angle £pX
specify 'deg' for degrees or
'rad' for radians (default)
$pEps - [optional] accuracy required
increase the number of decimal places for greater
accuracy but at the expense of performance.
=================================================================
-->
<xsl:template name="csc">
<xsl:param name="pX"/>
<xsl:param name="pUnit" select="'rad'"/>
<xsl:param name="pEps" select=".00000001"/>
<xsl:call-template name="_trigWrapper">
<xsl:with-param name="pFun" select="$x:vstTop/trigCsc:*[1]"/>
<xsl:with-param name="pX" select="$pX"/>
<xsl:with-param name="pUnit" select="$pUnit"/>
<xsl:with-param name="pEps" select="$pEps"/>
</xsl:call-template>
</xsl:template>
<!-- defined constant for pi -->
<xsl:variable name="pi" select="3.1415926535897"/>
<!-- ******************************************************** -->
<!-- ********************* INTERNAL USE ONLY **************** -->
<!-- ******************************************************** -->
<!-- defined constants -->
<xsl:variable name="halfPi" select="$pi div 2"/>
<xsl:variable name="twicePi" select="$pi*2"/>
<xsl:variable name="deg2rads" select="$pi div 180"/>
<!-- internal use only - applying functions via _trigWrapper -->
<trigSin:trigSin/>
<trigCos:trigCos/>
<trigTan:trigTan/>
<trigCot:trigCot/>
<trigSec:trigSec/>
<trigCsc:trigCsc/>
<xsl:variable name="x:vstTop" select="document('')/*"/>
<!-- internally used templates -->
<xsl:template name="_trigWrapper">
<xsl:param name="pFun" select="/.."/>
<xsl:param name="pX"/>
<xsl:param name="pUnit" select="'rad'"/>
<xsl:param name="pEps" select=".00000001"/>
<!-- convert degrees to radians (when 'deg' specified) -->
<xsl:variable name="vRads"
select="(($pUnit = 'rad') * $pX)
+ ((not($pUnit = 'rad')) * ($pX * $deg2rads))"/>
<!-- apply the appropriate function -->
<xsl:apply-templates select="$pFun">
<xsl:with-param name="pX" select="$vRads"/>
<xsl:with-param name="pEps" select="$pEps"/>
</xsl:apply-templates>
</xsl:template>
<xsl:template name="_sin" match="trigSin:*">
<xsl:param name="pX"/>
<xsl:param name="pEps" select=".00000001"/>
<xsl:variable name="pY">
<xsl:choose>
<xsl:when test="not(0 <= $pX and $twicePi > $pX)">
<xsl:call-template name="_cutIntervals">
<xsl:with-param name="pLength" select="$twicePi"/>
<xsl:with-param name="pX" select="$pX"/>
</xsl:call-template>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="$pX"/>
</xsl:otherwise>
</xsl:choose>
</xsl:variable>
<xsl:call-template name="_sineIter">
<xsl:with-param name="pX2" select="$pY*$pY"/>
<xsl:with-param name="pRslt" select="$pY"/>
<xsl:with-param name="pElem" select="$pY"/>
<xsl:with-param name="pN" select="1"/>
<xsl:with-param name="pEps" select="$pEps"/>
</xsl:call-template>
</xsl:template>
<xsl:template name="_sineIter">
<xsl:param name="pX2"/>
<xsl:param name="pRslt"/>
<xsl:param name="pElem"/>
<xsl:param name="pN"/>
<xsl:param name="pEps"/>
<xsl:variable name="vnextN" select="$pN+2"/>
<xsl:variable name="vnewElem"
select="-$pElem*$pX2 div ($vnextN*($vnextN - 1))"/>
<xsl:variable name="vnewResult"
select="$pRslt + $vnewElem"/>
<xsl:variable name="vdiffResult"
select="$vnewResult - $pRslt"/>
<xsl:choose>
<xsl:when test="$vdiffResult > $pEps
or $vdiffResult < -$pEps">
<xsl:call-template name="_sineIter">
<xsl:with-param name="pX2" select="$pX2"/>
<xsl:with-param name="pRslt" select="$vnewResult"/>
<xsl:with-param name="pElem" select="$vnewElem"/>
<xsl:with-param name="pN" select="$vnextN"/>
<xsl:with-param name="pEps" select="$pEps"/>
</xsl:call-template>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="$vnewResult"/>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<xsl:template name="_cos" match="trigCos:*">
<xsl:param name="pX"/>
<xsl:param name="pEps" select=".00000001"/>
<xsl:call-template name="_sin">
<xsl:with-param name="pX" select="$halfPi - $pX"/>
<xsl:with-param name="pEps" select="$pEps"/>
</xsl:call-template>
</xsl:template>
<xsl:template name="_tan" match="trigTan:*">
<xsl:param name="pX"/>
<xsl:param name="pEps" select=".00000001"/>
<xsl:param name="_pAbort" select="1"/>
<xsl:variable name="vnumHalfPis"
select="floor($pX div $halfPi)"/>
<xsl:variable name="vdiffHalfPi"
select="$pX - $halfPi*$vnumHalfPis"/>
<xsl:choose>
<xsl:when test="-$pEps < $vdiffHalfPi
and $vdiffHalfPi < $pEps
and $vnumHalfPis mod 2 = 1">
<xsl:choose>
<xsl:when test="$_pAbort">
<xsl:message terminate="yes">
<xsl:value-of
select="concat('[Error]tan() not defined for x=',
$pX)"/>
</xsl:message>
</xsl:when>
<xsl:otherwise>Infinity</xsl:otherwise>
</xsl:choose>
</xsl:when>
<xsl:otherwise>
<xsl:variable name="vSin">
<xsl:call-template name="_sin">
<xsl:with-param name="pX" select="$pX"/>
<xsl:with-param name="pEps" select="$pEps"/>
</xsl:call-template>
</xsl:variable>
<xsl:variable name="vCos">
<xsl:call-template name="_cos">
<xsl:with-param name="pX" select="$pX"/>
<xsl:with-param name="pEps" select="$pEps"/>
</xsl:call-template>
</xsl:variable>
<xsl:value-of select="$vSin div $vCos"/>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<xsl:template name="_cot" match="trigCot:*">
<xsl:param name="pX"/>
<xsl:param name="pEps" select=".00000001"/>
<xsl:variable name="vTan">
<xsl:call-template name="_tan">
<xsl:with-param name="pX" select="$pX"/>
<xsl:with-param name="_pAbort" select="0"/>
</xsl:call-template>
</xsl:variable>
<xsl:choose>
<xsl:when test="$vTan = 'Infinity'">0</xsl:when>
<xsl:when test="-$pEps < $vTan and $vTan < $pEps">
<xsl:message terminate="yes">
<xsl:value-of
select="concat('[Error]cot() not defined for x=',
$pX)"/>
</xsl:message>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="1 div $vTan"/>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<xsl:template name="_sec" match="trigSec:*">
<xsl:param name="pX"/>
<xsl:param name="pEps" select=".00000001"/>
<xsl:variable name="vCos">
<xsl:call-template name="_cos">
<xsl:with-param name="pX" select="$pX"/>
<xsl:with-param name="pEps" select="$pEps"/>
</xsl:call-template>
</xsl:variable>
<xsl:choose>
<xsl:when test="-$pEps < $vCos and $vCos < $pEps">
<xsl:message terminate="yes">
<xsl:value-of
select="concat('[Error]sec() not defined for x=',
$pX)"/>
</xsl:message>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="1 div $vCos"/>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<xsl:template name="_csc" match="trigCsc:*">
<xsl:param name="pX"/>
<xsl:param name="pEps" select=".00000001"/>
<xsl:call-template name="_sec">
<xsl:with-param name="pX" select="$halfPi - $pX"/>
<xsl:with-param name="pEps" select="$pEps"/>
</xsl:call-template>
</xsl:template>
<xsl:template name="_cutIntervals">
<xsl:param name="pLength"/>
<xsl:param name="pX"/>
<xsl:variable name="vsignX">
<xsl:choose>
<xsl:when test="$pX >= 0">1</xsl:when>
<xsl:otherwise>-1</xsl:otherwise>
</xsl:choose>
</xsl:variable>
<xsl:variable name="vdiff"
select="$pLength*floor($pX div $pLength) -$pX"/>
<xsl:choose>
<xsl:when test="$vdiff*$pX > 0">
<xsl:value-of select="$vsignX*$vdiff"/>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="-$vsignX*$vdiff"/>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
</xsl:stylesheet>