/*
 * The Apache Software License, Version 1.1
 *
 *
 * Copyright (c) 1999-2003 The Apache Software Foundation.  All rights
 * reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 *
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in
 *    the documentation and/or other materials provided with the
 *    distribution.
 *
 * 3. The end-user documentation included with the redistribution,
 *    if any, must include the following acknowledgment:
 *       "This product includes software developed by the
 *        Apache Software Foundation (http://www.apache.org/)."
 *    Alternately, this acknowledgment may appear in the software itself,
 *    if and wherever such third-party acknowledgments normally appear.
 *
 * 4. The names "Xalan" and "Apache Software Foundation" must
 *    not be used to endorse or promote products derived from this
 *    software without prior written permission. For written
 *    permission, please contact apache@apache.org.
 *
 * 5. Products derived from this software may not be called "Apache",
 *    nor may "Apache" appear in their name, without prior written
 *    permission of the Apache Software Foundation.
 *
 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 * ====================================================================
 *
 * This software consists of voluntary contributions made by many
 * individuals on behalf of the Apache Software Foundation and was
 * originally based on software copyright (c) 1999, Lotus
 * Development Corporation., http://www.lotus.com.  For more
 * information on the Apache Software Foundation, please see
 * <http://www.apache.org/>.
 */
package org.apache.xalan.lib;

import org.apache.xpath.NodeSet;

import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

/**
 * This class contains EXSLT math extension functions.
 * It is accessed by specifying a namespace URI as follows:
 * <pre>
 *    xmlns:math="http://exslt.org/math"
 * </pre>
 * 
 * The documentation for each function has been copied from the relevant
 * EXSLT Implementer page.
 * 
 * @see <a href="http://www.exslt.org/">EXSLT</a>

 * @xsl.usage general
 */
public class ExsltMath extends ExsltBase
{
  // Constants
  private static String PI = "3.1415926535897932384626433832795028841971693993751";
  private static String E  = "2.71828182845904523536028747135266249775724709369996";
  private static String SQRRT2 = "1.41421356237309504880168872420969807856967187537694";
  private static String LN2 = "0.69314718055994530941723212145817656807550013436025";
  private static String LN10 = "2.302585092994046";
  private static String LOG2E = "1.4426950408889633";
  private static String SQRT1_2 = "0.7071067811865476";
	
  /**
   * The math:max function returns the maximum value of the nodes passed as the argument. 
   * The maximum value is defined as follows. The node set passed as an argument is sorted 
   * in descending order as it would be by xsl:sort with a data type of number. The maximum 
   * is the result of converting the string value of the first node in this sorted list to 
   * a number using the number function. 
   * <p>
   * If the node set is empty, or if the result of converting the string values of any of the 
   * nodes to a number is NaN, then NaN is returned.
   * 
   * @param nl The NodeList for the node-set to be evaluated.
   * 
   * @return the maximum value found, NaN if any node cannot be converted to a number.
   * 
   * @see <a href="http://www.exslt.org/">EXSLT</a>
   */
  public static double max (NodeList nl)
  {
    if (nl == null || nl.getLength() == 0)
      return Double.NaN;
      
    double m = - Double.MAX_VALUE;
    for (int i = 0; i < nl.getLength(); i++)
    {
      Node n = nl.item(i);
      double d = toNumber(n);
      if (Double.isNaN(d))
        return Double.NaN;
      else if (d > m)
        m = d;
    }
  	
    return m;  	
  }

  /**
   * The math:min function returns the minimum value of the nodes passed as the argument. 
   * The minimum value is defined as follows. The node set passed as an argument is sorted 
   * in ascending order as it would be by xsl:sort with a data type of number. The minimum 
   * is the result of converting the string value of the first node in this sorted list to 
   * a number using the number function. 
   * <p>
   * If the node set is empty, or if the result of converting the string values of any of 
   * the nodes to a number is NaN, then NaN is returned.
   * 
   * @param nl The NodeList for the node-set to be evaluated.
   * 
   * @return the minimum value found, NaN if any node cannot be converted to a number.
   * 
   * @see <a href="http://www.exslt.org/">EXSLT</a>
   */
  public static double min (NodeList nl)
  {
    if (nl == null || nl.getLength() == 0)
      return Double.NaN;

    double m = Double.MAX_VALUE;
    for (int i = 0; i < nl.getLength(); i++)
    {
      Node n = nl.item(i);
      double d = toNumber(n);
      if (Double.isNaN(d))
        return Double.NaN;
      else if (d < m)
        m = d;
    }
    
    return m;
  }
  
  /**
   * The math:highest function returns the nodes in the node set whose value is the maximum 
   * value for the node set. The maximum value for the node set is the same as the value as 
   * calculated by math:max. A node has this maximum value if the result of converting its 
   * string value to a number as if by the number function is equal to the maximum value, 
   * where the equality comparison is defined as a numerical comparison using the = operator.
   * <p>
   * If any of the nodes in the node set has a non-numeric value, the math:max function will 
   * return NaN. The definition numeric comparisons entails that NaN != NaN. Therefore if any 
   * of the nodes in the node set has a non-numeric value, math:highest will return an empty 
   * node set. 
   * 
   * @param nl The NodeList for the node-set to be evaluated.
   * 
   * @return node-set with nodes containing the maximum value found, an empty node-set
   * if any node cannot be converted to a number.
   */
  public static NodeList highest (NodeList nl)
  {        
    double maxValue = max(nl);

    NodeSet highNodes = new NodeSet();
    highNodes.setShouldCacheNodes(true);    
    
    if (Double.isNaN(maxValue))
      return highNodes;  // empty Nodeset
    
    for (int i = 0; i < nl.getLength(); i++)
    {
      Node n = nl.item(i);
      double d = toNumber(n); 
      if (d == maxValue)
        highNodes.addElement(n);
    }
    return highNodes;
  }
  
