home *** CD-ROM | disk | FTP | other *** search
- <!--
- ===========================================================================
- Stylesheet: iter.xsl General Iteration of a Function
- Version: 1.0 (2002-03-16)
- 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.
- ===========================================================================-->
- <xsl:stylesheet version="1.0"
- xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
- xmlns:vendor="http://icl.com/saxon"
- exclude-result-prefixes="xsl vendor">
-
- <!--
- ===========================================================================
- this implements functional power composition,
- that is f(f(...f(x)))))...)
-
- f composed with itself n - 1 times
-
- The corresponding Haskell code is:
- > iter :: (Ord a, Num a) => a -> (b -> b) -> b -> b
- > iter n f
- > | n > 0 = f . iter (n-1) f
- > | otherwise = id
- ===========================================================================-->
- <!--
- Template: iter
- Purpose: Iterate (compose a function with itself) N times
- Parameters:-
- $pTimes - [optional] number of times to iterate
- $pFun - a template reference to the function that's to be iterated
- $pX - an initial argument to the function
- ========================================================================== -->
- <xsl:template name="iter">
- <xsl:param name="pTimes" select="0"/>
- <xsl:param name="pFun" select="/.."/>
- <xsl:param name="pX" />
-
- <xsl:choose>
- <xsl:when test="$pTimes = 0" >
- <xsl:copy-of select="$pX"/>
- </xsl:when>
- <xsl:when test="$pTimes = 1">
- <xsl:apply-templates select="$pFun">
- <xsl:with-param name="arg1" select="$pX"/>
- </xsl:apply-templates>
- </xsl:when>
- <xsl:when test="$pTimes > 1">
- <xsl:variable name="vHalfTimes" select="floor($pTimes div 2)"/>
- <xsl:variable name="vHalfIters">
- <xsl:call-template name="iter">
- <xsl:with-param name="pTimes" select="$vHalfTimes"/>
- <xsl:with-param name="pFun" select="$pFun"/>
- <xsl:with-param name="pX" select="$pX"/>
- </xsl:call-template>
- </xsl:variable>
-
- <xsl:call-template name="iter">
- <xsl:with-param name="pTimes" select="$pTimes - $vHalfTimes"/>
- <xsl:with-param name="pFun" select="$pFun"/>
- <xsl:with-param name="pX" select="vendor:node-set($vHalfIters)"/>
- </xsl:call-template>
- </xsl:when>
- <xsl:otherwise>
- <xsl:message>[iter]Error: the $pTimes argument must be
- a positive integer or 0.
- </xsl:message>
- </xsl:otherwise>
- </xsl:choose>
-
- </xsl:template>
-
- <!--
- ===========================================================================
- This is a variation of the iter function.
- Iterations are performed only while the predicate p
- is true on the argument of the iteration
- ===========================================================================-->
- <!--
- Template: iterUntil
- Purpose: Iterate (compose a function with itself)
- until a condition is satisfied
- Parameters:-
- $pCond - a template reference to a predicate that tests
- the iteration stop-condition. Returns 0 or 1
- $pFun - a template reference to the function that's to be iterated
- $arg1 - an initial argument to the function
- ========================================================================== -->
- <xsl:template name="iterUntil">
- <xsl:param name="pCond" select="/.."/>
- <xsl:param name="pFun" select="/.."/>
- <xsl:param name="arg1" select="/.."/>
-
- <xsl:variable name="vCond">
- <xsl:apply-templates select="$pCond">
- <xsl:with-param name="arg1" select="$arg1"/>
- </xsl:apply-templates>
- </xsl:variable>
-
- <xsl:choose>
- <xsl:when test="$vCond = 1" >
- <xsl:copy-of select="$arg1"/>
- </xsl:when>
- <xsl:otherwise>
- <xsl:variable name="vrtfFunResult">
- <xsl:apply-templates select="$pFun">
- <xsl:with-param name="arg1" select="$arg1"/>
- </xsl:apply-templates>
- </xsl:variable>
-
- <xsl:call-template name="iterUntil">
- <xsl:with-param name="pCond" select="$pCond"/>
- <xsl:with-param name="pFun" select="$pFun"/>
- <xsl:with-param name="arg1"
- select="vendor:node-set($vrtfFunResult)/node()"/>
- </xsl:call-template>
- </xsl:otherwise>
- </xsl:choose>
- </xsl:template>
-
- <!--
- This template implements the scanIter function
- defined in Haskell as:
-
- > scanIter :: (Ord a, Num a) => a -> (b -> b) -> b -> [b]
- > scanIter n f x
- > | n == 0 = [x]
- > | n > 0 = result ++ [f(last result)]
- > where result = scanIter (n-1) f x
- ==========================================================================-->
-
-
- <!--
- Template: scanIter
- Purpose: Iterate (compose a function with itself) N times
- and produce a list, whose elements are the results
- from the partial iterations
- Parameters:-
- $arg1 - the number of times to iterate
- $arg2 - a template reference to the function that's to be iterated
- $arg3 - an initial argument to the function
- $arg4 - [optional] name for the elements in the result node-set
- ==========================================================================-->
- <xsl:template name="scanIter">
- <xsl:param name="arg1"/> <!-- n -->
- <xsl:param name="arg2" select="/.."/> <!-- f -->
- <xsl:param name="arg3"/> <!-- x -->
- <xsl:param name="arg4" select="'el'"/> <!-- elName -->
-
- <xsl:choose>
- <xsl:when test="$arg1 < 0">
- <xsl:message>[scanIter]Error: Negative value for n.</xsl:message>
- </xsl:when>
- <xsl:when test="$arg1 = 0">
- <xsl:element name="{$arg4}">
- <xsl:value-of select="$arg3"/>
- </xsl:element>
- </xsl:when>
- <xsl:otherwise>
- <xsl:variable name="vrtfIterMinus">
- <xsl:call-template name="scanIter">
- <xsl:with-param name="arg1" select="$arg1 - 1"/>
- <xsl:with-param name="arg2" select="$arg2"/>
- <xsl:with-param name="arg3" select="$arg3"/>
- <xsl:with-param name="arg4" select="$arg4"/>
- </xsl:call-template>
- </xsl:variable>
-
- <xsl:variable name="vIterMinus"
- select="vendor:node-set($vrtfIterMinus)/*"/>
-
- <xsl:variable name="vrtfLastIter">
- <xsl:element name="{$arg4}">
- <xsl:apply-templates select="$arg2">
- <xsl:with-param name="arg1" select="$vIterMinus[last()]"/>
- </xsl:apply-templates>
- </xsl:element>
- </xsl:variable>
-
- <xsl:copy-of select="$vIterMinus"/>
- <xsl:copy-of select="vendor:node-set($vrtfLastIter)"/>
- </xsl:otherwise>
- </xsl:choose>
- </xsl:template>
- </xsl:stylesheet>