/*
 * This file is part of the ESO SINFONI Pipeline
 * Copyright (C) 2004,2005 European Southern Observatory
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, 51 Franklin St, Fifth Floor, Boston, MA  02111-1307  USA
 */
#ifdef HAVE_CONFIG_H
#  include <config.h>
#endif
/*
 * This function is so generic and used everywhere, it diserves its
 * own source file...
 */
/*
 $Id: sinfo_ipow.c,v 1.4 2012-03-02 08:42:20 amodigli Exp $
 $Author: amodigli $
 $Date: 2012-03-02 08:42:20 $
 $Revision: 1.4 $
 */
/**@{*/
/**
 * @addtogroup sinfo_utilities ipow
 *
 * TBD
 */

/**
  @name        sinfo_ipow
  @memo        Same as pow(x,y) but for integer values of y only (faster).
  @param    x    A double number.
  @param    p    An integer power.
  @return    x to the power p.
  @doc

  This is much faster than the math function due to the integer. Some
  compilers make this optimization already, some do not.

  p can be positive, negative or null.
 */

#include "sinfo_ipow.h"
double sinfo_ipow(double x, int p)
{

    /* Get rid of trivial cases */
    switch (p) {
    case 0:
        return 1.00 ;

    case 1:
        return x ;

    case 2:
        return x*x ;

    case 3:
        return x*x*x ;

    case -1:
        return 1.00 / x ;

    case -2:
        return (1.00 / x) * (1.00 / x) ;
    }
    double r;
    if (p>0) {
        r = x ;
        while (--p) r *= x ;
    } else {
        double recip;
        r = recip = 1.00 / x ;
        while (++p) r *= recip ;
    }
    return r;
}


/**@}*/