  /**
   * The math:lowest function returns the nodes in the node set whose value is the minimum value 
   * for the node set. The minimum value for the node set is the same as the value as calculated 
   * by math:min. A node has this minimum value if the result of converting its string value to 
   * a number as if by the number function is equal to the minimum value, where the equality 
   * comparison is defined as a numerical comparison using the = operator.
   * <p>
   * If any of the nodes in the node set has a non-numeric value, the math:min function will return 
   * NaN. The definition numeric comparisons entails that NaN != NaN. Therefore if any of the nodes 
   * in the node set has a non-numeric value, math:lowest will return an empty node set.
   * 
   * @param nl The NodeList for the node-set to be evaluated.
   * 
   * @return node-set with nodes containing the minimum value found, an empty node-set
   * if any node cannot be converted to a number.
   * 
   */
  public static NodeList lowest (NodeList nl)
  {
    double minValue = min(nl);

    NodeSet lowNodes = new NodeSet();
    lowNodes.setShouldCacheNodes(true);
    
    if (Double.isNaN(minValue))
      return lowNodes;  // empty Nodeset
    
    for (int i = 0; i < nl.getLength(); i++)
    {
      Node n = nl.item(i);
      double d = toNumber(n); 
      if (d == minValue)
        lowNodes.addElement(n);
    }
    return lowNodes;
  }
  
  /**
   * The math:abs function returns the absolute value of a number.
   *
   * @param num A number
   * @return The absolute value of the number
   */
   public static double abs(double num)
   {
     return Math.abs(num);
   }

  /**
   * The math:acos function returns the arccosine value of a number.
   *
   * @param num A number
   * @return The arccosine value of the number
   */
   public static double acos(double num)
   {
     return Math.acos(num);
   }

  /**
   * The math:asin function returns the arcsine value of a number. 
   *
   * @param num A number
   * @return The arcsine value of the number
   */
   public static double asin(double num)
   {
     return Math.asin(num);
   }

  /**
   * The math:atan function returns the arctangent value of a number. 
   *
   * @param num A number
   * @return The arctangent value of the number
   */
   public static double atan(double num)
   {
     return Math.atan(num);
   }
  
  /**
   * The math:atan2 function returns the angle ( in radians ) from the X axis to a point (y,x). 
   *
   * @param num1 The X axis value
   * @param num2 The Y axis value
   * @return The angle (in radians) from the X axis to a point (y,x)
   */
   public static double atan2(double num1, double num2)
   {
     return Math.atan2(num1, num2);
   }

  /**
   * The math:cos function returns cosine of the passed argument. 
   *
   * @param num A number
   * @return The cosine value of the number
   */
   public static double cos(double num)
   {
     return Math.cos(num);
   }

  /**
   * The math:exp function returns e (the base of natural logarithms) raised to a power. 
   *
   * @param num A number
   * @return The value of e raised to the given power
   */
   public static double exp(double num)
   {
     return Math.exp(num);
   }

  /**
   * The math:log function returns the natural logarithm of a number. 
   *
   * @param num A number
   * @return The natural logarithm of the number
   */
   public static double log(double num)
   {
     return Math.log(num);
   }

  /**
   * The math:power function returns the value of a base expression taken to a specified power. 
   *
   * @param num1 The base
   * @param num2 The power
   * @return The value of the base expression taken to the specified power
   */
   public static double power(double num1, double num2)
   {
     return Math.pow(num1, num2);
   }

  /**
   * The math:random function returns a random number from 0 to 1. 
   *
   * @return A random double from 0 to 1
   */
   public static double random()
   {
     return Math.random();
   }

  /**
   * The math:sin function returns the sine of the number. 
   *
   * @param num A number
   * @return The sine value of the number
   */
   public static double sin(double num)
   {
     return Math.sin(num);
   }

  /**
   * The math:sqrt function returns the square root of a number. 
   *
   * @param num A number
   * @return The square root of the number
   */
   public static double sqrt(double num)
   {
     return Math.sqrt(num);
   }

  /**
   * The math:tan function returns the tangent of the number passed as an argument. 
   *
   * @param num A number
   * @return The tangent value of the number
   */
   public static double tan(double num)
   {
     return Math.tan(num);
   }

  /**
   * The math:constant function returns the specified constant to a set precision. 
   * The possible constants are:
   * <pre>
   *  PI
   *  E
   *  SQRRT2
   *  LN2
   *  LN10
   *  LOG2E
   *  SQRT1_2
   * </pre>
   * @param name The name of the constant
   * @param precision The precision
   * @return The value of the specified constant to the given precision
   */
   public static double constant(String name, double precision)
   {
     String value = null;
     if (name.equals("PI"))
       value = PI;
     else if (name.equals("E"))
       value = E;
     else if (name.equals("SQRRT2"))
       value = SQRRT2;
     else if (name.equals("LN2"))
       value = LN2;
     else if (name.equals("LN10"))
       value = LN10;
     else if (name.equals("LOG2E"))
       value = LOG2E;
     else if (name.equals("SQRT1_2"))
       value = SQRT1_2;
     
     if (value != null)
     {
       int bits = new Double(precision).intValue();
       
       if (bits <= value.length())
         value = value.substring(0, bits);
         
       return new Double(value).doubleValue();
     }
     else
       return Double.NaN;
            
   }
      
}